From 00b3660e45c56cb3db35dc2596a054f801b5591a Mon Sep 17 00:00:00 2001 From: Youngman Jung Date: Wed, 11 Mar 2015 18:56:00 +0900 Subject: [PATCH] iotivity 0.9.0 Change-Id: I8bfbed02fe5836bfae624e8c3ae10ec360ac827d Signed-off-by: Youngman Jung --- .gitignore | 60 + Readme.scons.txt | 191 + SConstruct | 39 + android/Base/app/build.gradle | 60 + android/Base/app/jni/Android.mk | 57 + android/Base/app/jni/Application.mk | 2 + android/Base/app/jni/ocheaderoption-jni.cpp | 44 + android/Base/app/jni/ocplatform-jni.cpp | 124 + android/Base/app/jni/ocrepresentation-jni.cpp | 101 + android/Base/app/jni/ocresource-jni.cpp | 445 + android/Base/app/jni/ocstack-jni.cpp | 134 + android/Base/app/jni/ocstack-jni.h | 101 + android/Base/app/jni/platformcfg-jni.cpp | 80 + android/Base/app/proguard-rules.pro | 17 + .../org/iotivity/base/ApplicationTest.java | 33 + android/Base/app/src/main/AndroidManifest.xml | 11 + .../iotivity/base/AbstractDeleteCallback.java | 25 + .../iotivity/base/AbstractFindCallback.java | 26 + .../iotivity/base/AbstractGetCallback.java | 27 + .../base/AbstractObserveCallback.java | 27 + .../iotivity/base/AbstractPostCallback.java | 27 + .../iotivity/base/AbstractPutCallback.java | 7 + .../base/AbstractSubscriberCallback.java | 25 + .../java/org/iotivity/base/EntityHandler.java | 25 + .../org/iotivity/base/NativeInstance.java | 33 + .../org/iotivity/base/OCHeaderOption.java | 36 + .../java/org/iotivity/base/OCPlatform.java | 32 + .../org/iotivity/base/OCRepresentation.java | 49 + .../java/org/iotivity/base/OCResource.java | 60 + .../org/iotivity/base/OCResourceRequest.java | 24 + .../org/iotivity/base/OCResourceResponse.java | 24 + .../java/org/iotivity/base/OCStackResult.java | 54 + .../java/org/iotivity/base/ObserveType.java | 26 + .../org/iotivity/base/PlatformConfig.java | 68 + .../main/res/drawable-hdpi/ic_launcher.png | Bin 0 -> 9397 bytes .../main/res/drawable-mdpi/ic_launcher.png | Bin 0 -> 5237 bytes .../main/res/drawable-xhdpi/ic_launcher.png | Bin 0 -> 14383 bytes .../main/res/drawable-xxhdpi/ic_launcher.png | Bin 0 -> 19388 bytes .../Base/app/src/main/res/values/strings.xml | 3 + .../Base/app/src/main/res/values/styles.xml | 8 + android/Base/build.gradle | 19 + android/Base/gradle.properties | 18 + android/Base/gradlew | 164 + android/Base/gradlew.bat | 90 + android/Base/settings.gradle | 1 + android/SimpleClient/app/build.gradle | 40 + android/SimpleClient/app/proguard-rules.pro | 17 + .../simpleclient/ApplicationTest.java | 33 + .../app/src/main/AndroidManifest.xml | 23 + .../iotivity/simpleclient/FoundResource.java | 72 + .../java/org/iotivity/simpleclient/OnGet.java | 58 + .../org/iotivity/simpleclient/OnObserve.java | 75 + .../org/iotivity/simpleclient/OnPost.java | 77 + .../org/iotivity/simpleclient/OnPost2.java | 75 + .../java/org/iotivity/simpleclient/OnPut.java | 59 + .../iotivity/simpleclient/SimpleClient.java | 151 + .../iotivity/simpleclient/SimpleToast.java | 44 + .../main/res/drawable-hdpi/ic_launcher.png | Bin 0 -> 9397 bytes .../main/res/drawable-mdpi/ic_launcher.png | Bin 0 -> 5237 bytes .../main/res/drawable-xhdpi/ic_launcher.png | Bin 0 -> 14383 bytes .../main/res/drawable-xxhdpi/ic_launcher.png | Bin 0 -> 19388 bytes .../res/layout/activity_simple_client.xml | 16 + .../app/src/main/res/menu/simple_client.xml | 8 + .../app/src/main/res/values-w820dp/dimens.xml | 6 + .../app/src/main/res/values/dimens.xml | 5 + .../app/src/main/res/values/strings.xml | 8 + .../app/src/main/res/values/styles.xml | 8 + android/SimpleClient/build.gradle | 19 + android/SimpleClient/gradle.properties | 18 + android/SimpleClient/gradlew | 164 + android/SimpleClient/gradlew.bat | 90 + android/SimpleClient/settings.gradle | 1 + arduino.scons | 11 + auto_build.sh | 103 + build_common/SConscript | 239 + build_common/android/SConscript | 172 + .../compatibility/android_cpp11_compat.cpp | 73 + .../compatibility/android_cpp11_compat.h | 25 + build_common/android/compatibility/c_compat.c | 60 + .../android/compatibility/c_compat.scons | 20 + .../android/compatibility/cpp11_compat.scons | 17 + build_common/android/jni/Android.mk | 12 + build_common/arduino/SConscript | 400 + build_common/darwin/SConscript | 54 + build_common/ios/SConscript | 18 + build_common/linux/SConscript | 33 + build_common/windows/SConscript | 17 + examples/OICMiddle/Client.cpp | 83 + examples/OICMiddle/Client.h | 58 + examples/OICMiddle/LineInput.cpp | 458 + examples/OICMiddle/LineInput.h | 72 + examples/OICMiddle/OICMiddle.cpp | 152 + examples/OICMiddle/OICMiddle.h | 94 + examples/OICMiddle/README | 37 + examples/OICMiddle/RestInput.cpp | 166 + examples/OICMiddle/RestInput.h | 50 + examples/OICMiddle/SConstruct | 81 + examples/OICMiddle/Server.cpp | 155 + examples/OICMiddle/Server.h | 56 + examples/OICMiddle/WrapResource.cpp | 289 + examples/OICMiddle/WrapResource.h | 121 + examples/OICMiddle/makefile | 87 + .../OICSensorBoard/OICSensorBoardREADME.pdf | Bin 0 -> 299033 bytes examples/OICSensorBoard/SConstruct | 65 + examples/OICSensorBoard/client.cpp | 383 + examples/OICSensorBoard/client.h | 105 + examples/OICSensorBoard/namedefs.h | 35 + examples/OICSensorBoard/observer.cpp | 71 + examples/OICSensorBoard/observer.h | 55 + examples/OICSensorBoard/sensors.h | 90 + examples/OICSensorBoard/server.cpp | 359 + examples/OICSensorBoard/server.h | 71 + extlibs/buildDependencies.sh | 114 + extlibs/cjson/cJSON.c | 596 + extlibs/cjson/cJSON.h | 143 + extra_options.scons | 35 + resource/README.setup.txt | 266 + resource/SConscript | 29 + resource/android/OCAndroid.cpp | 104 + resource/android/SConscript | 30 + resource/artifact_output_locations.txt | 191 + resource/buildScript.mk | 531 + resource/csdk/README | 62 + resource/csdk/SConscript | 84 + resource/csdk/arduinodue.properties | 70 + resource/csdk/arduinomega.properties | 56 + resource/csdk/connectivity/RELEASE v0.1 | 69 + resource/csdk/connectivity/api/cacommon.h | 265 + resource/csdk/connectivity/api/cainterface.h | 207 + .../csdk/connectivity/build/linux/Makefile | 161 + .../csdk/connectivity/build/linux/common.mk | 59 + .../csdk/connectivity/common/inc/logger.h | 178 + .../common/inc/oic_console_logger.h | 44 + .../csdk/connectivity/common/inc/oic_logger.h | 48 + .../common/inc/oic_logger_types.h | 86 + .../csdk/connectivity/common/inc/oic_malloc.h | 84 + .../csdk/connectivity/common/inc/uarraylist.h | 116 + .../csdk/connectivity/common/inc/umutex.h | 143 + .../csdk/connectivity/common/inc/uqueue.h | 147 + .../connectivity/common/inc/uthreadpool.h | 94 + .../csdk/connectivity/common/src/logger.c | 379 + .../common/src/oic_console_logger.c | 93 + .../csdk/connectivity/common/src/oic_logger.c | 148 + .../csdk/connectivity/common/src/oic_malloc.c | 89 + .../csdk/connectivity/common/src/uarraylist.c | 149 + .../csdk/connectivity/common/src/umutex.c | 169 + .../csdk/connectivity/common/src/uqueue.c | 247 + .../connectivity/common/src/uthreadpool.c | 116 + .../connectivity/inc/caadapterinterface.h | 187 + resource/csdk/connectivity/inc/caedradapter.h | 141 + resource/csdk/connectivity/inc/caerrorcode.h | 65 + .../csdk/connectivity/inc/caethernetadapter.h | 137 + .../connectivity/inc/cainterfacecontroller.h | 52 + resource/csdk/connectivity/inc/caleadapter.h | 138 + .../csdk/connectivity/inc/camessagehandler.h | 58 + .../connectivity/inc/canetworkconfigurator.h | 45 + .../csdk/connectivity/inc/caprotocolmessage.h | 80 + .../csdk/connectivity/inc/caremotehandler.h | 55 + .../csdk/connectivity/inc/cawifiadapter.h | 135 + resource/csdk/connectivity/inc/cawificore.h | 83 + .../connectivity/inc/cawifiethernetadapter.h | 137 + .../connectivity/lib/libcoap-4.1.1/.gitignore | 1 + .../connectivity/lib/libcoap-4.1.1/ChangeLog | 159 + .../lib/libcoap-4.1.1/LICENSE.BSD | 26 + .../lib/libcoap-4.1.1/LICENSE.GPL | 280 + .../connectivity/lib/libcoap-4.1.1/Makefile | 113 + .../lib/libcoap-4.1.1/Makefile.in | 113 + .../connectivity/lib/libcoap-4.1.1/README | 27 + .../connectivity/lib/libcoap-4.1.1/address.h | 176 + .../connectivity/lib/libcoap-4.1.1/async.c | 105 + .../connectivity/lib/libcoap-4.1.1/async.h | 148 + .../connectivity/lib/libcoap-4.1.1/bits.h | 79 + .../connectivity/lib/libcoap-4.1.1/block.c | 140 + .../connectivity/lib/libcoap-4.1.1/block.h | 138 + .../connectivity/lib/libcoap-4.1.1/coap.h | 36 + .../lib/libcoap-4.1.1/coap_list.c | 92 + .../lib/libcoap-4.1.1/coap_list.h | 45 + .../lib/libcoap-4.1.1/coap_time.h | 167 + .../connectivity/lib/libcoap-4.1.1/config.h | 132 + .../lib/libcoap-4.1.1/config.h.in | 131 + .../lib/libcoap-4.1.1/config.status | 1020 + .../connectivity/lib/libcoap-4.1.1/configure | 5411 + .../lib/libcoap-4.1.1/configure.in | 98 + .../connectivity/lib/libcoap-4.1.1/debug.c | 391 + .../connectivity/lib/libcoap-4.1.1/debug.h | 75 + .../connectivity/lib/libcoap-4.1.1/encode.c | 50 + .../connectivity/lib/libcoap-4.1.1/encode.h | 52 + .../lib/libcoap-4.1.1/examples/Makefile | 61 + .../lib/libcoap-4.1.1/examples/Makefile.in | 61 + .../lib/libcoap-4.1.1/examples/client.c | 1270 + .../lib/libcoap-4.1.1/examples/etsi_iot_01.c | 796 + .../lib/libcoap-4.1.1/examples/rd.c | 750 + .../lib/libcoap-4.1.1/examples/server.c | 456 + .../lib/libcoap-4.1.1/examples/tiny.c | 157 + .../connectivity/lib/libcoap-4.1.1/hashkey.c | 31 + .../connectivity/lib/libcoap-4.1.1/hashkey.h | 57 + .../csdk/connectivity/lib/libcoap-4.1.1/mem.h | 18 + .../csdk/connectivity/lib/libcoap-4.1.1/net.c | 1805 + .../csdk/connectivity/lib/libcoap-4.1.1/net.h | 448 + .../connectivity/lib/libcoap-4.1.1/option.c | 440 + .../connectivity/lib/libcoap-4.1.1/option.h | 320 + .../csdk/connectivity/lib/libcoap-4.1.1/pdu.c | 467 + .../csdk/connectivity/lib/libcoap-4.1.1/pdu.h | 346 + .../connectivity/lib/libcoap-4.1.1/prng.h | 87 + .../connectivity/lib/libcoap-4.1.1/resource.c | 935 + .../connectivity/lib/libcoap-4.1.1/resource.h | 318 + .../csdk/connectivity/lib/libcoap-4.1.1/str.c | 37 + .../csdk/connectivity/lib/libcoap-4.1.1/str.h | 31 + .../lib/libcoap-4.1.1/subscribe.c | 445 + .../lib/libcoap-4.1.1/subscribe.h | 201 + .../connectivity/lib/libcoap-4.1.1/t_list.h | 152 + .../lib/libcoap-4.1.1/tests/Makefile | 57 + .../lib/libcoap-4.1.1/tests/Makefile.in | 57 + .../libcoap-4.1.1/tests/test_error_response.c | 330 + .../libcoap-4.1.1/tests/test_error_response.h | 11 + .../lib/libcoap-4.1.1/tests/test_options.c | 853 + .../lib/libcoap-4.1.1/tests/test_options.h | 11 + .../lib/libcoap-4.1.1/tests/test_pdu.c | 660 + .../lib/libcoap-4.1.1/tests/test_pdu.h | 11 + .../lib/libcoap-4.1.1/tests/test_sendqueue.c | 379 + .../lib/libcoap-4.1.1/tests/test_sendqueue.h | 11 + .../lib/libcoap-4.1.1/tests/test_uri.c | 396 + .../lib/libcoap-4.1.1/tests/test_uri.h | 11 + .../lib/libcoap-4.1.1/tests/test_wellknown.c | 337 + .../lib/libcoap-4.1.1/tests/test_wellknown.h | 11 + .../lib/libcoap-4.1.1/tests/testdriver.c | 53 + .../csdk/connectivity/lib/libcoap-4.1.1/uri.c | 577 + .../csdk/connectivity/lib/libcoap-4.1.1/uri.h | 171 + .../connectivity/lib/libcoap-4.1.1/uthash.h | 974 + .../connectivity/lib/libcoap-4.1.1/utlist.h | 489 + .../connectivity/samples/linux/.gitignore | 2 + .../csdk/connectivity/samples/linux/Makefile | 120 + .../csdk/connectivity/samples/linux/README | 26 + .../csdk/connectivity/samples/linux/sample.sh | 35 + .../connectivity/samples/linux/sample_main.c | 395 + .../samples/linux/threadpool/Makefile | 14 + .../samples/linux/threadpool/main.c | 127 + .../src/bt_edr_adapter/linux/caedradapter.c | 133 + .../src/bt_le_adapter/caleadapter.c | 417 + .../src/bt_le_adapter/linux/caleadapter.c | 133 + .../connectivity/src/caconnectivitymanager.c | 295 + .../connectivity/src/cainterfacecontroller.c | 312 + .../csdk/connectivity/src/camessagehandler.c | 686 + .../connectivity/src/canetworkconfigurator.c | 173 + .../csdk/connectivity/src/caprotocolmessage.c | 403 + .../csdk/connectivity/src/caremotehandler.c | 477 + .../linux/caethernetadapter.c | 134 + .../src/wifi_adapter/cawifiethernetadapter.c | 371 + .../src/wifi_adapter/linux/cawifiadapter.c | 190 + .../src/wifi_adapter/linux/cawificore.c | 500 + .../unittests/linux/sample1_unittest.cc | 366 + .../csdk/doc/CCF Lite GIT Repo Layout.docx | Bin 0 -> 127908 bytes resource/csdk/libcoap | 1 + resource/csdk/libcoap-4.1.1/ChangeLog | 159 + resource/csdk/libcoap-4.1.1/LICENSE.BSD | 26 + resource/csdk/libcoap-4.1.1/LICENSE.GPL | 280 + resource/csdk/libcoap-4.1.1/Makefile.in | 113 + resource/csdk/libcoap-4.1.1/README | 42 + resource/csdk/libcoap-4.1.1/SConscript | 86 + resource/csdk/libcoap-4.1.1/address.h | 208 + resource/csdk/libcoap-4.1.1/async.c | 101 + resource/csdk/libcoap-4.1.1/async.h | 154 + resource/csdk/libcoap-4.1.1/bits.h | 89 + resource/csdk/libcoap-4.1.1/block.c | 138 + resource/csdk/libcoap-4.1.1/block.h | 145 + resource/csdk/libcoap-4.1.1/coap.h | 36 + resource/csdk/libcoap-4.1.1/coap_list.c | 96 + resource/csdk/libcoap-4.1.1/coap_list.h | 53 + resource/csdk/libcoap-4.1.1/coap_time.h | 193 + resource/csdk/libcoap-4.1.1/config.h | 150 + resource/csdk/libcoap-4.1.1/config.h.in | 131 + resource/csdk/libcoap-4.1.1/configure | 5411 + resource/csdk/libcoap-4.1.1/configure.in | 98 + resource/csdk/libcoap-4.1.1/debug.c | 383 + resource/csdk/libcoap-4.1.1/debug.h | 93 + resource/csdk/libcoap-4.1.1/doc/Doxyfile | 1551 + resource/csdk/libcoap-4.1.1/doc/Doxyfile.in | 1551 + resource/csdk/libcoap-4.1.1/doc/Makefile.in | 45 + resource/csdk/libcoap-4.1.1/doc/makefile | 66 + resource/csdk/libcoap-4.1.1/encode.c | 48 + resource/csdk/libcoap-4.1.1/encode.h | 62 + resource/csdk/libcoap-4.1.1/examples/client.c | 1177 + resource/csdk/libcoap-4.1.1/examples/makefile | 82 + resource/csdk/libcoap-4.1.1/examples/rd.c | 705 + resource/csdk/libcoap-4.1.1/examples/server.c | 490 + resource/csdk/libcoap-4.1.1/examples/tiny.c | 149 + resource/csdk/libcoap-4.1.1/hashkey.c | 29 + resource/csdk/libcoap-4.1.1/hashkey.h | 65 + resource/csdk/libcoap-4.1.1/makefile | 151 + resource/csdk/libcoap-4.1.1/mem.h | 26 + resource/csdk/libcoap-4.1.1/net.c | 1642 + resource/csdk/libcoap-4.1.1/net.h | 545 + resource/csdk/libcoap-4.1.1/option.c | 407 + resource/csdk/libcoap-4.1.1/option.h | 345 + resource/csdk/libcoap-4.1.1/pdu.c | 406 + resource/csdk/libcoap-4.1.1/pdu.h | 377 + resource/csdk/libcoap-4.1.1/prng.h | 89 + resource/csdk/libcoap-4.1.1/resource.c | 869 + resource/csdk/libcoap-4.1.1/resource.h | 332 + resource/csdk/libcoap-4.1.1/sec/netdtls.c | 548 + resource/csdk/libcoap-4.1.1/sec/netdtls.h | 138 + resource/csdk/libcoap-4.1.1/str.c | 34 + resource/csdk/libcoap-4.1.1/str.h | 30 + resource/csdk/libcoap-4.1.1/subscribe.c | 401 + resource/csdk/libcoap-4.1.1/subscribe.h | 200 + resource/csdk/libcoap-4.1.1/t_list.h | 146 + resource/csdk/libcoap-4.1.1/uri.c | 529 + resource/csdk/libcoap-4.1.1/uri.h | 174 + resource/csdk/libcoap-4.1.1/uthash.h | 977 + resource/csdk/libcoap-4.1.1/utlist.h | 490 + resource/csdk/logger/README | 42 + resource/csdk/logger/include/logger.h | 182 + resource/csdk/logger/makefile | 122 + resource/csdk/logger/src/logger.c | 352 + resource/csdk/logger/test/android/README | 22 + .../test/android/androidloggertestoutput.txt | 43 + .../csdk/logger/test/android/loggertests.cpp | 123 + .../logger/test/arduino/ArduinoLoggerTest.cpp | 126 + .../logger/test/arduino/ArduinoLoggerTest.h | 50 + resource/csdk/logger/test/arduino/README | 22 + .../test/arduino/arduinologgertestoutput.txt | 38 + resource/csdk/logger/test/loggertests.cpp | 366 + resource/csdk/logger/test/std_logbuffer.txt | 29 + resource/csdk/logger/test/std_stringarg.txt | 1 + .../csdk/logger/test/std_stringarglevels.txt | 5 + .../logger/test/std_stringargmultiline.txt | 3 + .../logger/test/std_stringargnologstr.txt | 0 .../csdk/logger/test/std_stringargnotag.txt | 0 .../test/std_stringargnotagnologstr.txt | 0 resource/csdk/logger/test/std_variablearg.txt | 4 + resource/csdk/makefile | 206 + resource/csdk/occoap/README.txt | 27 + resource/csdk/occoap/include/occoap.h | 118 + resource/csdk/occoap/include/occoaphelper.h | 118 + resource/csdk/occoap/include/occoaptoken.h | 35 + resource/csdk/occoap/makefile | 139 + resource/csdk/occoap/src/occoap.c | 964 + resource/csdk/occoap/src/occoaphelper.c | 714 + resource/csdk/occoap/test/occoaptests.cpp | 61 + resource/csdk/ocmalloc/include/ocmalloc.h | 94 + resource/csdk/ocmalloc/src/ocmalloc.c | 106 + resource/csdk/ocmalloc/test/linux/README | 35 + resource/csdk/ocmalloc/test/linux/makefile | 107 + .../csdk/ocmalloc/test/linux/unittest.cpp | 140 + resource/csdk/ocrandom/include/ocrandom.h | 80 + resource/csdk/ocrandom/src/ocrandom.c | 134 + resource/csdk/ocrandom/test/android/makefile | 130 + .../csdk/ocrandom/test/android/randomtest.cpp | 65 + resource/csdk/ocrandom/test/arduino/makefile | 161 + .../csdk/ocrandom/test/arduino/randomtest.cpp | 81 + resource/csdk/ocrandom/test/linux/makefile | 125 + .../csdk/ocrandom/test/linux/randomtest.cpp | 66 + resource/csdk/ocsocket/README.txt | 28 + resource/csdk/ocsocket/include/ocsocket.h | 321 + resource/csdk/ocsocket/src/ocsocket.c | 433 + .../csdk/ocsocket/src/ocsocket_arduino.cpp | 268 + .../ocsocket/src/ocsocket_arduino_wifi.cpp | 306 + resource/csdk/ocsocket/test/android/makefile | 70 + .../ocsocket/test/android/ocsocket_gtest.cpp | 289 + resource/csdk/ocsocket/test/arduino/makefile | 104 + .../ocsocket/test/arduino/ocsocket_test.cpp | 339 + .../test/arduino/ocsocket_wifi_test.cpp | 204 + resource/csdk/ocsocket/test/linux/makefile | 65 + .../ocsocket/test/linux/ocsocket_gtest.cpp | 318 + resource/csdk/ocsocket/test/makefile | 36 + resource/csdk/ocsocket/test/sendrecv.cpp | 226 + .../csdk/ocsocket/test/sendrecv_README.txt | 3 + resource/csdk/stack/README | 45 + .../csdk/stack/include/internal/occlientcb.h | 195 + .../stack/include/internal/occollection.h | 32 + .../csdk/stack/include/internal/ocobserve.h | 86 + .../csdk/stack/include/internal/ocresource.h | 158 + .../include/internal/ocresourcehandler.h | 97 + .../stack/include/internal/ocserverrequest.h | 110 + .../stack/include/internal/ocstackinternal.h | 169 + .../csdk/stack/include/internal/oicgroup.h | 57 + resource/csdk/stack/include/ocsecurity.h | 49 + .../csdk/stack/include/ocsecurityconfig.h | 59 + resource/csdk/stack/include/ocstack.h | 853 + resource/csdk/stack/include/ocstackconfig.h | 86 + .../samples/arduino/SimpleClientServer/README | 46 + .../arduino/SimpleClientServer/makefile | 38 + .../SimpleClientServer/ocserver/README | 51 + .../SimpleClientServer/ocserver/SConscript | 23 + .../SimpleClientServer/ocserver/makefile | 122 + .../SimpleClientServer/ocserver/ocserver.cpp | 345 + .../linux/SimpleClientServer/common.cpp | 74 + .../samples/linux/SimpleClientServer/makefile | 137 + .../linux/SimpleClientServer/occlient.cpp | 706 + .../linux/SimpleClientServer/occlient.h | 139 + .../SimpleClientServer/occlientbasicops.cpp | 386 + .../SimpleClientServer/occlientbasicops.h | 102 + .../linux/SimpleClientServer/occlientcoll.cpp | 417 + .../linux/SimpleClientServer/occlientslow.cpp | 310 + .../linux/SimpleClientServer/occlientslow.h | 95 + .../linux/SimpleClientServer/ocserver.cpp | 1021 + .../linux/SimpleClientServer/ocserver.h | 117 + .../SimpleClientServer/ocserverbasicops.cpp | 363 + .../SimpleClientServer/ocserverbasicops.h | 80 + .../linux/SimpleClientServer/ocservercoll.cpp | 573 + .../linux/SimpleClientServer/ocserverslow.cpp | 362 + .../linux/SimpleClientServer/ocserverslow.h | 71 + .../stack/samples/linux/secure/common.cpp | 117 + .../csdk/stack/samples/linux/secure/common.h | 31 + .../samples/linux/secure/gen_sec_bin.cpp | 123 + .../csdk/stack/samples/linux/secure/makefile | 114 + .../samples/linux/secure/occlientbasicops.cpp | 442 + .../samples/linux/secure/occlientbasicops.h | 91 + .../samples/linux/secure/ocserverbasicops.cpp | 381 + .../samples/linux/secure/ocserverbasicops.h | 77 + resource/csdk/stack/src/occlientcb.c | 237 + resource/csdk/stack/src/occollection.c | 471 + resource/csdk/stack/src/ocobserve.c | 397 + resource/csdk/stack/src/ocresource.c | 866 + resource/csdk/stack/src/ocsecurity.c | 86 + resource/csdk/stack/src/ocserverrequest.c | 379 + resource/csdk/stack/src/ocstack.c | 2409 + resource/csdk/stack/src/oicgroup.c | 864 + resource/csdk/stack/test/README | 52 + resource/csdk/stack/test/android/README | 26 + .../csdk/stack/test/android/stacktests.cpp | 133 + .../stack/test/arduino/ArduinoStackTest.cpp | 220 + .../stack/test/arduino/ArduinoStackTest.h | 49 + resource/csdk/stack/test/arduino/README | 34 + resource/csdk/stack/test/arduino/makefile | 114 + resource/csdk/stack/test/arduino/ocserver.cpp | 34 + resource/csdk/stack/test/linux/makefile | 98 + resource/csdk/stack/test/linux/occlient.c | 99 + resource/csdk/stack/test/linux/ocserver.c | 104 + resource/csdk/stack/test/makefile | 106 + resource/csdk/stack/test/stacktests.cpp | 1420 + resource/docs/Doxyfile | 1856 + resource/docs/doxygenLayout.xml | 13 + resource/docs/guides/AboutOIC.txt | 51 + resource/docs/guides/Home.txt | 15 + resource/docs/guides/HowToGuidesIndex.txt | 1556 + resource/docs/guides/ProgrammersGuide.txt | 308 + resource/docs/html/footer.html | 7 + resource/docs/img/seq_find_resource.png | Bin 0 -> 129118 bytes resource/docs/img/seq_find_resource_2.png | Bin 0 -> 72559 bytes resource/docs/img/seq_find_resource_3.png | Bin 0 -> 13681 bytes resource/docs/img/seq_find_resource_4.png | Bin 0 -> 20593 bytes resource/docs/img/seq_get.png | Bin 0 -> 87635 bytes resource/docs/img/seq_observe.png | Bin 0 -> 141527 bytes resource/docs/img/seq_put.png | Bin 0 -> 93320 bytes resource/docs/img/seq_register_resource.png | Bin 0 -> 59726 bytes resource/docs/img/seq_register_resource_2.png | Bin 0 -> 52712 bytes resource/docs/img/seq_stack_init.png | Bin 0 -> 116787 bytes resource/docs/img/stack_diagram.png | Bin 0 -> 81345 bytes resource/examples/SConscript | 73 + resource/examples/devicediscoveryclient.cpp | 147 + resource/examples/devicediscoveryserver.cpp | 170 + resource/examples/fridgeclient.cpp | 256 + resource/examples/fridgeserver.cpp | 481 + resource/examples/garageclient.cpp | 305 + resource/examples/garageserver.cpp | 287 + resource/examples/groupclient.cpp | 234 + resource/examples/groupserver.cpp | 129 + resource/examples/lightserver.cpp | 334 + resource/examples/makefile | 137 + resource/examples/ocicuc/.gitignore | 4 + resource/examples/ocicuc/Makefile | 84 + resource/examples/ocicuc/README | 49 + resource/examples/ocicuc/SConscript | 48 + resource/examples/ocicuc/client.cpp | 126 + resource/examples/ocicuc/demo_client.hpp | 234 + resource/examples/ocicuc/driver.cpp | 58 + resource/examples/ocicuc/exec.hpp | 37 + resource/examples/ocicuc/light_resource.cpp | 211 + resource/examples/ocicuc/light_resource.hpp | 95 + resource/examples/ocicuc/monoprocess.cpp | 222 + resource/examples/ocicuc/server.cpp | 99 + resource/examples/ocicuc/small_example.cpp | 44 + resource/examples/ocicuc/utility.cpp | 81 + resource/examples/ocicuc/utility.hpp | 71 + .../old_tests/MyMultiResourceHandler.cpp | 158 + .../old_tests/MyMultiResourceHandler.h | 45 + .../examples/old_tests/MyObserverHandler.cpp | 26 + .../examples/old_tests/MyObserverHandler.h | 33 + .../examples/old_tests/MyResourceHandler.cpp | 107 + .../examples/old_tests/MyResourceHandler.h | 41 + .../examples/old_tests/OCWrapper/makefile | 64 + .../old_tests/OCWrapper/parsetest.cpp | 120 + .../old_tests/OCWrapper/testClient.cpp | 44 + .../old_tests/OCWrapper/testServer.cpp | 97 + .../old_tests/OCWrapper/testServerApp.cpp | 131 + .../examples/old_tests/multiple_resources.cpp | 264 + resource/examples/presenceclient.cpp | 316 + resource/examples/presenceserver.cpp | 257 + resource/examples/roomclient.cpp | 255 + resource/examples/roomserver.cpp | 604 + resource/examples/simpleclient.cpp | 393 + resource/examples/simpleclientHQ.cpp | 407 + resource/examples/simpleclientserver.cpp | 322 + resource/examples/simpleserver.cpp | 544 + resource/examples/simpleserverHQ.cpp | 480 + resource/examples/threadingsample.cpp | 384 + resource/include/AttributeValue.h | 82 + resource/include/IClientWrapper.h | 89 + resource/include/IServerWrapper.h | 86 + resource/include/InProcClientWrapper.h | 139 + resource/include/InProcServerWrapper.h | 86 + resource/include/InitializeException.h | 76 + resource/include/OCAndroid.h | 44 + resource/include/OCApi.h | 226 + resource/include/OCException.h | 56 + resource/include/OCHeaderOption.h | 88 + resource/include/OCPlatform.h | 443 + resource/include/OCPlatform_impl.h | 496 + resource/include/OCRepresentation.h | 229 + resource/include/OCResource.h | 322 + resource/include/OCResourceRequest.h | 232 + resource/include/OCResourceResponse.h | 268 + resource/include/OCSecurityModel.h | 56 + resource/include/OCSerialization.h | 280 + resource/include/OCUtilities.h | 101 + resource/include/OicJsonSerializer.hpp | 847 + resource/include/OutOfProcClientWrapper.h | 86 + resource/include/OutOfProcServerWrapper.h | 116 + resource/include/ResourceInitException.h | 127 + resource/include/StringConstants.h | 136 + resource/include/WrapperFactory.h | 89 + resource/makefile | 129 + resource/oc_logger/Makefile | 56 + resource/oc_logger/SConscript | 35 + resource/oc_logger/c/Makefile | 52 + resource/oc_logger/c/oc_console_logger.c | 100 + resource/oc_logger/c/oc_logger.c | 159 + resource/oc_logger/cpp/Makefile | 47 + resource/oc_logger/cpp/oc_ostream_logger.cpp | 199 + resource/oc_logger/examples/Makefile | 56 + resource/oc_logger/examples/SConscript | 34 + resource/oc_logger/examples/test_logging.c | 82 + resource/oc_logger/examples/test_logging.cpp | 97 + .../oc_logger/include/oc_console_logger.h | 43 + resource/oc_logger/include/oc_log.hpp | 27 + resource/oc_logger/include/oc_log_stream.hpp | 80 + resource/oc_logger/include/oc_logger.h | 54 + resource/oc_logger/include/oc_logger.hpp | 31 + resource/oc_logger/include/oc_logger_types.h | 84 + .../include/targets/oc_console_logger.h | 43 + .../include/targets/oc_ostream_logger.h | 49 + resource/oc_logger/samples/linux/README | 44 + resource/oc_logger/samples/linux/makefile | 94 + .../oc_logger/samples/linux/test_logging.c | 80 + resource/oc_logger/test/test_logging.cpp | 54 + .../arm-linux-androideabi/user-config.jam | 137 + resource/patches/boost/x86/user-config.jam | 137 + resource/patches/cereal_gcc46.patch | 485 + resource/releaseNotes/Aug5th2014.txt | 98 + resource/releaseNotes/Dec20th2014.txt | 130 + resource/releaseNotes/Dec6th2014.txt | 238 + resource/releaseNotes/Nov15th2014.txt | 119 + resource/releaseNotes/Oct14th2014.txt | 159 + resource/releaseNotes/Oct31st2014.txt | 110 + resource/releaseNotes/Sept17th2014.txt | 146 + resource/releaseNotes/Sept2nd2014.txt | 116 + resource/releaseNotes/Sept30th2014.txt | 162 + resource/src/InProcClientWrapper.cpp | 744 + resource/src/InProcServerWrapper.cpp | 606 + resource/src/OCApi.cpp | 21 + resource/src/OCException.cpp | 92 + resource/src/OCPlatform.cpp | 219 + resource/src/OCPlatform_impl.cpp | 321 + resource/src/OCRepresentation.cpp | 651 + resource/src/OCResource.cpp | 273 + resource/src/OCSecurityModel.cpp | 32 + resource/src/OCUtilities.cpp | 216 + resource/src/SConscript | 53 + resource/third_party_libs.scons | 60 + resource/unittests/README | 27 + resource/unittests/makefile | 82 + resource/unittests/tests.cpp | 101 + scons_script_how_to.txt | 240 + service/SConscript | 24 + ...trol Manager-Programmer's guide_v0.9.0.pdf | Bin 0 -> 729724 bytes .../docs/PPM - Programmer's Guide_v0.9.0.pdf | Bin 0 -> 399274 bytes .../docs/SSM - Programmer's guide_v0.9.0.pdf | Bin 0 -> 822752 bytes ...gs Manager - Programmer's guide_v0.9.0.pdf | Bin 0 -> 1501485 bytes service/notification-manager/.gitignore | 4 + .../build/linux/.gitignore | 11 + .../NotificationManager/build/linux/Makefile | 31 + .../include/HostingConfig.h | 47 + .../include/HostingHandler.h | 54 + .../include/HostingInterface.h | 34 + .../include/NotificationManager.h | 83 + .../include/OICPlatformConfig.h | 39 + .../include/RegistrationManager.h | 56 + .../include/ResourceManager.h | 76 + .../include/VirtualRepresentation.h | 82 + .../src/HostingHandler.cpp | 203 + .../src/HostingInterface.cpp | 133 + .../src/NotificationManager.cpp | 162 + .../src/OICPlatformConfig.cpp | 67 + .../src/RegistrationManager.cpp | 109 + .../src/ResourceManager.cpp | 232 + .../src/VirtualRepresentation.cpp | 247 + .../NotificationManager/src/linux/main.cpp | 66 + service/notification-manager/SConscript | 47 + .../notification-manager/SampleApp/SConscript | 10 + .../SampleApp/arduino/SConscript | 33 + .../SampleApp/arduino/Time/DateStrings.cpp | 90 + .../SampleApp/arduino/Time/Readme.txt | 131 + .../SampleApp/arduino/Time/Time.cpp | 318 + .../SampleApp/arduino/Time/Time.h | 144 + .../SyncArduinoClock/SyncArduinoClock.pde | 78 + .../Processing/SyncArduinoClock/readme.txt | 9 + .../TimeArduinoDue/TimeArduinoDue.ino | 69 + .../arduino/Time/examples/TimeGPS/TimeGPS.ino | 87 + .../arduino/Time/examples/TimeNTP/TimeNTP.ino | 135 + .../arduino/Time/examples/TimeRTC/TimeRTC.pde | 55 + .../Time/examples/TimeRTCLog/TimeRTCLog.pde | 107 + .../Time/examples/TimeRTCSet/TimeRTCSet.ino | 80 + .../Time/examples/TimeSerial/TimeSerial.ino | 81 + .../TimeSerialDateStrings.ino | 110 + .../Time/examples/TimeTeensy3/TimeTeensy3.ino | 78 + .../SampleApp/arduino/Time/keywords.txt | 33 + .../SampleApp/arduino/local.properties | 7 + .../SampleApp/arduino/makefile | 94 + .../SampleApp/arduino/readme.txt | 19 + .../SampleApp/arduino/thserver.cpp | 310 + .../SampleApp/linux/SConscript | 22 + .../linux/sampleConsumer/SampleConsumer.cpp | 339 + .../linux/sampleProvider/SampleProvider.cpp | 370 + .../sampleConsumer/src/oicapp-client.cpp | 340 + .../tizen/sampleConsumer/src/oicapp-log.h | 82 + .../src/oicapp-sampleConsumer.c | 409 + .../src/oicapp-sampleConsumer.h | 102 + .../tizen/sampleConsumer/src/oicapp-utils.c | 87 + .../tizen/sampleConsumer/src/oicapp-utils.h | 44 + .../build/linux/makefile/Makefile | 17 + .../build/linux/release/.gitignore | 4 + .../build/tizen/CMakeLists.txt | 30 + service/protocol-plugin/.gitignore | 4 + service/protocol-plugin/SConscript | 13 + service/protocol-plugin/build/linux/Makefile | 33 + .../build/tizen/CMakeLists.txt | 41 + service/protocol-plugin/config.mk | 1 + .../protocol-plugin/lib/cpluff/COPYRIGHT.txt | 65 + .../protocol-plugin/lib/cpluff/ChangeLog.txt | 62 + .../protocol-plugin/lib/cpluff/INSTALL.txt | 95 + service/protocol-plugin/lib/cpluff/Issues.txt | 43 + .../protocol-plugin/lib/cpluff/Makefile.am | 43 + .../protocol-plugin/lib/cpluff/Roadmap.txt | 12 + service/protocol-plugin/lib/cpluff/SConscript | 37 + .../lib/cpluff/auxliary/config.guess | 1500 + .../lib/cpluff/auxliary/config.rpath | 614 + .../lib/cpluff/auxliary/config.sub | 1608 + .../lib/cpluff/auxliary/depcomp | 584 + .../lib/cpluff/auxliary/install-sh | 507 + .../lib/cpluff/auxliary/ltmain.sh | 9661 + .../lib/cpluff/auxliary/missing | 367 + .../protocol-plugin/lib/cpluff/configure.ac | 313 + .../lib/cpluff/console/Makefile.am | 16 + .../lib/cpluff/console/cmdinput_basic.c | 61 + .../lib/cpluff/console/cmdinput_readline.c | 201 + .../lib/cpluff/console/console.c | 938 + .../lib/cpluff/console/console.h | 176 + .../protocol-plugin/lib/cpluff/doc/Makefile | 695 + .../lib/cpluff/doc/Makefile.am | 66 + .../lib/cpluff/doc/Makefile.in | 695 + .../lib/cpluff/doc/common_style.css | 33 + .../lib/cpluff/doc/copyright.en.html | 118 + .../lib/cpluff/doc/cpluff_style.css | 45 + .../lib/cpluff/doc/img/Makefile | 439 + .../lib/cpluff/doc/img/Makefile.am | 10 + .../lib/cpluff/doc/img/Makefile.in | 439 + .../lib/cpluff/doc/img/architecture.png | Bin 0 -> 23103 bytes .../lib/cpluff/doc/img/architecture.svg | 253 + .../lib/cpluff/doc/img/pageborder.png | Bin 0 -> 180 bytes .../lib/cpluff/doc/index.en.html | 91 + .../cpluff/doc/reference/c-api/annotated.html | 38 + .../doc/reference/c-api/architecture.html | 34 + .../doc/reference/c-api/architecture.png | Bin 0 -> 23103 bytes .../doc/reference/c-api/cMainProgram.html | 198 + .../doc/reference/c-api/cpluff_8h-source.html | 371 + .../cpluff/doc/reference/c-api/cpluff_8h.html | 279 + .../doc/reference/c-api/cpluff_8h__incl.map | 2 + .../doc/reference/c-api/cpluff_8h__incl.md5 | 1 + .../doc/reference/c-api/cpluff_8h__incl.png | Bin 0 -> 1410 bytes .../reference/c-api/cpluffdef_8h-source.html | 104 + .../doc/reference/c-api/cpluffdef_8h.html | 71 + .../c-api/cpluffdef_8h__dep__incl.map | 2 + .../c-api/cpluffdef_8h__dep__incl.md5 | 1 + .../c-api/cpluffdef_8h__dep__incl.png | Bin 0 -> 1509 bytes .../cpluff/doc/reference/c-api/doxygen.css | 360 + .../cpluff/doc/reference/c-api/doxygen.png | Bin 0 -> 1281 bytes .../lib/cpluff/doc/reference/c-api/files.html | 34 + .../cpluff/doc/reference/c-api/functions.html | 155 + .../doc/reference/c-api/functions_vars.html | 155 + .../cpluff/doc/reference/c-api/globals.html | 193 + .../doc/reference/c-api/globals_eval.html | 78 + .../doc/reference/c-api/globals_func.html | 129 + .../doc/reference/c-api/globals_type.html | 70 + .../doc/reference/c-api/graph_legend.dot | 23 + .../doc/reference/c-api/graph_legend.html | 87 + .../doc/reference/c-api/graph_legend.png | Bin 0 -> 8326 bytes .../doc/reference/c-api/group__cDefines.html | 76 + .../c-api/group__cDefinesGCCAttributes.html | 83 + .../doc/reference/c-api/group__cEnums.html | 180 + .../doc/reference/c-api/group__cFuncs.html | 74 + .../reference/c-api/group__cFuncsContext.html | 215 + .../c-api/group__cFuncsFrameworkInfo.html | 91 + .../reference/c-api/group__cFuncsInit.html | 123 + .../reference/c-api/group__cFuncsLogging.html | 222 + .../reference/c-api/group__cFuncsPlugin.html | 360 + .../c-api/group__cFuncsPluginExec.html | 228 + .../c-api/group__cFuncsPluginInfo.html | 498 + .../reference/c-api/group__cFuncsSymbols.html | 186 + .../reference/c-api/group__cScanFlags.html | 118 + .../doc/reference/c-api/group__cStructs.html | 52 + .../doc/reference/c-api/group__cTypedefs.html | 49 + .../c-api/group__cTypedefsFuncs.html | 149 + .../c-api/group__cTypedefsOpaque.html | 58 + .../c-api/group__cTypedefsShorthand.html | 218 + .../c-api/group__symbolVisibility.html | 104 + .../reference/c-api/group__versionInfo.html | 98 + .../lib/cpluff/doc/reference/c-api/index.html | 37 + .../doc/reference/c-api/inline_dotgraph_1.png | Bin 0 -> 1662 bytes .../cpluff/doc/reference/c-api/modules.html | 53 + .../lib/cpluff/doc/reference/c-api/pages.html | 33 + .../cpluff/doc/reference/c-api/plugin.html | 115 + .../c-api/structcp__cfg__element__t.html | 206 + ...structcp__cfg__element__t__coll__graph.map | 1 + ...structcp__cfg__element__t__coll__graph.md5 | 1 + ...structcp__cfg__element__t__coll__graph.png | Bin 0 -> 2129 bytes .../c-api/structcp__ext__point__t.html | 138 + .../structcp__ext__point__t__coll__graph.map | 5 + .../structcp__ext__point__t__coll__graph.md5 | 1 + .../structcp__ext__point__t__coll__graph.png | Bin 0 -> 8833 bytes .../c-api/structcp__extension__t.html | 172 + .../structcp__extension__t__coll__graph.map | 5 + .../structcp__extension__t__coll__graph.md5 | 1 + .../structcp__extension__t__coll__graph.png | Bin 0 -> 9671 bytes .../c-api/structcp__plugin__import__t.html | 105 + .../c-api/structcp__plugin__info__t.html | 372 + ...structcp__plugin__info__t__coll__graph.map | 5 + ...structcp__plugin__info__t__coll__graph.md5 | 1 + ...structcp__plugin__info__t__coll__graph.png | Bin 0 -> 8218 bytes .../c-api/structcp__plugin__runtime__t.html | 172 + .../lib/cpluff/doc/reference/c-api/tab_b.gif | Bin 0 -> 35 bytes .../lib/cpluff/doc/reference/c-api/tab_l.gif | Bin 0 -> 706 bytes .../lib/cpluff/doc/reference/c-api/tab_r.gif | Bin 0 -> 2585 bytes .../lib/cpluff/doc/reference/c-api/tabs.css | 102 + .../lib/cpluff/docsrc/Makefile | 385 + .../lib/cpluff/docsrc/Makefile.am | 7 + .../lib/cpluff/docsrc/Makefile.in | 385 + .../lib/cpluff/docsrc/doxygen.css | 360 + .../lib/cpluff/docsrc/doxygen.footer | 10 + .../lib/cpluff/examples/COPYRIGHT.txt | 11 + .../lib/cpluff/examples/INSTALL.txt | 149 + .../lib/cpluff/examples/Makefile | 588 + .../lib/cpluff/examples/Makefile.am | 9 + .../lib/cpluff/examples/Makefile.in | 588 + .../lib/cpluff/examples/Makefile.nmake | 9 + .../lib/cpluff/examples/autogen.sh | 22 + .../lib/cpluff/examples/common.nmake | 49 + .../lib/cpluff/examples/configure.ac | 60 + .../lib/cpluff/examples/cpfile/Makefile | 658 + .../lib/cpluff/examples/cpfile/Makefile.am | 10 + .../lib/cpluff/examples/cpfile/Makefile.in | 658 + .../lib/cpluff/examples/cpfile/Makefile.nmake | 13 + .../lib/cpluff/examples/cpfile/README.txt | 138 + .../lib/cpluff/examples/cpfile/cpfile | 9 + .../lib/cpluff/examples/cpfile/cpfile.bat | 5 + .../lib/cpluff/examples/cpfile/cpfile.in | 9 + .../cpluff/examples/cpfile/plugins/Makefile | 588 + .../examples/cpfile/plugins/Makefile.am | 9 + .../examples/cpfile/plugins/Makefile.in | 588 + .../examples/cpfile/plugins/Makefile.nmake | 9 + .../examples/cpfile/plugins/cext/Makefile | 440 + .../examples/cpfile/plugins/cext/Makefile.am | 11 + .../examples/cpfile/plugins/cext/Makefile.in | 440 + .../cpfile/plugins/cext/Makefile.nmake | 15 + .../examples/cpfile/plugins/cext/plugin.xml | 34 + .../cpfile/plugins/core/.deps/core.Plo | 1 + .../examples/cpfile/plugins/core/Makefile | 609 + .../examples/cpfile/plugins/core/Makefile.am | 19 + .../examples/cpfile/plugins/core/Makefile.in | 609 + .../cpfile/plugins/core/Makefile.nmake | 25 + .../cpfile/plugins/core/classifiers.xsd | 30 + .../examples/cpfile/plugins/core/core.c | 270 + .../examples/cpfile/plugins/core/core.h | 37 + .../examples/cpfile/plugins/core/plugin.xml | 21 + .../plugins/extension/.deps/extension.Plo | 1 + .../cpfile/plugins/extension/Makefile | 583 + .../cpfile/plugins/extension/Makefile.am | 20 + .../cpfile/plugins/extension/Makefile.in | 583 + .../cpfile/plugins/extension/Makefile.nmake | 27 + .../cpfile/plugins/extension/extension.c | 138 + .../cpfile/plugins/extension/file_types.xsd | 37 + .../cpfile/plugins/extension/plugin.xml | 34 + .../cpfile/plugins/special/.deps/special.Plo | 1 + .../examples/cpfile/plugins/special/Makefile | 583 + .../cpfile/plugins/special/Makefile.am | 20 + .../cpfile/plugins/special/Makefile.in | 583 + .../cpfile/plugins/special/Makefile.nmake | 27 + .../cpfile/plugins/special/plugin.xml | 22 + .../examples/cpfile/plugins/special/special.c | 79 + .../lib/cpluff/examples/nmakedir.bat | 11 + .../protocol-plugin/lib/cpluff/kazlib/hash.c | 1041 + .../protocol-plugin/lib/cpluff/kazlib/hash.h | 251 + .../protocol-plugin/lib/cpluff/kazlib/list.c | 935 + .../protocol-plugin/lib/cpluff/kazlib/list.h | 165 + .../lib/cpluff/libcpluff/.deps/context.Plo | 167 + .../lib/cpluff/libcpluff/.deps/cpluff.Plo | 166 + .../lib/cpluff/libcpluff/.deps/hash.Plo | 114 + .../lib/cpluff/libcpluff/.deps/list.Plo | 100 + .../lib/cpluff/libcpluff/.deps/logging.Plo | 167 + .../lib/cpluff/libcpluff/.deps/pcontrol.Plo | 167 + .../lib/cpluff/libcpluff/.deps/pinfo.Plo | 143 + .../lib/cpluff/libcpluff/.deps/ploader.Plo | 186 + .../lib/cpluff/libcpluff/.deps/pscan.Plo | 201 + .../lib/cpluff/libcpluff/.deps/psymbol.Plo | 143 + .../lib/cpluff/libcpluff/.deps/serial.Plo | 141 + .../cpluff/libcpluff/.deps/thread_posix.Plo | 178 + .../cpluff/libcpluff/.deps/thread_windows.Plo | 1 + .../lib/cpluff/libcpluff/.deps/util.Plo | 157 + .../lib/cpluff/libcpluff/Makefile | 820 + .../lib/cpluff/libcpluff/Makefile.am | 63 + .../lib/cpluff/libcpluff/Makefile.in | 820 + .../lib/cpluff/libcpluff/context.c | 526 + .../lib/cpluff/libcpluff/cpluff.c | 182 + .../lib/cpluff/libcpluff/cpluff.h | 1530 + .../lib/cpluff/libcpluff/cpluffdef.h | 200 + .../lib/cpluff/libcpluff/cpluffdef.h.in | 200 + .../lib/cpluff/libcpluff/defines.h | 69 + .../lib/cpluff/libcpluff/docsrc/Doxyfile-impl | 1256 + .../cpluff/libcpluff/docsrc/Doxyfile-impl.in | 1256 + .../lib/cpluff/libcpluff/docsrc/Doxyfile-ref | 1256 + .../cpluff/libcpluff/docsrc/Doxyfile-ref.in | 1256 + .../lib/cpluff/libcpluff/docsrc/Makefile | 390 + .../lib/cpluff/libcpluff/docsrc/Makefile.am | 7 + .../lib/cpluff/libcpluff/docsrc/Makefile.in | 390 + .../cpluff/libcpluff/docsrc/architecture.dox | 66 + .../lib/cpluff/libcpluff/docsrc/mainpage.dox | 57 + .../lib/cpluff/libcpluff/docsrc/mainprog.dox | 338 + .../lib/cpluff/libcpluff/docsrc/plugin.dox | 286 + .../lib/cpluff/libcpluff/internal.h | 579 + .../lib/cpluff/libcpluff/internal.h.gch | Bin 0 -> 2176080 bytes .../lib/cpluff/libcpluff/logging.c | 258 + .../lib/cpluff/libcpluff/pcontrol.c | 1240 + .../lib/cpluff/libcpluff/pinfo.c | 722 + .../lib/cpluff/libcpluff/ploader.c | 1192 + .../lib/cpluff/libcpluff/pscan.c | 308 + .../lib/cpluff/libcpluff/psymbol.c | 336 + .../lib/cpluff/libcpluff/serial.c | 201 + .../lib/cpluff/libcpluff/thread.h | 120 + .../lib/cpluff/libcpluff/thread_posix.c | 228 + .../lib/cpluff/libcpluff/thread_windows.c | 268 + .../lib/cpluff/libcpluff/util.c | 211 + .../lib/cpluff/libcpluff/util.h | 131 + .../lib/cpluff/loader/.deps/loader.Po | 141 + .../lib/cpluff/loader/Makefile | 539 + .../lib/cpluff/loader/Makefile.am | 11 + .../lib/cpluff/loader/Makefile.in | 539 + .../lib/cpluff/loader/loader.c | 416 + .../protocol-plugin/lib/cpluff/m4/gettext.m4 | 419 + .../protocol-plugin/lib/cpluff/m4/iconv.m4 | 101 + .../protocol-plugin/lib/cpluff/m4/lib-ld.m4 | 110 + .../protocol-plugin/lib/cpluff/m4/lib-link.m4 | 644 + .../lib/cpluff/m4/lib-prefix.m4 | 185 + service/protocol-plugin/lib/cpluff/m4/nls.m4 | 31 + service/protocol-plugin/lib/cpluff/m4/po.m4 | 428 + .../protocol-plugin/lib/cpluff/m4/progtest.m4 | 92 + service/protocol-plugin/lib/cpluff/plugin.xsd | 95 + service/protocol-plugin/lib/cpluff/po/LINGUAS | 4 + .../protocol-plugin/lib/cpluff/po/Makefile | 507 + .../protocol-plugin/lib/cpluff/po/Makefile.in | 403 + .../lib/cpluff/po/Makefile.in.in | 403 + .../protocol-plugin/lib/cpluff/po/Makevars | 41 + .../protocol-plugin/lib/cpluff/po/POTFILES | 16 + .../protocol-plugin/lib/cpluff/po/POTFILES.in | 19 + .../protocol-plugin/lib/cpluff/po/Rules-quot | 47 + .../lib/cpluff/po/boldquot.sed | 10 + .../protocol-plugin/lib/cpluff/po/cpluff.pot | 1119 + .../lib/cpluff/po/en@boldquot.gmo | Bin 0 -> 24758 bytes .../lib/cpluff/po/en@boldquot.header | 25 + .../protocol-plugin/lib/cpluff/po/en@quot.gmo | Bin 0 -> 24750 bytes .../lib/cpluff/po/en@quot.header | 22 + service/protocol-plugin/lib/cpluff/po/fi.gmo | Bin 0 -> 26526 bytes .../lib/cpluff/po/insert-header.sin | 23 + .../protocol-plugin/lib/cpluff/po/quot.sed | 6 + .../lib/cpluff/po/remove-potcdate.sin | 19 + .../protocol-plugin/lib/cpluff/po/stamp-po | 1 + .../lib/cpluff/test/.deps/collections.Po | 1 + .../lib/cpluff/test/.deps/cpinfo.Po | 1 + .../lib/cpluff/test/.deps/extcfg.Po | 1 + .../lib/cpluff/test/.deps/fatalerror.Po | 1 + .../lib/cpluff/test/.deps/initdestroy.Po | 1 + .../lib/cpluff/test/.deps/loggers.Po | 1 + .../lib/cpluff/test/.deps/pcallbacks.Po | 1 + .../lib/cpluff/test/.deps/pdependencies.Po | 1 + .../lib/cpluff/test/.deps/pinstallation.Po | 1 + .../lib/cpluff/test/.deps/ploading.Po | 1 + .../lib/cpluff/test/.deps/pscanning.Po | 1 + .../lib/cpluff/test/.deps/psymbolusage.Po | 1 + .../lib/cpluff/test/.deps/testmain.Po | 1 + .../protocol-plugin/lib/cpluff/test/Makefile | 770 + .../lib/cpluff/test/Makefile.am | 111 + .../lib/cpluff/test/Makefile.in | 770 + .../lib/cpluff/test/collections.c | 99 + .../protocol-plugin/lib/cpluff/test/cpinfo.c | 37 + .../test/expected/output-extensions.txt | 7 + .../cpluff/test/expected/output-extpoints.txt | 7 + .../test/expected/output-loadmaximal.txt | 93 + .../test/expected/output-loadminimal.txt | 14 + .../protocol-plugin/lib/cpluff/test/extcfg.c | 67 + .../lib/cpluff/test/fatalerror.c | 59 + .../lib/cpluff/test/initdestroy.c | 125 + .../protocol-plugin/lib/cpluff/test/loggers.c | 247 + .../lib/cpluff/test/pcallbacks.c | 119 + .../collection1/plugin1/plugin.xml | 2 + .../collection1v2/plugin1/plugin.xml | 2 + .../collection1v3/plugin1/plugin.xml | 2 + .../collection2/plugin2a/plugin.xml | 2 + .../collection2/plugin2b/plugin.xml | 2 + .../dependencies/chain1/plugin.xml | 6 + .../dependencies/chain2/plugin.xml | 6 + .../dependencies/chain3/plugin.xml | 2 + .../dependencies/chainmissingdep/plugin.xml | 6 + .../dependencies/loop1/plugin.xml | 6 + .../dependencies/loop2/plugin.xml | 7 + .../dependencies/loop3/plugin.xml | 6 + .../dependencies/loop4/plugin.xml | 2 + .../dependencies/loop5/plugin.xml | 6 + .../dependencies/missingdep/plugin.xml | 6 + .../dependencies/sloop1/plugin.xml | 6 + .../dependencies/sloop2/plugin.xml | 6 + .../lib/cpluff/test/pdependencies.c | 159 + .../lib/cpluff/test/pinstallation.c | 101 + .../lib/cpluff/test/ploading.c | 38 + .../lib/cpluff/test/plugins-source/Makefile | 587 + .../cpluff/test/plugins-source/Makefile.am | 7 + .../cpluff/test/plugins-source/Makefile.in | 587 + .../callbackcounter/.deps/callbackcounter.Plo | 1 + .../plugins-source/callbackcounter/Makefile | 582 + .../callbackcounter/Makefile.am | 17 + .../callbackcounter/Makefile.in | 582 + .../callbackcounter/callbackcounter.c | 124 + .../callbackcounter/callbackcounter.h | 67 + .../plugins-source/callbackcounter/plugin.xml | 4 + .../symprovider/.deps/symprovider.Plo | 1 + .../test/plugins-source/symprovider/Makefile | 582 + .../plugins-source/symprovider/Makefile.am | 17 + .../plugins-source/symprovider/Makefile.in | 582 + .../plugins-source/symprovider/plugin.xml | 8 + .../plugins-source/symprovider/symprovider.c | 70 + .../plugins-source/symuser/.deps/symuser.Plo | 1 + .../test/plugins-source/symuser/Makefile | 582 + .../test/plugins-source/symuser/Makefile.am | 17 + .../test/plugins-source/symuser/Makefile.in | 582 + .../test/plugins-source/symuser/plugin.xml | 5 + .../test/plugins-source/symuser/symuser.c | 97 + .../cpluff/test/plugins/maximal/plugin.xml | 34 + .../cpluff/test/plugins/minimal/plugin.xml | 1 + .../lib/cpluff/test/pscanning.c | 181 + .../lib/cpluff/test/psymbolusage.c | 51 + .../lib/cpluff/test/test-extensions | 17 + .../lib/cpluff/test/test-extpoints | 17 + .../lib/cpluff/test/test-fatalerrordefault | 10 + .../lib/cpluff/test/test-fatalerrorreset | 10 + .../lib/cpluff/test/test-loadmaximal | 17 + .../lib/cpluff/test/test-loadminimal | 17 + .../protocol-plugin/lib/cpluff/test/test.h | 100 + .../lib/cpluff/test/testmain.c | 176 + .../protocol-plugin/lib/cpluff/test/tests.txt | 44 + .../protocol-plugin/lib/rapidxml/rapidxml.hpp | 2601 + .../lib/rapidxml/rapidxml_iterators.hpp | 174 + .../lib/rapidxml/rapidxml_print.hpp | 422 + .../lib/rapidxml/rapidxml_utils.hpp | 122 + .../protocol-plugin/plugin-manager/.gitignore | 2 + .../protocol-plugin/plugin-manager/SConscript | 61 + .../plugin-manager/build/linux/Makefile | 47 + .../plugin-manager/src/Config.cpp | 161 + .../plugin-manager/src/Config.h | 122 + .../plugin-manager/src/CpluffAdapter.cpp | 595 + .../plugin-manager/src/CpluffAdapter.h | 277 + .../plugin-manager/src/FelixAdapter.cpp | 136 + .../plugin-manager/src/FelixAdapter.h | 271 + .../plugin-manager/src/Plugin.cpp | 142 + .../plugin-manager/src/Plugin.h | 148 + .../plugin-manager/src/PluginManager.cpp | 73 + .../plugin-manager/src/PluginManager.h | 102 + .../plugin-manager/src/PluginManagerImpl.cpp | 360 + .../plugin-manager/src/PluginManagerImpl.h | 232 + service/protocol-plugin/plugins/SConscript | 46 + .../plugins/mqtt-fan/build/linux/Makefile | 52 + .../plugins/mqtt-fan/build/linux/plugin.xml | 7 + .../plugins/mqtt-fan/lib/CMakeLists.txt | 71 + .../plugins/mqtt-fan/lib/Makefile | 99 + .../plugins/mqtt-fan/lib/SConscript | 27 + .../plugins/mqtt-fan/lib/config.h | 19 + .../plugins/mqtt-fan/lib/config.mk | 218 + .../plugins/mqtt-fan/lib/cpp/CMakeLists.txt | 18 + .../plugins/mqtt-fan/lib/cpp/Makefile | 31 + .../plugins/mqtt-fan/lib/cpp/SConscript | 24 + .../plugins/mqtt-fan/lib/cpp/mosquittopp.cpp | 305 + .../plugins/mqtt-fan/lib/cpp/mosquittopp.h | 122 + .../plugins/mqtt-fan/lib/cpp/test.txt | 883 + .../plugins/mqtt-fan/lib/dummypthread.h | 13 + .../plugins/mqtt-fan/lib/jsws/mosquitto.js | 363 + .../plugins/mqtt-fan/lib/linker.version | 71 + .../plugins/mqtt-fan/lib/logging_mosq.c | 69 + .../plugins/mqtt-fan/lib/logging_mosq.h | 36 + .../plugins/mqtt-fan/lib/memory_mosq.c | 134 + .../plugins/mqtt-fan/lib/memory_mosq.h | 50 + .../plugins/mqtt-fan/lib/messages_mosq.c | 400 + .../plugins/mqtt-fan/lib/messages_mosq.h | 44 + .../plugins/mqtt-fan/lib/mosquitto.c | 1306 + .../plugins/mqtt-fan/lib/mosquitto.h | 1429 + .../plugins/mqtt-fan/lib/mosquitto_internal.h | 243 + .../plugins/mqtt-fan/lib/mqtt3_protocol.h | 66 + .../plugins/mqtt-fan/lib/net_mosq.c | 1129 + .../plugins/mqtt-fan/lib/net_mosq.h | 104 + .../plugins/mqtt-fan/lib/python/Makefile | 23 + .../plugins/mqtt-fan/lib/python/mosquitto.py | 2079 + .../plugins/mqtt-fan/lib/python/setup.py | 28 + .../plugins/mqtt-fan/lib/python/sub.py | 66 + .../plugins/mqtt-fan/lib/read_handle.c | 168 + .../plugins/mqtt-fan/lib/read_handle.h | 47 + .../plugins/mqtt-fan/lib/read_handle_client.c | 76 + .../plugins/mqtt-fan/lib/read_handle_shared.c | 271 + .../plugins/mqtt-fan/lib/send_client_mosq.c | 227 + .../plugins/mqtt-fan/lib/send_mosq.c | 289 + .../plugins/mqtt-fan/lib/send_mosq.h | 50 + .../plugins/mqtt-fan/lib/srv_mosq.c | 106 + .../plugins/mqtt-fan/lib/thread_mosq.c | 114 + .../plugins/mqtt-fan/lib/time_mosq.c | 95 + .../plugins/mqtt-fan/lib/time_mosq.h | 35 + .../plugins/mqtt-fan/lib/tls_mosq.c | 147 + .../plugins/mqtt-fan/lib/tls_mosq.h | 49 + .../plugins/mqtt-fan/lib/util_mosq.c | 320 + .../plugins/mqtt-fan/lib/util_mosq.h | 48 + .../plugins/mqtt-fan/lib/will_mosq.c | 130 + .../plugins/mqtt-fan/lib/will_mosq.h | 39 + .../plugins/mqtt-fan/src/fanserver.cpp | 520 + .../plugins/mqtt-fan/src/fanserver.h | 2 + .../mqtt-fan/src/fanserver_mqtt_plugin.cpp | 80 + .../mqtt-fan/src/fanserver_mqtt_plugin.h | 6 + .../plugins/mqtt-light/build/linux/Makefile | 52 + .../plugins/mqtt-light/build/linux/plugin.xml | 7 + .../plugins/mqtt-light/lib/CMakeLists.txt | 71 + .../plugins/mqtt-light/lib/Makefile | 99 + .../plugins/mqtt-light/lib/config.h | 19 + .../plugins/mqtt-light/lib/config.mk | 218 + .../plugins/mqtt-light/lib/cpp/CMakeLists.txt | 18 + .../plugins/mqtt-light/lib/cpp/Makefile | 31 + .../mqtt-light/lib/cpp/mosquittopp.cpp | 305 + .../plugins/mqtt-light/lib/cpp/mosquittopp.h | 122 + .../plugins/mqtt-light/lib/cpp/test.txt | 883 + .../plugins/mqtt-light/lib/dummypthread.h | 13 + .../plugins/mqtt-light/lib/jsws/mosquitto.js | 363 + .../plugins/mqtt-light/lib/linker.version | 71 + .../plugins/mqtt-light/lib/logging_mosq.c | 69 + .../plugins/mqtt-light/lib/logging_mosq.h | 36 + .../plugins/mqtt-light/lib/memory_mosq.c | 134 + .../plugins/mqtt-light/lib/memory_mosq.h | 50 + .../plugins/mqtt-light/lib/messages_mosq.c | 400 + .../plugins/mqtt-light/lib/messages_mosq.h | 44 + .../plugins/mqtt-light/lib/mosquitto.c | 1306 + .../plugins/mqtt-light/lib/mosquitto.h | 1429 + .../mqtt-light/lib/mosquitto_internal.h | 243 + .../plugins/mqtt-light/lib/mqtt3_protocol.h | 66 + .../plugins/mqtt-light/lib/net_mosq.c | 1129 + .../plugins/mqtt-light/lib/net_mosq.h | 104 + .../plugins/mqtt-light/lib/python/Makefile | 23 + .../mqtt-light/lib/python/mosquitto.py | 2079 + .../plugins/mqtt-light/lib/python/setup.py | 28 + .../plugins/mqtt-light/lib/python/sub.py | 66 + .../plugins/mqtt-light/lib/read_handle.c | 168 + .../plugins/mqtt-light/lib/read_handle.h | 47 + .../mqtt-light/lib/read_handle_client.c | 76 + .../mqtt-light/lib/read_handle_shared.c | 271 + .../plugins/mqtt-light/lib/send_client_mosq.c | 227 + .../plugins/mqtt-light/lib/send_mosq.c | 289 + .../plugins/mqtt-light/lib/send_mosq.h | 50 + .../plugins/mqtt-light/lib/srv_mosq.c | 106 + .../plugins/mqtt-light/lib/thread_mosq.c | 114 + .../plugins/mqtt-light/lib/time_mosq.c | 95 + .../plugins/mqtt-light/lib/time_mosq.h | 35 + .../plugins/mqtt-light/lib/tls_mosq.c | 147 + .../plugins/mqtt-light/lib/tls_mosq.h | 49 + .../plugins/mqtt-light/lib/util_mosq.c | 320 + .../plugins/mqtt-light/lib/util_mosq.h | 48 + .../plugins/mqtt-light/lib/will_mosq.c | 130 + .../plugins/mqtt-light/lib/will_mosq.h | 39 + .../plugins/mqtt-light/src/lightserver.cpp | 520 + .../plugins/mqtt-light/src/lightserver.h | 2 + .../src/lightserver_mqtt_plugin.cpp | 80 + .../mqtt-light/src/lightserver_mqtt_plugin.h | 6 + service/protocol-plugin/readme | 80 + service/protocol-plugin/sample-app/SConscript | 10 + .../sample-app/linux/SConscript | 31 + .../sample-app/linux/mqtt/Makefile | 42 + .../sample-app/linux/mqtt/mqttclient.cpp | 635 + .../sample-app/linux/mqtt/pluginmanager.xml | 12 + service/soft-sensor-manager/Readme.txt | 212 + service/soft-sensor-manager/SConscript | 125 + .../SDK/cpp/build/linux/Makefile | 54 + .../SDK/cpp/include/SSMInterface.h | 229 + .../SDK/cpp/src/InprocSSMCore.cpp | 121 + .../iotivity/service/ssm/CoreController.java | 74 + .../org/iotivity/service/ssm/DataReader.java | 28 + .../service/ssm/IQueryEngineEvent.java | 5 + .../iotivity/service/ssm/IReportReceiver.java | 5 + .../org/iotivity/service/ssm/ModelData.java | 31 + .../org/iotivity/service/ssm/QueryEngine.java | 31 + .../iotivity/service/ssm/SSMInterface.java | 99 + .../SSMCore/build/linux/Makefile | 84 + .../SSMCore/include/SSMInterface.h | 229 + .../SSMCore/src/Common/InternalInterface.h | 1315 + .../SSMCore/src/Common/ObjectManager.h | 423 + .../SSMCore/src/Common/PlatformLayer.h | 176 + .../SSMCore/src/Common/ThreadManager.cpp | 380 + .../SSMCore/src/Common/ThreadManager.h | 521 + .../SSMCore/src/Common/rapidxml.hpp | 2601 + .../SSMCore/src/Common/rapidxml_iterators.hpp | 174 + .../SSMCore/src/Common/rapidxml_print.hpp | 422 + .../SSMCore/src/Common/rapidxml_utils.hpp | 122 + .../SSMCore/src/Common/sqlite3.c | 140456 +++++++++++++++ .../SSMCore/src/Common/sqlite3.h | 7261 + .../SSMCore/src/QueryProcessor/CQLParser.cpp | 444 + .../SSMCore/src/QueryProcessor/CQLParser.h | 189 + .../src/QueryProcessor/ConditionedModel.cpp | 175 + .../src/QueryProcessor/ConditionedModel.h | 190 + .../src/QueryProcessor/ConditionedQuery.cpp | 235 + .../src/QueryProcessor/ConditionedQuery.h | 184 + .../QueryProcessor/ConditionedQueryResult.cpp | 63 + .../QueryProcessor/ConditionedQueryResult.h | 104 + .../src/QueryProcessor/ContextModel.cpp | 545 + .../SSMCore/src/QueryProcessor/ContextModel.h | 358 + .../src/QueryProcessor/ContextQuery.cpp | 326 + .../SSMCore/src/QueryProcessor/ContextQuery.h | 166 + .../SSMCore/src/QueryProcessor/DataReader.cpp | 96 + .../SSMCore/src/QueryProcessor/DataReader.h | 106 + .../src/QueryProcessor/EvaluationEngine.cpp | 1147 + .../src/QueryProcessor/EvaluationEngine.h | 287 + .../SSMCore/src/QueryProcessor/ModelData.cpp | 75 + .../SSMCore/src/QueryProcessor/ModelData.h | 139 + .../src/QueryProcessor/PropagationEngine.cpp | 567 + .../src/QueryProcessor/PropagationEngine.h | 199 + .../src/QueryProcessor/QueryEngine.cpp | 417 + .../SSMCore/src/QueryProcessor/QueryEngine.h | 149 + .../SSMCore/src/SSMInterface/SSMCore.cpp | 150 + .../SSMCore/src/SSMInterface/SSMCore.h | 225 + .../SSMCore/src/SSMInterface/SSMCore_JNI.cpp | 412 + .../SSMCore/src/SSMInterface/SSMCore_JNI.h | 87 + .../src/SSMInterface/SSMModelDefinition.h | 101 + .../src/SSMInterface/SSMResourceServer.cpp | 340 + .../src/SSMInterface/SSMResourceServer.h | 44 + .../src/SSMInterface/SoftSensorManager.cpp | 387 + .../src/SSMInterface/SoftSensorManager.h | 169 + .../src/SensorProcessor/ContextDataReader.cpp | 95 + .../src/SensorProcessor/ContextDataReader.h | 93 + .../src/SensorProcessor/ContextExecutor.cpp | 399 + .../src/SensorProcessor/ContextExecutor.h | 219 + .../src/SensorProcessor/ContextRepository.cpp | 431 + .../src/SensorProcessor/ContextRepository.h | 152 + .../src/SensorProcessor/ResourceFinder.cpp | 251 + .../src/SensorProcessor/ResourceFinder.h | 213 + .../src/SensorProcessor/SensingEngine.cpp | 110 + .../src/SensorProcessor/SensingEngine.h | 140 + .../soft-sensor-manager/SampleApp/SConscript | 24 + .../SampleApp/arduino/Makefile | 39 + .../arduino/Reference_Thing/build/makefile | 130 + .../arduino/Reference_Thing/include/bleLib.h | 87 + .../Reference_Thing/include/oic_lanLib.h | 15 + .../arduino/Reference_Thing/src/bleLib.cpp | 584 + .../Reference_Thing/src/oic_lanLib.cpp | 98 + .../arduino/Reference_Thing/src/readme.txt | 19 + .../arduino/Reference_Thing/src/reference.cpp | 308 + .../arduino/THSensorApp/build/makefile | 126 + .../arduino/THSensorApp/src/readme.txt | 19 + .../arduino/THSensorApp/src/thserver.cpp | 442 + .../arduino/Trackee_Thing/build/makefile | 130 + .../arduino/Trackee_Thing/include/bleLib.h | 87 + .../Trackee_Thing/include/oic_lanLib.h | 15 + .../arduino/Trackee_Thing/include/proximity.h | 19 + .../arduino/Trackee_Thing/include/trackee.h | 15 + .../arduino/Trackee_Thing/src/bleLib.cpp | 586 + .../arduino/Trackee_Thing/src/oic_lanLib.cpp | 98 + .../arduino/Trackee_Thing/src/proximity.cpp | 88 + .../arduino/Trackee_Thing/src/readme.txt | 19 + .../arduino/Trackee_Thing/src/trackee.cpp | 443 + .../SampleApp/arduino/environment.mk | 3 + .../SampleApp/arduino/local.properties | 7 + .../SampleApp/arduino/readme.txt | 6 + .../SampleApp/linux/Makefile | 39 + .../SampleApp/linux/SSMTesterApp/SConscript | 35 + .../linux/SSMTesterApp/build/Makefile | 58 + .../linux/SSMTesterApp/include/SSMTestApp.h | 65 + .../linux/SSMTesterApp/src/SSMTestApp.cpp | 165 + .../SampleApp/linux/THSensorApp/SConscript | 30 + .../linux/THSensorApp/build/Makefile | 55 + .../THSensorApp/include/ThingResourceServer.h | 88 + .../THSensorApp/src/ThingResourceServer.cpp | 220 + .../SampleApp/linux/THSensorApp1/SConscript | 30 + .../linux/THSensorApp1/build/Makefile | 55 + .../include/ThingResourceServer1.h | 88 + .../THSensorApp1/src/ThingResourceServer1.cpp | 220 + .../tizen/SSMTesterApp/CMakeLists.txt | 45 + .../SampleApp/tizen/SSMTesterApp/README | 75 + .../SampleApp/tizen/SSMTesterApp/RELEASE.txt | 98 + .../SampleApp/tizen/SSMTesterApp/makefile_org | 70 + .../SSMTesterApp/oic-sample/CMakeLists.txt | 51 + .../oic-sample/com.samsung.ssmtester.rule | 3 + .../oic-sample/com.samsung.ssmtester.xml | 10 + .../SSMTesterApp/oic-sample/src/oicapp-log.h | 82 + .../oic-sample/src/oicapp-test.cpp | 497 + .../SSMTesterApp/oic-sample/src/oicapp-test.h | 86 + .../oic-sample/src/oicapp-utils.c | 98 + .../oic-sample/src/oicapp-utils.h | 41 + .../tizen/SSMTesterApp/packaging/ssm.manifest | 5 + .../tizen/SSMTesterApp/packaging/ssm.spec | 53 + .../build/linux/Makefile | 50 + .../include/DiscomfortIndexSensor.h | 96 + .../DiscomfortIndexSensor/include/SysTimer.h | 37 + .../src/DiscomfortIndexSensor.cpp | 287 + .../DiscomfortIndexSensor/src/SysTimer.cpp | 56 + .../SoftSensorDescription.xml | 98 + .../build/arduino/Makefile | 57 + .../build/arduino/environment.mk | 25 + .../build/arduino/local.properties | 2 + .../build/arduino/readme.txt | 5 + .../soft-sensor-manager/build/linux/Makefile | 62 + .../build/linux/environment.mk | 38 + .../build/tizen/CMakeLists.txt | 16 + .../soft-sensor-manager/build/tizen/Makefile | 0 .../build/tizen/SampleApp/CMakeLists.txt | 5 + .../tizen/SampleApp/ClientApp/CMakeLists.txt | 21 + .../SampleApp/THSensorApp/CMakeLists.txt | 21 + .../SampleApp/THSensorApp1/CMakeLists.txt | 21 + service/things-manager/.gitignore | 38 + service/things-manager/Readme.txt | 83 + service/things-manager/SConscript | 35 + service/things-manager/build/linux/makefile | 32 + service/things-manager/sampleapp/SConscript | 24 + .../configuration/ConfigurationCollection.cpp | 591 + .../configuration/ConfigurationCollection.h | 535 + .../configuration/DiagnosticsCollection.cpp | 245 + .../configuration/DiagnosticsCollection.h | 150 + .../configuration/FactorySetCollection.cpp | 141 + .../configuration/FactorySetCollection.h | 120 + .../sampleapp/linux/configuration/SConscript | 34 + .../linux/configuration/bootstrapserver.cpp | 237 + .../linux/configuration/con-client.cpp | 449 + .../linux/configuration/con-server.cpp | 358 + .../sampleapp/linux/configuration/makefile | 71 + .../sampleapp/linux/groupaction/SConscript | 35 + .../sampleapp/linux/groupaction/bookmark.cpp | 235 + .../linux/groupaction/groupserver.cpp | 433 + .../linux/groupaction/lightserver.cpp | 337 + .../sampleapp/linux/groupaction/makefile | 70 + .../linux/groupsyncaction/SConscript | 38 + .../sampleapp/linux/groupsyncaction/group.cpp | 223 + .../sampleapp/linux/groupsyncaction/makefile | 65 + .../linux/groupsyncaction/musicplayer.cpp | 163 + .../sampleapp/linux/groupsyncaction/phone.cpp | 478 + .../linux/groupsyncaction/speaker.cpp | 165 + .../things-manager/sampleapp/linux/makefile | 21 + .../things-manager/sdk/build/linux/Makefile | 82 + .../things-manager/sdk/inc/ThingsManager.h | 408 + .../things-manager/sdk/src/GroupManager.cpp | 600 + service/things-manager/sdk/src/GroupManager.h | 151 + .../sdk/src/GroupSynchronization.cpp | 1277 + .../sdk/src/GroupSynchronization.h | 138 + .../sdk/src/ThingsConfiguration.cpp | 612 + .../sdk/src/ThingsConfiguration.h | 546 + .../sdk/src/ThingsDiagnostics.cpp | 395 + .../sdk/src/ThingsDiagnostics.h | 223 + .../things-manager/sdk/src/ThingsManager.cpp | 188 + service/third_party_libs.scons | 80 + tools/Readme.scons.txt | 191 + tools/SConstruct | 39 + tools/arduino.scons | 11 + .../arduino/patches/arduino-1.0.5_linux.patch | 95 + .../arduino/patches/arduino-1.5.7_linux.patch | 88 + tools/auto_build.sh | 103 + tools/extra_options.scons | 35 + tools/scons_script_how_to.txt | 240 + tools/tizen/iotivity.spec | 73 + 1282 files changed, 412082 insertions(+) create mode 100644 .gitignore create mode 100644 Readme.scons.txt create mode 100644 SConstruct create mode 100644 android/Base/app/build.gradle create mode 100644 android/Base/app/jni/Android.mk create mode 100644 android/Base/app/jni/Application.mk create mode 100644 android/Base/app/jni/ocheaderoption-jni.cpp create mode 100644 android/Base/app/jni/ocplatform-jni.cpp create mode 100644 android/Base/app/jni/ocrepresentation-jni.cpp create mode 100644 android/Base/app/jni/ocresource-jni.cpp create mode 100644 android/Base/app/jni/ocstack-jni.cpp create mode 100644 android/Base/app/jni/ocstack-jni.h create mode 100644 android/Base/app/jni/platformcfg-jni.cpp create mode 100644 android/Base/app/proguard-rules.pro create mode 100644 android/Base/app/src/androidTest/java/org/iotivity/base/ApplicationTest.java create mode 100644 android/Base/app/src/main/AndroidManifest.xml create mode 100644 android/Base/app/src/main/java/org/iotivity/base/AbstractDeleteCallback.java create mode 100644 android/Base/app/src/main/java/org/iotivity/base/AbstractFindCallback.java create mode 100644 android/Base/app/src/main/java/org/iotivity/base/AbstractGetCallback.java create mode 100644 android/Base/app/src/main/java/org/iotivity/base/AbstractObserveCallback.java create mode 100644 android/Base/app/src/main/java/org/iotivity/base/AbstractPostCallback.java create mode 100644 android/Base/app/src/main/java/org/iotivity/base/AbstractPutCallback.java create mode 100644 android/Base/app/src/main/java/org/iotivity/base/AbstractSubscriberCallback.java create mode 100644 android/Base/app/src/main/java/org/iotivity/base/EntityHandler.java create mode 100644 android/Base/app/src/main/java/org/iotivity/base/NativeInstance.java create mode 100644 android/Base/app/src/main/java/org/iotivity/base/OCHeaderOption.java create mode 100644 android/Base/app/src/main/java/org/iotivity/base/OCPlatform.java create mode 100644 android/Base/app/src/main/java/org/iotivity/base/OCRepresentation.java create mode 100644 android/Base/app/src/main/java/org/iotivity/base/OCResource.java create mode 100644 android/Base/app/src/main/java/org/iotivity/base/OCResourceRequest.java create mode 100644 android/Base/app/src/main/java/org/iotivity/base/OCResourceResponse.java create mode 100644 android/Base/app/src/main/java/org/iotivity/base/OCStackResult.java create mode 100644 android/Base/app/src/main/java/org/iotivity/base/ObserveType.java create mode 100755 android/Base/app/src/main/java/org/iotivity/base/PlatformConfig.java create mode 100644 android/Base/app/src/main/res/drawable-hdpi/ic_launcher.png create mode 100644 android/Base/app/src/main/res/drawable-mdpi/ic_launcher.png create mode 100644 android/Base/app/src/main/res/drawable-xhdpi/ic_launcher.png create mode 100644 android/Base/app/src/main/res/drawable-xxhdpi/ic_launcher.png create mode 100644 android/Base/app/src/main/res/values/strings.xml create mode 100644 android/Base/app/src/main/res/values/styles.xml create mode 100644 android/Base/build.gradle create mode 100644 android/Base/gradle.properties create mode 100755 android/Base/gradlew create mode 100644 android/Base/gradlew.bat create mode 100644 android/Base/settings.gradle create mode 100644 android/SimpleClient/app/build.gradle create mode 100644 android/SimpleClient/app/proguard-rules.pro create mode 100644 android/SimpleClient/app/src/androidTest/java/org/iotivity/simpleclient/ApplicationTest.java create mode 100644 android/SimpleClient/app/src/main/AndroidManifest.xml create mode 100644 android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/FoundResource.java create mode 100644 android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/OnGet.java create mode 100644 android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/OnObserve.java create mode 100644 android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/OnPost.java create mode 100644 android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/OnPost2.java create mode 100644 android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/OnPut.java create mode 100644 android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/SimpleClient.java create mode 100644 android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/SimpleToast.java create mode 100644 android/SimpleClient/app/src/main/res/drawable-hdpi/ic_launcher.png create mode 100644 android/SimpleClient/app/src/main/res/drawable-mdpi/ic_launcher.png create mode 100644 android/SimpleClient/app/src/main/res/drawable-xhdpi/ic_launcher.png create mode 100644 android/SimpleClient/app/src/main/res/drawable-xxhdpi/ic_launcher.png create mode 100644 android/SimpleClient/app/src/main/res/layout/activity_simple_client.xml create mode 100644 android/SimpleClient/app/src/main/res/menu/simple_client.xml create mode 100644 android/SimpleClient/app/src/main/res/values-w820dp/dimens.xml create mode 100644 android/SimpleClient/app/src/main/res/values/dimens.xml create mode 100644 android/SimpleClient/app/src/main/res/values/strings.xml create mode 100644 android/SimpleClient/app/src/main/res/values/styles.xml create mode 100644 android/SimpleClient/build.gradle create mode 100644 android/SimpleClient/gradle.properties create mode 100755 android/SimpleClient/gradlew create mode 100644 android/SimpleClient/gradlew.bat create mode 100644 android/SimpleClient/settings.gradle create mode 100644 arduino.scons create mode 100755 auto_build.sh create mode 100644 build_common/SConscript create mode 100644 build_common/android/SConscript create mode 100644 build_common/android/compatibility/android_cpp11_compat.cpp create mode 100644 build_common/android/compatibility/android_cpp11_compat.h create mode 100644 build_common/android/compatibility/c_compat.c create mode 100644 build_common/android/compatibility/c_compat.scons create mode 100644 build_common/android/compatibility/cpp11_compat.scons create mode 100644 build_common/android/jni/Android.mk create mode 100644 build_common/arduino/SConscript create mode 100644 build_common/darwin/SConscript create mode 100644 build_common/ios/SConscript create mode 100644 build_common/linux/SConscript create mode 100644 build_common/windows/SConscript create mode 100644 examples/OICMiddle/Client.cpp create mode 100644 examples/OICMiddle/Client.h create mode 100644 examples/OICMiddle/LineInput.cpp create mode 100644 examples/OICMiddle/LineInput.h create mode 100644 examples/OICMiddle/OICMiddle.cpp create mode 100644 examples/OICMiddle/OICMiddle.h create mode 100644 examples/OICMiddle/README create mode 100644 examples/OICMiddle/RestInput.cpp create mode 100644 examples/OICMiddle/RestInput.h create mode 100644 examples/OICMiddle/SConstruct create mode 100644 examples/OICMiddle/Server.cpp create mode 100644 examples/OICMiddle/Server.h create mode 100644 examples/OICMiddle/WrapResource.cpp create mode 100644 examples/OICMiddle/WrapResource.h create mode 100644 examples/OICMiddle/makefile create mode 100644 examples/OICSensorBoard/OICSensorBoardREADME.pdf create mode 100644 examples/OICSensorBoard/SConstruct create mode 100644 examples/OICSensorBoard/client.cpp create mode 100644 examples/OICSensorBoard/client.h create mode 100644 examples/OICSensorBoard/namedefs.h create mode 100644 examples/OICSensorBoard/observer.cpp create mode 100644 examples/OICSensorBoard/observer.h create mode 100644 examples/OICSensorBoard/sensors.h create mode 100644 examples/OICSensorBoard/server.cpp create mode 100644 examples/OICSensorBoard/server.h create mode 100755 extlibs/buildDependencies.sh create mode 100644 extlibs/cjson/cJSON.c create mode 100644 extlibs/cjson/cJSON.h create mode 100644 extra_options.scons create mode 100644 resource/README.setup.txt create mode 100644 resource/SConscript create mode 100644 resource/android/OCAndroid.cpp create mode 100644 resource/android/SConscript create mode 100644 resource/artifact_output_locations.txt create mode 100644 resource/buildScript.mk create mode 100644 resource/csdk/README create mode 100644 resource/csdk/SConscript create mode 100644 resource/csdk/arduinodue.properties create mode 100644 resource/csdk/arduinomega.properties create mode 100644 resource/csdk/connectivity/RELEASE v0.1 create mode 100644 resource/csdk/connectivity/api/cacommon.h create mode 100644 resource/csdk/connectivity/api/cainterface.h create mode 100644 resource/csdk/connectivity/build/linux/Makefile create mode 100644 resource/csdk/connectivity/build/linux/common.mk create mode 100644 resource/csdk/connectivity/common/inc/logger.h create mode 100644 resource/csdk/connectivity/common/inc/oic_console_logger.h create mode 100644 resource/csdk/connectivity/common/inc/oic_logger.h create mode 100644 resource/csdk/connectivity/common/inc/oic_logger_types.h create mode 100644 resource/csdk/connectivity/common/inc/oic_malloc.h create mode 100644 resource/csdk/connectivity/common/inc/uarraylist.h create mode 100644 resource/csdk/connectivity/common/inc/umutex.h create mode 100644 resource/csdk/connectivity/common/inc/uqueue.h create mode 100644 resource/csdk/connectivity/common/inc/uthreadpool.h create mode 100644 resource/csdk/connectivity/common/src/logger.c create mode 100644 resource/csdk/connectivity/common/src/oic_console_logger.c create mode 100644 resource/csdk/connectivity/common/src/oic_logger.c create mode 100644 resource/csdk/connectivity/common/src/oic_malloc.c create mode 100644 resource/csdk/connectivity/common/src/uarraylist.c create mode 100644 resource/csdk/connectivity/common/src/umutex.c create mode 100644 resource/csdk/connectivity/common/src/uqueue.c create mode 100644 resource/csdk/connectivity/common/src/uthreadpool.c create mode 100644 resource/csdk/connectivity/inc/caadapterinterface.h create mode 100644 resource/csdk/connectivity/inc/caedradapter.h create mode 100644 resource/csdk/connectivity/inc/caerrorcode.h create mode 100644 resource/csdk/connectivity/inc/caethernetadapter.h create mode 100644 resource/csdk/connectivity/inc/cainterfacecontroller.h create mode 100644 resource/csdk/connectivity/inc/caleadapter.h create mode 100644 resource/csdk/connectivity/inc/camessagehandler.h create mode 100644 resource/csdk/connectivity/inc/canetworkconfigurator.h create mode 100644 resource/csdk/connectivity/inc/caprotocolmessage.h create mode 100644 resource/csdk/connectivity/inc/caremotehandler.h create mode 100644 resource/csdk/connectivity/inc/cawifiadapter.h create mode 100644 resource/csdk/connectivity/inc/cawificore.h create mode 100644 resource/csdk/connectivity/inc/cawifiethernetadapter.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/.gitignore create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/ChangeLog create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/LICENSE.BSD create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/LICENSE.GPL create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/Makefile create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/Makefile.in create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/README create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/address.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/async.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/async.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/bits.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/block.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/block.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/coap.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/coap_list.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/coap_list.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/coap_time.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/config.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/config.h.in create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/config.status create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/configure create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/configure.in create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/debug.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/debug.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/encode.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/encode.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/examples/Makefile create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/examples/Makefile.in create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/examples/client.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/examples/etsi_iot_01.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/examples/rd.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/examples/server.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/examples/tiny.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/hashkey.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/hashkey.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/mem.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/net.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/net.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/option.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/option.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/pdu.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/pdu.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/prng.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/resource.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/resource.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/str.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/str.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/subscribe.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/subscribe.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/t_list.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/tests/Makefile create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/tests/Makefile.in create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_error_response.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_error_response.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_options.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_options.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_pdu.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_pdu.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_sendqueue.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_sendqueue.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_uri.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_uri.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_wellknown.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_wellknown.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/tests/testdriver.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/uri.c create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/uri.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/uthash.h create mode 100644 resource/csdk/connectivity/lib/libcoap-4.1.1/utlist.h create mode 100644 resource/csdk/connectivity/samples/linux/.gitignore create mode 100644 resource/csdk/connectivity/samples/linux/Makefile create mode 100644 resource/csdk/connectivity/samples/linux/README create mode 100644 resource/csdk/connectivity/samples/linux/sample.sh create mode 100644 resource/csdk/connectivity/samples/linux/sample_main.c create mode 100644 resource/csdk/connectivity/samples/linux/threadpool/Makefile create mode 100644 resource/csdk/connectivity/samples/linux/threadpool/main.c create mode 100644 resource/csdk/connectivity/src/bt_edr_adapter/linux/caedradapter.c create mode 100644 resource/csdk/connectivity/src/bt_le_adapter/caleadapter.c create mode 100644 resource/csdk/connectivity/src/bt_le_adapter/linux/caleadapter.c create mode 100644 resource/csdk/connectivity/src/caconnectivitymanager.c create mode 100644 resource/csdk/connectivity/src/cainterfacecontroller.c create mode 100644 resource/csdk/connectivity/src/camessagehandler.c create mode 100644 resource/csdk/connectivity/src/canetworkconfigurator.c create mode 100644 resource/csdk/connectivity/src/caprotocolmessage.c create mode 100644 resource/csdk/connectivity/src/caremotehandler.c create mode 100644 resource/csdk/connectivity/src/ethernet_adapter/linux/caethernetadapter.c create mode 100644 resource/csdk/connectivity/src/wifi_adapter/cawifiethernetadapter.c create mode 100644 resource/csdk/connectivity/src/wifi_adapter/linux/cawifiadapter.c create mode 100644 resource/csdk/connectivity/src/wifi_adapter/linux/cawificore.c create mode 100644 resource/csdk/connectivity/unittests/linux/sample1_unittest.cc create mode 100644 resource/csdk/doc/CCF Lite GIT Repo Layout.docx create mode 120000 resource/csdk/libcoap create mode 100644 resource/csdk/libcoap-4.1.1/ChangeLog create mode 100644 resource/csdk/libcoap-4.1.1/LICENSE.BSD create mode 100644 resource/csdk/libcoap-4.1.1/LICENSE.GPL create mode 100644 resource/csdk/libcoap-4.1.1/Makefile.in create mode 100644 resource/csdk/libcoap-4.1.1/README create mode 100644 resource/csdk/libcoap-4.1.1/SConscript create mode 100644 resource/csdk/libcoap-4.1.1/address.h create mode 100644 resource/csdk/libcoap-4.1.1/async.c create mode 100644 resource/csdk/libcoap-4.1.1/async.h create mode 100644 resource/csdk/libcoap-4.1.1/bits.h create mode 100644 resource/csdk/libcoap-4.1.1/block.c create mode 100644 resource/csdk/libcoap-4.1.1/block.h create mode 100644 resource/csdk/libcoap-4.1.1/coap.h create mode 100644 resource/csdk/libcoap-4.1.1/coap_list.c create mode 100644 resource/csdk/libcoap-4.1.1/coap_list.h create mode 100644 resource/csdk/libcoap-4.1.1/coap_time.h create mode 100644 resource/csdk/libcoap-4.1.1/config.h create mode 100644 resource/csdk/libcoap-4.1.1/config.h.in create mode 100755 resource/csdk/libcoap-4.1.1/configure create mode 100644 resource/csdk/libcoap-4.1.1/configure.in create mode 100644 resource/csdk/libcoap-4.1.1/debug.c create mode 100644 resource/csdk/libcoap-4.1.1/debug.h create mode 100644 resource/csdk/libcoap-4.1.1/doc/Doxyfile create mode 100644 resource/csdk/libcoap-4.1.1/doc/Doxyfile.in create mode 100644 resource/csdk/libcoap-4.1.1/doc/Makefile.in create mode 100644 resource/csdk/libcoap-4.1.1/doc/makefile create mode 100644 resource/csdk/libcoap-4.1.1/encode.c create mode 100644 resource/csdk/libcoap-4.1.1/encode.h create mode 100644 resource/csdk/libcoap-4.1.1/examples/client.c create mode 100644 resource/csdk/libcoap-4.1.1/examples/makefile create mode 100644 resource/csdk/libcoap-4.1.1/examples/rd.c create mode 100644 resource/csdk/libcoap-4.1.1/examples/server.c create mode 100644 resource/csdk/libcoap-4.1.1/examples/tiny.c create mode 100644 resource/csdk/libcoap-4.1.1/hashkey.c create mode 100644 resource/csdk/libcoap-4.1.1/hashkey.h create mode 100644 resource/csdk/libcoap-4.1.1/makefile create mode 100644 resource/csdk/libcoap-4.1.1/mem.h create mode 100644 resource/csdk/libcoap-4.1.1/net.c create mode 100644 resource/csdk/libcoap-4.1.1/net.h create mode 100644 resource/csdk/libcoap-4.1.1/option.c create mode 100644 resource/csdk/libcoap-4.1.1/option.h create mode 100644 resource/csdk/libcoap-4.1.1/pdu.c create mode 100644 resource/csdk/libcoap-4.1.1/pdu.h create mode 100644 resource/csdk/libcoap-4.1.1/prng.h create mode 100644 resource/csdk/libcoap-4.1.1/resource.c create mode 100644 resource/csdk/libcoap-4.1.1/resource.h create mode 100644 resource/csdk/libcoap-4.1.1/sec/netdtls.c create mode 100644 resource/csdk/libcoap-4.1.1/sec/netdtls.h create mode 100644 resource/csdk/libcoap-4.1.1/str.c create mode 100644 resource/csdk/libcoap-4.1.1/str.h create mode 100644 resource/csdk/libcoap-4.1.1/subscribe.c create mode 100644 resource/csdk/libcoap-4.1.1/subscribe.h create mode 100644 resource/csdk/libcoap-4.1.1/t_list.h create mode 100644 resource/csdk/libcoap-4.1.1/uri.c create mode 100644 resource/csdk/libcoap-4.1.1/uri.h create mode 100644 resource/csdk/libcoap-4.1.1/uthash.h create mode 100644 resource/csdk/libcoap-4.1.1/utlist.h create mode 100644 resource/csdk/logger/README create mode 100644 resource/csdk/logger/include/logger.h create mode 100644 resource/csdk/logger/makefile create mode 100644 resource/csdk/logger/src/logger.c create mode 100644 resource/csdk/logger/test/android/README create mode 100644 resource/csdk/logger/test/android/androidloggertestoutput.txt create mode 100644 resource/csdk/logger/test/android/loggertests.cpp create mode 100644 resource/csdk/logger/test/arduino/ArduinoLoggerTest.cpp create mode 100644 resource/csdk/logger/test/arduino/ArduinoLoggerTest.h create mode 100644 resource/csdk/logger/test/arduino/README create mode 100644 resource/csdk/logger/test/arduino/arduinologgertestoutput.txt create mode 100644 resource/csdk/logger/test/loggertests.cpp create mode 100644 resource/csdk/logger/test/std_logbuffer.txt create mode 100644 resource/csdk/logger/test/std_stringarg.txt create mode 100644 resource/csdk/logger/test/std_stringarglevels.txt create mode 100644 resource/csdk/logger/test/std_stringargmultiline.txt create mode 100644 resource/csdk/logger/test/std_stringargnologstr.txt create mode 100644 resource/csdk/logger/test/std_stringargnotag.txt create mode 100644 resource/csdk/logger/test/std_stringargnotagnologstr.txt create mode 100644 resource/csdk/logger/test/std_variablearg.txt create mode 100644 resource/csdk/makefile create mode 100644 resource/csdk/occoap/README.txt create mode 100644 resource/csdk/occoap/include/occoap.h create mode 100644 resource/csdk/occoap/include/occoaphelper.h create mode 100644 resource/csdk/occoap/include/occoaptoken.h create mode 100644 resource/csdk/occoap/makefile create mode 100644 resource/csdk/occoap/src/occoap.c create mode 100644 resource/csdk/occoap/src/occoaphelper.c create mode 100644 resource/csdk/occoap/test/occoaptests.cpp create mode 100644 resource/csdk/ocmalloc/include/ocmalloc.h create mode 100644 resource/csdk/ocmalloc/src/ocmalloc.c create mode 100644 resource/csdk/ocmalloc/test/linux/README create mode 100644 resource/csdk/ocmalloc/test/linux/makefile create mode 100644 resource/csdk/ocmalloc/test/linux/unittest.cpp create mode 100644 resource/csdk/ocrandom/include/ocrandom.h create mode 100644 resource/csdk/ocrandom/src/ocrandom.c create mode 100644 resource/csdk/ocrandom/test/android/makefile create mode 100644 resource/csdk/ocrandom/test/android/randomtest.cpp create mode 100644 resource/csdk/ocrandom/test/arduino/makefile create mode 100644 resource/csdk/ocrandom/test/arduino/randomtest.cpp create mode 100644 resource/csdk/ocrandom/test/linux/makefile create mode 100644 resource/csdk/ocrandom/test/linux/randomtest.cpp create mode 100644 resource/csdk/ocsocket/README.txt create mode 100644 resource/csdk/ocsocket/include/ocsocket.h create mode 100644 resource/csdk/ocsocket/src/ocsocket.c create mode 100644 resource/csdk/ocsocket/src/ocsocket_arduino.cpp create mode 100644 resource/csdk/ocsocket/src/ocsocket_arduino_wifi.cpp create mode 100644 resource/csdk/ocsocket/test/android/makefile create mode 100644 resource/csdk/ocsocket/test/android/ocsocket_gtest.cpp create mode 100644 resource/csdk/ocsocket/test/arduino/makefile create mode 100644 resource/csdk/ocsocket/test/arduino/ocsocket_test.cpp create mode 100644 resource/csdk/ocsocket/test/arduino/ocsocket_wifi_test.cpp create mode 100644 resource/csdk/ocsocket/test/linux/makefile create mode 100644 resource/csdk/ocsocket/test/linux/ocsocket_gtest.cpp create mode 100644 resource/csdk/ocsocket/test/makefile create mode 100644 resource/csdk/ocsocket/test/sendrecv.cpp create mode 100644 resource/csdk/ocsocket/test/sendrecv_README.txt create mode 100644 resource/csdk/stack/README create mode 100644 resource/csdk/stack/include/internal/occlientcb.h create mode 100644 resource/csdk/stack/include/internal/occollection.h create mode 100644 resource/csdk/stack/include/internal/ocobserve.h create mode 100644 resource/csdk/stack/include/internal/ocresource.h create mode 100644 resource/csdk/stack/include/internal/ocresourcehandler.h create mode 100644 resource/csdk/stack/include/internal/ocserverrequest.h create mode 100644 resource/csdk/stack/include/internal/ocstackinternal.h create mode 100644 resource/csdk/stack/include/internal/oicgroup.h create mode 100644 resource/csdk/stack/include/ocsecurity.h create mode 100644 resource/csdk/stack/include/ocsecurityconfig.h create mode 100644 resource/csdk/stack/include/ocstack.h create mode 100644 resource/csdk/stack/include/ocstackconfig.h create mode 100644 resource/csdk/stack/samples/arduino/SimpleClientServer/README create mode 100644 resource/csdk/stack/samples/arduino/SimpleClientServer/makefile create mode 100644 resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/README create mode 100644 resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/SConscript create mode 100644 resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/makefile create mode 100644 resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/ocserver.cpp create mode 100644 resource/csdk/stack/samples/linux/SimpleClientServer/common.cpp create mode 100644 resource/csdk/stack/samples/linux/SimpleClientServer/makefile create mode 100644 resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp create mode 100644 resource/csdk/stack/samples/linux/SimpleClientServer/occlient.h create mode 100644 resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.cpp create mode 100644 resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.h create mode 100644 resource/csdk/stack/samples/linux/SimpleClientServer/occlientcoll.cpp create mode 100644 resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.cpp create mode 100644 resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.h create mode 100644 resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp create mode 100644 resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.h create mode 100644 resource/csdk/stack/samples/linux/SimpleClientServer/ocserverbasicops.cpp create mode 100644 resource/csdk/stack/samples/linux/SimpleClientServer/ocserverbasicops.h create mode 100644 resource/csdk/stack/samples/linux/SimpleClientServer/ocservercoll.cpp create mode 100644 resource/csdk/stack/samples/linux/SimpleClientServer/ocserverslow.cpp create mode 100644 resource/csdk/stack/samples/linux/SimpleClientServer/ocserverslow.h create mode 100644 resource/csdk/stack/samples/linux/secure/common.cpp create mode 100644 resource/csdk/stack/samples/linux/secure/common.h create mode 100644 resource/csdk/stack/samples/linux/secure/gen_sec_bin.cpp create mode 100644 resource/csdk/stack/samples/linux/secure/makefile create mode 100644 resource/csdk/stack/samples/linux/secure/occlientbasicops.cpp create mode 100644 resource/csdk/stack/samples/linux/secure/occlientbasicops.h create mode 100644 resource/csdk/stack/samples/linux/secure/ocserverbasicops.cpp create mode 100644 resource/csdk/stack/samples/linux/secure/ocserverbasicops.h create mode 100644 resource/csdk/stack/src/occlientcb.c create mode 100644 resource/csdk/stack/src/occollection.c create mode 100644 resource/csdk/stack/src/ocobserve.c create mode 100644 resource/csdk/stack/src/ocresource.c create mode 100644 resource/csdk/stack/src/ocsecurity.c create mode 100644 resource/csdk/stack/src/ocserverrequest.c create mode 100644 resource/csdk/stack/src/ocstack.c create mode 100644 resource/csdk/stack/src/oicgroup.c create mode 100644 resource/csdk/stack/test/README create mode 100644 resource/csdk/stack/test/android/README create mode 100644 resource/csdk/stack/test/android/stacktests.cpp create mode 100644 resource/csdk/stack/test/arduino/ArduinoStackTest.cpp create mode 100644 resource/csdk/stack/test/arduino/ArduinoStackTest.h create mode 100644 resource/csdk/stack/test/arduino/README create mode 100644 resource/csdk/stack/test/arduino/makefile create mode 100644 resource/csdk/stack/test/arduino/ocserver.cpp create mode 100644 resource/csdk/stack/test/linux/makefile create mode 100644 resource/csdk/stack/test/linux/occlient.c create mode 100644 resource/csdk/stack/test/linux/ocserver.c create mode 100644 resource/csdk/stack/test/makefile create mode 100644 resource/csdk/stack/test/stacktests.cpp create mode 100644 resource/docs/Doxyfile create mode 100644 resource/docs/doxygenLayout.xml create mode 100644 resource/docs/guides/AboutOIC.txt create mode 100644 resource/docs/guides/Home.txt create mode 100644 resource/docs/guides/HowToGuidesIndex.txt create mode 100644 resource/docs/guides/ProgrammersGuide.txt create mode 100644 resource/docs/html/footer.html create mode 100644 resource/docs/img/seq_find_resource.png create mode 100644 resource/docs/img/seq_find_resource_2.png create mode 100644 resource/docs/img/seq_find_resource_3.png create mode 100644 resource/docs/img/seq_find_resource_4.png create mode 100644 resource/docs/img/seq_get.png create mode 100644 resource/docs/img/seq_observe.png create mode 100644 resource/docs/img/seq_put.png create mode 100644 resource/docs/img/seq_register_resource.png create mode 100644 resource/docs/img/seq_register_resource_2.png create mode 100644 resource/docs/img/seq_stack_init.png create mode 100644 resource/docs/img/stack_diagram.png create mode 100644 resource/examples/SConscript create mode 100644 resource/examples/devicediscoveryclient.cpp create mode 100644 resource/examples/devicediscoveryserver.cpp create mode 100644 resource/examples/fridgeclient.cpp create mode 100644 resource/examples/fridgeserver.cpp create mode 100644 resource/examples/garageclient.cpp create mode 100644 resource/examples/garageserver.cpp create mode 100755 resource/examples/groupclient.cpp create mode 100755 resource/examples/groupserver.cpp create mode 100755 resource/examples/lightserver.cpp create mode 100755 resource/examples/makefile create mode 100644 resource/examples/ocicuc/.gitignore create mode 100644 resource/examples/ocicuc/Makefile create mode 100644 resource/examples/ocicuc/README create mode 100644 resource/examples/ocicuc/SConscript create mode 100644 resource/examples/ocicuc/client.cpp create mode 100644 resource/examples/ocicuc/demo_client.hpp create mode 100644 resource/examples/ocicuc/driver.cpp create mode 100644 resource/examples/ocicuc/exec.hpp create mode 100644 resource/examples/ocicuc/light_resource.cpp create mode 100644 resource/examples/ocicuc/light_resource.hpp create mode 100644 resource/examples/ocicuc/monoprocess.cpp create mode 100644 resource/examples/ocicuc/server.cpp create mode 100644 resource/examples/ocicuc/small_example.cpp create mode 100644 resource/examples/ocicuc/utility.cpp create mode 100644 resource/examples/ocicuc/utility.hpp create mode 100644 resource/examples/old_tests/MyMultiResourceHandler.cpp create mode 100644 resource/examples/old_tests/MyMultiResourceHandler.h create mode 100644 resource/examples/old_tests/MyObserverHandler.cpp create mode 100644 resource/examples/old_tests/MyObserverHandler.h create mode 100644 resource/examples/old_tests/MyResourceHandler.cpp create mode 100644 resource/examples/old_tests/MyResourceHandler.h create mode 100644 resource/examples/old_tests/OCWrapper/makefile create mode 100644 resource/examples/old_tests/OCWrapper/parsetest.cpp create mode 100644 resource/examples/old_tests/OCWrapper/testClient.cpp create mode 100644 resource/examples/old_tests/OCWrapper/testServer.cpp create mode 100644 resource/examples/old_tests/OCWrapper/testServerApp.cpp create mode 100644 resource/examples/old_tests/multiple_resources.cpp create mode 100644 resource/examples/presenceclient.cpp create mode 100644 resource/examples/presenceserver.cpp create mode 100644 resource/examples/roomclient.cpp create mode 100644 resource/examples/roomserver.cpp create mode 100644 resource/examples/simpleclient.cpp create mode 100644 resource/examples/simpleclientHQ.cpp create mode 100644 resource/examples/simpleclientserver.cpp create mode 100644 resource/examples/simpleserver.cpp create mode 100644 resource/examples/simpleserverHQ.cpp create mode 100644 resource/examples/threadingsample.cpp create mode 100644 resource/include/AttributeValue.h create mode 100644 resource/include/IClientWrapper.h create mode 100644 resource/include/IServerWrapper.h create mode 100644 resource/include/InProcClientWrapper.h create mode 100644 resource/include/InProcServerWrapper.h create mode 100644 resource/include/InitializeException.h create mode 100644 resource/include/OCAndroid.h create mode 100644 resource/include/OCApi.h create mode 100644 resource/include/OCException.h create mode 100644 resource/include/OCHeaderOption.h create mode 100644 resource/include/OCPlatform.h create mode 100644 resource/include/OCPlatform_impl.h create mode 100644 resource/include/OCRepresentation.h create mode 100644 resource/include/OCResource.h create mode 100644 resource/include/OCResourceRequest.h create mode 100644 resource/include/OCResourceResponse.h create mode 100644 resource/include/OCSecurityModel.h create mode 100644 resource/include/OCSerialization.h create mode 100644 resource/include/OCUtilities.h create mode 100644 resource/include/OicJsonSerializer.hpp create mode 100644 resource/include/OutOfProcClientWrapper.h create mode 100644 resource/include/OutOfProcServerWrapper.h create mode 100644 resource/include/ResourceInitException.h create mode 100644 resource/include/StringConstants.h create mode 100644 resource/include/WrapperFactory.h create mode 100644 resource/makefile create mode 100644 resource/oc_logger/Makefile create mode 100644 resource/oc_logger/SConscript create mode 100644 resource/oc_logger/c/Makefile create mode 100644 resource/oc_logger/c/oc_console_logger.c create mode 100644 resource/oc_logger/c/oc_logger.c create mode 100644 resource/oc_logger/cpp/Makefile create mode 100644 resource/oc_logger/cpp/oc_ostream_logger.cpp create mode 100644 resource/oc_logger/examples/Makefile create mode 100644 resource/oc_logger/examples/SConscript create mode 100644 resource/oc_logger/examples/test_logging.c create mode 100644 resource/oc_logger/examples/test_logging.cpp create mode 100644 resource/oc_logger/include/oc_console_logger.h create mode 100644 resource/oc_logger/include/oc_log.hpp create mode 100644 resource/oc_logger/include/oc_log_stream.hpp create mode 100644 resource/oc_logger/include/oc_logger.h create mode 100644 resource/oc_logger/include/oc_logger.hpp create mode 100644 resource/oc_logger/include/oc_logger_types.h create mode 100644 resource/oc_logger/include/targets/oc_console_logger.h create mode 100644 resource/oc_logger/include/targets/oc_ostream_logger.h create mode 100644 resource/oc_logger/samples/linux/README create mode 100644 resource/oc_logger/samples/linux/makefile create mode 100644 resource/oc_logger/samples/linux/test_logging.c create mode 100644 resource/oc_logger/test/test_logging.cpp create mode 100644 resource/patches/boost/arm-linux-androideabi/user-config.jam create mode 100644 resource/patches/boost/x86/user-config.jam create mode 100644 resource/patches/cereal_gcc46.patch create mode 100644 resource/releaseNotes/Aug5th2014.txt create mode 100644 resource/releaseNotes/Dec20th2014.txt create mode 100644 resource/releaseNotes/Dec6th2014.txt create mode 100644 resource/releaseNotes/Nov15th2014.txt create mode 100644 resource/releaseNotes/Oct14th2014.txt create mode 100644 resource/releaseNotes/Oct31st2014.txt create mode 100644 resource/releaseNotes/Sept17th2014.txt create mode 100644 resource/releaseNotes/Sept2nd2014.txt create mode 100644 resource/releaseNotes/Sept30th2014.txt create mode 100644 resource/src/InProcClientWrapper.cpp create mode 100644 resource/src/InProcServerWrapper.cpp create mode 100644 resource/src/OCApi.cpp create mode 100644 resource/src/OCException.cpp create mode 100644 resource/src/OCPlatform.cpp create mode 100644 resource/src/OCPlatform_impl.cpp create mode 100644 resource/src/OCRepresentation.cpp create mode 100644 resource/src/OCResource.cpp create mode 100644 resource/src/OCSecurityModel.cpp create mode 100644 resource/src/OCUtilities.cpp create mode 100644 resource/src/SConscript create mode 100644 resource/third_party_libs.scons create mode 100644 resource/unittests/README create mode 100644 resource/unittests/makefile create mode 100644 resource/unittests/tests.cpp create mode 100644 scons_script_how_to.txt create mode 100644 service/SConscript create mode 100644 service/docs/Control Manager-Programmer's guide_v0.9.0.pdf create mode 100644 service/docs/PPM - Programmer's Guide_v0.9.0.pdf create mode 100644 service/docs/SSM - Programmer's guide_v0.9.0.pdf create mode 100644 service/docs/Things Manager - Programmer's guide_v0.9.0.pdf create mode 100644 service/notification-manager/.gitignore create mode 100644 service/notification-manager/NotificationManager/build/linux/.gitignore create mode 100644 service/notification-manager/NotificationManager/build/linux/Makefile create mode 100644 service/notification-manager/NotificationManager/include/HostingConfig.h create mode 100644 service/notification-manager/NotificationManager/include/HostingHandler.h create mode 100644 service/notification-manager/NotificationManager/include/HostingInterface.h create mode 100644 service/notification-manager/NotificationManager/include/NotificationManager.h create mode 100644 service/notification-manager/NotificationManager/include/OICPlatformConfig.h create mode 100644 service/notification-manager/NotificationManager/include/RegistrationManager.h create mode 100644 service/notification-manager/NotificationManager/include/ResourceManager.h create mode 100644 service/notification-manager/NotificationManager/include/VirtualRepresentation.h create mode 100644 service/notification-manager/NotificationManager/src/HostingHandler.cpp create mode 100644 service/notification-manager/NotificationManager/src/HostingInterface.cpp create mode 100644 service/notification-manager/NotificationManager/src/NotificationManager.cpp create mode 100644 service/notification-manager/NotificationManager/src/OICPlatformConfig.cpp create mode 100644 service/notification-manager/NotificationManager/src/RegistrationManager.cpp create mode 100644 service/notification-manager/NotificationManager/src/ResourceManager.cpp create mode 100644 service/notification-manager/NotificationManager/src/VirtualRepresentation.cpp create mode 100644 service/notification-manager/NotificationManager/src/linux/main.cpp create mode 100644 service/notification-manager/SConscript create mode 100644 service/notification-manager/SampleApp/SConscript create mode 100644 service/notification-manager/SampleApp/arduino/SConscript create mode 100644 service/notification-manager/SampleApp/arduino/Time/DateStrings.cpp create mode 100644 service/notification-manager/SampleApp/arduino/Time/Readme.txt create mode 100644 service/notification-manager/SampleApp/arduino/Time/Time.cpp create mode 100644 service/notification-manager/SampleApp/arduino/Time/Time.h create mode 100644 service/notification-manager/SampleApp/arduino/Time/examples/Processing/SyncArduinoClock/SyncArduinoClock.pde create mode 100644 service/notification-manager/SampleApp/arduino/Time/examples/Processing/SyncArduinoClock/readme.txt create mode 100644 service/notification-manager/SampleApp/arduino/Time/examples/TimeArduinoDue/TimeArduinoDue.ino create mode 100644 service/notification-manager/SampleApp/arduino/Time/examples/TimeGPS/TimeGPS.ino create mode 100644 service/notification-manager/SampleApp/arduino/Time/examples/TimeNTP/TimeNTP.ino create mode 100644 service/notification-manager/SampleApp/arduino/Time/examples/TimeRTC/TimeRTC.pde create mode 100644 service/notification-manager/SampleApp/arduino/Time/examples/TimeRTCLog/TimeRTCLog.pde create mode 100644 service/notification-manager/SampleApp/arduino/Time/examples/TimeRTCSet/TimeRTCSet.ino create mode 100644 service/notification-manager/SampleApp/arduino/Time/examples/TimeSerial/TimeSerial.ino create mode 100644 service/notification-manager/SampleApp/arduino/Time/examples/TimeSerialDateStrings/TimeSerialDateStrings.ino create mode 100644 service/notification-manager/SampleApp/arduino/Time/examples/TimeTeensy3/TimeTeensy3.ino create mode 100644 service/notification-manager/SampleApp/arduino/Time/keywords.txt create mode 100644 service/notification-manager/SampleApp/arduino/local.properties create mode 100644 service/notification-manager/SampleApp/arduino/makefile create mode 100644 service/notification-manager/SampleApp/arduino/readme.txt create mode 100644 service/notification-manager/SampleApp/arduino/thserver.cpp create mode 100644 service/notification-manager/SampleApp/linux/SConscript create mode 100644 service/notification-manager/SampleApp/linux/sampleConsumer/SampleConsumer.cpp create mode 100644 service/notification-manager/SampleApp/linux/sampleProvider/SampleProvider.cpp create mode 100644 service/notification-manager/SampleApp/tizen/sampleConsumer/src/oicapp-client.cpp create mode 100644 service/notification-manager/SampleApp/tizen/sampleConsumer/src/oicapp-log.h create mode 100644 service/notification-manager/SampleApp/tizen/sampleConsumer/src/oicapp-sampleConsumer.c create mode 100644 service/notification-manager/SampleApp/tizen/sampleConsumer/src/oicapp-sampleConsumer.h create mode 100644 service/notification-manager/SampleApp/tizen/sampleConsumer/src/oicapp-utils.c create mode 100644 service/notification-manager/SampleApp/tizen/sampleConsumer/src/oicapp-utils.h create mode 100644 service/notification-manager/build/linux/makefile/Makefile create mode 100644 service/notification-manager/build/linux/release/.gitignore create mode 100644 service/notification-manager/build/tizen/CMakeLists.txt create mode 100644 service/protocol-plugin/.gitignore create mode 100644 service/protocol-plugin/SConscript create mode 100644 service/protocol-plugin/build/linux/Makefile create mode 100644 service/protocol-plugin/build/tizen/CMakeLists.txt create mode 100644 service/protocol-plugin/config.mk create mode 100644 service/protocol-plugin/lib/cpluff/COPYRIGHT.txt create mode 100644 service/protocol-plugin/lib/cpluff/ChangeLog.txt create mode 100644 service/protocol-plugin/lib/cpluff/INSTALL.txt create mode 100644 service/protocol-plugin/lib/cpluff/Issues.txt create mode 100644 service/protocol-plugin/lib/cpluff/Makefile.am create mode 100644 service/protocol-plugin/lib/cpluff/Roadmap.txt create mode 100644 service/protocol-plugin/lib/cpluff/SConscript create mode 100644 service/protocol-plugin/lib/cpluff/auxliary/config.guess create mode 100644 service/protocol-plugin/lib/cpluff/auxliary/config.rpath create mode 100644 service/protocol-plugin/lib/cpluff/auxliary/config.sub create mode 100644 service/protocol-plugin/lib/cpluff/auxliary/depcomp create mode 100644 service/protocol-plugin/lib/cpluff/auxliary/install-sh create mode 100644 service/protocol-plugin/lib/cpluff/auxliary/ltmain.sh create mode 100644 service/protocol-plugin/lib/cpluff/auxliary/missing create mode 100644 service/protocol-plugin/lib/cpluff/configure.ac create mode 100644 service/protocol-plugin/lib/cpluff/console/Makefile.am create mode 100644 service/protocol-plugin/lib/cpluff/console/cmdinput_basic.c create mode 100644 service/protocol-plugin/lib/cpluff/console/cmdinput_readline.c create mode 100644 service/protocol-plugin/lib/cpluff/console/console.c create mode 100644 service/protocol-plugin/lib/cpluff/console/console.h create mode 100644 service/protocol-plugin/lib/cpluff/doc/Makefile create mode 100644 service/protocol-plugin/lib/cpluff/doc/Makefile.am create mode 100644 service/protocol-plugin/lib/cpluff/doc/Makefile.in create mode 100644 service/protocol-plugin/lib/cpluff/doc/common_style.css create mode 100644 service/protocol-plugin/lib/cpluff/doc/copyright.en.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/cpluff_style.css create mode 100644 service/protocol-plugin/lib/cpluff/doc/img/Makefile create mode 100644 service/protocol-plugin/lib/cpluff/doc/img/Makefile.am create mode 100644 service/protocol-plugin/lib/cpluff/doc/img/Makefile.in create mode 100644 service/protocol-plugin/lib/cpluff/doc/img/architecture.png create mode 100644 service/protocol-plugin/lib/cpluff/doc/img/architecture.svg create mode 100644 service/protocol-plugin/lib/cpluff/doc/img/pageborder.png create mode 100644 service/protocol-plugin/lib/cpluff/doc/index.en.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/annotated.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/architecture.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/architecture.png create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/cMainProgram.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/cpluff_8h-source.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/cpluff_8h.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/cpluff_8h__incl.map create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/cpluff_8h__incl.md5 create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/cpluff_8h__incl.png create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/cpluffdef_8h-source.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/cpluffdef_8h.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/cpluffdef_8h__dep__incl.map create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/cpluffdef_8h__dep__incl.md5 create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/cpluffdef_8h__dep__incl.png create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/doxygen.css create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/doxygen.png create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/files.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/functions.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/functions_vars.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/globals.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/globals_eval.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/globals_func.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/globals_type.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/graph_legend.dot create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/graph_legend.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/graph_legend.png create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/group__cDefines.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/group__cDefinesGCCAttributes.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/group__cEnums.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/group__cFuncs.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/group__cFuncsContext.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/group__cFuncsFrameworkInfo.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/group__cFuncsInit.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/group__cFuncsLogging.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/group__cFuncsPlugin.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/group__cFuncsPluginExec.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/group__cFuncsPluginInfo.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/group__cFuncsSymbols.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/group__cScanFlags.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/group__cStructs.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/group__cTypedefs.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/group__cTypedefsFuncs.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/group__cTypedefsOpaque.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/group__cTypedefsShorthand.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/group__symbolVisibility.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/group__versionInfo.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/index.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/inline_dotgraph_1.png create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/modules.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/pages.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/plugin.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/structcp__cfg__element__t.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/structcp__cfg__element__t__coll__graph.map create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/structcp__cfg__element__t__coll__graph.md5 create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/structcp__cfg__element__t__coll__graph.png create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/structcp__ext__point__t.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/structcp__ext__point__t__coll__graph.map create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/structcp__ext__point__t__coll__graph.md5 create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/structcp__ext__point__t__coll__graph.png create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/structcp__extension__t.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/structcp__extension__t__coll__graph.map create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/structcp__extension__t__coll__graph.md5 create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/structcp__extension__t__coll__graph.png create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/structcp__plugin__import__t.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/structcp__plugin__info__t.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/structcp__plugin__info__t__coll__graph.map create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/structcp__plugin__info__t__coll__graph.md5 create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/structcp__plugin__info__t__coll__graph.png create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/structcp__plugin__runtime__t.html create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/tab_b.gif create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/tab_l.gif create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/tab_r.gif create mode 100644 service/protocol-plugin/lib/cpluff/doc/reference/c-api/tabs.css create mode 100644 service/protocol-plugin/lib/cpluff/docsrc/Makefile create mode 100644 service/protocol-plugin/lib/cpluff/docsrc/Makefile.am create mode 100644 service/protocol-plugin/lib/cpluff/docsrc/Makefile.in create mode 100644 service/protocol-plugin/lib/cpluff/docsrc/doxygen.css create mode 100644 service/protocol-plugin/lib/cpluff/docsrc/doxygen.footer create mode 100644 service/protocol-plugin/lib/cpluff/examples/COPYRIGHT.txt create mode 100644 service/protocol-plugin/lib/cpluff/examples/INSTALL.txt create mode 100644 service/protocol-plugin/lib/cpluff/examples/Makefile create mode 100644 service/protocol-plugin/lib/cpluff/examples/Makefile.am create mode 100644 service/protocol-plugin/lib/cpluff/examples/Makefile.in create mode 100644 service/protocol-plugin/lib/cpluff/examples/Makefile.nmake create mode 100644 service/protocol-plugin/lib/cpluff/examples/autogen.sh create mode 100644 service/protocol-plugin/lib/cpluff/examples/common.nmake create mode 100644 service/protocol-plugin/lib/cpluff/examples/configure.ac create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/Makefile create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/Makefile.am create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/Makefile.in create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/Makefile.nmake create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/README.txt create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/cpfile create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/cpfile.bat create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/cpfile.in create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/Makefile create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/Makefile.am create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/Makefile.in create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/Makefile.nmake create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/cext/Makefile create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/cext/Makefile.am create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/cext/Makefile.in create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/cext/Makefile.nmake create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/cext/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/core/.deps/core.Plo create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/core/Makefile create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/core/Makefile.am create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/core/Makefile.in create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/core/Makefile.nmake create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/core/classifiers.xsd create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/core/core.c create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/core/core.h create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/core/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/extension/.deps/extension.Plo create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/extension/Makefile create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/extension/Makefile.am create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/extension/Makefile.in create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/extension/Makefile.nmake create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/extension/extension.c create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/extension/file_types.xsd create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/extension/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/special/.deps/special.Plo create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/special/Makefile create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/special/Makefile.am create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/special/Makefile.in create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/special/Makefile.nmake create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/special/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/examples/cpfile/plugins/special/special.c create mode 100644 service/protocol-plugin/lib/cpluff/examples/nmakedir.bat create mode 100644 service/protocol-plugin/lib/cpluff/kazlib/hash.c create mode 100644 service/protocol-plugin/lib/cpluff/kazlib/hash.h create mode 100644 service/protocol-plugin/lib/cpluff/kazlib/list.c create mode 100644 service/protocol-plugin/lib/cpluff/kazlib/list.h create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/.deps/context.Plo create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/.deps/cpluff.Plo create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/.deps/hash.Plo create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/.deps/list.Plo create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/.deps/logging.Plo create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/.deps/pcontrol.Plo create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/.deps/pinfo.Plo create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/.deps/ploader.Plo create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/.deps/pscan.Plo create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/.deps/psymbol.Plo create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/.deps/serial.Plo create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/.deps/thread_posix.Plo create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/.deps/thread_windows.Plo create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/.deps/util.Plo create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/Makefile create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/Makefile.am create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/Makefile.in create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/context.c create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/cpluff.c create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/cpluff.h create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/cpluffdef.h create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/cpluffdef.h.in create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/defines.h create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/docsrc/Doxyfile-impl create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/docsrc/Doxyfile-impl.in create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/docsrc/Doxyfile-ref create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/docsrc/Doxyfile-ref.in create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/docsrc/Makefile create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/docsrc/Makefile.am create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/docsrc/Makefile.in create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/docsrc/architecture.dox create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/docsrc/mainpage.dox create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/docsrc/mainprog.dox create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/docsrc/plugin.dox create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/internal.h create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/internal.h.gch create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/logging.c create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/pcontrol.c create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/pinfo.c create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/ploader.c create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/pscan.c create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/psymbol.c create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/serial.c create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/thread.h create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/thread_posix.c create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/thread_windows.c create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/util.c create mode 100644 service/protocol-plugin/lib/cpluff/libcpluff/util.h create mode 100644 service/protocol-plugin/lib/cpluff/loader/.deps/loader.Po create mode 100644 service/protocol-plugin/lib/cpluff/loader/Makefile create mode 100644 service/protocol-plugin/lib/cpluff/loader/Makefile.am create mode 100644 service/protocol-plugin/lib/cpluff/loader/Makefile.in create mode 100644 service/protocol-plugin/lib/cpluff/loader/loader.c create mode 100644 service/protocol-plugin/lib/cpluff/m4/gettext.m4 create mode 100644 service/protocol-plugin/lib/cpluff/m4/iconv.m4 create mode 100644 service/protocol-plugin/lib/cpluff/m4/lib-ld.m4 create mode 100644 service/protocol-plugin/lib/cpluff/m4/lib-link.m4 create mode 100644 service/protocol-plugin/lib/cpluff/m4/lib-prefix.m4 create mode 100644 service/protocol-plugin/lib/cpluff/m4/nls.m4 create mode 100644 service/protocol-plugin/lib/cpluff/m4/po.m4 create mode 100644 service/protocol-plugin/lib/cpluff/m4/progtest.m4 create mode 100644 service/protocol-plugin/lib/cpluff/plugin.xsd create mode 100644 service/protocol-plugin/lib/cpluff/po/LINGUAS create mode 100644 service/protocol-plugin/lib/cpluff/po/Makefile create mode 100644 service/protocol-plugin/lib/cpluff/po/Makefile.in create mode 100644 service/protocol-plugin/lib/cpluff/po/Makefile.in.in create mode 100644 service/protocol-plugin/lib/cpluff/po/Makevars create mode 100644 service/protocol-plugin/lib/cpluff/po/POTFILES create mode 100644 service/protocol-plugin/lib/cpluff/po/POTFILES.in create mode 100644 service/protocol-plugin/lib/cpluff/po/Rules-quot create mode 100644 service/protocol-plugin/lib/cpluff/po/boldquot.sed create mode 100644 service/protocol-plugin/lib/cpluff/po/cpluff.pot create mode 100644 service/protocol-plugin/lib/cpluff/po/en@boldquot.gmo create mode 100644 service/protocol-plugin/lib/cpluff/po/en@boldquot.header create mode 100644 service/protocol-plugin/lib/cpluff/po/en@quot.gmo create mode 100644 service/protocol-plugin/lib/cpluff/po/en@quot.header create mode 100644 service/protocol-plugin/lib/cpluff/po/fi.gmo create mode 100644 service/protocol-plugin/lib/cpluff/po/insert-header.sin create mode 100644 service/protocol-plugin/lib/cpluff/po/quot.sed create mode 100644 service/protocol-plugin/lib/cpluff/po/remove-potcdate.sin create mode 100644 service/protocol-plugin/lib/cpluff/po/stamp-po create mode 100644 service/protocol-plugin/lib/cpluff/test/.deps/collections.Po create mode 100644 service/protocol-plugin/lib/cpluff/test/.deps/cpinfo.Po create mode 100644 service/protocol-plugin/lib/cpluff/test/.deps/extcfg.Po create mode 100644 service/protocol-plugin/lib/cpluff/test/.deps/fatalerror.Po create mode 100644 service/protocol-plugin/lib/cpluff/test/.deps/initdestroy.Po create mode 100644 service/protocol-plugin/lib/cpluff/test/.deps/loggers.Po create mode 100644 service/protocol-plugin/lib/cpluff/test/.deps/pcallbacks.Po create mode 100644 service/protocol-plugin/lib/cpluff/test/.deps/pdependencies.Po create mode 100644 service/protocol-plugin/lib/cpluff/test/.deps/pinstallation.Po create mode 100644 service/protocol-plugin/lib/cpluff/test/.deps/ploading.Po create mode 100644 service/protocol-plugin/lib/cpluff/test/.deps/pscanning.Po create mode 100644 service/protocol-plugin/lib/cpluff/test/.deps/psymbolusage.Po create mode 100644 service/protocol-plugin/lib/cpluff/test/.deps/testmain.Po create mode 100644 service/protocol-plugin/lib/cpluff/test/Makefile create mode 100644 service/protocol-plugin/lib/cpluff/test/Makefile.am create mode 100644 service/protocol-plugin/lib/cpluff/test/Makefile.in create mode 100644 service/protocol-plugin/lib/cpluff/test/collections.c create mode 100644 service/protocol-plugin/lib/cpluff/test/cpinfo.c create mode 100644 service/protocol-plugin/lib/cpluff/test/expected/output-extensions.txt create mode 100644 service/protocol-plugin/lib/cpluff/test/expected/output-extpoints.txt create mode 100644 service/protocol-plugin/lib/cpluff/test/expected/output-loadmaximal.txt create mode 100644 service/protocol-plugin/lib/cpluff/test/expected/output-loadminimal.txt create mode 100644 service/protocol-plugin/lib/cpluff/test/extcfg.c create mode 100644 service/protocol-plugin/lib/cpluff/test/fatalerror.c create mode 100644 service/protocol-plugin/lib/cpluff/test/initdestroy.c create mode 100644 service/protocol-plugin/lib/cpluff/test/loggers.c create mode 100644 service/protocol-plugin/lib/cpluff/test/pcallbacks.c create mode 100644 service/protocol-plugin/lib/cpluff/test/pcollections/collection1/plugin1/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/pcollections/collection1v2/plugin1/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/pcollections/collection1v3/plugin1/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/pcollections/collection2/plugin2a/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/pcollections/collection2/plugin2b/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/pcollections/dependencies/chain1/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/pcollections/dependencies/chain2/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/pcollections/dependencies/chain3/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/pcollections/dependencies/chainmissingdep/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/pcollections/dependencies/loop1/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/pcollections/dependencies/loop2/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/pcollections/dependencies/loop3/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/pcollections/dependencies/loop4/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/pcollections/dependencies/loop5/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/pcollections/dependencies/missingdep/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/pcollections/dependencies/sloop1/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/pcollections/dependencies/sloop2/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/pdependencies.c create mode 100644 service/protocol-plugin/lib/cpluff/test/pinstallation.c create mode 100644 service/protocol-plugin/lib/cpluff/test/ploading.c create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/Makefile create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/Makefile.am create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/Makefile.in create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/callbackcounter/.deps/callbackcounter.Plo create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/callbackcounter/Makefile create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/callbackcounter/Makefile.am create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/callbackcounter/Makefile.in create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/callbackcounter/callbackcounter.c create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/callbackcounter/callbackcounter.h create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/callbackcounter/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/symprovider/.deps/symprovider.Plo create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/symprovider/Makefile create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/symprovider/Makefile.am create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/symprovider/Makefile.in create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/symprovider/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/symprovider/symprovider.c create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/symuser/.deps/symuser.Plo create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/symuser/Makefile create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/symuser/Makefile.am create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/symuser/Makefile.in create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/symuser/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins-source/symuser/symuser.c create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins/maximal/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/plugins/minimal/plugin.xml create mode 100644 service/protocol-plugin/lib/cpluff/test/pscanning.c create mode 100644 service/protocol-plugin/lib/cpluff/test/psymbolusage.c create mode 100644 service/protocol-plugin/lib/cpluff/test/test-extensions create mode 100644 service/protocol-plugin/lib/cpluff/test/test-extpoints create mode 100644 service/protocol-plugin/lib/cpluff/test/test-fatalerrordefault create mode 100644 service/protocol-plugin/lib/cpluff/test/test-fatalerrorreset create mode 100644 service/protocol-plugin/lib/cpluff/test/test-loadmaximal create mode 100644 service/protocol-plugin/lib/cpluff/test/test-loadminimal create mode 100644 service/protocol-plugin/lib/cpluff/test/test.h create mode 100644 service/protocol-plugin/lib/cpluff/test/testmain.c create mode 100644 service/protocol-plugin/lib/cpluff/test/tests.txt create mode 100644 service/protocol-plugin/lib/rapidxml/rapidxml.hpp create mode 100644 service/protocol-plugin/lib/rapidxml/rapidxml_iterators.hpp create mode 100644 service/protocol-plugin/lib/rapidxml/rapidxml_print.hpp create mode 100644 service/protocol-plugin/lib/rapidxml/rapidxml_utils.hpp create mode 100644 service/protocol-plugin/plugin-manager/.gitignore create mode 100644 service/protocol-plugin/plugin-manager/SConscript create mode 100644 service/protocol-plugin/plugin-manager/build/linux/Makefile create mode 100644 service/protocol-plugin/plugin-manager/src/Config.cpp create mode 100644 service/protocol-plugin/plugin-manager/src/Config.h create mode 100644 service/protocol-plugin/plugin-manager/src/CpluffAdapter.cpp create mode 100644 service/protocol-plugin/plugin-manager/src/CpluffAdapter.h create mode 100644 service/protocol-plugin/plugin-manager/src/FelixAdapter.cpp create mode 100644 service/protocol-plugin/plugin-manager/src/FelixAdapter.h create mode 100644 service/protocol-plugin/plugin-manager/src/Plugin.cpp create mode 100644 service/protocol-plugin/plugin-manager/src/Plugin.h create mode 100644 service/protocol-plugin/plugin-manager/src/PluginManager.cpp create mode 100644 service/protocol-plugin/plugin-manager/src/PluginManager.h create mode 100644 service/protocol-plugin/plugin-manager/src/PluginManagerImpl.cpp create mode 100644 service/protocol-plugin/plugin-manager/src/PluginManagerImpl.h create mode 100644 service/protocol-plugin/plugins/SConscript create mode 100644 service/protocol-plugin/plugins/mqtt-fan/build/linux/Makefile create mode 100644 service/protocol-plugin/plugins/mqtt-fan/build/linux/plugin.xml create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/CMakeLists.txt create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/Makefile create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/SConscript create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/config.h create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/config.mk create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/cpp/CMakeLists.txt create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/cpp/Makefile create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/cpp/SConscript create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/cpp/mosquittopp.cpp create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/cpp/mosquittopp.h create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/cpp/test.txt create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/dummypthread.h create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/jsws/mosquitto.js create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/linker.version create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/logging_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/logging_mosq.h create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/memory_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/memory_mosq.h create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/messages_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/messages_mosq.h create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/mosquitto.c create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/mosquitto.h create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/mosquitto_internal.h create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/mqtt3_protocol.h create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/net_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/net_mosq.h create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/python/Makefile create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/python/mosquitto.py create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/python/setup.py create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/python/sub.py create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/read_handle.c create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/read_handle.h create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/read_handle_client.c create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/read_handle_shared.c create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/send_client_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/send_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/send_mosq.h create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/srv_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/thread_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/time_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/time_mosq.h create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/tls_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/tls_mosq.h create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/util_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/util_mosq.h create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/will_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-fan/lib/will_mosq.h create mode 100644 service/protocol-plugin/plugins/mqtt-fan/src/fanserver.cpp create mode 100644 service/protocol-plugin/plugins/mqtt-fan/src/fanserver.h create mode 100644 service/protocol-plugin/plugins/mqtt-fan/src/fanserver_mqtt_plugin.cpp create mode 100644 service/protocol-plugin/plugins/mqtt-fan/src/fanserver_mqtt_plugin.h create mode 100644 service/protocol-plugin/plugins/mqtt-light/build/linux/Makefile create mode 100644 service/protocol-plugin/plugins/mqtt-light/build/linux/plugin.xml create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/CMakeLists.txt create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/Makefile create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/config.h create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/config.mk create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/cpp/CMakeLists.txt create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/cpp/Makefile create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/cpp/mosquittopp.cpp create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/cpp/mosquittopp.h create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/cpp/test.txt create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/dummypthread.h create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/jsws/mosquitto.js create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/linker.version create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/logging_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/logging_mosq.h create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/memory_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/memory_mosq.h create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/messages_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/messages_mosq.h create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/mosquitto.c create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/mosquitto.h create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/mosquitto_internal.h create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/mqtt3_protocol.h create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/net_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/net_mosq.h create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/python/Makefile create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/python/mosquitto.py create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/python/setup.py create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/python/sub.py create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/read_handle.c create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/read_handle.h create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/read_handle_client.c create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/read_handle_shared.c create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/send_client_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/send_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/send_mosq.h create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/srv_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/thread_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/time_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/time_mosq.h create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/tls_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/tls_mosq.h create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/util_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/util_mosq.h create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/will_mosq.c create mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/will_mosq.h create mode 100644 service/protocol-plugin/plugins/mqtt-light/src/lightserver.cpp create mode 100644 service/protocol-plugin/plugins/mqtt-light/src/lightserver.h create mode 100644 service/protocol-plugin/plugins/mqtt-light/src/lightserver_mqtt_plugin.cpp create mode 100644 service/protocol-plugin/plugins/mqtt-light/src/lightserver_mqtt_plugin.h create mode 100644 service/protocol-plugin/readme create mode 100644 service/protocol-plugin/sample-app/SConscript create mode 100644 service/protocol-plugin/sample-app/linux/SConscript create mode 100644 service/protocol-plugin/sample-app/linux/mqtt/Makefile create mode 100644 service/protocol-plugin/sample-app/linux/mqtt/mqttclient.cpp create mode 100644 service/protocol-plugin/sample-app/linux/mqtt/pluginmanager.xml create mode 100644 service/soft-sensor-manager/Readme.txt create mode 100644 service/soft-sensor-manager/SConscript create mode 100644 service/soft-sensor-manager/SDK/cpp/build/linux/Makefile create mode 100644 service/soft-sensor-manager/SDK/cpp/include/SSMInterface.h create mode 100644 service/soft-sensor-manager/SDK/cpp/src/InprocSSMCore.cpp create mode 100644 service/soft-sensor-manager/SDK/java/org/iotivity/service/ssm/CoreController.java create mode 100644 service/soft-sensor-manager/SDK/java/org/iotivity/service/ssm/DataReader.java create mode 100644 service/soft-sensor-manager/SDK/java/org/iotivity/service/ssm/IQueryEngineEvent.java create mode 100644 service/soft-sensor-manager/SDK/java/org/iotivity/service/ssm/IReportReceiver.java create mode 100644 service/soft-sensor-manager/SDK/java/org/iotivity/service/ssm/ModelData.java create mode 100644 service/soft-sensor-manager/SDK/java/org/iotivity/service/ssm/QueryEngine.java create mode 100644 service/soft-sensor-manager/SDK/java/org/iotivity/service/ssm/SSMInterface.java create mode 100644 service/soft-sensor-manager/SSMCore/build/linux/Makefile create mode 100644 service/soft-sensor-manager/SSMCore/include/SSMInterface.h create mode 100644 service/soft-sensor-manager/SSMCore/src/Common/InternalInterface.h create mode 100644 service/soft-sensor-manager/SSMCore/src/Common/ObjectManager.h create mode 100644 service/soft-sensor-manager/SSMCore/src/Common/PlatformLayer.h create mode 100644 service/soft-sensor-manager/SSMCore/src/Common/ThreadManager.cpp create mode 100644 service/soft-sensor-manager/SSMCore/src/Common/ThreadManager.h create mode 100644 service/soft-sensor-manager/SSMCore/src/Common/rapidxml.hpp create mode 100644 service/soft-sensor-manager/SSMCore/src/Common/rapidxml_iterators.hpp create mode 100644 service/soft-sensor-manager/SSMCore/src/Common/rapidxml_print.hpp create mode 100644 service/soft-sensor-manager/SSMCore/src/Common/rapidxml_utils.hpp create mode 100644 service/soft-sensor-manager/SSMCore/src/Common/sqlite3.c create mode 100644 service/soft-sensor-manager/SSMCore/src/Common/sqlite3.h create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/CQLParser.cpp create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/CQLParser.h create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/ConditionedModel.cpp create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/ConditionedModel.h create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/ConditionedQuery.cpp create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/ConditionedQuery.h create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/ConditionedQueryResult.cpp create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/ConditionedQueryResult.h create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/ContextModel.cpp create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/ContextModel.h create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/ContextQuery.cpp create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/ContextQuery.h create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/DataReader.cpp create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/DataReader.h create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/EvaluationEngine.cpp create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/EvaluationEngine.h create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/ModelData.cpp create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/ModelData.h create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/PropagationEngine.cpp create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/PropagationEngine.h create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/QueryEngine.cpp create mode 100644 service/soft-sensor-manager/SSMCore/src/QueryProcessor/QueryEngine.h create mode 100644 service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMCore.cpp create mode 100644 service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMCore.h create mode 100644 service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMCore_JNI.cpp create mode 100644 service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMCore_JNI.h create mode 100644 service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMModelDefinition.h create mode 100644 service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMResourceServer.cpp create mode 100644 service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMResourceServer.h create mode 100644 service/soft-sensor-manager/SSMCore/src/SSMInterface/SoftSensorManager.cpp create mode 100644 service/soft-sensor-manager/SSMCore/src/SSMInterface/SoftSensorManager.h create mode 100644 service/soft-sensor-manager/SSMCore/src/SensorProcessor/ContextDataReader.cpp create mode 100644 service/soft-sensor-manager/SSMCore/src/SensorProcessor/ContextDataReader.h create mode 100644 service/soft-sensor-manager/SSMCore/src/SensorProcessor/ContextExecutor.cpp create mode 100644 service/soft-sensor-manager/SSMCore/src/SensorProcessor/ContextExecutor.h create mode 100644 service/soft-sensor-manager/SSMCore/src/SensorProcessor/ContextRepository.cpp create mode 100644 service/soft-sensor-manager/SSMCore/src/SensorProcessor/ContextRepository.h create mode 100644 service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResourceFinder.cpp create mode 100644 service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResourceFinder.h create mode 100644 service/soft-sensor-manager/SSMCore/src/SensorProcessor/SensingEngine.cpp create mode 100644 service/soft-sensor-manager/SSMCore/src/SensorProcessor/SensingEngine.h create mode 100644 service/soft-sensor-manager/SampleApp/SConscript create mode 100644 service/soft-sensor-manager/SampleApp/arduino/Makefile create mode 100644 service/soft-sensor-manager/SampleApp/arduino/Reference_Thing/build/makefile create mode 100644 service/soft-sensor-manager/SampleApp/arduino/Reference_Thing/include/bleLib.h create mode 100644 service/soft-sensor-manager/SampleApp/arduino/Reference_Thing/include/oic_lanLib.h create mode 100644 service/soft-sensor-manager/SampleApp/arduino/Reference_Thing/src/bleLib.cpp create mode 100644 service/soft-sensor-manager/SampleApp/arduino/Reference_Thing/src/oic_lanLib.cpp create mode 100644 service/soft-sensor-manager/SampleApp/arduino/Reference_Thing/src/readme.txt create mode 100644 service/soft-sensor-manager/SampleApp/arduino/Reference_Thing/src/reference.cpp create mode 100644 service/soft-sensor-manager/SampleApp/arduino/THSensorApp/build/makefile create mode 100644 service/soft-sensor-manager/SampleApp/arduino/THSensorApp/src/readme.txt create mode 100644 service/soft-sensor-manager/SampleApp/arduino/THSensorApp/src/thserver.cpp create mode 100644 service/soft-sensor-manager/SampleApp/arduino/Trackee_Thing/build/makefile create mode 100644 service/soft-sensor-manager/SampleApp/arduino/Trackee_Thing/include/bleLib.h create mode 100644 service/soft-sensor-manager/SampleApp/arduino/Trackee_Thing/include/oic_lanLib.h create mode 100644 service/soft-sensor-manager/SampleApp/arduino/Trackee_Thing/include/proximity.h create mode 100644 service/soft-sensor-manager/SampleApp/arduino/Trackee_Thing/include/trackee.h create mode 100644 service/soft-sensor-manager/SampleApp/arduino/Trackee_Thing/src/bleLib.cpp create mode 100644 service/soft-sensor-manager/SampleApp/arduino/Trackee_Thing/src/oic_lanLib.cpp create mode 100644 service/soft-sensor-manager/SampleApp/arduino/Trackee_Thing/src/proximity.cpp create mode 100644 service/soft-sensor-manager/SampleApp/arduino/Trackee_Thing/src/readme.txt create mode 100644 service/soft-sensor-manager/SampleApp/arduino/Trackee_Thing/src/trackee.cpp create mode 100644 service/soft-sensor-manager/SampleApp/arduino/environment.mk create mode 100644 service/soft-sensor-manager/SampleApp/arduino/local.properties create mode 100644 service/soft-sensor-manager/SampleApp/arduino/readme.txt create mode 100644 service/soft-sensor-manager/SampleApp/linux/Makefile create mode 100644 service/soft-sensor-manager/SampleApp/linux/SSMTesterApp/SConscript create mode 100644 service/soft-sensor-manager/SampleApp/linux/SSMTesterApp/build/Makefile create mode 100644 service/soft-sensor-manager/SampleApp/linux/SSMTesterApp/include/SSMTestApp.h create mode 100644 service/soft-sensor-manager/SampleApp/linux/SSMTesterApp/src/SSMTestApp.cpp create mode 100644 service/soft-sensor-manager/SampleApp/linux/THSensorApp/SConscript create mode 100644 service/soft-sensor-manager/SampleApp/linux/THSensorApp/build/Makefile create mode 100644 service/soft-sensor-manager/SampleApp/linux/THSensorApp/include/ThingResourceServer.h create mode 100644 service/soft-sensor-manager/SampleApp/linux/THSensorApp/src/ThingResourceServer.cpp create mode 100644 service/soft-sensor-manager/SampleApp/linux/THSensorApp1/SConscript create mode 100644 service/soft-sensor-manager/SampleApp/linux/THSensorApp1/build/Makefile create mode 100644 service/soft-sensor-manager/SampleApp/linux/THSensorApp1/include/ThingResourceServer1.h create mode 100644 service/soft-sensor-manager/SampleApp/linux/THSensorApp1/src/ThingResourceServer1.cpp create mode 100644 service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/CMakeLists.txt create mode 100644 service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/README create mode 100644 service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/RELEASE.txt create mode 100644 service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/makefile_org create mode 100644 service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/CMakeLists.txt create mode 100644 service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/com.samsung.ssmtester.rule create mode 100644 service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/com.samsung.ssmtester.xml create mode 100644 service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/src/oicapp-log.h create mode 100644 service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/src/oicapp-test.cpp create mode 100644 service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/src/oicapp-test.h create mode 100644 service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/src/oicapp-utils.c create mode 100644 service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/src/oicapp-utils.h create mode 100644 service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/packaging/ssm.manifest create mode 100644 service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/packaging/ssm.spec create mode 100644 service/soft-sensor-manager/SoftSensorPlugin/DiscomfortIndexSensor/build/linux/Makefile create mode 100644 service/soft-sensor-manager/SoftSensorPlugin/DiscomfortIndexSensor/include/DiscomfortIndexSensor.h create mode 100644 service/soft-sensor-manager/SoftSensorPlugin/DiscomfortIndexSensor/include/SysTimer.h create mode 100644 service/soft-sensor-manager/SoftSensorPlugin/DiscomfortIndexSensor/src/DiscomfortIndexSensor.cpp create mode 100644 service/soft-sensor-manager/SoftSensorPlugin/DiscomfortIndexSensor/src/SysTimer.cpp create mode 100644 service/soft-sensor-manager/SoftSensorPlugin/SoftSensorDescription.xml create mode 100644 service/soft-sensor-manager/build/arduino/Makefile create mode 100644 service/soft-sensor-manager/build/arduino/environment.mk create mode 100644 service/soft-sensor-manager/build/arduino/local.properties create mode 100644 service/soft-sensor-manager/build/arduino/readme.txt create mode 100644 service/soft-sensor-manager/build/linux/Makefile create mode 100644 service/soft-sensor-manager/build/linux/environment.mk create mode 100644 service/soft-sensor-manager/build/tizen/CMakeLists.txt create mode 100644 service/soft-sensor-manager/build/tizen/Makefile create mode 100644 service/soft-sensor-manager/build/tizen/SampleApp/CMakeLists.txt create mode 100644 service/soft-sensor-manager/build/tizen/SampleApp/ClientApp/CMakeLists.txt create mode 100644 service/soft-sensor-manager/build/tizen/SampleApp/THSensorApp/CMakeLists.txt create mode 100644 service/soft-sensor-manager/build/tizen/SampleApp/THSensorApp1/CMakeLists.txt create mode 100644 service/things-manager/.gitignore create mode 100755 service/things-manager/Readme.txt create mode 100644 service/things-manager/SConscript create mode 100644 service/things-manager/build/linux/makefile create mode 100644 service/things-manager/sampleapp/SConscript create mode 100644 service/things-manager/sampleapp/linux/configuration/ConfigurationCollection.cpp create mode 100644 service/things-manager/sampleapp/linux/configuration/ConfigurationCollection.h create mode 100644 service/things-manager/sampleapp/linux/configuration/DiagnosticsCollection.cpp create mode 100644 service/things-manager/sampleapp/linux/configuration/DiagnosticsCollection.h create mode 100644 service/things-manager/sampleapp/linux/configuration/FactorySetCollection.cpp create mode 100644 service/things-manager/sampleapp/linux/configuration/FactorySetCollection.h create mode 100644 service/things-manager/sampleapp/linux/configuration/SConscript create mode 100644 service/things-manager/sampleapp/linux/configuration/bootstrapserver.cpp create mode 100644 service/things-manager/sampleapp/linux/configuration/con-client.cpp create mode 100755 service/things-manager/sampleapp/linux/configuration/con-server.cpp create mode 100644 service/things-manager/sampleapp/linux/configuration/makefile create mode 100644 service/things-manager/sampleapp/linux/groupaction/SConscript create mode 100644 service/things-manager/sampleapp/linux/groupaction/bookmark.cpp create mode 100644 service/things-manager/sampleapp/linux/groupaction/groupserver.cpp create mode 100644 service/things-manager/sampleapp/linux/groupaction/lightserver.cpp create mode 100644 service/things-manager/sampleapp/linux/groupaction/makefile create mode 100644 service/things-manager/sampleapp/linux/groupsyncaction/SConscript create mode 100644 service/things-manager/sampleapp/linux/groupsyncaction/group.cpp create mode 100644 service/things-manager/sampleapp/linux/groupsyncaction/makefile create mode 100644 service/things-manager/sampleapp/linux/groupsyncaction/musicplayer.cpp create mode 100644 service/things-manager/sampleapp/linux/groupsyncaction/phone.cpp create mode 100644 service/things-manager/sampleapp/linux/groupsyncaction/speaker.cpp create mode 100644 service/things-manager/sampleapp/linux/makefile create mode 100644 service/things-manager/sdk/build/linux/Makefile create mode 100644 service/things-manager/sdk/inc/ThingsManager.h create mode 100644 service/things-manager/sdk/src/GroupManager.cpp create mode 100644 service/things-manager/sdk/src/GroupManager.h create mode 100644 service/things-manager/sdk/src/GroupSynchronization.cpp create mode 100644 service/things-manager/sdk/src/GroupSynchronization.h create mode 100755 service/things-manager/sdk/src/ThingsConfiguration.cpp create mode 100644 service/things-manager/sdk/src/ThingsConfiguration.h create mode 100644 service/things-manager/sdk/src/ThingsDiagnostics.cpp create mode 100644 service/things-manager/sdk/src/ThingsDiagnostics.h create mode 100644 service/things-manager/sdk/src/ThingsManager.cpp create mode 100644 service/third_party_libs.scons create mode 100644 tools/Readme.scons.txt create mode 100644 tools/SConstruct create mode 100644 tools/arduino.scons create mode 100644 tools/arduino/patches/arduino-1.0.5_linux.patch create mode 100644 tools/arduino/patches/arduino-1.5.7_linux.patch create mode 100755 tools/auto_build.sh create mode 100644 tools/extra_options.scons create mode 100644 tools/scons_script_how_to.txt create mode 100644 tools/tizen/iotivity.spec diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..04161afa4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,60 @@ +# Ignore output dirs +/release +resource/release +resource/csdk/release +resource/csdk/libcoap-4.1.1/release/ +resource/examples/release +resource/examples/debug + +/debug +resource/debug +resource/csdk/debug/ +resource/csdk/libcoap-4.1.1/debug/ +resource/csdk/libcoap-4.1.1/linux/ +resource/csdk/linux +resource/csdk/stack/samples/linux/SimpleClientServer/debug/ +resource/csdk/stack/samples/linux/SimpleClientServer/release/ + +resource/csdk/connectivity/build/out/ + +resource/oc_logger/bin/ +resource/oc_logger/lib/ +resource/oc_logger/samples/linux/release/ +resource/oc_logger/samples/linux/debug + +service/things-manager/build/linux/release +service/things-manager/build/linux/debug +service/things-manager/sdk/build/linux/ +# Ignore any object files +*.o +*.obj + + +# Ignore Eclipse workspace files +*.settings/ +*.cproject +*.project + +# Ignore dependencies folder, which should be generated +dependencies/ + +#ignore Klocwork stuff +.kwlp/ +.kwps/ + +#ignore various swap files +*.swp + +# Ignore SCons generated files and directories +.scon* +config.log +os +out/ +platform + +# Ignore downloaded dependencies +extlibs/gtest* +extlibs/cereal + +*~ +cscope.out diff --git a/Readme.scons.txt b/Readme.scons.txt new file mode 100644 index 000000000..2129efe8e --- /dev/null +++ b/Readme.scons.txt @@ -0,0 +1,191 @@ +== How to build IoTivity projects == + +IoTivity includes a series of projects. You can find all these projects here: + https://gerrit.iotivity.org/gerrit/#/admin/projects/ + +You can build IoTivity project on Linux / Windows / MAC OSX for various OS( +Linux, Tizen, Android, Arduino, Windows, MAC OSX, IOS ...). +The output of the build is in: + /out//// +e.g. + oic-resource/out/android/armeabi-v7a/release/. + +This document takes 'iotivity' project as example, the way to build other +projects is almost the same. + +=== IoTivity project build tool scons === + +Scons is a cross-platform build tool, its usage is quite similar to GNU make. +To build a project, you just require to run following command at the directory +where a SConstruct file exists(SConstruct is the entrance of scons build, it's +equivalent to Makefile of 'make') : + $ scons [options] [target] + +In additional, usually the scons build script of a project provides useful help +information(include build options). To see the help information: + $ scons [options] -h + +Note: If no value is specified for an option, the default value will be used. +The change of options value may impact the output. + + +=== Prerequites === + +* 1. Scons + +Please refer to the following page to install scons: + http://www.scons.org/doc/production/HTML/scons-user.html#chap-build-install +(Note: on Windows, install Python 2.x before installing scons) + +* 2. IDE/SDK Prerequites +To build for some OS (Android / Arduino / IOS ...), an IDE/SDK may be required, +please go to the relative page to download and install the required IDE/SDK. + +Android: +To build for Android, Andorid NDK and SDK are required. + Android NDK: http://developer.android.com/tools/sdk/ndk/index.html + Android SDK: http://developer.android.com/sdk/index.html +(Note: as in some IoTivity projects, C++11 features are used, recommend Android + NDK >= r10, according to our test result r10c is the best one currently) + +Arduino: +To build for Arduino, Arduino IDE is required. + Arduino IDE: http://arduino.cc/en/Main/Software + (Note: recommend install Arduino IDE >=1.5.7) + +Arduino builds are dependent on latest Time library. Download it from here: + http://www.pjrc.com/teensy/td_libs_Time.html +and extract to /libraries/ + +(Note: If you are using Arduino IDE 1.5.8 BETA on Windows, it may pop up some +dll isn't found. please copy relative dll from the IDE directory to +C:\Windows\SysWOW64. IDE 1.5.7 doesn't have this issue. Other version IDE isn't +tested.) + +Apple: +To build for Mac OSX or IOS, Xcode is required. + Xcode: https://developer.apple.com/xcode/downloads/ + +Java: +To build the Java code, JDK is required. + JDK: http://www.oracle.com/technetwork/java/javase/downloads/index.html +(If the project doesn't include Java code or you wouldn't like build the +Java codes, this isn't required) + +(Note: for convenience, suggest add the IDE/SDK path in environment variable, +so you don't need to add it in command line each time. The build script will +guide you to do that.) + +* 3. External libraries +For Android and IOS build, most of the external libraries are provided as +binary in oic-utilities project (https://oic-review.01.org/gerrit/oic-utilities). +Please download it in the same directory as other IoTivity projects. If it's +in different directory, an additional option (OIC_UITLS) will be required. The +build command should be: + $ scons OIC_UITLS= [other options] [target] + +(Note: for convenience, you can also add it in environment variable. So you +don't need to add this option in command line each time.) + e.g.: + $ export OIC_UITLS= + + +=== Build IoTivity project on Linux(Ubuntu) === + +Generally, it's required to specify the target OS and target ARCH, that's to say +tell Scons which OS and which ARCH you'd like build this project for. By default, +the target OS and ARCH is the same as the host. + +Some more options may be required, please care the 'error' notification when build. +For help about how to set an option, please run: + $ scons TARGET_OS=xxx TARGET_ARCH=yyy [XXX=zzz ...] -h + +1. Build IoTivity project for Linux + $ cd + $ sudo apt-get install libboost-dev libboost-program-options-dev libexpat1-dev + $ scons + +2. Build IoTivity project for Android + $ cd + $ scons TARGET_OS=android TARGET_ARCH=xxx +(xxx can be x86, armeabi, armeabi-v7a, armeabi-v7a-hard. To see all of its +allowed value, please execute command 'scons TARGET_OS=android -Q -h') + +Note: Currently as x86_64/arm64_v8a external library binaries aren't provided, +you may meet link problem if build executable binary which depends on external +library for x86_64/arm64_v8a. + +3. Build IoTivity project for Arduino + $ cd + $ scons TARGET_OS=arduino TARGET_ARCH=xxx BOARD=yyy +(xxx can be avr, arm; yyy is the name of the board, to get its allowed value +run: scons TARGET_OS=arduino TARGET_ARCH=xxx -h. You may see a option 'CPU' in +the output of above command line, that's due to some boards have different +processors, to specify the processor, add 'CPU=zzz' in the command line. If no +'CPU' option exists, that means the board only support one kind of processor, +it's unnecessary to specify it) + +4. Build Iotivity project for Tizen + $ cd + $ gbs build -A xxx --packaging-dir tools/tizen/ +(xxx can be i586 or armv7l, we provide the spec file required by gbs tool at +toools/tizen directory. gbs is default build tool for Tizen platfrom, we can +refer the following wiki to setup Tizen development environment: +https://source.tizen.org/documentation/developer-guide/getting-started-guide) + +=== Build IoTivity project on Windows === + +1. Build IoTivity project for Android(It's the same as on Ubuntu) + $ cd + $ scons TARGET_OS=android TARGET_ARCH=xxx +(xxx can be x86, armeabi, armeabi-v7a, armeabi-v7a-hard ...) + +2. Build IoTivity project for Arduino(It's the same as on Ubuntu) + $ cd + $ scons TARGET_OS=arduino TARGET_ARCH=xxx BOARD=yyy +(xxx can be avr, arm; yyy is the name of the board, to get its allowed value +run: scons TARGET_OS=arduino TARGET_ARCH=xxx -h. You may see a option 'CPU' in +the output of above command line, that's due to some boards have different +processor, to specify the processor, add 'CPU=zzz' in the command line. If no +'CPU' option exists, that means the board only support one kind of processor, +it's unnecessary to specify it) + + +Note: Currently most IoTivity project doesn't support Windows, so you can't set +TARGET_OS to 'windows' except the project support Windows. + +That's to say if the project doesn't support Windows, run: + $ scons TARGET_OS=windows .... +or run on Windows + $ scons +may always fail. + + +=== Build IoTivity project on Mac OSX === + +1. Build IoTivity project for Mac OSX + $ cd + $ scons SYS_VERSION=yyy +(yyy is the OSX version, e.g. 10.9) + +2. Build IoTivity project for Android(It's the same as on Ubuntu) + $ cd + $ scons TARGET_OS=android TARGET_ARCH=xxx +(xxx can be x86, armeabi, armeabi-v7a, armeabi-v7a-hard) + +3. Build IoTivity project for IOS + $ cd + $ scons TARGET_OS=ios TARGET_ARCH=xxx SYS_VERSION=yyy +(xxx can be i386, x86_64, armv7, armv7s, arm64, yyy is IOS version, e.g. 7.0) + +Note: +1) for convenience, a script (auto_build.sh) is provided to run possible build +at once. Following is the usage: + +To build: + $ auto_build.sh +To clean: + $ auto_build.sh -c + +2) For Arduino build, the Time library should >=1.3. The old can only be built +with Arduino IDE 1.0.x diff --git a/SConstruct b/SConstruct new file mode 100644 index 000000000..92eac3822 --- /dev/null +++ b/SConstruct @@ -0,0 +1,39 @@ +## +# The main build script +# +## + +# Load common build config +SConscript('build_common/SConscript') + +# Load extra options +SConscript('extra_options.scons') +Import('env') + +target_os = env.get('TARGET_OS') +if target_os == 'arduino': + SConscript('arduino.scons') +# By default, src_dir is current dir, the build_dir is: +# ./out//// +# +# The build_dir is a variant directory of the source directory(You can +# consider build_dir as a soft link to src_dir, for detail please refer to: +# http://www.scons.org/doc/production/HTML/scons-user.html#f-VariantDir +# +# Any way, to make the output is in build_dir, when load scripts, the path should +# be relevant to build_dir. +build_dir = env.get('BUILD_DIR') + +# Build 'resource' sub-project +SConscript(build_dir + 'resource/SConscript') + +# Build 'service' sub-project +SConscript(build_dir + 'service/SConscript') + +# Append targets information to the help information, to see help info, execute command line: +# $ scon [options] -h +env.PrintTargets() + +# Print bin upload command line (arduino only) +if target_os == 'arduino': + env.UploadHelp() diff --git a/android/Base/app/build.gradle b/android/Base/app/build.gradle new file mode 100644 index 000000000..31d66bb60 --- /dev/null +++ b/android/Base/app/build.gradle @@ -0,0 +1,60 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion 19 + buildToolsVersion "19.1.0" + + defaultConfig { + applicationId "org.iotivity.base" + minSdkVersion 19 + targetSdkVersion 19 + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + runProguard false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) +} + + +////////////// +// NDK Support +////////////// +// If using this, Android studio will fail run the following to set the environment variable for android studio: +// launchctl setenv ANDROID_NDK_HOME /Users/boos_patrick/Development/Android/android-ndk-r8e +// otherwise remove the dependsOn part and run ./gradlew buildNative from the command line +task copyNativeLibs(type: Copy, dependsOn: 'buildNative') { + dependsOn 'buildNative' + from(new File('libs')) { include '**/*.so' } + into new File(buildDir, 'native-libs') +} + +tasks.withType(Compile) { compileTask -> compileTask.dependsOn copyNativeLibs } + +clean.dependsOn 'cleanCopyNativeLibs' + +tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask -> + pkgTask.jniFolders = new HashSet() + pkgTask.jniFolders.add(new File(buildDir, 'native-libs')) +} + +task buildNative(type: Exec) { + if (System.env.ANDROID_NDK_HOME != null) { + def ndkBuild = new File(System.env.ANDROID_NDK_HOME, 'ndk-build') + commandLine ndkBuild + } else { + doLast { + println '##################' + println 'Skipping NDK build' + println 'Reason: ANDROID_NDK_HOME not set.' + println '##################' + } + } +} diff --git a/android/Base/app/jni/Android.mk b/android/Base/app/jni/Android.mk new file mode 100644 index 000000000..58e9a36ef --- /dev/null +++ b/android/Base/app/jni/Android.mk @@ -0,0 +1,57 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +OIC_LIB_PATH := ../../../../out/android/$(TARGET_ARCH_ABI)/release +LOCAL_MODULE := libandroid-oc_logger +LOCAL_SRC_FILES := $(OIC_LIB_PATH)/liboc_logger.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +OIC_LIB_PATH := ../../../../out/android/$(TARGET_ARCH_ABI)/release +LOCAL_MODULE := libandroid-octbstack +LOCAL_SRC_FILES := $(OIC_LIB_PATH)/liboctbstack.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +OIC_LIB_PATH := ../../../../out/android/$(TARGET_ARCH_ABI)/release +LOCAL_MODULE := libandroid-oc +LOCAL_SRC_FILES := $(OIC_LIB_PATH)/liboc.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +OIC_LIB_PATH := ../../../../out/android/$(TARGET_ARCH_ABI)/release +LOCAL_MODULE := libandroid-coap +LOCAL_SRC_FILES := $(OIC_LIB_PATH)/libcoap.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +OIC_LIB_PATH := ../../../../out/android/$(TARGET_ARCH_ABI)/release +LOCAL_MODULE := libandroid-compatibility +LOCAL_SRC_FILES := $(OIC_LIB_PATH)/libcompatibility.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +OIC_SRC_PATH := ../../../resource +OIC_OUT_PATH := ../../../out +LOCAL_MODULE := ocstack-jni +LOCAL_SRC_FILES := ocstack-jni.cpp \ + ocheaderoption-jni.cpp \ + ocrepresentation-jni.cpp \ + ocresource-jni.cpp \ + ocplatform-jni.cpp \ + platformcfg-jni.cpp +LOCAL_LDLIBS := -llog +LOCAL_STATIC_LIBRARIES := android-oc +LOCAL_STATIC_LIBRARIES += android-octbstack +LOCAL_STATIC_LIBRARIES += android-coap +LOCAL_STATIC_LIBRARIES += android-oc_logger +LOCAL_STATIC_LIBRARIES += libandroid-compatibility +LOCAL_CPPFLAGS += -std=c++0x -frtti -fexceptions +LOCAL_C_INCLUDES := $(OIC_SRC_PATH)/include +LOCAL_C_INCLUDES += $(OIC_SRC_PATH)/csdk/stack/include +LOCAL_C_INCLUDES += $(OIC_SRC_PATH)/csdk/ocsocket/include +LOCAL_C_INCLUDES += $(OIC_SRC_PATH)/oc_logger/include +LOCAL_C_INCLUDES += $(OIC_OUT_PATH)/android/include +LOCAL_C_INCLUDES += $(OIC_SRC_PATH)/dependencies/cereal/include +include $(BUILD_SHARED_LIBRARY) + diff --git a/android/Base/app/jni/Application.mk b/android/Base/app/jni/Application.mk new file mode 100644 index 000000000..4450fdf45 --- /dev/null +++ b/android/Base/app/jni/Application.mk @@ -0,0 +1,2 @@ +NDK_TOOLCHAIN_VERSION := 4.9 +APP_STL := gnustl_static diff --git a/android/Base/app/jni/ocheaderoption-jni.cpp b/android/Base/app/jni/ocheaderoption-jni.cpp new file mode 100644 index 000000000..7dcd320c0 --- /dev/null +++ b/android/Base/app/jni/ocheaderoption-jni.cpp @@ -0,0 +1,44 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "ocstack-jni.h" + +static const char* TAG = "OCHEADEROPTION-JNI"; + +JNIEXPORT jint JNICALL getOptionID(JNIEnv *env, jobject jobj) +{ + OC::HeaderOption::OCHeaderOption *option = getHandle(env, jobj); + return option->getOptionID(); +} + +JNIEXPORT jstring JNICALL getOptionData(JNIEnv *env, jobject jobj) +{ + OC::HeaderOption::OCHeaderOption *option = getHandle(env, jobj); + std::string data = option->getOptionData(); + return env->NewStringUTF(data.c_str()); +} + +JNIEXPORT jlong JNICALL OCHeaderOptionConstructor(JNIEnv *env, jobject jobj, jint joption, jstring jdata) +{ + OC::HeaderOption::OCHeaderOption *option = new OC::HeaderOption::OCHeaderOption(joption, env->GetStringUTFChars(jdata, 0)); + jlong instptr = reinterpret_cast(option); + return instptr; +} + diff --git a/android/Base/app/jni/ocplatform-jni.cpp b/android/Base/app/jni/ocplatform-jni.cpp new file mode 100644 index 000000000..a69ac2db2 --- /dev/null +++ b/android/Base/app/jni/ocplatform-jni.cpp @@ -0,0 +1,124 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "ocstack-jni.h" + +static const char* TAG = "OCPLATFORM-JNI"; + +JNIEXPORT void JNICALL configure(JNIEnv *env, jobject obj, jobject jcfg) +{ + OC::PlatformConfig *cfg = getHandle(env, jcfg); + + __android_log_print(ANDROID_LOG_INFO, TAG, "service : %d\n", (int) cfg->serviceType); + __android_log_print(ANDROID_LOG_INFO, TAG, "mode : %d\n", (int) cfg->mode); + __android_log_print(ANDROID_LOG_INFO, TAG, "IP : %s\n", (cfg->ipAddress).c_str()); + __android_log_print(ANDROID_LOG_INFO, TAG, "port : %d\n", cfg->port); + __android_log_print(ANDROID_LOG_INFO, TAG, "QOS : %d\n", (int) cfg->QoS); + + OC::OCPlatform::Configure(*cfg); +} + + +JNIEXPORT jint JNICALL findResource(JNIEnv* env, jobject obj, jstring jhost, jstring juri, jobject found) +{ + string host = env->GetStringUTFChars(jhost,0); + string uri = env->GetStringUTFChars(juri,0); + + JNICallBackContext *callbackContext; + string key = uri + "/FIND"; + std:map::iterator iter = gJNICallBackContextList.find(key); + if(iter == gJNICallBackContextList.end()) { + gJNICallBackContextList[key] = new JNICallBackContext(env->NewGlobalRef(found)); + callbackContext = gJNICallBackContextList[key]; + __android_log_print(ANDROID_LOG_INFO, TAG, "Adding %s to gJNICallBackContextList", key.c_str()); + } + else + callbackContext = iter->second; + + __android_log_print(ANDROID_LOG_ERROR, TAG, "Calling oic base findresource()\n"); + try { + OC::OCPlatform::findResource(host, uri, + [callbackContext](std::shared_ptr resource) + { + JNIEnv * env; + + // Attach to JavaVM + // double check it's all ok + int getEnvStat = g_JavaVM->GetEnv((void **)&env, JNI_VERSION_1_6); + if (getEnvStat == JNI_EDETACHED) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "GetEnv: not attached"); + if (g_JavaVM->AttachCurrentThread(&env, NULL) != 0) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "Failed to attach"); + } + else + __android_log_print(ANDROID_LOG_INFO, TAG, "Attached OK"); + } else if (getEnvStat == JNI_OK) { + // + } else if (getEnvStat == JNI_EVERSION) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "GetEnv: version not supported"); + } + + // save the C++ resource ptr now + jmethodID resource_constructor = env->GetMethodID(g_ocresource_clazz, "", "(J)V"); + + callbackContext->m_resource = resource; + jobject jresource = env->NewObject(g_ocresource_clazz, resource_constructor, \ + (jlong) reinterpret_cast(&callbackContext->m_resource)); + + if(jresource == NULL) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "cannot create OCResource class"); + return; + } + + jclass clazz = env->GetObjectClass(callbackContext->m_callBackFunction); + if (clazz == NULL) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "Failed to find class"); + } + + // Find Callback function + jmethodID mid = env->GetMethodID(clazz, "Callback", \ + "(Lorg/iotivity/base/OCResource;)V"); + if(mid == NULL) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "FoundResource.Callback() is not defined in JAVA"); + return; + } + + __android_log_print(ANDROID_LOG_INFO, TAG, "calling JAVA FindCallback"); + try { + env->CallVoidMethod(callbackContext->m_callBackFunction, mid, jresource); + } catch(OC::OCException& e) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "callbackContext() exception : %s", e.reason(e).c_str()); + } + + __android_log_print(ANDROID_LOG_INFO, TAG, "fineResourceCB detach"); + env->DeleteLocalRef(jresource); + g_JavaVM->DetachCurrentThread(); + + } + ); + } + catch(OC::OCException& e) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "FindCB() exception : %s", e.reason(e).c_str()); + } + __android_log_print(ANDROID_LOG_ERROR, TAG, "Called oic base findresource()\n"); + + return 0; +} + diff --git a/android/Base/app/jni/ocrepresentation-jni.cpp b/android/Base/app/jni/ocrepresentation-jni.cpp new file mode 100644 index 000000000..d7c894db4 --- /dev/null +++ b/android/Base/app/jni/ocrepresentation-jni.cpp @@ -0,0 +1,101 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "ocstack-jni.h" + +static const char* TAG = "OCREPRESENTATION-JNI"; + +JNIEXPORT jlong JNICALL OCRepresentationConstructor(JNIEnv *env, jobject jobj) +{ + OC::OCRepresentation *rep = new OC::OCRepresentation(); + jlong instptr = reinterpret_cast(rep); + return instptr; +} + +JNIEXPORT jstring JNICALL getUri(JNIEnv *env, jobject jobj) +{ + OC::OCRepresentation *rep = getHandle(env, jobj); + string uri = rep->getUri(); + __android_log_print(ANDROID_LOG_INFO, TAG, "getUri() URI : %s", uri.c_str()); + return env->NewStringUTF(uri.c_str()); +} + +JNIEXPORT jint JNICALL getValueInt(JNIEnv *env, jobject jobj, jstring jstr) +{ + OC::OCRepresentation *rep = getHandle(env, jobj); + string str = env->GetStringUTFChars(jstr,0); + int val; + rep->getValue(str, val); + __android_log_print(ANDROID_LOG_INFO, TAG, "getValueInt() : %d", val); + return((jint) val); +} + + +JNIEXPORT jboolean JNICALL getValueBool(JNIEnv *env, jobject jobj, jstring jstr) +{ + OC::OCRepresentation *rep = getHandle(env, jobj); + string str = env->GetStringUTFChars(jstr,0); + bool val; + rep->getValue(str, val); + __android_log_print(ANDROID_LOG_INFO, TAG, "getValueBool() : %d", val); + return((jboolean) val); +} + +JNIEXPORT jstring JNICALL getValueString(JNIEnv *env, jobject jobj, jstring jstr) +{ + OC::OCRepresentation *rep = getHandle(env, jobj); + string str = env->GetStringUTFChars(jstr,0); + string get_val; + rep->getValue(str, get_val); + + __android_log_print(ANDROID_LOG_INFO, TAG, "getValueString() : %s", get_val.c_str()); + return env->NewStringUTF(get_val.c_str()); +} + +JNIEXPORT void JNICALL setValueInt(JNIEnv *env, jobject jobj, jstring jstr, jint jval) +{ + OC::OCRepresentation *rep = getHandle(env, jobj); + string str = env->GetStringUTFChars(jstr,0); + rep->setValue(str, jval); +} + +JNIEXPORT void JNICALL setValueBool(JNIEnv *env, jobject jobj, jstring jstr, jboolean jval) +{ + OC::OCRepresentation *rep = getHandle(env, jobj); + string str = env->GetStringUTFChars(jstr,0); + rep->setValue(str, (bool) jval); +} + +JNIEXPORT void JNICALL setValueString(JNIEnv *env, jobject jobj, jstring jstr, jstring jval) +{ + OC::OCRepresentation *rep = getHandle(env, jobj); + string str = env->GetStringUTFChars(jstr,0); + string val = env->GetStringUTFChars(jval,0); + + rep->setValue(str, val); +} + +JNIEXPORT jboolean JNICALL hasAttribute(JNIEnv *env, jobject jobj, jstring jstr) +{ + OC::OCRepresentation *rep = getHandle(env, jobj); + string str = env->GetStringUTFChars(jstr,0); + + return rep->hasAttribute(str); +} diff --git a/android/Base/app/jni/ocresource-jni.cpp b/android/Base/app/jni/ocresource-jni.cpp new file mode 100644 index 000000000..95c2c3927 --- /dev/null +++ b/android/Base/app/jni/ocresource-jni.cpp @@ -0,0 +1,445 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "ocstack-jni.h" + +static const char* TAG = "OCRESOURCE-JNI"; + +JNIEXPORT jobject JNICALL jniOicGet(JNIEnv *env, jobject jobj, jobject jattributeHandler) +{ + + std::shared_ptr *resource = getHandle>(env, jobj); + __android_log_print(ANDROID_LOG_ERROR, TAG, "get() resource = %p\n", resource); + + JNICallBackContext *callbackContext; + string key = (*resource)->uri() + "/GET"; + std:map::iterator iter = gJNICallBackContextList.find(key); + if(iter == gJNICallBackContextList.end()) { + gJNICallBackContextList[key] = new JNICallBackContext(*resource, env->NewGlobalRef(jattributeHandler)); + callbackContext = gJNICallBackContextList[key]; + __android_log_print(ANDROID_LOG_INFO, TAG, "Adding %s to gJNICallBackContextList", key.c_str()); + } + else { + iter->second->m_callBackFunction = env->NewGlobalRef(jattributeHandler); + callbackContext = iter->second; + } + + OC::QueryParamsMap test; + __android_log_print(ANDROID_LOG_ERROR, TAG, "calling oic base get()\n"); + + (*resource)->get(test, + [callbackContext](const OC::HeaderOptions& headerOptions, const OC::OCRepresentation& rep, const int eCode) + { + JNIEnv * env; + + // Attach to JavaVM + // double check it's all ok + int getEnvStat = g_JavaVM->GetEnv((void **)&env, JNI_VERSION_1_6); + if (getEnvStat == JNI_EDETACHED) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "GetEnv: not attached"); + if (g_JavaVM->AttachCurrentThread(&env, NULL) != 0) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "Failed to attach"); + } + else + __android_log_print(ANDROID_LOG_INFO, TAG, "Attached OK"); + } else if (getEnvStat == JNI_OK) { + // + } else if (getEnvStat == JNI_EVERSION) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "GetEnv: version not supported"); + } + + // save C++ ocheaderoption ptr now + jmethodID option_constructor = env->GetMethodID(g_ocheaderoption_clazz, "", "(J)V"); + int size = headerOptions.size(); + jobjectArray joptions = env->NewObjectArray(size, g_ocheaderoption_clazz, 0); + for (int n=0; nNewObject(g_ocheaderoption_clazz, option_constructor, \ + (jlong) reinterpret_cast(&headerOptions[n])); + + __android_log_print(ANDROID_LOG_ERROR, TAG, "jelem : %llu", (jlong) reinterpret_cast(&headerOptions[n])); + + env->SetObjectArrayElement(joptions, n, jelem); + env->DeleteLocalRef(jelem); + } + + // save C++ ocrepresentation ptr now + jmethodID representation_constructor = env->GetMethodID(g_ocrepresentation_clazz, "", "(J)V"); + jobject jrepresentation = env->NewObject(g_ocrepresentation_clazz, representation_constructor, \ + (jlong) reinterpret_cast(&rep)); + if(jrepresentation == NULL) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "cannot create OCRepresentation class"); + return; + } + + jclass cb_clazz = env->GetObjectClass(callbackContext->m_callBackFunction); + if (cb_clazz == NULL) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "Failed to find class"); + } + + // Find Callback function + jmethodID cb_mid = env->GetMethodID(cb_clazz, "Callback", \ + "([Lorg/iotivity/base/OCHeaderOption;Lorg/iotivity/base/OCRepresentation;I)V"); + if(cb_mid == NULL) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "onGet.Callback() is not defined in JAVA"); + return; + } + + __android_log_print(ANDROID_LOG_INFO, TAG, "calling JAVA GetCallback"); + env->CallVoidMethod(callbackContext->m_callBackFunction, cb_mid, joptions, jrepresentation, eCode); + + __android_log_print(ANDROID_LOG_INFO, TAG, "getCB detach"); + g_JavaVM->DetachCurrentThread(); + + } + ); + return NULL; + +} + +JNIEXPORT jobject JNICALL jniOicPut(JNIEnv *env, jobject jobj, jobject jocrepresentation, jobject jattributeHandler) +{ + std::shared_ptr *resource = getHandle>(env, jobj); + __android_log_print(ANDROID_LOG_ERROR, TAG, "put1() resource = %p\n", resource); + + JNICallBackContext *callbackContext; + string key = (*resource)->uri() + "/PUT"; + std:map::iterator iter = gJNICallBackContextList.find(key); + if(iter == gJNICallBackContextList.end()) { + gJNICallBackContextList[key] = new JNICallBackContext(*resource, env->NewGlobalRef(jattributeHandler)); + callbackContext = gJNICallBackContextList[key]; + __android_log_print(ANDROID_LOG_INFO, TAG, "Adding %s to gJNICallBackContextList", key.c_str()); + } + else { + iter->second->m_callBackFunction = env->NewGlobalRef(jattributeHandler); + callbackContext = iter->second; + } + + OC::OCRepresentation *rep = getHandle(env, jocrepresentation); + OC::QueryParamsMap test; + __android_log_print(ANDROID_LOG_ERROR, TAG, "calling oic base put()\n"); + + (*resource)->put(*rep, test, + [callbackContext](const OC::HeaderOptions& headerOptions, const OC::OCRepresentation& rep, const int eCode) + { + JNIEnv * env; + + // Attach to JavaVM + // double check it's all ok + int getEnvStat = g_JavaVM->GetEnv((void **)&env, JNI_VERSION_1_6); + if (getEnvStat == JNI_EDETACHED) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "GetEnv: not attached"); + if (g_JavaVM->AttachCurrentThread(&env, NULL) != 0) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "Failed to attach"); + } + else + __android_log_print(ANDROID_LOG_INFO, TAG, "Attached OK"); + } else if (getEnvStat == JNI_OK) { + // + } else if (getEnvStat == JNI_EVERSION) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "GetEnv: version not supported"); + } + + // save C++ ocheaderoption ptr now + jmethodID option_constructor = env->GetMethodID(g_ocheaderoption_clazz, "", "(J)V"); + int size = headerOptions.size(); + jobjectArray joptions = env->NewObjectArray(size, g_ocheaderoption_clazz, 0); + for (int n=0; nNewObject(g_ocheaderoption_clazz, option_constructor, \ + (jlong) reinterpret_cast(&headerOptions[n])); + + __android_log_print(ANDROID_LOG_ERROR, TAG, "jelem : %llu", (jlong) reinterpret_cast(&headerOptions[n])); + + env->SetObjectArrayElement(joptions, n, jelem); + env->DeleteLocalRef(jelem); + } + + // save C++ ocrepresentation ptr now + jmethodID representation_constructor = env->GetMethodID(g_ocrepresentation_clazz, "", "(J)V"); + jobject jrepresentation = env->NewObject(g_ocrepresentation_clazz, representation_constructor, \ + (jlong) reinterpret_cast(&rep)); + if(jrepresentation == NULL) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "cannot create OCRepresentation class"); + return; + } + + jclass cb_clazz = env->GetObjectClass(callbackContext->m_callBackFunction); + if (cb_clazz == NULL) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "Failed to find class"); + } + + // Find Callback function + jmethodID cb_mid = env->GetMethodID(cb_clazz, "Callback", \ + "([Lorg/iotivity/base/OCHeaderOption;Lorg/iotivity/base/OCRepresentation;I)V"); + if(cb_mid == NULL) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "onPut.Callback() is not defined in JAVA"); + return; + } + + __android_log_print(ANDROID_LOG_INFO, TAG, "calling JAVA PutCallback"); + env->CallVoidMethod(callbackContext->m_callBackFunction, cb_mid, joptions, jrepresentation, eCode); + + __android_log_print(ANDROID_LOG_INFO, TAG, "putCB detach"); + g_JavaVM->DetachCurrentThread(); + } + ); + return NULL; +} + +JNIEXPORT jobject JNICALL jniOicPost(JNIEnv *env, jobject jobj, jobject jocrepresentation, jobject jattributeHandler) +{ + std::shared_ptr *resource = getHandle>(env, jobj); + __android_log_print(ANDROID_LOG_ERROR, TAG, "post1() resource = %p\n", resource); + + JNICallBackContext *callbackContext; + string key = (*resource)->uri() + "/POST"; + std:map::iterator iter = gJNICallBackContextList.find(key); + if(iter == gJNICallBackContextList.end()) { + gJNICallBackContextList[key] = new JNICallBackContext(*resource, env->NewGlobalRef(jattributeHandler)); + callbackContext = gJNICallBackContextList[key]; + __android_log_print(ANDROID_LOG_INFO, TAG, "Adding %s to gJNICallBackContextList", key.c_str()); + } + else { + iter->second->m_callBackFunction = env->NewGlobalRef(jattributeHandler); + callbackContext = iter->second; + } + + OC::OCRepresentation *rep = getHandle(env, jocrepresentation); + OC::QueryParamsMap test; + __android_log_print(ANDROID_LOG_ERROR, TAG, "calling oic base post()\n"); + + (*resource)->post(*rep, test, + [callbackContext](const OC::HeaderOptions& headerOptions, const OC::OCRepresentation& rep, const int eCode) + { + JNIEnv * env; + + // Attach to JavaVM + // double check it's all ok + int getEnvStat = g_JavaVM->GetEnv((void **)&env, JNI_VERSION_1_6); + if (getEnvStat == JNI_EDETACHED) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "GetEnv: not attached"); + if (g_JavaVM->AttachCurrentThread(&env, NULL) != 0) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "Failed to attach"); + } + else + __android_log_print(ANDROID_LOG_INFO, TAG, "Attached OK"); + } else if (getEnvStat == JNI_OK) { + // + } else if (getEnvStat == JNI_EVERSION) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "GetEnv: version not supported"); + } + + // save C++ ocheaderoption ptr now + jmethodID option_constructor = env->GetMethodID(g_ocheaderoption_clazz, "", "(J)V"); + int size = headerOptions.size(); + jobjectArray joptions = env->NewObjectArray(size, g_ocheaderoption_clazz, 0); + for (int n=0; nNewObject(g_ocheaderoption_clazz, option_constructor, \ + (jlong) reinterpret_cast(&headerOptions[n])); + + __android_log_print(ANDROID_LOG_ERROR, TAG, "jelem : %llu", (jlong) reinterpret_cast(&headerOptions[n])); + + env->SetObjectArrayElement(joptions, n, jelem); + env->DeleteLocalRef(jelem); + } + + // save C++ ocrepresentation ptr now + jmethodID representation_constructor = env->GetMethodID(g_ocrepresentation_clazz, "", "(J)V"); + jobject jrepresentation = env->NewObject(g_ocrepresentation_clazz, representation_constructor, \ + (jlong) reinterpret_cast(&rep)); + if(jrepresentation == NULL) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "cannot create OCRepresentation class"); + return; + } + + jclass cb_clazz = env->GetObjectClass(callbackContext->m_callBackFunction); + if (cb_clazz == NULL) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "Failed to find class"); + } + + // Find Callback function + jmethodID cb_mid = env->GetMethodID(cb_clazz, "Callback", \ + "([Lorg/iotivity/base/OCHeaderOption;Lorg/iotivity/base/OCRepresentation;I)V"); + if(cb_mid == NULL) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "onPost.Callback() is not defined in JAVA"); + return; + } + + __android_log_print(ANDROID_LOG_INFO, TAG, "calling JAVA PostCallback"); + env->CallVoidMethod(callbackContext->m_callBackFunction, cb_mid, joptions, jrepresentation, eCode); + + __android_log_print(ANDROID_LOG_INFO, TAG, "postCB detach"); + g_JavaVM->DetachCurrentThread(); + + } + ); + return NULL; +} + +JNIEXPORT jobject JNICALL jniOicObserve(JNIEnv *env, jobject jobj, jint jobservetype, jobject jattributeHandler) +{ + std::shared_ptr *resource = getHandle>(env, jobj); + __android_log_print(ANDROID_LOG_ERROR, TAG, "observe1() resource = %p\n", resource); + + JNICallBackContext *callbackContext; + string key = (*resource)->uri() + "/OBSERVE"; + std:map::iterator iter = gJNICallBackContextList.find(key); + if(iter == gJNICallBackContextList.end()) { + gJNICallBackContextList[key] = new JNICallBackContext(*resource, env->NewGlobalRef(jattributeHandler)); + callbackContext = gJNICallBackContextList[key]; + __android_log_print(ANDROID_LOG_INFO, TAG, "Adding %s to gJNICallBackContextList", key.c_str()); + } + else { + iter->second->m_callBackFunction = env->NewGlobalRef(jattributeHandler); + callbackContext = iter->second; + } + + OC::QueryParamsMap test; + __android_log_print(ANDROID_LOG_ERROR, TAG, "calling oic base observe()\n"); + + (*resource)->observe((OC::ObserveType) jobservetype, test, + [callbackContext](const OC::HeaderOptions& headerOptions, const OC::OCRepresentation& rep, const int eCode, const int seqNum) + { + JNIEnv * env; + + // Attach to JavaVM + // double check it's all ok + int getEnvStat = g_JavaVM->GetEnv((void **)&env, JNI_VERSION_1_6); + if (getEnvStat == JNI_EDETACHED) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "GetEnv: not attached"); + if (g_JavaVM->AttachCurrentThread(&env, NULL) != 0) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "Failed to attach"); + } + else + __android_log_print(ANDROID_LOG_INFO, TAG, "Attached OK"); + } else if (getEnvStat == JNI_OK) { + // + } else if (getEnvStat == JNI_EVERSION) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "GetEnv: version not supported"); + } + + // save C++ ocheaderoption ptr now + jmethodID option_constructor = env->GetMethodID(g_ocheaderoption_clazz, "", "(J)V"); + int size = headerOptions.size(); + jobjectArray joptions = env->NewObjectArray(size, g_ocheaderoption_clazz, 0); + for (int n=0; nNewObject(g_ocheaderoption_clazz, option_constructor, \ + (jlong) reinterpret_cast(&headerOptions[n])); + + __android_log_print(ANDROID_LOG_ERROR, TAG, "jelem : %llu", (jlong) reinterpret_cast(&headerOptions[n])); + + env->SetObjectArrayElement(joptions, n, jelem); + env->DeleteLocalRef(jelem); + } + + // save C++ ocrepresentation ptr now + jmethodID representation_constructor = env->GetMethodID(g_ocrepresentation_clazz, "", "(J)V"); + jobject jrepresentation = env->NewObject(g_ocrepresentation_clazz, representation_constructor, \ + (jlong) reinterpret_cast(&rep)); + if(jrepresentation == NULL) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "cannot create OCRepresentation class"); + return; + } + + jclass cb_clazz = env->GetObjectClass(callbackContext->m_callBackFunction); + if (cb_clazz == NULL) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "Failed to find class"); + } + + // Find Callback function + jmethodID cb_mid = env->GetMethodID(cb_clazz, "Callback", \ + "([Lorg/iotivity/base/OCHeaderOption;Lorg/iotivity/base/OCRepresentation;II)V"); + if(cb_mid == NULL) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "onObserve.Callback() is not defined in JAVA"); + return; + } + + __android_log_print(ANDROID_LOG_INFO, TAG, "calling JAVA ObserveCallback"); + env->CallVoidMethod(callbackContext->m_callBackFunction, cb_mid, joptions, jrepresentation, eCode, seqNum); + + __android_log_print(ANDROID_LOG_INFO, TAG, "observeCB detach"); + g_JavaVM->DetachCurrentThread(); + + } + ); + return NULL; +} + +JNIEXPORT jobject JNICALL jniOicCancelObserve(JNIEnv *env, jobject jobj) +{ + std::shared_ptr *resource = getHandle>(env, jobj); + __android_log_print(ANDROID_LOG_ERROR, TAG, "cancelObserve1() resource = %p\n", resource); + __android_log_print(ANDROID_LOG_ERROR, TAG, "calling oic base cancelObserve()\n"); + + (*resource)->cancelObserve(); + return NULL; +} + +JNIEXPORT jstring JNICALL uri(JNIEnv *env, jobject jobj) +{ + __android_log_print(ANDROID_LOG_ERROR, TAG, "uri()"); + std::shared_ptr *resource = getHandle>(env, jobj); + return env->NewStringUTF((*resource)->uri().c_str()); +} + +JNIEXPORT jstring JNICALL host(JNIEnv *env, jobject jobj) +{ + __android_log_print(ANDROID_LOG_ERROR, TAG, "host()"); + std::shared_ptr *resource = getHandle>(env, jobj); + return env->NewStringUTF((*resource)->host().c_str()); +} + +JNIEXPORT jobjectArray JNICALL getResourceTypes(JNIEnv *env, jobject jobj) +{ + __android_log_print(ANDROID_LOG_ERROR, TAG, "getResourceTypes()"); + std::shared_ptr *resource = getHandle>(env, jobj); + + std::vector resourceTypes = (*resource)->getResourceTypes(); + + int size = resourceTypes.size(); + jclass clazz = env->FindClass("java/lang/String"); + jobjectArray jresourceTypes = env->NewObjectArray(size, clazz, 0); + + for (int n=0; nNewStringUTF(resourceTypes[n].c_str()); + env->SetObjectArrayElement(jresourceTypes, n, jstr); + } + + return jresourceTypes; +} + +JNIEXPORT jobjectArray JNICALL getResourceInterfaces(JNIEnv *env, jobject jobj) +{ + __android_log_print(ANDROID_LOG_ERROR, TAG, "getResourceInterfaces()"); + std::shared_ptr *resource = getHandle>(env, jobj); + + std::vector resourceInterfaces = (*resource)->getResourceInterfaces(); + + int size = resourceInterfaces.size(); + jclass clazz = env->FindClass("java/lang/String"); + jobjectArray jresourceInterfaces = env->NewObjectArray(size, clazz, 0); + + for (int n=0; nNewStringUTF(resourceInterfaces[n].c_str()); + env->SetObjectArrayElement(jresourceInterfaces, n, jstr); + } + + return jresourceInterfaces; +} + diff --git a/android/Base/app/jni/ocstack-jni.cpp b/android/Base/app/jni/ocstack-jni.cpp new file mode 100644 index 000000000..d9ae85025 --- /dev/null +++ b/android/Base/app/jni/ocstack-jni.cpp @@ -0,0 +1,134 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "ocstack-jni.h" + +// Global map to maintain callback functions and ocresource +// with key = URL + callback operation +// e.g. key = /a/light/GET +std::map gJNICallBackContextList; + +JavaVM* g_JavaVM = NULL; + +jclass g_ocplatform_clazz; +jclass g_ocresource_clazz; +jclass g_ocheaderoption_clazz; +jclass g_ocrepresentation_clazz; +jclass g_platformcfg_clazz; + +static const char* TAG = "OCSTACK-JNI"; + +static JNINativeMethod ocplatform_method_table[] = { + { "configure", "(Lorg/iotivity/base/PlatformConfig;)V", (void *) configure}, + { "findResource", "(Ljava/lang/String;Ljava/lang/String;Lorg/iotivity/base/AbstractFindCallback;)I", (void *) findResource } +}; + +static int ocplatform_method_table_size = sizeof(ocplatform_method_table) / sizeof(ocplatform_method_table[0]); + +static JNINativeMethod platformconfig_method_table[] = { + { "createNativeInstance", "(IILjava/lang/String;II)J", (void *) createNativeInstance }, +}; + +static int platformconfig_method_table_size = sizeof(platformconfig_method_table) / sizeof(platformconfig_method_table[0]); + +static JNINativeMethod ocresource_method_table[] = { + { "get", "(Lorg/iotivity/base/AbstractGetCallback;)Lorg/iotivity/base/OCStackResult;", (void *) jniOicGet}, + + { "put", "(Lorg/iotivity/base/OCRepresentation;Lorg/iotivity/base/AbstractPutCallback;)Lorg/iotivity/base/OCStackResult;", (void *) jniOicPut}, + { "post", "(Lorg/iotivity/base/OCRepresentation;Lorg/iotivity/base/AbstractPostCallback;)Lorg/iotivity/base/OCStackResult;", (void *) jniOicPost}, + { "observe", "(ILorg/iotivity/base/AbstractObserveCallback;)Lorg/iotivity/base/OCStackResult;", (void *) jniOicObserve}, + { "cancelObserve", "()Lorg/iotivity/base/OCStackResult;", (void *) jniOicCancelObserve}, + { "uri", "()Ljava/lang/String;", (void *) uri}, + { "host", "()Ljava/lang/String;", (void *) host}, + { "getResourceTypes", "()[Ljava/lang/String;", (void *) getResourceTypes}, + { "getResourceInterfaces", "()[Ljava/lang/String;", (void *) getResourceInterfaces}, +}; + +static int ocresource_method_table_size = sizeof(ocresource_method_table) / sizeof(ocresource_method_table[0]); + +static JNINativeMethod ocheaderoption_method_table[] = { + { "getOptionID", "()I", (void *) getOptionID}, + { "getOptionData", "()Ljava/lang/String;", (void *) getOptionData}, + { "OCHeaderOptionConstructor", "(ILjava/lang/String;)J", (void *) OCHeaderOptionConstructor}, +}; + +static int ocheaderoption_method_table_size = sizeof(ocheaderoption_method_table) / sizeof(ocheaderoption_method_table[0]); + +static JNINativeMethod ocrepresentation_method_table[] = { + { "OCRepresentationConstructor", "()J", (void *) OCRepresentationConstructor}, + { "getUri", "()Ljava/lang/String;", (void *) getUri}, + { "getValueInt", "(Ljava/lang/String;)I", (void *) getValueInt}, + { "getValueBool", "(Ljava/lang/String;)Z", (void *) getValueBool}, + { "getValueString", "(Ljava/lang/String;)Ljava/lang/String;", (void *) getValueString}, + { "setValueInt", "(Ljava/lang/String;I)V", (void *) setValueInt}, + { "setValueBool", "(Ljava/lang/String;Z)V", (void *) setValueBool}, + { "setValueString", "(Ljava/lang/String;Ljava/lang/String;)V", (void *) setValueString}, + { "hasAttribute", "(Ljava/lang/String;)Z", (void *) hasAttribute}, +}; + +static int ocrepresentation_method_table_size = sizeof(ocrepresentation_method_table) / sizeof(ocrepresentation_method_table[0]); + +// JNI OnLoad +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) +{ + JNIEnv* env; + + g_JavaVM = vm; + __android_log_print(ANDROID_LOG_ERROR, TAG, "g_JavaVM = %p\n", g_JavaVM); + + if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) { + return JNI_ERR; + } else { + jint ret; + jclass clazz; + + clazz = env->FindClass("org/iotivity/base/OCPlatform"); + g_ocplatform_clazz = (jclass) env->NewGlobalRef(clazz); + env->DeleteLocalRef(clazz); + ret = env->RegisterNatives(g_ocplatform_clazz, ocplatform_method_table, ocplatform_method_table_size); + __android_log_print(ANDROID_LOG_ERROR, TAG, "load ocplatform = %d\n", ret); + + clazz = env->FindClass("org/iotivity/base/OCResource"); + g_ocresource_clazz = (jclass) env->NewGlobalRef(clazz); + env->DeleteLocalRef(clazz); + ret = env->RegisterNatives(g_ocresource_clazz, ocresource_method_table, ocresource_method_table_size); + __android_log_print(ANDROID_LOG_ERROR, TAG, "load ocresource = %d\n", ret); + + clazz = env->FindClass("org/iotivity/base/PlatformConfig"); + g_platformcfg_clazz = (jclass) env->NewGlobalRef(clazz); + env->DeleteLocalRef(clazz); + ret = env->RegisterNatives(g_platformcfg_clazz, platformconfig_method_table, platformconfig_method_table_size); + __android_log_print(ANDROID_LOG_ERROR, TAG, "load platformconfig = %d\n", ret); + + clazz = env->FindClass("org/iotivity/base/OCHeaderOption"); + g_ocheaderoption_clazz = (jclass) env->NewGlobalRef(clazz); + env->DeleteLocalRef(clazz); + ret = env->RegisterNatives(g_ocheaderoption_clazz, ocheaderoption_method_table, ocheaderoption_method_table_size); + __android_log_print(ANDROID_LOG_ERROR, TAG, "load ocheaderoption = %d\n", ret); + + clazz = env->FindClass("org/iotivity/base/OCRepresentation"); + g_ocrepresentation_clazz = (jclass) env->NewGlobalRef(clazz); + env->DeleteLocalRef(clazz); + ret = env->RegisterNatives(g_ocrepresentation_clazz, ocrepresentation_method_table, ocrepresentation_method_table_size); + __android_log_print(ANDROID_LOG_ERROR, TAG, "load ocrepresentation = %d\n", ret); + + return JNI_VERSION_1_6; + } +} diff --git a/android/Base/app/jni/ocstack-jni.h b/android/Base/app/jni/ocstack-jni.h new file mode 100644 index 000000000..dd55aa4a2 --- /dev/null +++ b/android/Base/app/jni/ocstack-jni.h @@ -0,0 +1,101 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef _Included_org_iotivity_base_ocstack +#define _Included_org_iotivity_base_ocstack + +#include +#include +#include "OCApi.h" +#include "OCPlatform.h" + +class JNICallBackContext { + public: + + std::shared_ptr m_resource; + jobject m_callBackFunction; + + JNICallBackContext(jobject callback) { + m_resource = NULL; + m_callBackFunction = callback; + } + + JNICallBackContext(std::shared_ptr rsrc, + jobject callback) { + m_resource = rsrc; + m_callBackFunction = callback; + } +}; + +extern std::map gJNICallBackContextList; + +extern JavaVM* g_JavaVM; + +extern jclass g_ocplatform_clazz; +extern jclass g_ocresource_clazz; +extern jclass g_ocheaderoption_clazz; +extern jclass g_ocrepresentation_clazz; +extern jclass g_platformcfg_clazz; + +template +T *getHandle(JNIEnv *env, jobject obj) +{ + jclass cls = env->GetObjectClass(obj); + jfieldID fid = env->GetFieldID(cls, "nativeHandle", "J"); + jlong handle = env->GetLongField(obj, fid); + return reinterpret_cast(handle); +} + +// ocplatform-jni +extern JNIEXPORT void JNICALL configure(JNIEnv *env, jobject obj, jobject jcfg); +extern JNIEXPORT jint JNICALL findResource(JNIEnv* env, jobject obj, jstring jhost, jstring juri, jobject found); + +// platformcfg-jni +extern JNIEXPORT jlong JNICALL createNativeInstance + (JNIEnv *env, jobject obj, jint jServiceType, jint jModeType, jstring jIpAddress, jint port, jint jQOS); + +// ocheaderoption-jni +extern JNIEXPORT jint JNICALL getOptionID(JNIEnv *env, jobject jobj); +extern JNIEXPORT jstring JNICALL getOptionData(JNIEnv *env, jobject jobj); +extern JNIEXPORT jlong JNICALL OCHeaderOptionConstructor(JNIEnv *env, jobject jobj, jint joption, jstring jdata); + +// ocrepresentation-jni +extern JNIEXPORT jlong JNICALL OCRepresentationConstructor(JNIEnv *env, jobject jobj); +extern JNIEXPORT jstring JNICALL getUri(JNIEnv *env, jobject jobj); +extern JNIEXPORT jint JNICALL getValueInt(JNIEnv *env, jobject jobj, jstring jstr); +extern JNIEXPORT jboolean JNICALL getValueBool(JNIEnv *env, jobject jobj, jstring jstr); +extern JNIEXPORT jstring JNICALL getValueString(JNIEnv *env, jobject jobj, jstring jstr); +extern JNIEXPORT void JNICALL setValueInt(JNIEnv *env, jobject jobj, jstring jstr, jint jval); +extern JNIEXPORT void JNICALL setValueBool(JNIEnv *env, jobject jobj, jstring jstr, jboolean jval); +extern JNIEXPORT void JNICALL setValueString(JNIEnv *env, jobject jobj, jstring jstr, jstring jval); +extern JNIEXPORT jboolean JNICALL hasAttribute(JNIEnv *env, jobject jobj, jstring jstr); + +// ocresource-jni +extern JNIEXPORT jobject JNICALL jniOicGet(JNIEnv *env, jobject jobj, jobject jattributeHandler); +extern JNIEXPORT jobject JNICALL jniOicPut(JNIEnv *env, jobject jobj, jobject jocrepresentation, jobject jattributeHandler); +extern JNIEXPORT jobject JNICALL jniOicPost(JNIEnv *env, jobject jobj, jobject jocrepresentation, jobject jattributeHandler); +extern JNIEXPORT jobject JNICALL jniOicObserve(JNIEnv *env, jobject jobj, jint jobservetype, jobject jattributeHandler); +extern JNIEXPORT jobject JNICALL jniOicCancelObserve(JNIEnv *env, jobject jobj); +extern JNIEXPORT jstring JNICALL uri(JNIEnv *env, jobject jobj); +extern JNIEXPORT jstring JNICALL host(JNIEnv *env, jobject jobj); +extern JNIEXPORT jobjectArray JNICALL getResourceTypes(JNIEnv *env, jobject jobj); +extern JNIEXPORT jobjectArray JNICALL getResourceInterfaces(JNIEnv *env, jobject jobj); + +#endif diff --git a/android/Base/app/jni/platformcfg-jni.cpp b/android/Base/app/jni/platformcfg-jni.cpp new file mode 100644 index 000000000..73d40f9c5 --- /dev/null +++ b/android/Base/app/jni/platformcfg-jni.cpp @@ -0,0 +1,80 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "ocstack-jni.h" + +static const char* TAG = "PLATFORMCFG-JNI"; + +OC::ServiceType getServiceType(int type) +{ + switch (type) { + case 0: + return OC::ServiceType::InProc; + case 1: + default: + return OC::ServiceType::OutOfProc; + }; +} + +OC::ModeType getModeType(int type) +{ + switch (type) { + case 0: + return OC::ModeType::Server; + case 1: + return OC::ModeType::Client; + case 2: + default: + return OC::ModeType::Both; + }; +} + +OC::QualityOfService getQOS(int type) +{ + switch (type) { + case 0: + return OC::QualityOfService::LowQos; + case 1: + return OC::QualityOfService::MidQos; + case 2: + return OC::QualityOfService::HighQos; + case 3: + default: + return OC::QualityOfService::NaQos; + }; +} + +OC::PlatformConfig *g_cfg; + +JNIEXPORT jlong JNICALL createNativeInstance + (JNIEnv *env, jobject obj, jint jServiceType, jint jModeType, jstring jIpAddress, jint port, jint jQOS) +{ + + g_cfg = new OC::PlatformConfig{getServiceType(jServiceType), + getModeType(jModeType), + env->GetStringUTFChars(jIpAddress, 0), + (uint16_t) port, + getQOS(jQOS) + }; + + + jlong instptr = reinterpret_cast(g_cfg); + return instptr; +} diff --git a/android/Base/app/proguard-rules.pro b/android/Base/app/proguard-rules.pro new file mode 100644 index 000000000..0e559b082 --- /dev/null +++ b/android/Base/app/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /home/vchen/ubuntu_sw/adt-bundle-linux-x86_64/sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/android/Base/app/src/androidTest/java/org/iotivity/base/ApplicationTest.java b/android/Base/app/src/androidTest/java/org/iotivity/base/ApplicationTest.java new file mode 100644 index 000000000..ac4bdc3f1 --- /dev/null +++ b/android/Base/app/src/androidTest/java/org/iotivity/base/ApplicationTest.java @@ -0,0 +1,33 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.base; + +import android.app.Application; +import android.test.ApplicationTestCase; + +/** + * Testing Fundamentals + */ +public class ApplicationTest extends ApplicationTestCase { + public ApplicationTest() { + super(Application.class); + } +} diff --git a/android/Base/app/src/main/AndroidManifest.xml b/android/Base/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..32cf1c1a3 --- /dev/null +++ b/android/Base/app/src/main/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/android/Base/app/src/main/java/org/iotivity/base/AbstractDeleteCallback.java b/android/Base/app/src/main/java/org/iotivity/base/AbstractDeleteCallback.java new file mode 100644 index 000000000..d1c26b444 --- /dev/null +++ b/android/Base/app/src/main/java/org/iotivity/base/AbstractDeleteCallback.java @@ -0,0 +1,25 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.base; + +public abstract class AbstractDeleteCallback { + public abstract void Callback(OCHeaderOption options, int a); +} diff --git a/android/Base/app/src/main/java/org/iotivity/base/AbstractFindCallback.java b/android/Base/app/src/main/java/org/iotivity/base/AbstractFindCallback.java new file mode 100644 index 000000000..132b1a874 --- /dev/null +++ b/android/Base/app/src/main/java/org/iotivity/base/AbstractFindCallback.java @@ -0,0 +1,26 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.base; + +public abstract class AbstractFindCallback { + public abstract void Callback(OCResource resource); +// public OCResource ocresource = new OCResource(); +} diff --git a/android/Base/app/src/main/java/org/iotivity/base/AbstractGetCallback.java b/android/Base/app/src/main/java/org/iotivity/base/AbstractGetCallback.java new file mode 100644 index 000000000..6ba339b33 --- /dev/null +++ b/android/Base/app/src/main/java/org/iotivity/base/AbstractGetCallback.java @@ -0,0 +1,27 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.base; + +public abstract class AbstractGetCallback { + public abstract void Callback(OCHeaderOption[] options, OCRepresentation rep, int a); +// public OCHeaderOption[] ocoptions; +// public OCRepresentation ocrep = new OCRepresentation(); +} diff --git a/android/Base/app/src/main/java/org/iotivity/base/AbstractObserveCallback.java b/android/Base/app/src/main/java/org/iotivity/base/AbstractObserveCallback.java new file mode 100644 index 000000000..6c90561eb --- /dev/null +++ b/android/Base/app/src/main/java/org/iotivity/base/AbstractObserveCallback.java @@ -0,0 +1,27 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.base; + +public abstract class AbstractObserveCallback { + public abstract void Callback(OCHeaderOption[] options, OCRepresentation rep, int a, int b); +// public OCHeaderOption[] ocoptions; +// public OCRepresentation ocrep = new OCRepresentation(); +} diff --git a/android/Base/app/src/main/java/org/iotivity/base/AbstractPostCallback.java b/android/Base/app/src/main/java/org/iotivity/base/AbstractPostCallback.java new file mode 100644 index 000000000..20acbead2 --- /dev/null +++ b/android/Base/app/src/main/java/org/iotivity/base/AbstractPostCallback.java @@ -0,0 +1,27 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.base; + +public abstract class AbstractPostCallback { + public abstract void Callback(OCHeaderOption[] options, OCRepresentation rep, int a); +// public OCHeaderOption[] ocoptions; +// public OCRepresentation ocrep = new OCRepresentation(); +} diff --git a/android/Base/app/src/main/java/org/iotivity/base/AbstractPutCallback.java b/android/Base/app/src/main/java/org/iotivity/base/AbstractPutCallback.java new file mode 100644 index 000000000..46f2a19b4 --- /dev/null +++ b/android/Base/app/src/main/java/org/iotivity/base/AbstractPutCallback.java @@ -0,0 +1,7 @@ +package org.iotivity.base; + +public abstract class AbstractPutCallback { + public abstract void Callback(OCHeaderOption[] options, OCRepresentation rep, int a); +// public OCHeaderOption[] ocoptions; +// public OCRepresentation ocrep = new OCRepresentation(); +} diff --git a/android/Base/app/src/main/java/org/iotivity/base/AbstractSubscriberCallback.java b/android/Base/app/src/main/java/org/iotivity/base/AbstractSubscriberCallback.java new file mode 100644 index 000000000..1f996cb89 --- /dev/null +++ b/android/Base/app/src/main/java/org/iotivity/base/AbstractSubscriberCallback.java @@ -0,0 +1,25 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.base; + +public abstract class AbstractSubscriberCallback { + public abstract void Callback(OCStackResult result, int a); +} diff --git a/android/Base/app/src/main/java/org/iotivity/base/EntityHandler.java b/android/Base/app/src/main/java/org/iotivity/base/EntityHandler.java new file mode 100644 index 000000000..779543cfb --- /dev/null +++ b/android/Base/app/src/main/java/org/iotivity/base/EntityHandler.java @@ -0,0 +1,25 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.base; + +public interface EntityHandler { + public abstract void Callback(OCResourceRequest request, OCResourceResponse response); +} diff --git a/android/Base/app/src/main/java/org/iotivity/base/NativeInstance.java b/android/Base/app/src/main/java/org/iotivity/base/NativeInstance.java new file mode 100644 index 000000000..f6d02bbb5 --- /dev/null +++ b/android/Base/app/src/main/java/org/iotivity/base/NativeInstance.java @@ -0,0 +1,33 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.base; + +public abstract class NativeInstance +{ + protected long nativeHandle = 0; + + public NativeInstance() + { + } + + public long getHandle() { return nativeHandle;} + +} diff --git a/android/Base/app/src/main/java/org/iotivity/base/OCHeaderOption.java b/android/Base/app/src/main/java/org/iotivity/base/OCHeaderOption.java new file mode 100644 index 000000000..c1698702b --- /dev/null +++ b/android/Base/app/src/main/java/org/iotivity/base/OCHeaderOption.java @@ -0,0 +1,36 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.base; + +public class OCHeaderOption extends NativeInstance { + final private static String TAG = "OCHeaderOption"; + static { + System.loadLibrary("ocstack-jni"); + } + + public OCHeaderOption(long instPtr) { + super.nativeHandle = instPtr; + } + + public native int getOptionID(); + public native String getOptionData(); + public native long OCHeaderOptionConstructor(int optionID, String optionData); +} diff --git a/android/Base/app/src/main/java/org/iotivity/base/OCPlatform.java b/android/Base/app/src/main/java/org/iotivity/base/OCPlatform.java new file mode 100644 index 000000000..e4424a6a7 --- /dev/null +++ b/android/Base/app/src/main/java/org/iotivity/base/OCPlatform.java @@ -0,0 +1,32 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.base; + +public class OCPlatform { + final private static String TAG = "OCPlatform"; + static { + System.loadLibrary("ocstack-jni"); + } + + public static native void configure(PlatformConfig cfg); + public static native int findResource(String host, String Uri, AbstractFindCallback found); + +} diff --git a/android/Base/app/src/main/java/org/iotivity/base/OCRepresentation.java b/android/Base/app/src/main/java/org/iotivity/base/OCRepresentation.java new file mode 100644 index 000000000..06a2156ce --- /dev/null +++ b/android/Base/app/src/main/java/org/iotivity/base/OCRepresentation.java @@ -0,0 +1,49 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.base; + +public class OCRepresentation extends NativeInstance { + final private static String TAG = "OCRepresentation"; + static { + System.loadLibrary("ocstack-jni"); + } + + public OCRepresentation(long instPtr) { + super.nativeHandle = instPtr; + } + public OCRepresentation() { + super.nativeHandle = OCRepresentationConstructor(); + } + + public native long OCRepresentationConstructor(); + + public native int getValueInt(String str); + public native boolean getValueBool(String str); + public native String getValueString(String str); + + public native void setValueInt (String str, int val); + public native void setValueBool (String str, boolean val); + public native void setValueString (String str, String val); + + public native String getUri(); + + public native boolean hasAttribute(String str); +} diff --git a/android/Base/app/src/main/java/org/iotivity/base/OCResource.java b/android/Base/app/src/main/java/org/iotivity/base/OCResource.java new file mode 100644 index 000000000..7a7f6c809 --- /dev/null +++ b/android/Base/app/src/main/java/org/iotivity/base/OCResource.java @@ -0,0 +1,60 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.base; + +public class OCResource extends NativeInstance { + final private static String TAG = "OCResource"; + static { + System.loadLibrary("ocstack-jni"); + } + + public native OCStackResult get(AbstractGetCallback attributeHandler); +// public native OCStackResult get(AbstractGetCallback attributeHandler, PlatformConfig.QualityOfService QoS); + + public native OCStackResult get(String resourceType, String resourceInterface, AbstractGetCallback attributeHandler); +// public native OCStackResult get(String resourceType, String resourceInterface, AbstractGetCallback attributeHandler, PlatformConfig.QualityOfService QoS); + + public native OCStackResult put(OCRepresentation rep, AbstractPutCallback attributeHandler); +// public native OCStackResult put(OCRepresentation rep, AbstractPutCallback attributeHandler, PlatformConfig.QualityOfService QoS); +// public native OCStackResult put(String resourceType, String resourceInterface, OCRepresentation rep, AbstractPutCallback attributeHandler); +// public native OCStackResult put(String resourceType, String resourceInterface, OCRepresentation rep, AbstractPutCallback attributeHandler, PlatformConfig.QualityOfService QoS); + + public native OCStackResult post(OCRepresentation rep, AbstractPostCallback attributeHandler); +// public native OCStackResult post(OCRepresentation rep, AbstractPostCallback attributeHandler, PlatformConfig.QualityOfService QoS); +// public native OCStackResult post(String resourceType, String resourceInterface, OCRepresentation rep, AbstractPostCallback attributeHandler); +// public native OCStackResult post(String resourceType, String resourceInterface, OCRepresentation rep, AbstractPostCallback attributeHandler, PlatformConfig.QualityOfService QoS); + + public native OCStackResult observe(int observeType, AbstractObserveCallback observerHandler); +// public native OCStackResult observe(int observeType, AbstractObserveCallback observerHandler, PlatformConfig.QualityOfService QoS); + + public native OCStackResult cancelObserve(); +// public native OCStackResult cancelObserve(PlatformConfig.QualityOfService QoS); + + public native String uri(); + public native String host(); + + public native String[] getResourceInterfaces(); + public native String[] getResourceTypes(); + + public OCResource(long instPtr) { + super.nativeHandle = instPtr; + } +} diff --git a/android/Base/app/src/main/java/org/iotivity/base/OCResourceRequest.java b/android/Base/app/src/main/java/org/iotivity/base/OCResourceRequest.java new file mode 100644 index 000000000..87c406e52 --- /dev/null +++ b/android/Base/app/src/main/java/org/iotivity/base/OCResourceRequest.java @@ -0,0 +1,24 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.base; + +public class OCResourceRequest { +} diff --git a/android/Base/app/src/main/java/org/iotivity/base/OCResourceResponse.java b/android/Base/app/src/main/java/org/iotivity/base/OCResourceResponse.java new file mode 100644 index 000000000..283d8ded4 --- /dev/null +++ b/android/Base/app/src/main/java/org/iotivity/base/OCResourceResponse.java @@ -0,0 +1,24 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.base; + +public class OCResourceResponse { +} diff --git a/android/Base/app/src/main/java/org/iotivity/base/OCStackResult.java b/android/Base/app/src/main/java/org/iotivity/base/OCStackResult.java new file mode 100644 index 000000000..10440b6fe --- /dev/null +++ b/android/Base/app/src/main/java/org/iotivity/base/OCStackResult.java @@ -0,0 +1,54 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.base; + +public class OCStackResult { + /* Success status code - START HERE */ + static final public int OC_STACK_OK = 0; + static final public int OC_STACK_RESOURCE_CREATED = 1; + static final public int OC_STACK_RESOURCE_DELETED = 2; + /* Success status code - END HERE */ + /* Error status code - START HERE */ + static final public int OC_STACK_INVALID_URI = 3; + static final public int OC_STACK_INVALID_QUERY = 4; + static final public int OC_STACK_INVALID_IP = 5; + static final public int OC_STACK_INVALID_PORT = 6; + static final public int OC_STACK_INVALID_CALLBACK = 7; + static final public int OC_STACK_INVALID_METHOD = 8; + static final public int OC_STACK_INVALID_PARAM = 9; + static final public int OC_STACK_INVALID_OBSERVE_PARAM = 10; + static final public int OC_STACK_NO_MEMORY = 11; + static final public int OC_STACK_COMM_ERROR = 12; + static final public int OC_STACK_NOTIMPL = 13; + static final public int OC_STACK_NO_RESOURCE = 14; /* resource not found */ + static final public int OC_STACK_RESOURCE_ERROR = 15; /* ex: not supported method or interface */ + static final public int OC_STACK_SLOW_RESOURCE = 16; + static final public int OC_STACK_NO_OBSERVERS = 17; /* resource has no registered observers */ + static final public int OC_STACK_OBSERVER_NOT_FOUND = 18; + static final public int OC_STACK_OBSERVER_NOT_ADDED = 19; + static final public int OC_STACK_OBSERVER_NOT_REMOVED = 20; + static final public int OC_STACK_PRESENCE_STOPPED = 21; + static final public int OC_STACK_PRESENCE_DO_NOT_HANDLE = 22; + static final public int OC_STACK_INVALID_OPTION = 23; + static final public int OC_STACK_MALFORMED_RESPONSE = 24; /* the remote reply contained malformed data */ + static final public int OC_STACK_ERROR = 25; + /* Error status code - END HERE */ +} diff --git a/android/Base/app/src/main/java/org/iotivity/base/ObserveType.java b/android/Base/app/src/main/java/org/iotivity/base/ObserveType.java new file mode 100644 index 000000000..f61c5d892 --- /dev/null +++ b/android/Base/app/src/main/java/org/iotivity/base/ObserveType.java @@ -0,0 +1,26 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.base; + +public class ObserveType { + static final public int Observe = 0; + static final public int ObserveAll = 1; +} diff --git a/android/Base/app/src/main/java/org/iotivity/base/PlatformConfig.java b/android/Base/app/src/main/java/org/iotivity/base/PlatformConfig.java new file mode 100755 index 000000000..301cddea5 --- /dev/null +++ b/android/Base/app/src/main/java/org/iotivity/base/PlatformConfig.java @@ -0,0 +1,68 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.base; + +public class PlatformConfig extends NativeInstance +{ + final private static String TAG = "PlatformConfig"; + static { + System.loadLibrary("ocstack-jni"); + } + + // ENUM definition. Need to match with OCApi.h + public class ServiceType + { + static final public int INPROC = 0; + static final public int OUTPROC = 1; + }; + + public class ModeType + { + static final public int SERVER = 0; + static final public int CLIENT = 1; + static final public int BOTH = 2; + + }; + + public class QualityOfService + { + static final public int LO_QOS = 0; + static final public int ME_QOS = 1; + static final public int HI_QOS = 2; + static final public int NA_QOS = 3; + } + + public PlatformConfig(int serviceType, + int mode, + String ipAddress, + int port, + int QoS) + { + super.nativeHandle = createNativeInstance(serviceType, mode, ipAddress, port, QoS); + } + + + protected native long createNativeInstance(int serviceType, + int mode, + String ipAddress, + int port, + int QoS); +} diff --git a/android/Base/app/src/main/res/drawable-hdpi/ic_launcher.png b/android/Base/app/src/main/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..96a442e5b8e9394ccf50bab9988cb2316026245d GIT binary patch literal 9397 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 literal 0 HcmV?d00001 diff --git a/android/Base/app/src/main/res/drawable-xhdpi/ic_launcher.png b/android/Base/app/src/main/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..71c6d760f05183ef8a47c614d8d13380c8528499 GIT binary patch literal 14383 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 literal 0 HcmV?d00001 diff --git a/android/Base/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/android/Base/app/src/main/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4df18946442ed763bd52cf3adca31617848656fa GIT binary patch literal 19388 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 literal 0 HcmV?d00001 diff --git a/android/Base/app/src/main/res/values/strings.xml b/android/Base/app/src/main/res/values/strings.xml new file mode 100644 index 000000000..73ef2254e --- /dev/null +++ b/android/Base/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Base + diff --git a/android/Base/app/src/main/res/values/styles.xml b/android/Base/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..ff6c9d2c0 --- /dev/null +++ b/android/Base/app/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/android/Base/build.gradle b/android/Base/build.gradle new file mode 100644 index 000000000..9b8abe4fe --- /dev/null +++ b/android/Base/build.gradle @@ -0,0 +1,19 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:0.12.2' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + jcenter() + } +} diff --git a/android/Base/gradle.properties b/android/Base/gradle.properties new file mode 100644 index 000000000..5d08ba75b --- /dev/null +++ b/android/Base/gradle.properties @@ -0,0 +1,18 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Settings specified in this file will override any Gradle settings +# configured through the IDE. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx10248m -XX:MaxPermSize=256m +# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true \ No newline at end of file diff --git a/android/Base/gradlew b/android/Base/gradlew new file mode 100755 index 000000000..91a7e269e --- /dev/null +++ b/android/Base/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/android/Base/gradlew.bat b/android/Base/gradlew.bat new file mode 100644 index 000000000..aec99730b --- /dev/null +++ b/android/Base/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/android/Base/settings.gradle b/android/Base/settings.gradle new file mode 100644 index 000000000..e7b4def49 --- /dev/null +++ b/android/Base/settings.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/android/SimpleClient/app/build.gradle b/android/SimpleClient/app/build.gradle new file mode 100644 index 000000000..bf753bf78 --- /dev/null +++ b/android/SimpleClient/app/build.gradle @@ -0,0 +1,40 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 20 + buildToolsVersion "19.1.0" + + defaultConfig { + applicationId "org.iotivity.simpleclient" + minSdkVersion 19 + targetSdkVersion 20 + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + runProguard false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) +} + +repositories { + mavenCentral() + flatDir { + dirs 'libs' + } +} + + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) + compile fileTree(dir: 'libs', include: ['*.so']) + compile fileTree(dir: 'libs', include: ['**/*.so']) +// compile(name: 'OicLib', ext:'aar') + compile 'org.iotivity.Base:app:1.0@aar' +} \ No newline at end of file diff --git a/android/SimpleClient/app/proguard-rules.pro b/android/SimpleClient/app/proguard-rules.pro new file mode 100644 index 000000000..0e559b082 --- /dev/null +++ b/android/SimpleClient/app/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /home/vchen/ubuntu_sw/adt-bundle-linux-x86_64/sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/android/SimpleClient/app/src/androidTest/java/org/iotivity/simpleclient/ApplicationTest.java b/android/SimpleClient/app/src/androidTest/java/org/iotivity/simpleclient/ApplicationTest.java new file mode 100644 index 000000000..a2b677833 --- /dev/null +++ b/android/SimpleClient/app/src/androidTest/java/org/iotivity/simpleclient/ApplicationTest.java @@ -0,0 +1,33 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.simpleclient; + +import android.app.Application; +import android.test.ApplicationTestCase; + +/** + * Testing Fundamentals + */ +public class ApplicationTest extends ApplicationTestCase { + public ApplicationTest() { + super(Application.class); + } +} diff --git a/android/SimpleClient/app/src/main/AndroidManifest.xml b/android/SimpleClient/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..08329dae3 --- /dev/null +++ b/android/SimpleClient/app/src/main/AndroidManifest.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + diff --git a/android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/FoundResource.java b/android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/FoundResource.java new file mode 100644 index 000000000..cd558f4d4 --- /dev/null +++ b/android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/FoundResource.java @@ -0,0 +1,72 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.simpleclient; + +import android.util.Log; + +import org.iotivity.base.AbstractFindCallback; +import org.iotivity.base.OCResource; + +public class FoundResource extends AbstractFindCallback { + final private static String TAG = "FoundResource"; + + + public void Callback(OCResource resource) { + + if(SimpleClient.curResource != null) { + Log.e(TAG, "Found another resource, ignoring"); + } + + String resourceURI; + String hostAddress; + + if(resource != null) { + Log.i(TAG, "DISCOVERED Resource"); + + resourceURI = resource.uri(); + Log.i(TAG, "URI of the resource: " + resourceURI); + + hostAddress = resource.host(); + Log.i(TAG, "Host address of the resource: " + hostAddress); + + new SimpleToast().execute("URI of the resource: " + resourceURI + "\nHost address of the resource: " + hostAddress); + + String[] resourceTypes = resource.getResourceTypes(); + for(int i=0; i 5) { + Log.i(TAG, "Cancelling Observe ..."); + OCStackResult result = SimpleClient.curResource.cancelObserve(); + Log.i(TAG, "Cancel result : " + result); + try { + Thread.sleep(10000); // 10 sec + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + Log.i(TAG, "DONE"); + new SimpleToast().execute( + "DONE" + ); + } + + } + } + else { + Log.e(TAG, "onPut Response error : " + eCode); + } + + } +} diff --git a/android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/OnPost.java b/android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/OnPost.java new file mode 100644 index 000000000..ca7e1ae2c --- /dev/null +++ b/android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/OnPost.java @@ -0,0 +1,77 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.simpleclient; + +import android.util.Log; + +import org.iotivity.base.AbstractPostCallback; +import org.iotivity.base.OCHeaderOption; +import org.iotivity.base.OCRepresentation; + +public class OnPost extends AbstractPostCallback { + + final private static String TAG = "OnPost"; + + public void Callback(OCHeaderOption[] options, OCRepresentation rep, int eCode) { +//FIXME : Need to check why ocstack is returning error code 28 to us after 12/6/14 rebase +// if(eCode == OCStackResult.OC_STACK_OK || eCode == OCStackResult.OC_STACK_RESOURCE_CREATED) { + if(true) { + Log.i(TAG, "POST request was successful"); + + if(rep.hasAttribute("createduri")) { + Log.i(TAG, "Uri of the created resource : " + rep.getValueString("createduri")); + } + else { + SimpleClient.mylight.m_state = rep.getValueBool("state"); + Log.i(TAG, "state : " + SimpleClient.mylight.m_state); + SimpleClient.mylight.m_power = rep.getValueInt("power"); + Log.i(TAG, "power : " + SimpleClient.mylight.m_power); + SimpleClient.mylight.m_name = rep.getValueString("name"); + Log.i(TAG, "name : " + SimpleClient.mylight.m_name); + + new SimpleToast().execute( + "state : " + SimpleClient.mylight.m_state + + "\npower : " + SimpleClient.mylight.m_power + + "\nname : " + SimpleClient.mylight.m_name + ); + } + + OCRepresentation rep2 = new OCRepresentation(); + + Log.e(TAG, "Posting Light Representation ..."); + + SimpleClient.mylight.m_state = true; + SimpleClient.mylight.m_power = 55; + + Log.i(TAG, "setValueBool : " + SimpleClient.mylight.m_state); + Log.i(TAG, "setValueInt : " + SimpleClient.mylight.m_power); + rep2.setValueBool("state", SimpleClient.mylight.m_state); + rep2.setValueInt("power", SimpleClient.mylight.m_power); + + OnPost2 onPost2 = new OnPost2(); + SimpleClient.curResource.post(rep2, onPost2); + } + else { + Log.e(TAG, "onPost Response error : " + eCode); + } + + } +} diff --git a/android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/OnPost2.java b/android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/OnPost2.java new file mode 100644 index 000000000..cfc6ae6cc --- /dev/null +++ b/android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/OnPost2.java @@ -0,0 +1,75 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.simpleclient; + +import android.util.Log; + +import org.iotivity.base.AbstractPostCallback; +import org.iotivity.base.OCHeaderOption; +import org.iotivity.base.OCRepresentation; +import org.iotivity.base.OCStackResult; +import org.iotivity.base.ObserveType; + +public class OnPost2 extends AbstractPostCallback { + + final private static String TAG = "OnPost2"; + + public void Callback(OCHeaderOption[] options, OCRepresentation rep, int eCode) { +//FIXME : Need to check why ocstack is returning error code 28 to us after 12/6/14 rebase +// if(eCode == OCStackResult.OC_STACK_OK || eCode == OCStackResult.OC_STACK_RESOURCE_CREATED) { + if(true) { + + Log.i(TAG, "POST2 request was successful"); + + if(rep.hasAttribute("createduri")) { + String createdUri = rep.getValueString("createduri"); + Log.i(TAG, "Uri of the created resource : " + createdUri); // FIXME + new SimpleToast().execute( + "Uri of the created resource : " + createdUri + ); + } + else { + SimpleClient.mylight.m_state = rep.getValueBool("state"); + Log.i(TAG, "state : " + SimpleClient.mylight.m_state); + SimpleClient.mylight.m_power = rep.getValueInt("power"); + Log.i(TAG, "power : " + SimpleClient.mylight.m_power); + SimpleClient.mylight.m_name = rep.getValueString("name"); + Log.i(TAG, "name : " + SimpleClient.mylight.m_name); + new SimpleToast().execute( + "state : " + SimpleClient.mylight.m_state + + "\npower : " + SimpleClient.mylight.m_power + + "\nname : " + SimpleClient.mylight.m_name + ); + } + + if(SimpleClient.OBSERVE_TYPE_TO_USE == ObserveType.Observe) + Log.i(TAG, "Observe is used"); + else if(SimpleClient.OBSERVE_TYPE_TO_USE == ObserveType.ObserveAll) + Log.i(TAG, "ObserveAll is used"); + + OnObserve onObserve = new OnObserve(); + SimpleClient.curResource.observe(SimpleClient.OBSERVE_TYPE_TO_USE, onObserve); + } + else { + Log.e(TAG, "onPost Response error : " + eCode); + } + } +} diff --git a/android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/OnPut.java b/android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/OnPut.java new file mode 100644 index 000000000..fa8410c4e --- /dev/null +++ b/android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/OnPut.java @@ -0,0 +1,59 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.simpleclient; + +import android.util.Log; + +import org.iotivity.base.AbstractPutCallback; +import org.iotivity.base.OCHeaderOption; +import org.iotivity.base.OCRepresentation; +import org.iotivity.base.OCStackResult; + +public class OnPut extends AbstractPutCallback { + + final private static String TAG = "OnGet"; + + public void Callback(OCHeaderOption[] options, OCRepresentation rep, int eCode) { + if(eCode == OCStackResult.OC_STACK_OK) { + { + Log.i(TAG, "PUT request was successful"); + + SimpleClient.mylight.m_state = rep.getValueBool("state"); + Log.i(TAG, "state : " + SimpleClient.mylight.m_state); + SimpleClient.mylight.m_power = rep.getValueInt("power"); + Log.i(TAG, "power : " + SimpleClient.mylight.m_power); + SimpleClient.mylight.m_name = rep.getValueString("name"); + Log.i(TAG, "name : " + SimpleClient.mylight.m_name); + new SimpleToast().execute( + "state : " + SimpleClient.mylight.m_state + + "\npower : " + SimpleClient.mylight.m_power + + "\nname : " + SimpleClient.mylight.m_name + ); + + SimpleClient.postLightRepresentation(SimpleClient.curResource); + } + } + else { + Log.e(TAG, "onPut Response error : " + eCode); + } + + } +} diff --git a/android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/SimpleClient.java b/android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/SimpleClient.java new file mode 100644 index 000000000..7413ca2a1 --- /dev/null +++ b/android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/SimpleClient.java @@ -0,0 +1,151 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.simpleclient; + +import android.app.Activity; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; + +import org.iotivity.base.OCPlatform; +import org.iotivity.base.OCRepresentation; +import org.iotivity.base.OCResource; +import org.iotivity.base.ObserveType; +import org.iotivity.base.PlatformConfig; + + +public class SimpleClient extends Activity { + final private static String TAG = "SimpleClient"; + + class Light { + public boolean m_state; + public int m_power; + public String m_name; + + public Light() { + m_state = false; + m_power = 0; + m_name = "vincent"; + } + } + + static int OBSERVE_TYPE_TO_USE = ObserveType.Observe; + + public static Light mylight; + public static OCResource curResource; + static int oc = 0; + static Activity mActivity; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mActivity = this; + + mylight = new Light(); + + PlatformConfig cfg = new PlatformConfig(PlatformConfig.ServiceType.INPROC, + PlatformConfig.ModeType.CLIENT, + "0.0.0.0", + 0, + PlatformConfig.QualityOfService.LO_QOS); + + OCPlatform.configure(cfg); + FoundResource foundResource = new FoundResource(); + OCPlatform.findResource("", "coap://224.0.1.187/oc/core?rt=core.light", foundResource); + + setContentView(R.layout.activity_simple_client); + } + + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.simple_client, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + int id = item.getItemId(); + if (id == R.id.action_settings) { + return true; + } + return super.onOptionsItemSelected(item); + } + + protected static void getLightRepresentation(OCResource resource) { + if(resource != null) { + Log.e(TAG, "Getting Light Representation ..."); + + OnGet onGet = new OnGet(); + resource.get(onGet); + } + } + + protected static void putLightRepresentation(OCResource resource) { + if(resource != null) { + + OCRepresentation rep = new OCRepresentation(); + + Log.e(TAG, "Putting Light Representation ..."); + + mylight.m_state = true; + mylight.m_power = 15; + + Log.i(TAG, "setValueBool : " + SimpleClient.mylight.m_state); + Log.i(TAG, "setValueInt : " + SimpleClient.mylight.m_power); + rep.setValueBool("state", mylight.m_state); + rep.setValueInt("power", mylight.m_power); + + OnPut onPut = new OnPut(); + resource.put(rep, onPut); + } + } + + protected static void postLightRepresentation(OCResource resource) { + if(resource != null) { + + OCRepresentation rep = new OCRepresentation(); + + Log.e(TAG, "Posting Light Representation ..."); + + mylight.m_state = false; + mylight.m_power = 105; + + Log.i(TAG, "setValueBool : " + SimpleClient.mylight.m_state); + Log.i(TAG, "setValueInt : " + SimpleClient.mylight.m_power); + rep.setValueBool("state", mylight.m_state); + rep.setValueInt("power", mylight.m_power); + + OnPost onPost = new OnPost(); + resource.post(rep, onPost); + } + } + + protected static int observe_count() { + return ++oc; + } + +} diff --git a/android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/SimpleToast.java b/android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/SimpleToast.java new file mode 100644 index 000000000..8f7d67295 --- /dev/null +++ b/android/SimpleClient/app/src/main/java/org/iotivity/simpleclient/SimpleToast.java @@ -0,0 +1,44 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +package org.iotivity.simpleclient; + +import android.os.AsyncTask; +import android.widget.Toast; + +public class SimpleToast extends AsyncTask { + String toastMessage; + + @Override + protected String doInBackground(String... params) { + toastMessage = params[0]; + return toastMessage; + } + + protected void OnProgressUpdate(String... values) { + super.onProgressUpdate(values); + } + // This is executed in the context of the main GUI thread + protected void onPostExecute(String result){ + Toast toast = Toast.makeText(SimpleClient.mActivity, result, Toast.LENGTH_SHORT); + toast.show(); + } + +} diff --git a/android/SimpleClient/app/src/main/res/drawable-hdpi/ic_launcher.png b/android/SimpleClient/app/src/main/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..96a442e5b8e9394ccf50bab9988cb2316026245d GIT binary patch literal 9397 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 literal 0 HcmV?d00001 diff --git a/android/SimpleClient/app/src/main/res/drawable-xhdpi/ic_launcher.png b/android/SimpleClient/app/src/main/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..71c6d760f05183ef8a47c614d8d13380c8528499 GIT binary patch literal 14383 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 literal 0 HcmV?d00001 diff --git a/android/SimpleClient/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/android/SimpleClient/app/src/main/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4df18946442ed763bd52cf3adca31617848656fa GIT binary patch literal 19388 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 literal 0 HcmV?d00001 diff --git a/android/SimpleClient/app/src/main/res/layout/activity_simple_client.xml b/android/SimpleClient/app/src/main/res/layout/activity_simple_client.xml new file mode 100644 index 000000000..f347f6c52 --- /dev/null +++ b/android/SimpleClient/app/src/main/res/layout/activity_simple_client.xml @@ -0,0 +1,16 @@ + + + + + diff --git a/android/SimpleClient/app/src/main/res/menu/simple_client.xml b/android/SimpleClient/app/src/main/res/menu/simple_client.xml new file mode 100644 index 000000000..1a65997fb --- /dev/null +++ b/android/SimpleClient/app/src/main/res/menu/simple_client.xml @@ -0,0 +1,8 @@ + + + diff --git a/android/SimpleClient/app/src/main/res/values-w820dp/dimens.xml b/android/SimpleClient/app/src/main/res/values-w820dp/dimens.xml new file mode 100644 index 000000000..63fc81644 --- /dev/null +++ b/android/SimpleClient/app/src/main/res/values-w820dp/dimens.xml @@ -0,0 +1,6 @@ + + + 64dp + diff --git a/android/SimpleClient/app/src/main/res/values/dimens.xml b/android/SimpleClient/app/src/main/res/values/dimens.xml new file mode 100644 index 000000000..47c822467 --- /dev/null +++ b/android/SimpleClient/app/src/main/res/values/dimens.xml @@ -0,0 +1,5 @@ + + + 16dp + 16dp + diff --git a/android/SimpleClient/app/src/main/res/values/strings.xml b/android/SimpleClient/app/src/main/res/values/strings.xml new file mode 100644 index 000000000..532e40d25 --- /dev/null +++ b/android/SimpleClient/app/src/main/res/values/strings.xml @@ -0,0 +1,8 @@ + + + + SimpleClient + Hello world! + Settings + + diff --git a/android/SimpleClient/app/src/main/res/values/styles.xml b/android/SimpleClient/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..ff6c9d2c0 --- /dev/null +++ b/android/SimpleClient/app/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/android/SimpleClient/build.gradle b/android/SimpleClient/build.gradle new file mode 100644 index 000000000..9b8abe4fe --- /dev/null +++ b/android/SimpleClient/build.gradle @@ -0,0 +1,19 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:0.12.2' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + jcenter() + } +} diff --git a/android/SimpleClient/gradle.properties b/android/SimpleClient/gradle.properties new file mode 100644 index 000000000..5d08ba75b --- /dev/null +++ b/android/SimpleClient/gradle.properties @@ -0,0 +1,18 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Settings specified in this file will override any Gradle settings +# configured through the IDE. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx10248m -XX:MaxPermSize=256m +# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true \ No newline at end of file diff --git a/android/SimpleClient/gradlew b/android/SimpleClient/gradlew new file mode 100755 index 000000000..91a7e269e --- /dev/null +++ b/android/SimpleClient/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/android/SimpleClient/gradlew.bat b/android/SimpleClient/gradlew.bat new file mode 100644 index 000000000..aec99730b --- /dev/null +++ b/android/SimpleClient/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/android/SimpleClient/settings.gradle b/android/SimpleClient/settings.gradle new file mode 100644 index 000000000..e7b4def49 --- /dev/null +++ b/android/SimpleClient/settings.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/arduino.scons b/arduino.scons new file mode 100644 index 000000000..4ab2affff --- /dev/null +++ b/arduino.scons @@ -0,0 +1,11 @@ +## +# This script includes arduino specific config for oic-resource +## +Import('env') + +env.ImportLib('Time') +if env.get('NET') == 'Ethernet': + env.ImportLib('Ethernet') +else: + env.ImportLib('WiFi') +env.ImportLib('SPI') \ No newline at end of file diff --git a/auto_build.sh b/auto_build.sh new file mode 100755 index 000000000..536331c34 --- /dev/null +++ b/auto_build.sh @@ -0,0 +1,103 @@ +#! /bin/bash + +# Ideally we will capture the exit code of each step and try them all before failing +# the build script. For now, use set -e and fail the build at first failure. +set -e + +function clean() +{ + echo "*********** Clean build *************" + scons -c + rm -rf out +} + +function build() +{ + if [ $(uname -s) = "Linux" ] + then + echo "*********** Build for linux *************" + scons RELEASE=$3 + fi + + # Note: for android, as oic-resource uses C++11 feature stoi and to_string, + # it requires gcc-4.9, currently only android-ndk-r10(for linux) + # and windows android-ndk-r10(64bit target version) support these features. + if [ "$BUILD_FOR_ANDROID" = "true" ] + then + + echo "*********** Build Boost for android ***********" + pushd extlibs + ./buildDependencies.sh + popd + + echo "*********** Build for android x86 *************" + scons TARGET_OS=android TARGET_ARCH=x86 ANDROID_NDK=$1 RELEASE=$3 + + echo "*********** Build for android armeabi *************" + scons TARGET_OS=android TARGET_ARCH=armeabi ANDROID_NDK=$1 RELEASE=$3 + + echo "*********** Build for android armeabi-v7a *************" + scons TARGET_OS=android TARGET_ARCH=armeabi-v7a ANDROID_NDK=$1 RELEASE=$3 + + echo "*********** Build for android armeabi-v7a-hard *************" + scons TARGET_OS=android TARGET_ARCH=armeabi-v7a-hard ANDROID_NDK=$1 RELEASE=$3 + fi + + echo "*********** Build for arduino avr *************" + scons TARGET_OS=arduino TARGET_ARCH=avr ARDUINO_HOME=$2 RELEASE=$3 + + echo "*********** Build for arduino arm *************" + scons TARGET_OS=arduino TARGET_ARCH=arm ARDUINO_HOME=$2 RELEASE=$3 + + if [ $(uname -s) = "Darwin" ] + then + echo "*********** Build for OSX *************" + scons TARGET_OS=darwin SYS_VERSION=10.9 RELEASE=$3 + + echo "*********** Build for IOS i386 *************" + scons TARGET_OS=ios TARGET_ARCH=i386 SYS_VERSION=7.0 RELEASE=$3 + + echo "*********** Build for IOS x86_64 *************" + scons TARGET_OS=ios TARGET_ARCH=x86_64 SYS_VERSION=7.0 RELEASE=$3 + + echo "*********** Build for IOS armv7 *************" + scons TARGET_OS=ios TARGET_ARCH=armv7 SYS_VERSION=7.0 RELEASE=$3 + + echo "*********** Build for IOS armv7s *************" + scons TARGET_OS=ios TARGET_ARCH=armv7s SYS_VERSION=7.0 RELEASE=$3 + + echo "*********** Build for IOS arm64 *************" + scons TARGET_OS=ios TARGET_ARCH=arm64 SYS_VERSION=7.0 RELEASE=$3 + fi +} + +function help() +{ + echo "Usage:" + echo " build:" + echo " `basename $0` " + echo " clean:" + echo " `basename $0` -c" +} + +if [ $# -eq 1 ] +then + if [ $1 = '-c' ] + then + clean + exit 0 + else + help + exit -1 + fi +elif [ $# -ne 2 ] +then + help + exit -1 +fi + +# Suppress "Reading ..." message and enable parallel build +export SCONSFLAGS="-Q -j 4" +build $1 $2 true +build $1 $2 false +echo "===================== done =====================" diff --git a/build_common/SConscript b/build_common/SConscript new file mode 100644 index 000000000..db23ac31d --- /dev/null +++ b/build_common/SConscript @@ -0,0 +1,239 @@ +## +# This script includes generic build options: +# release/debug, target os, target arch, cross toolchain, build environment etc +## +import os +import platform + +# Map of host os and allowed target os (host: allowed target os) +host_target_map = { + 'linux': ['linux', 'android', 'arduino', 'yocto', 'tizen'], + 'windows': ['windows', 'winrt', 'android', 'arduino'], + 'darwin': ['darwin', 'ios', 'android', 'arduino'], + } + +# Map of os and allowed archs (os: allowed archs) +os_arch_map = { + 'linux': ['x86', 'x86_64', 'arm', 'arm64'], + 'tizen': ['x86', 'x86_64', 'arm', 'arm64'], + 'android': ['x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'armeabi-v7a-hard', 'arm64-v8a'], + 'windows': ['x86', 'amd64', 'arm'], + 'winrt': ['arm'], + 'darwin': ['i386', 'x86_64'], + 'ios': ['i386', 'x86_64', 'armv7', 'armv7s', 'arm64'], + 'arduino': ['avr', 'arm'], + 'yocto': ['x86', 'x86_64'], + } + +host = platform.system().lower() + +if not host_target_map.has_key(host): + print "\nError: Current system (%s) isn't supported\n" % host + Exit(1) + +###################################################################### +# Get build options (the optins from command line) +###################################################################### +target_os = ARGUMENTS.get('TARGET_OS', host).lower() # target os + +if target_os not in host_target_map[host]: + print "\nError: Unknown target os: %s (Allow values: %s)\n" % (target_os, host_target_map[host]) + Exit(1) + +default_arch = platform.machine() +if default_arch not in os_arch_map[target_os]: + default_arch = os_arch_map[target_os][0].lower() + +target_arch = ARGUMENTS.get('TARGET_ARCH', default_arch) # target arch + +###################################################################### +# Common build options (release, target os, target arch) +###################################################################### +help_vars = Variables() +help_vars.Add(BoolVariable('RELEASE', 'Build for release?', True)) # set to 'no', 'false' or 0 for debug +help_vars.Add(EnumVariable('TARGET_OS', 'Target platform', host, host_target_map[host])) +help_vars.Add(EnumVariable('TARGET_ARCH', 'Target architecture', default_arch, os_arch_map[target_os])) + +###################################################################### +# Platform(build target) specific options: SDK/NDK & toolchain +###################################################################### +targets_support_cc = ['linux', 'arduino'] + +if target_os in targets_support_cc: + # Set cross compile toolchain + help_vars.Add('TC_PREFIX', "Toolchain prefix (Generally only be required for cross-compiling)", os.environ.get('TC_PREFIX')) + help_vars.Add(PathVariable('TC_PATH', + 'Toolchain path (Generally only be required for cross-compiling)', + os.environ.get('TC_PATH'))) + +if target_os in ['android', 'arduino']: # Android/Arduino always uses GNU compiler regardless of the host + env = Environment(variables = help_vars, + tools = ['gnulink', 'gcc', 'g++', 'ar', 'as'] + ) +else: + env = Environment(variables = help_vars, TARGET_ARCH = target_arch, TARGET_OS = target_os) + +Help(help_vars.GenerateHelpText(env)) + +tc_set_msg = ''' +************************************ Warning ********************************** +* Enviornment variable TC_PREFIX/TC_PATH is set. It will change the default * +* toolchain, if it isn't what you expect you should unset it, otherwise it may* +* cause inexplicable errors. * +******************************************************************************* +''' + +if target_os in targets_support_cc: + prefix = env.get('TC_PREFIX') + tc_path = env.get('TC_PATH') + if prefix: + env.Replace(CC = prefix + 'gcc') + env.Replace(CXX = prefix + 'g++') + env.Replace(AR = prefix + 'ar') + env.Replace(AS = prefix + 'as') + env.Replace(LINK = prefix + 'ld') + env.Replace(RANLIB = prefix + 'ranlib') + + if tc_path: + env.PrependENVPath('PATH', tc_path) + sys_root = os.path.abspath(tc_path + '/../') + env.AppendUnique(CCFLAGS = ['--sysroot=' + sys_root]) + env.AppendUnique(LINKFLAGS = ['--sysroot=' + sys_root]) + + if prefix or tc_path: + print tc_set_msg + +# Ensure scons be able to change its working directory +env.SConscriptChdir(1) + +# Set the source directory and build directory +# Source directory: 'dir' +# Build directory: 'dir'/out//// +# +# You can get the directory as following: +# env.get('SRC_DIR') +# env.get('BUILD_DIR') + +def __set_dir(env, dir): + if not os.path.exists(dir + '/SConstruct'): + print ''' +*************************************** Error ********************************* +* The directory(%s) seems isn't a source code directory, no SConstruct file is +* found. * +******************************************************************************* +''' % dir + Exit(1) + + if env.get('RELEASE'): + build_dir = dir + '/out/' + target_os + '/' + target_arch + '/release/' + else: + build_dir = dir + '/out/' + target_os + '/' + target_arch + '/debug/' + env.VariantDir(build_dir, dir, duplicate=0) + + env.Replace(BUILD_DIR = build_dir) + env.Replace(SRC_DIR = dir) + +def __src_to_obj(env, src, home = ''): + obj = env.get('BUILD_DIR') + src.replace(home, '') + if env.get('OBJSUFFIX'): + obj += env.get('OBJSUFFIX') + return env.Object(obj, src) + +def __install(ienv, targets, name): + i_n = ienv.Install(env.get('BUILD_DIR'), targets) + Alias(name, i_n) + env.AppendUnique(TS = [name]) + +def __append_target(ienv, target): + env.AppendUnique(TS = [target]) + +def __print_targets(env): + Help(''' +=============================================================================== +Targets:\n ''') + for t in env.get('TS'): + Help(t + ' ') + Help(''' +\nDefault all targets will be built. You can specify the target to build: + + $ scons [options] [target] +=============================================================================== +''') + +env.AddMethod(__set_dir, 'SetDir') +env.AddMethod(__print_targets, 'PrintTargets') +env.AddMethod(__src_to_obj, 'SrcToObj') +env.AddMethod(__append_target, 'AppendTarget') +env.AddMethod(__install, 'InstallTarget') +env.SetDir(env.GetLaunchDir()) + +Export('env') + +###################################################################### +# Link scons to Yocto cross-toolchain ONLY when target_os is yocto +###################################################################### +if target_os == "yocto": + ''' + This code injects Yocto cross-compilation tools+flags into scons' + build environment in order to invoke the relevant tools while + performing a build. + ''' + import os.path + try: + CC = os.environ['CC'] + target_prefix = CC.split()[0] + target_prefix = target_prefix[:len(target_prefix)-3] + tools = {"CC" : target_prefix+"gcc", + "CXX" : target_prefix+"g++", + "AS" : target_prefix+"as", + "LD" : target_prefix+"ld", + "GDB" : target_prefix+"gdb", + "STRIP" : target_prefix+"strip", + "RANLIB" : target_prefix+"ranlib", + "OBJCOPY" : target_prefix+"objcopy", + "OBJDUMP" : target_prefix+"objdump", + "AR" : target_prefix+"ar", + "NM" : target_prefix+"nm", + "M4" : "m4", + "STRINGS": target_prefix+"strings"} + PATH = os.environ['PATH'].split(os.pathsep) + for tool in tools: + if tool in os.environ: + for path in PATH: + if os.path.isfile(os.path.join(path, tools[tool])): + env[tool] = os.path.join(path, os.environ[tool]) + break + except: + print "ERROR in Yocto cross-toolchain environment" + Exit(1) + ''' + Now reset TARGET_OS to linux so that all linux specific build configurations + hereupon apply for the entirety of the build process. + ''' + env['TARGET_OS'] = 'linux' + ''' + We want to preserve debug symbols to allow BitBake to generate both DEBUG and + RELEASE packages for OIC. + ''' + env['CCFLAGS'].append('-g') + Export('env') +else: + ''' + If target_os is not Yocto, continue with the regular build process + ''' + # Load config of target os + if target_os in ['linux', 'tizen']: + env.SConscript('linux/SConscript') + else: + env.SConscript(target_os + '/SConscript') + +# Delete the temp files of configuration +if env.GetOption('clean'): + dir = env.get('SRC_DIR') + + if os.path.exists(dir + '/config.log'): + Execute(Delete(dir + '/config.log')) + Execute(Delete(dir + '/.sconsign.dblite')) + Execute(Delete(dir + '/.sconf_temp')) + +Return('env') diff --git a/build_common/android/SConscript b/build_common/android/SConscript new file mode 100644 index 000000000..4ae0fe492 --- /dev/null +++ b/build_common/android/SConscript @@ -0,0 +1,172 @@ +## +# This script includes android specific config (GNU GCC) +## +import os +import platform +import subprocess + +Import('env') + +help_vars = Variables() +help_vars.Add(PathVariable('ANDROID_NDK', 'Android NDK root directory', os.environ.get('ANDROID_NDK'))) +help_vars.Update(env) +Help(help_vars.GenerateHelpText(env)) + +android_ndk = env.get('ANDROID_NDK') +if not android_ndk: + print ''' +*************************************** Error ********************************* +* Android NDK path isn't set, you can set enviornment variable ANDROID_NDK * +* or add it in command line as: * +* # scons ANDROID_NDK= ... * +******************************************************************************* +''' + Exit(1) + +# Overwrite suffixes and prefixes +if env['HOST_OS'] == 'win32': + env['OBJSUFFIX'] = '.o' + env['SHOBJSUFFIX'] = '.os' + env['LIBPREFIX'] = 'lib' + env['LIBSUFFIX'] = '.a' + env['SHLIBPREFIX'] = 'lib' + env['SHLIBSUFFIX'] = '.so' + env['LIBPREFIXES'] = ['lib'] + env['LIBSUFFIXES'] = ['.a', '.so'] + env['PROGSUFFIX'] = '' +elif platform.system().lower() == 'darwin': + env['SHLIBSUFFIX'] = '.so' + env['LIBSUFFIXES'] = ['.a', '.so'] + env['PROGSUFFIX'] = '' + +###################################################################### +# Set common flags +###################################################################### + +# Android build system default cofig +env.AppendUnique(CPPDEFINES = ['ANDROID']) +env.AppendUnique(SHCFLAGS = ['-Wa,--noexecstack']) +env.AppendUnique(LINKFLAGS = ['-Wl,--gc-sections', '-Wl,-z,nocopyreloc']) + +###################################################################### +# Probe Android NDK default flags +###################################################################### +ndk_build_cmd = android_ndk + '/ndk-build' +if env['HOST_OS'] == 'win32': + if os.path.isfile(ndk_build_cmd + '.cmd'): + ndk_build_cmd += '.cmd' + +if not os.path.isfile(ndk_build_cmd): + print ''' +*************************************** Error ********************************* +* It seems android ndk path is not set properly, please check if "%s" +* is the root directory of android ndk. * +******************************************************************************* +''' % android_ndk + Exit(1) + +ANDROID_HOME = os.environ.get('ANDROID_HOME') +if ANDROID_HOME is not None: + ANDROID_HOME = os.path.abspath(ANDROID_HOME) + +if ANDROID_HOME is None or not os.path.exists(ANDROID_HOME): + print ''' +*************************************** Warning ******************************* +* Enviornment variable ANDROID_HOME is not set properly. It should be the * +* root directory of android sdk. If you'd like build Java code, it's required.* +******************************************************************************* +''' + +target_arch = env.get('TARGET_ARCH') + +# Android ndk early version doesn't support C++11. Detect the toolchain version +# to make sure proper toolchain is used +for tc_ver in ['4.9', '4.8', '4.7', '']: + if os.path.exists(android_ndk + '/toolchains/x86-' + tc_ver): + break + +cmd = [ndk_build_cmd] +cmd.append('APP_ABI=' + target_arch) +cmd.append('APP_STL=gnustl_static') +if env.get('RELEASE'): + cmd.append('APP_OPTIM=release') +else: + cmd.append('APP_OPTIM=debug') +if tc_ver != '': + cmd.append('NDK_TOOLCHAIN_VERSION=' + tc_ver) +else: + print ''' +*************************************** Warning ******************************* +* To support C++11, the toolchain should be >= 4.7, please make sure your * +* android NDK is at least r8e! * +******************************************************************************* +''' + +cmd.append('-n') + +p = subprocess.Popen(cmd, stdout = subprocess.PIPE) + +for flags in p.stdout.readlines(): + if cmp(flags[0:10], 'TC_PREFIX=') == 0: # toolchain prefix (include path) + prefix = flags[10:].strip() + env.Replace(CC = prefix + 'gcc') + env.Replace(CXX = prefix + 'g++') + env.Replace(AR = prefix + 'ar') + env.Replace(RANLIB = prefix + 'ranlib') + + elif cmp(flags[0:7], 'CFLAGS=') == 0: + env.AppendUnique(CFLAGS = Split(flags[7:])) + + elif cmp(flags[0:9], 'CXXFLAGS=') == 0: + env.AppendUnique(CXXFLAGS = Split(flags[9:])) + + elif cmp(flags[0:8], 'CPPPATH=') == 0: + env.AppendUnique(CPPPATH = Split(flags[8:])) + + elif cmp(flags[0:8], 'SYSROOT=') == 0: + sysroot = flags[8:].strip() + env.AppendUnique(LINKFLAGS = ['--sysroot=' + sysroot]) + env.AppendUnique(LIBPATH = [sysroot + '/usr/lib']) + + elif cmp(flags[0:8], 'LDFLAGS=') == 0: + env.AppendUnique(LINKFLAGS = Split(flags[8:])) + + elif cmp(flags[0:7], 'TC_VER=') == 0: # set gnustl library path + ver = flags[7:].strip() + env.AppendUnique(LIBPATH = [android_ndk + '/sources/cxx-stl/gnu-libstdc++/' + + ver + '/libs/' + target_arch]) + + elif cmp(flags[0:9], 'PLATFORM=') == 0: # get target platform: android-x + platform_ver = flags[9+8:].strip() + if not platform_ver.isdigit(): + platform_ver = '' + +# Add external libraries including boost +env.AppendUnique(CPPPATH = [env.get('SRC_DIR') + '/out/android/include' ]) +if target_arch == 'x86': + env.AppendUnique(LIBPATH = [env.get('SRC_DIR') + '/out/android/lib/x86']) +else: + env.AppendUnique(LIBPATH = [env.get('SRC_DIR') + '/out/android/lib/arm-linux-androideabi']) + +###################################################################### +# Set release/debug flags +###################################################################### +if env.get('RELEASE'): + env.AppendUnique(CCFLAGS = ['-Os']) + env.AppendUnique(CPPDEFINES = ['NDEBUG']) + env.AppendUnique(LINKFLAGS = ['-s']) +else: + env.AppendUnique(CCFLAGS = ['-g']) + +# From android-5 (API > 20), all application must be built with flags '-fPIE' '-pie'. +# Due to the limitation of Scons, it's required to added it into the command line +# directly (otherwise, it will also be added when build share library) +env.Replace(CCCOM = '$CC -o $TARGET -c $CFLAGS $CCFLAGS $_CCCOMCOM -fPIE $SOURCES') +env.Replace(CXXCOM = '$CXX -o $TARGET -c $CXXFLAGS $CCFLAGS $_CCCOMCOM -fPIE $SOURCES') +env.Replace(LINKCOM = '$LINK -o $TARGET -pie $LINKFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS') + +# Fix android-ndk compatibility issue, make applications build on new NDK can run on old platform +#if platform_ver == '' or int(platform_ver) > 20: +# SConscript('compatibility/c_compat.scons') +# +#SConscript('compatibility/cpp11_compat.scons') diff --git a/build_common/android/compatibility/android_cpp11_compat.cpp b/build_common/android/compatibility/android_cpp11_compat.cpp new file mode 100644 index 000000000..dedc92721 --- /dev/null +++ b/build_common/android/compatibility/android_cpp11_compat.cpp @@ -0,0 +1,73 @@ +#include +#include "android_cpp11_compat.h" + +namespace OC { + template + void from_string(const std::string& s, T& result) { + std::stringstream ss(s); + ss >> result; // TODO handle errors + } +} + +namespace std { + + int stoi(const string& s) + { + int ret; + int &ref = ret; + OC::from_string(s, ref); + return ret; + } + + double stod(const std::string& s) + { + double ret; + double &ref = ret; + OC::from_string(s, ref); + return ret; + } + + long long stoll(const std::string& s) + { + long long ret; + long long int &ref = ret; + OC::from_string(s, ref); + return ret; + } + + unsigned long long stoull(const std::string& s) + { + unsigned long long ret; + unsigned long long &ref = ret; + OC::from_string(s, ref); + return ret; + } + + long double stold(const string& s) + { + long double ret; + long double &ref = ret; + OC::from_string(s, ref); + return ret; + } + + std::string to_string(int t) { + std::ostringstream os; + os << t; + return os.str(); + } + + std::string to_string(double t) { + std::ostringstream os; + os << t; + return os.str(); + } + + std::string to_string(uint32_t t) + { + std::ostringstream os; + os << t; + return os.str(); + } + +} // std diff --git a/build_common/android/compatibility/android_cpp11_compat.h b/build_common/android/compatibility/android_cpp11_compat.h new file mode 100644 index 000000000..78af52231 --- /dev/null +++ b/build_common/android/compatibility/android_cpp11_compat.h @@ -0,0 +1,25 @@ +#ifndef _ANDRDIO_STRING_H_ +#define _ANDRDIO_STRING_H_ + +#ifdef __ANDROID__ +#include + +#ifndef ANDROID_C11_COMPAT +using std::to_string; +#else +namespace std { + int stoi(const std::string& s); + double stod(const std::string& s); + long long stoll(const std::string& s); + unsigned long long stoull(const std::string& s); + long double stold(const string& s); + + std::string to_string(int i); + std::string to_string(uint32_t i); + std::string to_string(double d); +} +#endif + +#endif + +#endif \ No newline at end of file diff --git a/build_common/android/compatibility/c_compat.c b/build_common/android/compatibility/c_compat.c new file mode 100644 index 000000000..000428a77 --- /dev/null +++ b/build_common/android/compatibility/c_compat.c @@ -0,0 +1,60 @@ +#include + +/* from stdlib.h */ +float strtof(const char *nptr, char **endptr) +{ + return (float)strtod(nptr, endptr); +} + +double atof(const char *nptr) +{ + return strtod(nptr, NULL); +} + +int abs(int __n) +{ + return (__n < 0) ? -__n : __n; +} + +long labs(long __n) +{ + return (__n < 0L) ? -__n : __n; +} + +long long llabs(long long __n) +{ + return (__n < 0LL) ? -__n : __n; +} + +int rand(void) +{ + return (int)lrand48(); +} + +void srand(unsigned int __s) +{ + srand48(__s); +} + +long random(void) +{ + return lrand48(); +} + +void srandom(unsigned int __s) +{ + srand48(__s); +} + +/* from unistd.h */ +int getpagesize(void) +{ + extern unsigned int __page_size; + return __page_size; +} + +int __getpageshift(void) +{ + extern unsigned int __page_shift; + return __page_shift; +} diff --git a/build_common/android/compatibility/c_compat.scons b/build_common/android/compatibility/c_compat.scons new file mode 100644 index 000000000..8aa4456dc --- /dev/null +++ b/build_common/android/compatibility/c_compat.scons @@ -0,0 +1,20 @@ +## +# This script is for fixing android platform compatibility problem +## + +# To fix android NDK compatibility problem +# Some functions, e.g. rand, srand. strtof ... are static inline prior to +# android-L. So before android-L libc.so doesn't include them. If build +# on android-L and run on an old platform(earlier than android-L), there will +# be 'can't locate xxx' problem. +import os + +Import('env') + +sif_env = env.Clone() + +sif_lib = sif_env.StaticLibrary(env.get('BUILD_DIR') + '/c_compat', + env.SrcToObj(os.path.abspath('./c_compat.c'), env.get('SRC_DIR'))) + +env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')]) +env.AppendUnique(LIBS = ['c_compat']) \ No newline at end of file diff --git a/build_common/android/compatibility/cpp11_compat.scons b/build_common/android/compatibility/cpp11_compat.scons new file mode 100644 index 000000000..a06455f54 --- /dev/null +++ b/build_common/android/compatibility/cpp11_compat.scons @@ -0,0 +1,17 @@ +## +# This script is for fixing android platform compatibility problem +## +import os + +Import('env') + +env.AppendUnique(CPPDEFINES = ['ANDROID_C11_COMPAT']) + +cc_env = env.Clone() +cc_env.AppendUnique(CPPPATH = ['.']) +cc_lib = cc_env.StaticLibrary(env.get('BUILD_DIR') + '/android_cpp11_compat', + env.SrcToObj(os.path.abspath('./android_cpp11_compat.cpp'), env.get('SRC_DIR'))) + +env.AppendUnique(CPPPATH = [os.path.abspath('.')]) +env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')]) +env.AppendUnique(LIBS = ['android_cpp11_compat']) diff --git a/build_common/android/jni/Android.mk b/build_common/android/jni/Android.mk new file mode 100644 index 000000000..282900a36 --- /dev/null +++ b/build_common/android/jni/Android.mk @@ -0,0 +1,12 @@ +include $(CLEAR_VARS) +LOCAL_MODULE := flags_probe +include $(BUILD_SHARED_LIBRARY) + +$(info TC_PREFIX=$(TOOLCHAIN_PREFIX)) +$(info CFLAGS=$(TARGET_CFLAGS)) +$(info CXXFLAGS=$(TARGET_CXXFLAGS) $(TARGET_NO_EXECUTE_CFLAGS)) +$(info CPPPATH=$(TARGET_C_INCLUDES) $(__ndk_modules.$(APP_STL).EXPORT_C_INCLUDES)) +$(info SYSROOT=$(SYSROOT_LINK)) +$(info LDFLAGS=$(TARGET_LDFLAGS) $(TARGET_NO_EXECUTE_LDFLAGS) $(TARGET_NO_UNDEFINED_LDFLAGS) $(TARGET_RELRO_LDFLAGS)) +$(info TC_VER=$(TOOLCHAIN_VERSION)) +$(info PLATFORM=$(APP_PLATFORM)) \ No newline at end of file diff --git a/build_common/arduino/SConscript b/build_common/arduino/SConscript new file mode 100644 index 000000000..4c3a01f43 --- /dev/null +++ b/build_common/arduino/SConscript @@ -0,0 +1,400 @@ +## +# This script includes arduino specific config +## +import os +import platform + +Import('env') + +def __parse_config(f): + dict = {} + + if not os.path.isfile(f): + return dict + + file = open(f, 'r') + strs = file.readlines() + for str in strs: + str = str.strip() + if len(str) > 0 and str[0] == '#': + continue + + idx = str.find('=') + if idx > 0: + dict.setdefault(str[0:idx], str[idx + 1:]) + + return dict + +def __get_boards(dict): + boards = [] + keys = dict.keys() + for key in keys: + idx = key.find('.name') + if idx > 0: + if key.endswith('.name'): + boards.append(key[0:idx]) + return boards + +def __get_cpu(dict, board): + cpus = [] + keys = dict.keys() + for key in keys: + idx = key.find(board + '.menu.cpu.') + start = len(board + '.menu.cpu.') + if idx >= 0: + end = key.find('.', start) + if end > 0: + cpu = key[start:end] + exist = False + for c in cpus: + if c == cpu: + exist = True + break + + if not exist: + cpus.append(cpu) + return cpus + +def __get_board_info(board, key): + if cpu: + v = boards_info.get(board + '.menu.cpu.' + cpu + key) + if not v: + v = boards_info.get(board + key) + else: + v = boards_info.get(board + key) + return v + +def __search_files(path, pattern, ondisk=True, source=True, strings=False, recursive=True): + if not recursive: + return Glob(pattern, ondisk, source, strings) + + matches = [] + for root, dirnames, filenames in os.walk(path): + matches.extend(Glob(root + '/' + pattern, ondisk, source, strings)) + + return matches + +# To make sure the src is built in 'BUILD_DIR' (by default it will be built at +# the same directory as the .c .cpp .S) +def __src_to_obj(env, srcs): + objs = [] + prefix = env.get('BOARD') + '_' + if env.get('CPU'): + prefix += env.get('CPU') + '_' + + build_dir = env.get('BUILD_DIR') + '/arduino/' + for src in srcs: + obj = src.path.replace(arduino_home, build_dir) + i = obj.rfind('.') + obj = obj[0:i] + if env.get('OBJSUFFIX'): + obj += env.get('OBJSUFFIX') + objs.extend(env.Object(obj, src, OBJPREFIX=prefix)) + return objs + +def __import_lib(env, lib): + lib_path = arduino_home + '/libraries/' + lib + if not os.path.exists(lib_path): + if target_arch == 'avr': + lib_path = arduino_home + '/hardware/arduino/avr/libraries/' + lib + else: + lib_path = arduino_home + '/hardware/arduino/sam/libraries/' + lib + + if os.path.exists(lib_path + '/src'): + lib_path = lib_path + '/src' + + env.AppendUnique(CPPPATH = [lib_path]) + + if os.path.exists(lib_path + '/utility'): + env.AppendUnique(CPPPATH = [lib_path + '/utility']) + + lib_src = [] + lib_src.extend(__search_files(lib_path, '*.S')) + lib_src.extend(__search_files(lib_path, '*.c')) + lib_src.extend(__search_files(lib_path, '*.cpp')) + + build_dir = env.get('BUILD_DIR') + if build_dir: + lib_a = env.StaticLibrary(build_dir + lib, __src_to_obj(env, lib_src)) + else: + lib_a = env.StaticLibrary(lib, __src_to_obj(env, lib_src)) + env.AppendUnique(LIBS = [File(lib_a[0])]) + +def __build_core(env): + core_src = __search_files(core_folder, '*.S') + core_src.extend(__search_files(core_folder, '*.c')) + core_src.extend(__search_files(core_folder, '*.cpp')) + + core_src.extend(__search_files(variant_folder, '*.S')) + core_src.extend(__search_files(variant_folder, '*.c')) + core_src.extend(__search_files(variant_folder, '*.cpp')) + + core_obj = __src_to_obj(env, core_src) + build_dir = env.get('BUILD_DIR') + if build_dir: + s_core = env.StaticLibrary(build_dir + 'core', core_obj) + else: + s_core = env.StaticLibrary('core', core_obj) + env.AppendUnique(LIBS = [File(s_core[0])]) + + # To avoid compiler issue. Otherewise there may be warnings: + # undefined reference to '_exit' '_close', '_getpid' ... + # Above functions are used in libc.a and implemented in syscalls_sam3.c + if env.get('TARGET_ARCH') == 'arm': + for obj in core_obj: + if obj.name.endswith('syscalls_sam3.o'): + env.AppendUnique(LIBS = [File(obj)]) + +def __create_bin(env, source): + name = source + if env.get('TARGET_ARCH') == 'avr': + eep = env.Command(name + '.eep', source, 'avr-objcopy -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 $SOURCE $TARGET') + hex = env.Command(name + '.hex', source, 'avr-objcopy -O ihex -R .eeprom $SOURCE $TARGET') + else: + hex = env.Command(name + '.hex', source, 'arm-none-eabi-objcopy -O binary $SOURCE $TARGET') + +# Print the command line that to upload binary to the board +def __upload_help(env): + if target_arch == 'avr': + protocol = __get_board_info(board, '.upload.protocol') + speed = __get_board_info(board, '.upload.speed') + + upload_cmd = arduino_home + '/hardware/tools/avr/bin/avrdude -C' + arduino_home +'/hardware/tools/avr/etc/avrdude.conf -v -v -v -v -p' \ + + mcu + ' -c' + protocol + ' -P' + ' -b' + speed + ' -D -Uflash:w::i' + else: + uu = __get_board_info(board, '.upload.native_usb') + upload_cmd = arduino_home + '/hardware/tools/bossac -i -d --port= -U ' + uu + ' -e -w -v -b -R' + + Help(''' +=============================================================================== +You can upload the bin file with following command line: +''') + Help('\n $ ' + upload_cmd) + Help(''' +\nPlease replace according to the actual situation. +=============================================================================== +''') + +# ARDUINO_HOME build option +help_vars = Variables() +help_vars.Add(PathVariable('ARDUINO_HOME', 'ARDUINO root directory', os.environ.get('ARDUINO_HOME'))) +help_vars.Update(env) +Help(help_vars.GenerateHelpText(env)) + +target_arch = env.get('TARGET_ARCH') +arduino_home = env.get('ARDUINO_HOME') +if not arduino_home: + print ''' +************************************* Error *********************************** +* Arduino root directory isn't set, you can set enviornment variable * +* ARDUINO_HOME or add it in command line as: * +* # scons ARDUINO_HOME= ... * +******************************************************************************* +''' + Exit(1) + +# Overwrite suffixes and prefixes +if env['HOST_OS'] == 'win32': + env['OBJSUFFIX'] = '.o' + env['SHOBJSUFFIX'] = '.os' + env['LIBPREFIX'] = 'lib' + env['LIBSUFFIX'] = '.a' + env['SHLIBPREFIX'] = 'lib' + env['SHLIBSUFFIX'] = '.so' + env['LIBPREFIXES'] = ['lib'] + env['LIBSUFFIXES'] = ['.a', '.so'] + env['PROGSUFFIX'] = '' +elif platform.system().lower() == 'darwin': + env['SHLIBSUFFIX'] = '.so' + env['LIBSUFFIXES'] = ['.a', '.so'] + env['PROGSUFFIX'] = '' + +# Debug/release relative flags +if env.get('RELEASE'): + env.AppendUnique(CCFLAGS = ['-Os']) + env.AppendUnique(CPPDEFINES = ['NDEBUG']) +else: + env.AppendUnique(CCFLAGS = ['-g']) + +# BOARD / CPU option + +# Get IDE version +if os.path.exists(arduino_home + '/lib/version.txt'): + vf = open(arduino_home + '/lib/version.txt', 'r') + version = vf.readline().replace('.', '') +else: + print ''' +************************************* Error *********************************** +* Can't find version file (lib/version.txt), please check if (%s) +* is arduino root directory. * +******************************************************************************* +''' % arduino_home + Exit(1) + +if version[0:2] == '10': + is_1_0_x = True + boards_info = __parse_config(arduino_home + '/hardware/arduino/boards.txt') + env.PrependENVPath('PATH', arduino_home + '/hardware/tools/avr/bin/') + env.Replace(CC = 'avr-gcc') + env.Replace(CXX = 'avr-g++') + env.Replace(AR = 'avr-ar') + env.Replace(AS = 'avr-as') + env.Replace(LINK = 'avr-gcc') + env.Replace(RANLIB = 'avr-ranlib') + if target_arch != 'avr': + print ''' +************************************* Error *********************************** +* Arduino 1.0.x IDE only support 'avr', to support other arch at least 1.5.x * +* is required. +******************************************************************************* +''' + Exit(1) +else: + is_1_0_x = False + if target_arch == 'avr': + boards_info = __parse_config(arduino_home + '/hardware/arduino/avr/boards.txt') + platform_info = __parse_config(arduino_home + '/hardware/arduino/avr/platform.txt') + elif target_arch == 'arm': + boards_info = __parse_config(arduino_home + '/hardware/arduino/sam/boards.txt') + platform_info = __parse_config(arduino_home + '/hardware/arduino/sam/platform.txt') + else: + print ''' +************************************* Error *********************************** +* CPU arch %s isn't supported currently. +******************************************************************************* +''' % target_arch + +#Board option, let user to select the board +boards = __get_boards(boards_info) +help_vars = Variables() +help_vars.Add(EnumVariable('BOARD', 'arduino board', boards[0], boards)) +help_vars.Update(env) +Help(help_vars.GenerateHelpText(env)) + +#CPU option +board = env.get('BOARD') +cpus = __get_cpu(boards_info, board) +if len(cpus) > 0: + help_vars = Variables() + help_vars.Add(EnumVariable('CPU', 'arduino board cpu', cpus[0], cpus)) + help_vars.Update(env) + Help(help_vars.GenerateHelpText(env)) + +# Arduino commom flags +cpu = env.get('CPU') +board = env.get('BOARD') +mcu = __get_board_info(board, '.build.mcu') +f_cpu = __get_board_info(board, '.build.f_cpu') +usb_vid = __get_board_info(board, '.build.vid') +usb_pid = __get_board_info(board, '.build.pid') +variant = __get_board_info(board, '.build.variant') + +if not usb_vid: + usb_vid = __get_board_info(board, '.vid.0') +if not usb_pid: + usb_pid = __get_board_info(board, '.pid.0') + +if is_1_0_x: + core_base = arduino_home + '/hardware/arduino/' +else: + if target_arch == 'avr': + core_base = arduino_home + '/hardware/arduino/avr/' + else: + core_base = arduino_home + '/hardware/arduino/sam/' + +variant_folder = core_base + 'variants/' + variant +env.AppendUnique(CPPPATH = [variant_folder]) + +core = __get_board_info(board, '.build.core') +core_folder = core_base + 'cores/' + core + '/' +env.AppendUnique(CPPPATH = [core_folder]) + +if is_1_0_x: + comm_flags = [] + if mcu: + comm_flags.extend(['-mmcu=' + mcu]) + if f_cpu: + comm_flags.extend(['-DF_CPU=' + f_cpu]) + comm_flags.extend(['-DARDUINO=' + version]) + if usb_vid: + comm_flags.extend(['-DUSB_VID=' + usb_vid]) + if usb_pid: + comm_flags.extend(['-DUSB_PID=' + usb_pid]) + + env.AppendUnique(ASFLAGS = ['-x', 'assembler-with-cpp']) + env.AppendUnique(ASFLAGS = comm_flags) + + env.AppendUnique(CFLAGS = ['-Os', '-ffunction-sections', '-fdata-sections', '-MMD']) + env.AppendUnique(CFLAGS = comm_flags) + + env.AppendUnique(CXXFLAGS = ['-Os', '-fno-exceptions', '-ffunction-sections', '-fdata-sections','-MMD']) + env.AppendUnique(CXXFLAGS = comm_flags) + + env.AppendUnique(LINKFLAGS = ['-Os']) + if mcu == 'atmega2560': + env.AppendUnique(LINKFLAGS = ['-Wl,--gc-sections,--relax']) + else: + env.AppendUnique(LINKFLAGS = ['-Wl,--gc-sections']) + env.AppendUnique(LINKFLAGS = ['-mmcu=' + mcu]) +else: + if target_arch == 'avr': + cpu_flag = '-mmcu=' + mcu + else: + cpu_flag = '-mcpu=' + mcu + + comm_flag = [cpu_flag, '-DF_CPU=' + f_cpu, '-DARDUINO=' + version, '-DARDUINO_' + __get_board_info(board, '.build.board')] + if target_arch == 'arm': + comm_flag.extend(['-DARDUINO_ARCH_SAM']) + else: + comm_flag.extend(['-DARDUINO_ARCH_AVR']) + + compiler_path = platform_info.get('compiler.path') + compiler_path = compiler_path.replace('{runtime.ide.path}', arduino_home) + env.PrependENVPath('PATH', compiler_path) + env.Replace(CC = platform_info.get('compiler.c.cmd')) + env.Replace(CXX = platform_info.get('compiler.cpp.cmd')) + env.Replace(AR = platform_info.get('compiler.ar.cmd')) + if target_arch == 'arm': + env.AppendUnique(CPPPATH = [arduino_home + '/hardware/arduino/sam/system/libsam', + arduino_home + '/hardware/arduino/sam/system/CMSIS/CMSIS/Include/', + arduino_home + '/hardware/arduino/sam/system//CMSIS/Device/ATMEL']) + env.AppendUnique(ASFLAGS = ['-x', 'assembler-with-cpp']) + env.AppendUnique(ASFLAGS = comm_flag) + env.AppendUnique(CFLAGS = Split(platform_info.get('compiler.c.flags'))) + env.AppendUnique(CXXFLAGS = Split(platform_info.get('compiler.cpp.flags'))) + env.AppendUnique(ARFLAGS = Split(platform_info.get('compiler.ar.flags'))) + env.AppendUnique(CCFLAGS = comm_flag) + + extra_flags = __get_board_info(board, '.build.extra_flags') + if extra_flags: + extra_flags = extra_flags.replace('{build.usb_flags}', '') + env.AppendUnique(CCFLAGS = Split(extra_flags)) + usb_flags = ['-DUSB_VID=' + usb_vid, '-DUSB_PID=' + usb_pid, '-DUSBCON', '-DUSB_MANUFACTURER="Unknown"'] + env.AppendUnique(CCFLAGS = usb_flags) + + if target_arch == 'arm': + env.AppendUnique(LINKFLAGS = ['-Os', '-Wl,--gc-sections', cpu_flag, + '-T' + variant_folder + '/' + __get_board_info(board, '.build.ldscript'), + '-Wl,-Map,' + env.get('BUILD_DIR') + 'arduino_prj.map']) + env.AppendUnique(LINKFLAGS = Split('-lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group')) + + variant_system_lib = __get_board_info(board, '.build.variant_system_lib') + if variant_system_lib: + if variant_folder.find(' ') >= 0: + variant_folder = '"' + variant_folder + '"' + env.Replace(LINKCOM = '$LINK -o $TARGET $_LIBDIRFLAGS $LINKFLAGS $SOURCES $_LIBFLAGS ' + + variant_folder + '/' + variant_system_lib + ' -Wl,--end-group') + else: + env.Replace(LINKCOM = '$LINK -o $TARGET $_LIBDIRFLAGS $LINKFLAGS $SOURCES $_LIBFLAGS -Wl,--end-group') + else: + env.AppendUnique(LINKFLAGS = Split(platform_info.get('compiler.c.elf.flags'))) + env.AppendUnique(LINKFLAGS = [cpu_flag]) + env.AppendUnique(LIBS = 'm') + env.Replace(ARCOM = '$AR ' + platform_info.get('compiler.ar.flags') + ' $TARGET $SOURCES') + +__build_core(env) + +env.AddMethod(__import_lib, "ImportLib") #import arduino library +#env.AddMethod(__build_core, "BuildCore") #build arduino core +env.AddMethod(__create_bin, "CreateBin") #create binary files(.eep and .hex) +env.AddMethod(__upload_help, "UploadHelp") #print the command line that to upload binary to the boardf diff --git a/build_common/darwin/SConscript b/build_common/darwin/SConscript new file mode 100644 index 000000000..7d57774fe --- /dev/null +++ b/build_common/darwin/SConscript @@ -0,0 +1,54 @@ +## +# This script set darwin specific flags (GNU GCC) +# +## +import os +import platform + +Import('env') + +# SYS_VERSION build option +help_vars = Variables() +help_vars.Add('SYS_VERSION', 'MAC OS X version / IOS version', os.environ.get('SYS_VERSION')) +help_vars.Update(env) +Help(help_vars.GenerateHelpText(env)) + +sys_version = env.get('SYS_VERSION') + +if sys_version is None: + print ''' +*********************************** Error ************************************* +* MAC OSX/IOS version isn't set, please set it in command line as : * +* # scons SYS_VERSION= ... * +* To get the version, please see: * +* /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ * +* /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/ * +******************************************************************************* +''' + Exit(1) + +target_arch = env.get('TARGET_ARCH') +target_os = env.get('TARGET_OS') +# Set release/debug flags +if env.get('RELEASE'): + env.AppendUnique(CCFLAGS = ['-Os']) + env.AppendUnique(CPPDEFINES = ['NDEBUG']) +else: + env.AppendUnique(CCFLAGS = ['-g']) + +if target_os == 'darwin': + sys_root = '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX' + sys_version + '.sdk/' +else: + if target_arch in ['i386', 'x86_64']: + sys_root = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator' + sys_version + '.sdk/' + else: + sys_root = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS' + sys_version + '.sdk/' + +# Set arch flags +env.AppendUnique(CCFLAGS = ['-arch', target_arch, '-isysroot', sys_root]) +env.AppendUnique(LINKFLAGS = ['-arch', target_arch, '-isysroot', sys_root]) + +if target_os == 'darwin': + flag = '-mmacosx-version-min=' + sys_version + env.AppendUnique(CCFLAGS = [flag]) + env.AppendUnique(LINKFLAGS = [flag]) \ No newline at end of file diff --git a/build_common/ios/SConscript b/build_common/ios/SConscript new file mode 100644 index 000000000..fcf62aa59 --- /dev/null +++ b/build_common/ios/SConscript @@ -0,0 +1,18 @@ +## +# This script set ios specific flags (GNU GCC) +# +## +Import('env') + +# setting of IOS is almost the same as Darwin(MAC OSX) +env.SConscript('../darwin/SConscript') + +sys_version = env.get('SYS_VERSION') +if env.get('TARGET_ARCH') in ['i386', 'x86_64']: #Simulator + flag = '-mios-simulator-version-min=' + sys_version + env.AppendUnique(CCFLAGS = [flag]) + env.AppendUnique(LINKFLAGS = [flag]) +else: + flag = '-miphoneos-version-min=' + sys_version + env.AppendUnique(CCFLAGS = [flag]) + env.AppendUnique(LINKFLAGS = [flag]) \ No newline at end of file diff --git a/build_common/linux/SConscript b/build_common/linux/SConscript new file mode 100644 index 000000000..bb939bed3 --- /dev/null +++ b/build_common/linux/SConscript @@ -0,0 +1,33 @@ +## +# This script set linux specific flags (GNU GCC) +# +## +Import('env') + +# Set release/debug flags +if env.get('RELEASE'): + env.AppendUnique(CCFLAGS = ['-Os']) + env.AppendUnique(CPPDEFINES = ['NDEBUG']) + env.AppendUnique(LINKFLAGS = ['-s']) +else: + env.AppendUnique(CCFLAGS = ['-g']) + +# Set arch flags +target_arch = env.get('TARGET_ARCH') +if target_arch in ['x86']: + env.AppendUnique(CCFLAGS = ['-m32']) + env.AppendUnique(LINKFLAGS = ['-m32']) +elif target_arch in ['x86_64']: + env.AppendUnique(CCFLAGS = ['-m64']) + env.AppendUnique(LINKFLAGS = ['-m64']) +elif target_arch.find('v7a-hard') > 0: + env.AppendUnique(CPPFLAGS = ['-march=armv7-a']) + env.AppendUnique(CPPFLAGS = ['-mfloat-abi=hard']) + env.AppendUnique(CCFLAGS = ['-mfloat-abi=hard']) + env.AppendUnique(LINKFLAGS = ['-mfloat-abi=hard']) +elif target_arch.find('v7a') > 0: + env.AppendUnique(CPPFLAGS = ['-march=armv7-a']) +elif target_arch.find('arm64') > 0: + env.AppendUnique(CPPFLAGS = ['-march=armv8-a']) +else: + env.AppendUnique(CPPFLAGS = ['-march=armv5te']) diff --git a/build_common/windows/SConscript b/build_common/windows/SConscript new file mode 100644 index 000000000..4c35d350e --- /dev/null +++ b/build_common/windows/SConscript @@ -0,0 +1,17 @@ +## +# This script includes windows specific config (MSVS/MSVC) +## +Import('env') + +# Set common flags +env.AppendUnique(CXXFLAGS=['/wd4244', '/wd4267','/wd4345', '/wd4355', '/wd4800', '/wd4996']) +env.AppendUnique(CCFLAGS=['/EHsc']) + +# Set release/debug flags +if env.get('RELEASE'): + env.AppendUnique(CCFLAGS = ['/MD', '/O2', '/GF']) + env.AppendUnique(CPPDEFINES = ['NDEBUG']) +else: + env.AppendUnique(CCFLAGS = ['/MDd', '/Od', '/ZI', '/GZ', '/Gm']) + env.AppendUnique(CPPDEFINES = ['_DEBUG']) + env.AppendUnique(LINKFLAGS = ['/debug']) diff --git a/examples/OICMiddle/Client.cpp b/examples/OICMiddle/Client.cpp new file mode 100644 index 000000000..8d6e7d16e --- /dev/null +++ b/examples/OICMiddle/Client.cpp @@ -0,0 +1,83 @@ +//****************************************************************** +// +// Copyright 2014 Intel Corporation. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include + +#include "WrapResource.h" +#include "Client.h" + +MiddleClient::MiddleClient() +{ + m_findCB = bind(&MiddleClient::foundOCResource, this, placeholders::_1); +} + +bool MiddleClient::init() +{ + findResources(); + return true; +} + +void MiddleClient::findResources() +{ + m_resourceMap.clear(); + + OC::OCPlatform::findResource("", OC_WELL_KNOWN_QUERY, m_findCB); +} + +void MiddleClient::foundOCResource(shared_ptr resource) +{ + WrapResource *wres; + string resourceID = formatResourceID(resource); + + m_mutexFoundCB.lock(); + + try { + wres = m_resourceMap.at(resourceID); + } catch (const std::out_of_range) { + wres = new WrapResource(resourceID, resource); + m_resourceMap[resourceID] = wres; + } + + m_mutexFoundCB.unlock(); + + wres->findTypes(); +} + +/* + * I need a unique ID, so I concatenate the host string and resource uri + * It's arbitrary and sufficient. + */ +string MiddleClient::formatResourceID(std::shared_ptr resource) +{ + string host = resource->host(); + if (host.compare(0, 7, "coap://") == 0) + host = host.erase(0, 7); + return host + resource->uri(); +} + +void MiddleClient::addResource(WrapResource *wres) +{ + string resourceID = wres->getResourceID(); + try { + m_resourceMap[resourceID]; + } catch (const std::out_of_range) { + m_resourceMap[resourceID] = wres; + } +} diff --git a/examples/OICMiddle/Client.h b/examples/OICMiddle/Client.h new file mode 100644 index 000000000..ef32e8635 --- /dev/null +++ b/examples/OICMiddle/Client.h @@ -0,0 +1,58 @@ +#ifndef CLIENT_H +#define CLIENT_H + +//****************************************************************** +// +// Copyright 2014 Intel Corporation. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include + +#include "OICMiddle.h" + +typedef map resourcemap_t; +typedef pair resourcemappair_t; + +class MiddleClient +{ +public: + MiddleClient(); + + bool init(); + void findResources(); + + friend class LineInput; + friend class HueResource; + friend class HueResources; + friend class RestInput; + +protected: + mutex m_mutexFoundCB; + map m_resourceMap; + HueResources *m_hueResources; + std::function resource)> m_findCB; + + void foundOCResource(shared_ptr resource); + string formatResourceID(std::shared_ptr resource); + void findHueResources(); + void addResource(WrapResource *wres); +}; + + +#endif // CLIENT_H + diff --git a/examples/OICMiddle/LineInput.cpp b/examples/OICMiddle/LineInput.cpp new file mode 100644 index 000000000..52a8528d8 --- /dev/null +++ b/examples/OICMiddle/LineInput.cpp @@ -0,0 +1,458 @@ +//****************************************************************** +// +// Copyright 2014 Intel Corporation. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include + +#include + +#include "WrapResource.h" +#include "LineInput.h" + +#define NEED_CLIENT { if (!m_client) return LR_NoClient; } + +LineInput::LineInput(MiddleClient *client) + : m_client(client), m_server(nullptr), + m_obsCB(nullptr), m_observer(nullptr) +{ + m_obsCB = std::bind(&LineInput::obsCB, this, + placeholders::_1, + placeholders::_2, + placeholders::_3, + placeholders::_4, + placeholders::_5); +} + +void LineInput::setServer(MiddleServer *server) { + m_server = server; +} + +int LineInput::run() +{ + size_t len; + char *line = nullptr; + + while (true) { + fputs(">", stdout); + len = 0; + getline(&line, &len, stdin); + int n = strlen(line); + if (!n) + continue; + if (m_observer) { + m_observer->cancelObserve(); + m_observer = nullptr; + } + if (line[n - 1] == '\n') { + if (n == 1) + continue; + line[n - 1] = '\0'; + } + stringstream result; + LineResult lr = processLine(line, result, m_obsCB); + if (lr == LR_Quit) + break; + cout << result.str(); + } + free(line); + return true; +} + +LineResult LineInput::processLine(string command, stringstream& result, observecb_t cb) +{ + elements_t elems; + + if (parseLine(command, elems) != LR_OK) { + cerr << "syntax error" << endl; + return LR_Syntax; + } + if (!elems.size()) + return LR_NoCommand; + + if (elems[0] == "quit" || elems[0] == "exit") + return LR_Quit; + + if (elems.size() == 1) { + if (elems[0] == "help") { + return processHelp(elems, result); + } else if (elems[0] == "find") { + NEED_CLIENT return processFind(elems, result); + } else if (elems[0] == "show") { + NEED_CLIENT return processShow(elems, result); + } + } else if (elems.size() == 2) { + if (elems[0] == "details") { + NEED_CLIENT return processDetails(elems, result); + } else if (elems[0] == "get") { + NEED_CLIENT return processGet(elems, result); + } else if (elems[0] == "observe") { + NEED_CLIENT return processObserve(elems, result, cb); + } else if (elems[0] == "cancel") { + NEED_CLIENT return processCancel(elems, result); + } + } else { + if (elems[0] == "put") { + NEED_CLIENT return processPut(elems, result); + } + } + + return processUnrecognized(elems, result); +} + +LineResult LineInput::processHelp(elements_t& elems, stringstream& ss) +{ + ss << "\nUsage:\n" + "\tfind\t\tFind resources\n" + "\tshow\t\tShow resources\n" + "\tdetails n\tShow details of resource n\n" + "\tget n\t\tGet value(s) of resource n\n" + "\tput n v\t\tPut value(s) to resource n\n" + "\tobserve n\tObserve value(s) of resource n\n" + "\thelp\t\tThis usage message\n" + "\nResource can be identified by Resource ID or Show index\n" + "\nValue in 'put' can be key=value or key:value\n\n" + ; + return LR_OK; +} + +LineResult LineInput::processUnrecognized(elements_t& elems, stringstream& ss) +{ + ss << "Command not recognized\n"; + processHelp(elems, ss); + return LR_Unrecognized; +} + +LineResult LineInput::processFind(elements_t& elems, stringstream& ss) +{ + m_client->findResources(); + return LR_OK; +} + +void LineInput::registerResourceWithServer(std::string & url) { + string type; + std::size_t index = url.rfind("/"); + if (index != std::string::npos) { + type = url.substr(index+1); + } + const std::string resType = type; + const std::string iface = "MB_INTERFACE"; + m_server->registerResource(url, resType, iface); +} + +LineResult LineInput::processShow(elements_t& elems, stringstream& ss) +{ + int index = 0; + m_resourceList.clear(); + resourcemap_t& pmap = m_client->m_resourceMap; + + for (resourcemap_t::iterator it = pmap.begin(); it != pmap.end(); it++) { + string resID = it->first; + ss << index++ << '\t' << resID << '\n'; + m_resourceList.push_back(resID); + if (m_server) { + registerResourceWithServer(resID); + } + } + + return LR_OK; +} + +LineResult LineInput::processDetails(elements_t& elems, stringstream& ss) +{ + WrapResource *wres = resolveResource(elems[1], ss); + if (!wres) + return LR_NoResource; + + ss << wres->getResourceID() + " [ "; + for (auto &types : wres->getResourceTypes()) { + ss << types + ' '; + } + ss << "] "; + for (auto &ifs : wres->getResourceInterfaces()) { + ss << ifs << " "; + } + ss << '\n'; + return LR_OK; +} + +void printJSONAsTable(std::string &jsonString) { + std::string str = jsonString; + std::string key, value; + size_t found = str.find("rep"); + if (found == std::string::npos) { // not found + return; + } + str = str.substr(found+5); + while (true) { + found = str.find(":"); + if (found == std::string::npos) { + return; + } + key = str.substr(1, found-1); + str = str.substr(found); + found = str.find(","); + if (found != std::string::npos) { + value = str.substr(1, found-1); + str = str.substr(found); + } else { + found = str.find("}"); + if (found != std::string::npos) { + value = str.substr(1, found-1); + str = str.substr(found); + } + } + cout << key << "\t:" << value << endl; + } +} + +LineResult LineInput::processGet(elements_t& elems, stringstream& ss) +{ + WrapResource *wres = resolveResource(elems[1], ss); + if (!wres) + return LR_NoResource; + + token_t token = wres->getResource(); + + WrapRequest *wreq = wres->waitResource(token); + if (!wreq) { + ss << "Get timed out\n"; + return LR_Timeout; + } + + std::string jsonRep = wreq->m_rep.getJSONRepresentation(); + //ss << jsonRep << endl; + printJSONAsTable(jsonRep); + return LR_OK; +} + +LineResult LineInput::processPut(elements_t& elems, stringstream& ss) +{ + WrapResource *wres = resolveResource(elems[1], ss); + if (!wres) + return LR_NoResource; + + string format; + OCRepresentation rep; + + bool error = false; + for (size_t i = 2; i < elems.size(); i++) { + string elem = elems[i]; + char *s = (char *)elem.c_str(); // elem string is intentionally damaged + char *key = strtok(s, "=:"); + char *value = strtok(nullptr, ""); + if (!value) { + ss << "missing separator in element starting with " << key << '\n'; + error = true; + continue; + } + char delim = value[0]; + size_t len = strlen(value); + if (delim == '\'' || delim == '"') { + if (len > 1 && delim == value[len - 1]) { + value[len - 1] = '\0'; + value++; + } + } + string v(value, len); + stringmap_t formats = wres->getFormats(); + try { + format = formats.at(key); + } catch (...) { + cerr << "element in arg " << i << " has no format\n"; + continue; + } + if (format == "bool") { + bool b = v != "0" && v != "false"; + rep.setValue(key, b); + } else if (format == "number") { + char *end; + int n = (int)strtol(value, &end, 10); + if (size_t(end - value) != len) { + double d = atof(value); + rep.setValue(key, d); + } else { + rep.setValue(key, n); + } + } else { // assume string + rep.setValue(key, v); + } + } + if (error) + return LR_Param; + + token_t token = wres->putResource(rep); + + WrapRequest *wreq = wres->waitResource(token); + if (!wreq) { + ss << "Get timed out\n"; + return LR_Timeout; + } + + return LR_OK; +} + +LineResult LineInput::processObserve(elements_t& elems, stringstream& ss, observecb_t cb) +{ + WrapResource *wres = resolveResource(elems[1], ss); + if (!wres) + return LR_NoResource; + m_observer = wres; + wres->observeResource(cb); + return LR_OK; +} + +LineResult LineInput::processCancel(elements_t& elems, stringstream& ss) +{ + WrapResource *wres = resolveResource(elems[1], ss); + if (!wres) + return LR_NoResource; + + wres->cancelObserve(); + m_observer = nullptr; + return LR_OK; +} + +WrapResource *LineInput::resolveResource(string resID, stringstream& ss) +{ + size_t len; + string useID = resID; + int index = std::stoi(useID, &len); + + if (len == resID.size()) { // it's an index, not a uri + if (size_t(index) >= m_resourceList.size()) { + cout << "Resource index out of range (use 'show')\n"; + return nullptr; + } + useID = m_resourceList[index]; // now it's a uri + } + + resourcemap_t::iterator it = m_client->m_resourceMap.find(useID); + if (it == m_client->m_resourceMap.end()) { + cout << resID << " is currently not available\n"; + return nullptr; + } + + return it->second; +} + +void LineInput::obsCB(token_t token, const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode, const int sequenceNumber) +{ + if (!m_observer) + return; + cout << "cb " << eCode << " " << sequenceNumber << '\n'; + cout << rep.getJSONRepresentation() << "\n"; +} + +ParseState LineInput::finishElem(char*& e, elements_t& elems) +{ + *e = '\0'; + elems.push_back(m_elem); + e = m_elem; + return PS_Between; +} + +ParseState LineInput::putCharInElem(char c, char *& e, ParseState newState) +{ + *e++ = c; + if (size_t(e - m_elem) >= sizeof (m_elem)) + throw 20; // hightly unlikely exception + return newState; +} + +/* + * See processHelp() above for line format + */ +LineResult LineInput::parseLine(string lineIn, elements_t& elems) +{ + const char *d; + char c, *e, delim; + bool isSep1, isSep2; + size_t len = lineIn.size(); + ParseState state = PS_Between; + const char *line = lineIn.c_str(); + + d = line; + e = m_elem; + while (true) { + if (size_t(d - line) >= len) { + if (e != m_elem) { + if (state == PS_Infirst || state == PS_Endsecond || (state == PS_Insecond && !delim)) { + state = finishElem(e, elems); + return LR_OK; + } + } + return LR_Syntax; + } + c = *d++; + if (c == '\n') + continue; + isSep1 = c == ' ' || c == '\t'; + isSep2 = c == '=' || c == ':'; + + switch (state) { + case PS_Between: + if (isSep1) + continue; + if (isSep2) + return LR_Syntax; + state = putCharInElem(c, e, PS_Infirst); + break; + case PS_Infirst: + if (isSep1) { + state = finishElem(e, elems); + continue; + } + if (isSep2) { + delim = 0; + state = PS_Startsecond; + } + putCharInElem(c, e, state); + break; + case PS_Startsecond: + if (isSep1 || isSep2) + return LR_Syntax; + if (c == '\'' || c == '"' || c == '|') + delim = c; + state = putCharInElem(c, e, PS_Insecond); + break; + case PS_Insecond: + if (isSep1 && delim == 0) { + state = finishElem(e, elems); + continue; + } + if (c == delim) { + state = PS_Endsecond; + } + *e++ = c; + break; + case PS_Endsecond: + if (isSep1) { + state = finishElem(e, elems); + continue; + } + return LR_Syntax; + case PS_None: + return LR_Syntax; + } + } + return LR_OK; +} + + diff --git a/examples/OICMiddle/LineInput.h b/examples/OICMiddle/LineInput.h new file mode 100644 index 000000000..bc7d4afa2 --- /dev/null +++ b/examples/OICMiddle/LineInput.h @@ -0,0 +1,72 @@ +#ifndef LINEINPUT_H +#define LINEINPUT_H + +//****************************************************************** +// +// Copyright 2014 Intel Corporation. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "OICMiddle.h" +#include "Client.h" +#include "Server.h" + +typedef vector elements_t; + +enum ParseState { + PS_None, + PS_Between, + PS_Infirst, + PS_Startsecond, + PS_Insecond, + PS_Endsecond, +}; + +class LineInput +{ +public: + LineInput(MiddleClient *client); + void setServer(MiddleServer *server); + int run(); + LineResult processLine(string command, stringstream& result, observecb_t cb); + +protected: + MiddleClient *m_client; + MiddleServer *m_server; + vector m_resourceList; + observecb_t m_obsCB; + WrapResource *m_observer; + char m_elem[1000]; + + LineResult processHelp(elements_t& elems, stringstream& ss); + LineResult processUnrecognized(elements_t& elems, stringstream& ss); + LineResult processFind(elements_t& elems, stringstream& ss); + LineResult processShow(elements_t& elems, stringstream& ss); + LineResult processDetails(elements_t& elems, stringstream& ss); + LineResult processGet(elements_t& elems, stringstream& ss); + LineResult processPut(elements_t& elems, stringstream& ss); + LineResult processObserve(elements_t& elems, stringstream& ss, observecb_t cb); + LineResult processCancel(elements_t& elems, stringstream& ss); + WrapResource *resolveResource(string resID, stringstream& ss); + LineResult parseLine(string lineIn, elements_t& elems); + ParseState finishElem(char*& e, elements_t& elems); + ParseState putCharInElem(char c, char *& e, ParseState newState); + void obsCB(const token_t token, const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode, const int sequenceNumber); + void registerResourceWithServer(std::string &url); +}; + +#endif // LINEINPUT_H diff --git a/examples/OICMiddle/OICMiddle.cpp b/examples/OICMiddle/OICMiddle.cpp new file mode 100644 index 000000000..0da414599 --- /dev/null +++ b/examples/OICMiddle/OICMiddle.cpp @@ -0,0 +1,152 @@ +//****************************************************************** +// +// Copyright 2014 Intel Corporation. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// +// OICMiddle.cpp : OIC demo application for Minnowboard +// + +#include + +#include "OICMiddle.h" +#include "WrapResource.h" +#include "Client.h" +#include "Server.h" +#include "LineInput.h" +#include "RestInput.h" + +class Middle middle; // one and only + +Middle::Middle() : + m_appType(AT_None), + m_useLineInput(false), + m_useRestInput(false), + m_client(nullptr), + m_server(nullptr), + m_lineInput(nullptr), + m_restInput(nullptr) +{ +} + +void Middle::init() +{ + +} + +void Middle::run(int argc, char* argv[]) +{ + parseCommandLineOptions(argc, argv); + + startPlatform(); + + if (m_appType & AT_Client) { + m_client = new MiddleClient(); + m_client->init(); + } + + m_lineInput = new LineInput(m_client); + + if (m_appType & AT_Server) { + m_server = new MiddleServer(); + m_server->init(); + } + if (m_useRestInput) { + if (!m_server) { + m_server = new MiddleServer(); + m_server->init(); + } + m_restInput = new RestInput(m_lineInput); + m_restInput->init(); + } + if (m_useLineInput) { + if (m_server) { + m_lineInput->setServer(m_server); + } + m_lineInput->run(); + } else { + while (true) + sleep(1); + } +} + +void Middle::startPlatform() +{ + uint16_t port = 0; + //std::string ipaddr = INADDR_ANY; + std::string ipaddr = "0.0.0.0"; + + PlatformConfig cfg { ServiceType::InProc, ModeType::Both, + ipaddr, port, QualityOfService::LowQos}; + + OC::OCPlatform::Configure(cfg); +} + +void Middle::provideHelp() +{ + static const char usage[] = "\nUsage: IOCMiddle args\n" + " where args may include any of these:\n" + "\t-client Run OIC client\n" + "\t-server Run OIC server\n" + "\t-both Run OIC client and server\n" + "\t-console Run console line interpreter\n" + "\t-rest Run ReST server\n" + "\t-hue addr Enable Hue resources on bridge at addr\n" + "\t-help Show Usage again\n" + "Any combination of the above is okay.\n\n"; + cout << usage; +} + +bool Middle::parseCommandLineOptions(int argc, char *argv[]) +{ + bool any = false; + + for (int i = 1; i < argc; i++) { + if (argv[i] == string("-server")) { + middle.m_appType = AT_Server; any = true; + } else if (argv[i] == string("-client")) { + middle.m_appType = AT_Client; any = true; + } else if (argv[i] == string("-both")) { + middle.m_appType = AT_Both; any = true; + } else if (argv[i] == string("-console")) { + middle.m_useLineInput = true; any = true; + } else if (argv[i] == string("-rest")) { + middle.m_useRestInput = true; any = true; + } else if (argv[i] == string("-hue")) { + if (i + 1 < argc && argv[i + 1][0] != '-') { + m_hueAddr = argv[++i]; + any = true; + } + } else if (argv[i] == string("-help")) { + any = false; + break; + } else { + std::cerr << "Not enough or invalid arguments, please try again.\n"; + exit(1); + } + } + if (!any) + provideHelp(); + return true; +} + +int main(int argc, char* argv[]) +{ + middle.run(argc, argv); + return 0; +} diff --git a/examples/OICMiddle/OICMiddle.h b/examples/OICMiddle/OICMiddle.h new file mode 100644 index 000000000..457b7a8fd --- /dev/null +++ b/examples/OICMiddle/OICMiddle.h @@ -0,0 +1,94 @@ +#ifndef OICMIDDLE_H +#define OICMIDDLE_H + +//****************************************************************** +// +// Copyright 2014 Intel Corporation. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include "OCPlatform.h" +#include "OCApi.h" + +class MiddleClient; +class MiddleServer; +class LineInput; +class RestInput; +class WrapResource; +class HueResources; + +using namespace OC; +using namespace std; + +enum AppType { + AT_None = 0, + AT_Server = 1, + AT_Client = 2, + AT_Both = 3 +}; + +enum LineResult { + LR_OK, + LR_NoCommand, + LR_NoClient, + LR_NoResource, + LR_Timeout, + LR_Param, + LR_Unrecognized, + LR_Quit, + LR_Syntax, + LR_Error +}; + +class HueResource; + +typedef int token_t; +typedef map stringmap_t; + +class Middle +{ +public: + Middle(); + void init(); + void run(int argc, char* argv[]); + +protected: + friend class MiddleClient; + friend class MiddleServer; + friend class RestInput; + friend class HueResources; + + AppType m_appType; + bool m_useLineInput; + bool m_useRestInput; + string m_hueAddr; + MiddleClient *m_client; + MiddleServer *m_server; + LineInput *m_lineInput; + RestInput *m_restInput; + +protected: + void startPlatform(); + bool parseCommandLineOptions(int argc, char *argv[]); + void provideHelp(); +}; + +extern Middle middle; + +#endif // OICMIDDLE_H diff --git a/examples/OICMiddle/README b/examples/OICMiddle/README new file mode 100644 index 000000000..518fb2a3a --- /dev/null +++ b/examples/OICMiddle/README @@ -0,0 +1,37 @@ +OICMiddle was written to +* be part of a demonstration of OIC Yocto capability, +* act as an example of resource callbacks using class methods, +* provide a simple promiscuous resource editor for examining OIC systems, and +* act as a starting code base for further exploration of OIC capabilities. + +As a demonstration, it runs on an Minnowboard running a Yocto-built OS, acting +as a gateway between an Android device (acting as an OIC client) and an +Edison board (acting as an OIC server) with sensors and actuators. + +As an example of resource callbacks, it shows a method of using class methods +as callbacks, a critical capability not shown in any of the examples in +iotivity/resource/examples. + +As a promiscuous resource editor, it can find, get, put and observe any +resource using a simple command-line interface using the system console. + +As a code base, the command-line editor can be the basis for adding additional +editing capabilities, like the additions of various filters. + +Running OICMiddle with no arguments on a console shows the various capabilities +it offers. The most important are: + -client. Act as an OIC client. + -console. Accept command lines from console input to drive the OIC client. + -server. Advertise resources found by the OIC client as OIC resources. + +The -server capabilites might be the basis for a gateway. + +Typing 'help' (or invalid commands) to the console gives a console usage +message. The important ones are: + find Find all resources. Also performed automatically at startup. + show Show the found resources and an assigned index. + get Get the value(s) of the resource with the given index. + put Put one or more resource values for the given index. + + +12/24/2014 diff --git a/examples/OICMiddle/RestInput.cpp b/examples/OICMiddle/RestInput.cpp new file mode 100644 index 000000000..b6e240f35 --- /dev/null +++ b/examples/OICMiddle/RestInput.cpp @@ -0,0 +1,166 @@ +//****************************************************************** +// +// Copyright 2014 Intel Corporation. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "WrapResource.h" +#include "RestInput.h" +#include "LineInput.h" +#include "OICMiddle.h" + +using namespace std; + +#define BUFLEN 10000 +#define MAX_CONNS 5 + +static bool enableDebug = false; // set to true to print debug messages + +void printDebugMessage(std::string message) +{ + if (enableDebug) { + cout << "RestInput: " << message << endl; + } +} + +RestInput::RestInput(LineInput *lineInput) : m_lineInput(lineInput) +{ + m_data = (char*)malloc(BUFLEN); + m_thread = new std::thread[MAX_CONNS]; + m_threadCount = 0; +} + +bool RestInput::init() +{ + m_sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (m_sockfd < 0) { + cerr << "Failed to open socket. Exiting" << endl; + return false; + } + m_port = 1441; //listening on port 1441 + + m_serverAddr.sin_family = AF_INET; + m_serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); + m_serverAddr.sin_port = htons(m_port); + + if (::bind(m_sockfd, (struct sockaddr*)&m_serverAddr, sizeof m_serverAddr) < 0) { + cerr << "Failed to bind. Exiting " << endl; + return false; + } + + listen(m_sockfd, MAX_CONNS); + startAccept(m_sockfd); + return true; +} + +// accept incoming connection(s) +void RestInput::startAccept(int &sockfd) +{ + if (m_threadCount >= MAX_CONNS) { + cerr << " Max # of connections reached. Skipping " << endl; + return; + } else { + while (true) { + int connfd = accept(sockfd, (struct sockaddr *)NULL, NULL); + if (connfd < 0) { + cerr << " Failed to accept incoming connection " << endl; + return; + } + int n = read(connfd, m_data, BUFLEN); + if (n < 0) { + cerr << "Failed to read from socket" << endl; + return; + } + startThread(); + } + } +} + +// start client thread +void RestInput::startThread() +{ + std::thread t(&RestInput::processClient, this); + m_thread[m_threadCount] = std::move(t); + m_thread[m_threadCount++].join(); +} + +// process read commands for the client +void RestInput::processClient(void) +{ + std::string restCmd = m_data; + std::size_t found = restCmd.find('\n'); + if (found != std::string::npos) { + restCmd = restCmd.substr(0, found-1); + } + handleRead(restCmd); +} + +void RestInput::handleRead(std::string& restCmd) +{ + parseString(restCmd); + if (restCmd.find("exit") == 0) { + std::thread::id id = std::this_thread::get_id(); + for(int i = 0; i < m_threadCount; ++i) { + if (id == m_thread[i].get_id()) { + m_thread[i].detach(); + --m_threadCount; + cout << "Exiting thread " << id << endl; + } + } + return; + } + stringstream ss; + observecb_t cb; + std::string msg = "command sent to LineInput is: " + restCmd; + printDebugMessage(msg); + m_lineInput->processLine(restCmd, ss, cb); + if (restCmd.find("show") != string::npos) { + // if command is show, we want to list out the details of each resource + handleShow(ss, cb); + } +} + +void RestInput::handleShow(stringstream &ss, observecb_t &cb) { + std::string temp = ss.str(); + size_t n = std::count(temp.begin(), temp.end(), '\n'); // number of resources found + std::stringstream sstm; + std::string lineInputData; + + for (size_t i = 0; i < n; ++i) { + sstm.str(""); + sstm << "details " << i; + lineInputData = sstm.str(); + std::string msg = "Details: " + lineInputData; + printDebugMessage(msg); + m_lineInput->processLine(lineInputData, ss, cb); + sstm.str(""); + sstm << "get " << i; + lineInputData = sstm.str(); + msg = "Get: " + lineInputData; + printDebugMessage(msg); + m_lineInput->processLine(lineInputData, ss, cb); + } +} + +void RestInput::parseString(std::string &toParse) +{ + std::size_t pos = toParse.find("HTTP"); // split on HTTP + toParse = toParse.substr(0, pos); + pos = toParse.find("/"); // find 1st occurance of / + toParse = toParse.substr(pos + 1, toParse.size() - 1); + std::replace(toParse.begin(), toParse.end(), '/', ' '); // replace all '/' with ' ' +} diff --git a/examples/OICMiddle/RestInput.h b/examples/OICMiddle/RestInput.h new file mode 100644 index 000000000..2e1cad6fd --- /dev/null +++ b/examples/OICMiddle/RestInput.h @@ -0,0 +1,50 @@ +#ifndef RESTINPUT_H +#define RESTINPUT_H + +//****************************************************************** +// +// Copyright 2014 Intel Corporation. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include + +class LineInput; +class Connection; + +class RestInput +{ +public: + RestInput(LineInput *lineInput); + bool init(); + void startAccept(int &sockfd); + void startThread(); + void processClient(void); + void handleRead(std::string & restCmd); + void handleShow(stringstream &ss, observecb_t &cb); + void parseString(std::string &toParse); + +protected: + LineInput *m_lineInput; + int m_sockfd, m_port, m_threadCount; + struct sockaddr_in m_serverAddr; + char *m_data; + std::thread *m_thread; +}; + +#endif // RESTINPUT_H + diff --git a/examples/OICMiddle/SConstruct b/examples/OICMiddle/SConstruct new file mode 100644 index 000000000..02a2d8e9b --- /dev/null +++ b/examples/OICMiddle/SConstruct @@ -0,0 +1,81 @@ +#For Yocto builds, set OS=yocto as a command-line argument to scons once +#the Yocto toolchain is installed and configured. + +#For Linux builds, set the following two variables: +#Set OIC_RESOURCE_PATH to the root of oic-resource on Ubuntu. + +OIC_RESOURCE_PATH = '../..' + +#Set OIC_LIBS_PATH to path on Ubuntu that contains liboc.so, liboctbstack.so, +#liboc_logger.so and libcoap.so. + +OIC_LIBS_PATH = '../../out/linux/x86_64/release' + +env = DefaultEnvironment() +target_os = ARGUMENTS.get("OS", "linux").lower() +output_dir = env.GetLaunchDir() + "/out/" + target_os +env.VariantDir(output_dir, env.GetLaunchDir(), duplicate=0) +env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall']) +env.AppendUnique(LINKFLAGS = ['-pthread']) +env.AppendUnique(LIBS = ['oc', 'octbstack', 'oc_logger', 'coap']) +env.Program(output_dir + '/OICMiddle', [output_dir + '/OICMiddle.cpp', + output_dir + '/Client.cpp', + output_dir + '/Server.cpp', + output_dir + '/WrapResource.cpp', + output_dir + '/LineInput.cpp', + output_dir + '/RestInput.cpp']) + +if target_os == "yocto": + ''' + This code injects Yocto cross-compilation flags into scons' default environment + in order to invoke the relevant tools while performing a build. + ''' + import os.path, re + sdk_root = '' + try: + CC = os.environ['CC'] + sdk_root = re.search(r'--sysroot=\S+', CC).group().split('=')[1] + target_prefix = CC.split()[0] + target_prefix = target_prefix[:len(target_prefix)-3] + tools = {"CC" : target_prefix+"gcc", + "CXX" : target_prefix+"g++", + "AS" : target_prefix+"as", + "LD" : target_prefix+"ld", + "GDB" : target_prefix+"gdb", + "STRIP" : target_prefix+"strip", + "RANLIB" : target_prefix+"ranlib", + "OBJCOPY" : target_prefix+"objcopy", + "OBJDUMP" : target_prefix+"objdump", + "AR" : target_prefix+"ar", + "NM" : target_prefix+"nm", + "M4" : "m4", + "STRINGS": target_prefix+"strings"} + PATH = os.environ['PATH'].split(os.pathsep) + for tool in tools: + if tool in os.environ: + for path in PATH: + if os.path.isfile(os.path.join(path, tools[tool])): + env[tool] = os.path.join(path, os.environ[tool]) + env.AppendUnique(CPPPATH = [ + sdk_root + '/usr/include/oic/', + sdk_root + '/usr/include/oic/stack/', + sdk_root + '/usr/include/oic/ocsocket/', + sdk_root + '/usr/include/oic/oc_logger/', + ]) + except: + print "ERROR configuring Yocto cross-toolchain environment." + Exit(1) +elif target_os == "linux": + if OIC_RESOURCE_PATH == '' or OIC_LIBS_PATH == '': + print "ERROR Please set both OIC_RESOURCE_PATH and OIC_LIBS_PATH in SConstruct" + Exit(1) + env.AppendUnique(CPPPATH = [ + OIC_RESOURCE_PATH + '/resource/include', + OIC_RESOURCE_PATH + '/resource/csdk/stack/include', + OIC_RESOURCE_PATH + '/resource/csdk/ocsocket/include', + OIC_RESOURCE_PATH + '/resource/oc_logger/include', + ]) + env.AppendUnique(LIBPATH = [OIC_LIBS_PATH]) +else: + print "ERROR ", target_os, " is an unsupported target" + Exit(1) diff --git a/examples/OICMiddle/Server.cpp b/examples/OICMiddle/Server.cpp new file mode 100644 index 000000000..b55e71556 --- /dev/null +++ b/examples/OICMiddle/Server.cpp @@ -0,0 +1,155 @@ +//****************************************************************** +// +// Copyright 2014 Intel Corporation. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "Server.h" +#include "OCPlatform.h" +#include "OCApi.h" + +namespace PH = std::placeholders; + +MiddleServer *serverObject = nullptr; // to be filled in by object + +MiddleServer::MiddleServer() +{ + cb = std::bind(&MiddleServer::entityHandler, this, std::placeholders::_1); + serverObject = this; +} + +bool MiddleServer::init() { + return true; +} + +OCEntityHandlerResult MiddleServer::entityHandler(const std::shared_ptr request) { + if (!request) { + return OC_EH_OK; + } + + std::string requestType = request->getRequestType(); + int requestFlag = request->getRequestHandlerFlag(); + bool responseNeeded = false; + + if (requestFlag && RequestHandlerFlag::InitFlag) { + return OC_EH_OK; + } + + if (requestFlag && RequestHandlerFlag::RequestFlag) { + if (requestType == "PUT") { + responseNeeded = true; + } else if (requestType == "GET") { + responseNeeded = true; + } else if (requestType == "POST") { // handle post requests here + } else if (requestType == "DELETE") { // handle delete requests here + } + } + + if (requestFlag && RequestHandlerFlag::ObserverFlag) { + } + + if (responseNeeded) { + auto response = std::make_shared(); + response->setRequestHandle(request->getRequestHandle()); + response->setResourceHandle(request->getResourceHandle()); + response->setErrorCode(200); + response->setResponseResult(OC_EH_OK); + if (OC_STACK_OK != OCPlatform::sendResponse(response)) { + return OC_EH_ERROR; + } + } + return OC_EH_OK; +} + +// for debug purposes - to see if the result of registerResource is valid or not +void MiddleServer::printRegisterResourceResult(OCStackResult &result) { + switch (result) { + case OC_STACK_OK: + cout << "OC_STACK_OK\n"; + break; + case OC_STACK_INVALID_URI: + cout << "OC_STACK_INVALID_URI\n"; + break; + case OC_STACK_INVALID_QUERY: + cout << "OC_STACK_INVALID_QUERY\n"; + break; + case OC_STACK_INVALID_IP: + cout << "OC_STACK_INVALID_IP\n"; + break; + case OC_STACK_INVALID_PORT: + cout << "OC_STACK_INVALID_PORT\n"; + break; + case OC_STACK_INVALID_CALLBACK: + cout << "OC_STACK_INVALID_CALLBACK\n"; + break; + case OC_STACK_INVALID_METHOD: + cout << "OC_STACK_INVALID_METHOD\n"; + break; + case OC_STACK_NO_MEMORY: + cout << "OC_STACK_NO_MEMORY\n"; + break; + case OC_STACK_COMM_ERROR: + cout << "OC_STACK_COMM_ERROR\n"; + break; + case OC_STACK_INVALID_PARAM: + cout << "OC_STACK_INVALID_PARAM\n"; + break; + case OC_STACK_NOTIMPL: + cout << "OC_STACK_NOTIMPL\n"; + break; + case OC_STACK_NO_RESOURCE: + cout << "OC_STACK_NO_RESOURCE\n"; + break; + case OC_STACK_RESOURCE_ERROR: + cout << "OC_STACK_RESOURCE_ERROR\n"; + break; + case OC_STACK_SLOW_RESOURCE: + cout << "OC_STACK_SLOW_RESOURCE\n"; + break; + case OC_STACK_NO_OBSERVERS: + cout << "OC_STACK_NO_OBSERVERS\n"; + break; + case OC_STACK_ERROR: + cout << "OC_STACK_ERROR\n"; + break; + default: + cout << "UNKNOWN\n"; + break; + } +} + +bool MiddleServer::registerResource(std::string & resourceUrl, const std::string& resourceTypeName, const std::string& resourceInterface) +{ + OCResourceHandle resourceHandle; + // OCResourceProperty is defined ocstack.h + uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE; + + //uncomment to enable debugging + + // This will internally create and register the resource. + OCStackResult result = OC::OCPlatform::registerResource( + resourceHandle, resourceUrl, resourceTypeName, + resourceInterface, + cb, + resourceProperty); + // enable this to see the result of registerResource + //printRegisterResourceResult_(result); + if (result != OC_STACK_OK) { + return false; + } + return true; +} diff --git a/examples/OICMiddle/Server.h b/examples/OICMiddle/Server.h new file mode 100644 index 000000000..049c708f3 --- /dev/null +++ b/examples/OICMiddle/Server.h @@ -0,0 +1,56 @@ +#ifndef SERVER_H +#define SERVER_H + +//****************************************************************** +// +// Copyright 2014 Intel Corporation. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "OICMiddle.h" + +class MiddleServer +{ +private: + std::string m_name; + bool m_state; + int m_power; + std::string m_url; + OCResourceHandle m_resourceHandle; + OCRepresentation *m_rep; + std::function)> cb; + +public: + MiddleServer(); + + bool init(); + bool createAndRegisterResources(std::vector &resourceUrlList, + std::vector &resourceTypeList, + std::vector &resourceInterfaceList, + std::vector &nameList, + std::vector &powerList, + std::vector &stateList); + OCEntityHandlerResult entityHandler(const std::shared_ptr); + + bool registerResource(std::string & resourceUrl, + const std::string &resourceTypeName, + const std::string & resourceInterface); +private: + void printRegisterResourceResult(OCStackResult &result); +}; + +#endif // SERVER_H diff --git a/examples/OICMiddle/WrapResource.cpp b/examples/OICMiddle/WrapResource.cpp new file mode 100644 index 000000000..3cadb7ddf --- /dev/null +++ b/examples/OICMiddle/WrapResource.cpp @@ -0,0 +1,289 @@ +//****************************************************************** +// +// Copyright 2014 Intel Corporation. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include + +#include "WrapResource.h" + +unsigned long GetTickCount() +{ + struct timeval tv; + if (gettimeofday(&tv, NULL) != 0) + return 0; + return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); +} + +WrapResource::WrapResource(string resourceID, ocresource_t resource) + : m_resourceID(resourceID), m_ocResource(resource), + m_listIndex(-1), m_x(0), m_repGetReady(false), m_gettingRep(false), + m_observeCB(nullptr), m_callbackRunning(false), + m_requestToken(0), m_observeRequest(nullptr), + m_typeRequest(nullptr) +{ +} + +string WrapResource::getResourceID() { + return m_resourceID; +} + +token_t WrapResource::getResource() +{ + WrapRequest *wreq; + QueryParamsMap m; + + wreq = newRequest(RT_Get); + m_ocResource->get(m, wreq->m_getCB, QualityOfService::HighQos); + return wreq->m_token; +} + +token_t WrapResource::putResource(OCRepresentation& rep) +{ + WrapRequest *wreq; + QueryParamsMap m; + + wreq = newRequest(RT_Put); + rep.setUri(m_ocResource->uri()); + m_ocResource->put(rep, m, wreq->m_putCB, QualityOfService::HighQos); + return wreq->m_token; +} + +token_t WrapResource::observeResource(observecb_t& cb) +{ + WrapRequest *wreq; + QueryParamsMap m; + ObserveType type; + + wreq = newRequest(RT_Observe); + m_observeRequest = wreq; + m_observeCB = cb; + m_callbackRunning = true; + type = ObserveType::Observe; + m_ocResource->observe(type, m, wreq->m_obsCB); + return wreq->m_token; +} + +bool WrapResource::cancelObserve() +{ + m_callbackRunning = false; + m_observeCB = nullptr; + + if (!m_observeRequest) + return false; + + OCStackResult result = m_ocResource->cancelObserve(); + if (result != OC_STACK_OK) + return false; + + m_observeRequest->m_touchTime = GetTickCount(); + return true; +} + +WrapRequest *WrapResource::waitResource(token_t token) +{ + WrapRequest *wreq; + cv_status st; + + try { + m_mutexMap.lock(); + wreq = m_requestMap.at(token); + m_mutexMap.unlock(); + } catch (const out_of_range& oor) { + m_mutexMap.unlock(); + return nullptr; + } + + std::unique_lock lk(m_mutexGet); + st = wreq->m_cvGet.wait_for(lk, chrono::seconds(5)); + return (st == cv_status::no_timeout) ? wreq : nullptr; +} + +std::vector WrapResource::getResourceTypes() +{ + return m_ocResource->getResourceTypes(); +} + +std::vector WrapResource::getResourceInterfaces() +{ + return m_ocResource->getResourceInterfaces(); +} + +WrapRequest *WrapResource::newRequest(RequestType type) +{ + WrapRequest *wreq = new WrapRequest(this, type, ++m_requestToken); + m_requestMap[m_requestToken] = wreq; + return wreq; +} + +void WrapResource::resourceCallback(WrapRequest *wreq) +{ + parseJSON(wreq); + + if (wreq->m_forTypeOnly) { + wreq->m_typeReady = true; + return; + } + + if (wreq->m_type == RT_Observe) { + if (!m_observeCB) { + if (m_callbackRunning) + cout << "callback missing " << m_resourceID << '\n'; + return; + } + m_observeCB(wreq->m_token, wreq->m_headerOptions, wreq->m_rep, wreq->m_eCode, + wreq->m_sequenceNumber); + } else { + wreq->m_cvGet.notify_one(); + } + + wreq->m_touchTime = GetTickCount(); +} + +/* + * this parser infers types from json string since no other introspection + * is available. It also parses the key-value pairs. + */ +void WrapResource::parseJSON(WrapRequest *wreq) +{ + string sep = "\":"; + string anchor = "\"rep\":{"; + string json = wreq->m_rep.getJSONRepresentation(); + string name, type, value, next; + size_t r, e, e1, s, c; + + r = json.find(anchor); + if (r == string::npos) { + return; + } + c = r + anchor.length() - 1; + do { + c++; + if (json[c] != '"') { + if (json[c] == '}') + break; + return; + } + c++; + e = json.find(sep, c); + if (e == string::npos) { + return; + } + name = json.substr(c, e - c); + s = e + sep.length(); + char q = json[s]; + switch (q) { + case 't': + case 'f': + type = "bool"; + e1 = json.find_first_of(",}", s + 1); + if (e1 == string::npos) { + return; + } + value = json.substr(s, e1 - s); + break; + case '"': + type = "string"; + s++; + e1 = json.find_first_of("\"", s); + if (e1 == string::npos) { + return; + } + value = json.substr(s, e1 - s); + e1++; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '.': + type = "number"; + e1 = json.find_first_of(",}", s + 1); + if (e1 == string::npos) { + return; + } + value = json.substr(s, e1 - s); + break; + default: + return; + } + wreq->m_valueMap[name] = value; // key-value map + m_typeMap[name] = type; // key-type map + c = e1; + } while (json[c] == ','); +} + +void WrapResource::findTypes() +{ + delete m_typeRequest; + m_typeRequest = new WrapRequest(this, RT_Get, ++m_requestToken); + m_typeRequest->m_forTypeOnly = true; + getResource(); +} + +const stringmap_t& WrapResource::getFormats() +{ + return m_typeMap; +} + +/********** WrapRequest ***********/ + +WrapRequest::WrapRequest(WrapResource *wres, RequestType type, token_t token) + : m_eCode(0), m_sequenceNumber(0), m_parent(wres), m_type(type), + m_token(token), m_forTypeOnly(false), m_typeReady(false) +{ + m_getCB = std::bind(&WrapRequest::getCB, this, + placeholders::_1, placeholders::_2, placeholders::_3); + m_putCB = std::bind(&WrapRequest::putCB, this, + placeholders::_1, placeholders::_2, placeholders::_3); + m_obsCB = std::bind(&WrapRequest::observeCB, this, + placeholders::_1, placeholders::_2, placeholders::_3, placeholders::_4); + m_touchTime = GetTickCount(); +} + +void WrapRequest::getCB(const HeaderOptions& headerOptions, const OCRepresentation& rep, int eCode) +{ + m_headerOptions = headerOptions; + m_rep = rep; + m_eCode = eCode; + m_parent->resourceCallback(this); +} + +void WrapRequest::putCB(const HeaderOptions& headerOptions, const OCRepresentation& rep, int eCode) +{ + m_headerOptions = headerOptions; + m_rep = rep; + m_eCode = eCode; + m_parent->resourceCallback(this); +} + +void WrapRequest::observeCB(const HeaderOptions& headerOptions, const OCRepresentation& rep, int eCode, int sequenceNumber) +{ + m_headerOptions = headerOptions; + m_rep = rep; + m_eCode = eCode; + m_sequenceNumber = sequenceNumber; + m_parent->resourceCallback(this); +} diff --git a/examples/OICMiddle/WrapResource.h b/examples/OICMiddle/WrapResource.h new file mode 100644 index 000000000..472ce12de --- /dev/null +++ b/examples/OICMiddle/WrapResource.h @@ -0,0 +1,121 @@ +#ifndef WRAPRESOURCE_H +#define WRAPRESOURCE_H + +//****************************************************************** +// +// Copyright 2014 Intel Corporation. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include + +#include "OCPlatform.h" +#include "OCApi.h" + +#include "OICMiddle.h" + +using namespace OC; +using namespace std; + +class WrapRequest; +class MiddleClient; + +enum RequestType { + RT_Get, + RT_Put, + RT_Observe, +}; + +typedef std::shared_ptr ocresource_t; +typedef std::map requestmap_t; +typedef std::function observecb_t; + +class WrapResource +{ +public: + WrapResource(string resourceID, ocresource_t resource); + + token_t getResource(); + token_t putResource(OCRepresentation& rep); + token_t observeResource(observecb_t& callback); + string getResourceID(); + bool cancelObserve(); + std::vector getResourceTypes(); + std::vector getResourceInterfaces(); + WrapRequest *waitResource(token_t token); + const stringmap_t& getFormats(); + + friend class WrapRequest; + friend class MiddleClient; + +protected: + WrapRequest *newRequest(RequestType type); + void resourceCallback(WrapRequest *wreq); + void parseJSON(WrapRequest *wreq); + void findTypes(); + + string m_resourceID; + ocresource_t m_ocResource; + int m_listIndex; + int m_x; + bool m_repGetReady; + bool m_gettingRep; + mutex m_mutexMap; + mutex m_mutexGet; + observecb_t m_observeCB; + bool m_callbackRunning; + int m_requestToken; + requestmap_t m_requestMap; + WrapRequest *m_observeRequest; // can only be one + stringmap_t m_typeMap; + vector m_typeResults; + WrapRequest *m_typeRequest; +}; + +struct WrapRequest +{ + WrapRequest(WrapResource *wres, RequestType type, token_t token); + + friend class WrapResource; + + HeaderOptions m_headerOptions; + OCRepresentation m_rep; + int m_eCode; + int m_sequenceNumber; + stringmap_t m_valueMap; + unsigned long m_touchTime; + +protected: + WrapResource *m_parent; + RequestType m_type; + token_t m_token; + condition_variable m_cvGet; + bool m_forTypeOnly; + bool m_typeReady; + + void getCB(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode); + void putCB(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode); + void observeCB(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode, const int sequenceNumber); + + GetCallback m_getCB; + PutCallback m_putCB; + ObserveCallback m_obsCB; +}; + +#endif // WRAPRESOURCE_H diff --git a/examples/OICMiddle/makefile b/examples/OICMiddle/makefile new file mode 100644 index 000000000..527921835 --- /dev/null +++ b/examples/OICMiddle/makefile @@ -0,0 +1,87 @@ +#//****************************************************************** +#// +#// Copyright 2014 Intel Corporation. +#// +#//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#// +#// Licensed under the Apache License, Version 2.0 (the "License"); +#// you may not use this file except in compliance with the License. +#// You may obtain a copy of the License at +#// +#// http://www.apache.org/licenses/LICENSE-2.0 +#// +#// Unless required by applicable law or agreed to in writing, software +#// distributed under the License is distributed on an "AS IS" BASIS, +#// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#// See the License for the specific language governing permissions and +#// limitations under the License. +#// +#//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +# override with `make BUILD=release` +# default to release build +BUILD := debug +PLATFORM := linux +CXX := g++ +#CXX := clang +OUT_DIR := $(BUILD) +OIC := ../.. +OIC_RES := $(OIC)/resource +OIC_LIB := $(OIC)/out/linux/x86_64/release +OBJS := OICMiddle.o \ + Client.o \ + Server.o \ + WrapResource.o \ + LineInput.o \ + RestInput.o + +CXX_FLAGS.debug := -O0 -g3 -std=c++0x -Wall -pthread + +CXX_FLAGS.release := -O3 -std=c++0x -Wall -pthread + +CXX_INC := -I$(OIC_RES)/include/ +CXX_INC += -I$(OIC_RES)/oc_logger/include +CXX_INC += -I$(OIC_RES)/csdk/stack/include +CXX_INC += -I$(OIC_RES)/csdk/ocsocket/include +CXX_INC += -I$(OIC_RES)/csdk/ocrandom/include +CXX_INC += -I$(OIC_RES)/csdk/logger/include +CXX_INC += -I$(OIC_RES)/csdk/libcoap +CXX_INC += -I$(OIC_RES)/../extlibs/cereal/include + +CXX_LIBS := $(OIC_LIB)/liboc.so +CXX_LIBS += $(OIC_LIB)/liboctbstack.so +CXX_LIBS += $(OIC_LIB)/liboc_logger.so +CXX_LIBS += $(OIC_LIB)/liboc_logger_core.so +CXX_LIBS += $(OIC_LIB)/libcoap.so + +all: prep_dirs OICMiddle + +prep_dirs: + -mkdir -p $(OUT_DIR) + +OICMiddle: $(OBJS) + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ $(OBJS) $(CXX_LIBS) + +OICMiddle.o: OICMiddle.cpp OICMiddle.h + $(CXX) -c $(CXX_FLAGS.$(BUILD)) OICMiddle.cpp $(CXX_INC) + +Client.o: Client.cpp Client.h OICMiddle.h + $(CXX) -c $(CXX_FLAGS.$(BUILD)) Client.cpp $(CXX_INC) + +Server.o: Server.cpp Server.h OICMiddle.h + $(CXX) -c $(CXX_FLAGS.$(BUILD)) Server.cpp $(CXX_INC) + +WrapResource.o: WrapResource.cpp WrapResource.h OICMiddle.h + $(CXX) -c $(CXX_FLAGS.$(BUILD)) WrapResource.cpp $(CXX_INC) + +LineInput.o: LineInput.cpp LineInput.h OICMiddle.h + $(CXX) -c $(CXX_FLAGS.$(BUILD)) LineInput.cpp $(CXX_INC) + +RestInput.o: RestInput.cpp RestInput.h OICMiddle.h + $(CXX) -c $(CXX_FLAGS.$(BUILD)) RestInput.cpp $(CXX_INC) + +clean: + rm $(OBJS) + rm -rf debug + rm -rf release + diff --git a/examples/OICSensorBoard/OICSensorBoardREADME.pdf b/examples/OICSensorBoard/OICSensorBoardREADME.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d5f9f2d8b26d04d14fc67fd17f4692f2d5071449 GIT binary patch literal 299033 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%0A0ciMO_IXI) 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

pnJ#_98~c?b=qDZ$bRdEmqR&)yscv9 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 Y7;Pc)@}L{F=Vv_GxPA>5Os_}FwLey~ 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ℜ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 W4GSKj;Ef9SPZT`Jr7nMS&;JMRI}B?8 literal 0 HcmV?d00001 diff --git a/resource/csdk/libcoap b/resource/csdk/libcoap new file mode 120000 index 000000000..ec55e690a --- /dev/null +++ b/resource/csdk/libcoap @@ -0,0 +1 @@ +libcoap-4.1.1 \ No newline at end of file diff --git a/resource/csdk/libcoap-4.1.1/ChangeLog b/resource/csdk/libcoap-4.1.1/ChangeLog new file mode 100644 index 000000000..404e33113 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/ChangeLog @@ -0,0 +1,159 @@ +2014-02-04 Olaf Bergmann + + * resource.c (coap_print_link): This function now takes an offset + where printing starts. This is used for generating blocks on the + fly. + + * net.c (wellknown_response): Added support for Block2 options + when generating a response for .well-known/core. + + * block.h (coap_opt_block_num): Fixed handling of zero-length + options. COAP_OPT_BLOCK_LAST now returns NULL when the option + value's length is zero. + +2014-01-07 Olaf Bergmann + + * resource.c (coap_print_link): Output partial resource + descriptions. The function now provides a sliding window over the + textual representation of the resource. Output starts at the given + offset and ends at the buffer's upper bound. The meaning of the + return value has changed to allow distinguishing whether or not + the resource description has been truncated at the buffer's upper + bound. + (print_wellknown): Support for the new coap_print_link(). An + additional parameter now is used to provide the offset into the + resource description. The meaning of the return value has been + adjusted accordingly. + +2013-12-23 Olaf Bergmann + + * configure.in: merged with LWIP port from chrysn + . This + introduces new compiler flags WITH_POSIX and WITH_LWIP to + distinguish target platforms. + +2013-09-03 Olaf Bergmann + + * option.h (coap_option_setb): increased size of option type + argument + + * tests/test_error_response.c (t_init_error_response_tests): new + tests for error response generation + + * tests/test_pdu.c (t_encode_pdu5): fixed number for option Accept + + * net.c (coap_new_error_response): fixed option size calculation + +2013-07-04 Olaf Bergmann + + * net.c (coap_new_context): register critical Accept option + + * pdu.c: option codes for Accept and Size1 according to coap-18 + +2013-02-01 Olaf Bergmann + + * coap_time.h (coap_clock_init_impl): fix invalid preprocessor + directive. #warning is now only used for gcc only (close sf bug #15) + + * net.c (wellknown_response): applied patch from chrysn to + fix bug in generation of .well-known/core representation + +2013-01-21 Olaf Bergmann + + * option.h: renamed option field in coap_opt_iterator_t to + next_option to detect erroneous use in old code + +2013-01-18 Olaf Bergmann + + * configure.in: new option --with-tests to enable unit tests + + * tests/testdriver.c: unit tests for parser functions + + * pdu.c (coap_pdu_parse): new PDU parser for Klaus-encoding + according to coap-13 + + * net.c (coap_read): call coap_pdu_parse() to check PDU integrity + + * option.c: Klaus-encoding for coap-13, including new option + iterator interface + +2012-11-20 Olaf Bergmann + + * net.c (next_option_safe): made option parsing more robust in + presence of option jumps + + * pdu.h: new option codes from draft-ietf-core-coap-12 + + * option.c (coap_opt_setlength): new function to set option length + + * uri.c (make_decoded_option): use coap_opt_setlength() instead of + obsolete macro COAP_OPT_SETLENGTH. + +2012-11-19 Olaf Bergmann + + * uri.c (make_decoded_option): use coap_opt_encode() instead of writing + +2012-11-03 Olaf Bergmann + + * net.c (coap_read): read new option encoding + +2012-11-01 Olaf Bergmann + + * option.c (coap_opt_size, coap_opt_value, coap_opt_length): + several functions to access fields of options (possibly preceeded + by option jump) + +2012-10-25 Olaf Bergmann + + * option.c (coap_opt_encode): new function for option encoding + with option jumps + +2012-03-23 Olaf Bergmann + + * examples/client.c (clear_obs): clear observation relationship after + user-specified duration + +2012-03-21 Olaf Bergmann + + * resource.c (print_wellknown): filtering by attributes + +2012-03-19 Olaf Bergmann + + * pdu.c (coap_add_option): allow more than 15 options. + +2012-03-15 Olaf Bergmann + + * examples/client.c (cmdline_uri): split path and query here to + make it easier to include these options in subsequent requests for + block transfer. + +2012-03-14 Olaf Bergmann + + * examples/etsi_iot_01.c: Support for POST, PUT, DELETE on /test + +2012-03-13 Olaf Bergmann + + * encode.c (coap_encode_var_bytes): more efficient coding for 0 + +2012-03-11 Olaf Bergmann + + * examples/etsi_iot_01.c: Test cases for 1st ETSI CoAP Plugtest, + March 24/25, 2012 in Paris, France. + +2012-03-10 Olaf Bergmann + + * block.c: support for block transfer. + +2012-03-07 Olaf Bergmann + + * examples/client.c (usage): new command line options + -B to set timeout after which the main loop is left. + -e to specify a payload (incompatible with -f) + (message_handler): bugfixes + + * resource.h: (coap_method_handler_t): new API for method handlers. + + +Copyright 2012 Olaf Bergmann, TZI +Copying and distribution of this file, with or without modification, are +permitted provided the copyright notice and this notice are preserved. diff --git a/resource/csdk/libcoap-4.1.1/LICENSE.BSD b/resource/csdk/libcoap-4.1.1/LICENSE.BSD new file mode 100644 index 000000000..2fc333a5d --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/LICENSE.BSD @@ -0,0 +1,26 @@ +Copyright (c) 2010--2011, Olaf Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + o Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + o Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/resource/csdk/libcoap-4.1.1/LICENSE.GPL b/resource/csdk/libcoap-4.1.1/LICENSE.GPL new file mode 100644 index 000000000..d8cf7d463 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/LICENSE.GPL @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/resource/csdk/libcoap-4.1.1/Makefile.in b/resource/csdk/libcoap-4.1.1/Makefile.in new file mode 100644 index 000000000..d9b1c555a --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/Makefile.in @@ -0,0 +1,113 @@ +# Makefile for libcoap +# +# Copyright (C) 2010--2013 Olaf Bergmann +# +# This file is part of the CoAP library libcoap. Please see +# README for terms of use. + +# the library's version +VERSION:=@PACKAGE_VERSION@ + +# tools +@SET_MAKE@ +RANLIB=@RANLIB@ +SHELL = /bin/sh +MKDIR = mkdir +ETAGS = @ETAGS@ + +abs_builddir = @abs_builddir@ +top_builddir = @top_builddir@ +package = @PACKAGE_TARNAME@-@PACKAGE_VERSION@ + +# files and flags +SOURCES:= pdu.c net.c debug.c encode.c uri.c coap_list.c resource.c hashkey.c \ + str.c option.c async.c subscribe.c block.c +OBJECTS:= $(patsubst %.c, %.o, $(SOURCES)) +HEADERS:=coap.h config.h debug.h pdu.h net.h encode.h uri.h coap_list.h mem.h \ + str.h option.h bits.h uthash.h utlist.h resource.h hashkey.h async.h \ + subscribe.h block.h address.h prng.h coap_time.h t_list.h +CFLAGS:=-Wall -Wextra -std=c99 -pedantic @CFLAGS@ +CPPFLAGS:=@CPPFLAGS@ +DISTDIR=$(top_builddir)/$(package) +SUBDIRS:=examples doc tests +FILES:=ChangeLog README LICENSE.BSD LICENSE.GPL Makefile.in configure configure.in config.h.in $(SOURCES) $(HEADERS) +LIB:=libcoap.a +LDSOFLAGS=-shared +LDFLAGS:=@LIBS@ +ARFLAGS:=cru +examples:=examples +doc:=doc +@BUILD_SO@ + +ifdef BUILD_SO + MACHINE?=$(shell $(CC) -dumpmachine) + ifeq ($(findstring Darwin, $(MACHINE)), Darwin) + LDSOFLAGS=-dynamiclib + LIBSO=libcoap.dylib + endif + ifeq ($(findstring Windows, $(MACHINE)), Windows) + LIBSO=libcoap.dll + endif + # more platforms go here + ifndef LIBSO + LIBSO=libcoap.so + endif + ifndef PICFLAG + CFLAGS+=-fPIC + else + CFLAGS+=$(PICFLAG) + endif +endif + +.PHONY: all dirs clean distclean .gitignore doc TAGS + +.SUFFIXES: +.SUFFIXES: .c .o + +all: $(LIB) $(LIBSO) dirs + +check: + echo DISTDIR: $(DISTDIR) + echo top_builddir: $(top_builddir) + $(MAKE) -C examples check + +dirs: $(SUBDIRS) + for dir in $^; do \ + $(MAKE) -C $$dir ; \ + done + +$(LIB): $(OBJECTS) + $(AR) $(ARFLAGS) $@ $^ + $(RANLIB) $@ + +$(LIBSO): $(OBJECTS) + $(LD) $(LDSOFLAGS) $(LDFLAGS) -o $@ $^ + +clean: + @rm -f $(PROGRAM) main.o $(LIB) $(LIBSO) $(OBJECTS) + for dir in $(SUBDIRS); do \ + $(MAKE) -C $$dir clean ; \ + done + +doc: + $(MAKE) -C doc + +distclean: clean + @rm -rf $(DISTDIR) + @rm -f *~ $(DISTDIR).tar.gz + +dist: $(FILES) $(SUBDIRS) + test -d $(DISTDIR) || mkdir $(DISTDIR) + cp $(FILES) $(DISTDIR) + for dir in $(SUBDIRS); do \ + $(MAKE) -C $$dir dist; \ + done + tar czf $(package).tar.gz $(DISTDIR) + +TAGS: + $(ETAGS) -o $@.new $(SOURCES) + $(ETAGS) -a -o $@.new $(HEADERS) + mv $@.new $@ + +.gitignore: + echo "core\n*~\n*.[oa]\n*.gz\n*.cap\n$(PROGRAM)\n$(DISTDIR)\n.gitignore" >$@ diff --git a/resource/csdk/libcoap-4.1.1/README b/resource/csdk/libcoap-4.1.1/README new file mode 100644 index 000000000..043a31774 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/README @@ -0,0 +1,42 @@ +libcoap: A C implementation of IETF Core Application protocol + +Copyright (C) 2010--2013 by Olaf Bergmann + +ABOUT LIBCOAP + +libcoap is a C implementation of a lightweight application-protocol +for devices that are constrained their resources such as computing +power, RF range, memory, bandwith, or network packet sizes. This +protocol, CoAP, is developed in the IETF working group "Constrained +RESTful Environments (core)", see . + +PACKAGE CONTENTS + +This directory contains a protocol parser and basic networking +functions for platform with support for malloc() and BSD-style +sockets. The examples directory contains a client and a server to +demonstrate the use of this library. + +LICENSE INFORMATION + +This library is published as open-source software without any warranty +of any kind. Use is permitted under the terms of the GNU General +Public License (GPL), Version 2 or higher, OR the revised BSD +license. Please refer to LICENSE.GPL oder LICENSE.BSD for further +details. + +NOTICE - TRANSITION TO SCONS + +The IoTivity build system is transitioning to SCONS. Although the +makefiles are still available (until v1.0) and some developers are +still using them, they are currently no longer supported. To learn more +about building using SCONS see Readme.scons.txt in the repository root +directory. The build steps used in continuous integration can be found +in auto_build.sh which is also in the the repository root directory. + +BUILD STEPS FOR INTEL OC STACK + +Use below command to build libcoap: +make all PLATFORM=linux +make all PLATFORM=android + diff --git a/resource/csdk/libcoap-4.1.1/SConscript b/resource/csdk/libcoap-4.1.1/SConscript new file mode 100644 index 000000000..d10bba064 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/SConscript @@ -0,0 +1,86 @@ +## +# libcoap (share library) build script +## + +Import('env') + +libcoap_env = env.Clone() + +target_os = env.get('TARGET_OS') +# As in the source code(C) includes arduino Time library head file(C++) +# It requires compile the .c with g++ +if target_os == 'arduino': + libcoap_env.Replace(CC = env.get('CXX')) + libcoap_env.Replace(CFLAGS = env.get('CXXFLAGS')) + +###################################################################### +# Build flags +###################################################################### +libcoap_env.PrependUnique(CPPPATH = [ + '../ocsocket/include', + '../ocmalloc/include', + '../logger/include', + '../ocrandom/include', + '../stack', + '../../oc_logger/include' + ]) + +if target_os not in ['arduino', 'windows', 'winrt']: + libcoap_env.AppendUnique(CPPDEFINES = ['WITH_POSIX']) + libcoap_env.AppendUnique(CFLAGS = ['-std=gnu99', '-fPIC']) + +if target_os not in ['windows', 'winrt']: + libcoap_env.AppendUnique(CFLAGS = ['-Wall', '-ffunction-sections', + '-fdata-sections', '-fno-exceptions']) + +if target_os == 'android': + libcoap_env.AppendUnique(LIBS = ['log']) + +if target_os == 'arduino': + libcoap_env.AppendUnique(CPPDEFINES = ['NDEBUG', 'WITH_ARDUINO']) + +if target_os in ['darwin', 'ios']: + libcoap_env.AppendUnique(CPPDEFINES = ['_DARWIN_C_SOURCE']) + +if not env.get('RELEASE'): + libcoap_env.AppendUnique(CPPDEFINES = ['TB_LOG']) + +###################################################################### +# Source files and Target(s) +###################################################################### +libcoap_src = [ + 'pdu.c', + 'net.c', + 'debug.c', + 'encode.c', + 'uri.c', + 'coap_list.c', +# 'resource.c', + 'hashkey.c', + 'str.c', + 'option.c', + 'async.c', + 'subscribe.c', + 'block.c', + '../logger/src/logger.c', + '../ocrandom/src/ocrandom.c', + '../ocmalloc/src/ocmalloc.c', + '../../oc_logger/c/oc_logger.c', + '../../oc_logger/c/oc_console_logger.c' + ] + +if target_os == 'arduino': + if env.get('NET') == 'Wifi': + libcoap_src.append(['../ocsocket/src/ocsocket_arduino_wifi.cpp']) + else: + libcoap_src.append(['../ocsocket/src/ocsocket_arduino.cpp']) +else: + libcoap_src.append(['../ocsocket/src/ocsocket.c']) + +if target_os == 'arduino': + static_libcoap = libcoap_env.StaticLibrary('libcoap', libcoap_src, OBJPREFIX='libcoap_') + libcoap_env.InstallTarget(static_libcoap, 'libcoap') +else: + static_libcoap = libcoap_env.StaticLibrary('libcoap', libcoap_src, OBJPREFIX='libcoap_') + shared_libcoap = libcoap_env.SharedLibrary('libcoap', libcoap_src, OBJPREFIX='libcoap_') + libcoap_env.InstallTarget([static_libcoap, shared_libcoap], 'libcoap') diff --git a/resource/csdk/libcoap-4.1.1/address.h b/resource/csdk/libcoap-4.1.1/address.h new file mode 100644 index 000000000..39e122182 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/address.h @@ -0,0 +1,208 @@ +/* address.h -- representation of network addresses + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file address.h + * @brief representation of network addresses + */ + +#ifndef _COAP_ADDRESS_H_ +#define _COAP_ADDRESS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "config.h" + +#ifdef HAVE_ASSERT_H +#include +#else +#ifndef assert +#warning "assertions are disabled" +# define assert(x) +#endif +#endif + +#include +#include +#include "ocsocket.h" + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef WITH_LWIP +#include + +typedef struct coap_address_t { + uint16_t port; + ip_addr_t addr; +} coap_address_t; + +/* FIXME oversimplification: just assuming it's an ipv4 address instead of + * looking up the appropraite lwip function */ + +#define _coap_address_equals_impl(A, B) ((A)->addr.addr == (B)->addr.addr && A->port == B->port) + +/* FIXME sure there is something in lwip */ + +#define _coap_is_mcast_impl(Address) 0 + +#endif /* WITH_LWIP */ +#ifdef WITH_CONTIKI +#include "uip.h" + +typedef struct coap_address_t { + unsigned char size; + uip_ipaddr_t addr; + unsigned short port; +} coap_address_t; + +#define _coap_address_equals_impl(A,B) \ + ((A)->size == (B)->size \ + && (A)->port == (B)->port \ + && uip_ipaddr_cmp(&((A)->addr),&((B)->addr))) + +#define _coap_is_mcast_impl(Address) uip_is_addr_mcast(&((Address)->addr)) +#endif /* WITH_CONTIKI */ + +#ifdef WITH_POSIX + +#pragma pack(push, 1) +/** multi-purpose address abstraction */ +typedef struct coap_address_t { + socklen_t size; /**< size of addr */ + union { + struct sockaddr sa; + struct sockaddr_storage st; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + } addr; +} coap_address_t; +#pragma pack(pop) + +static inline int +_coap_address_equals_impl(const coap_address_t *a, + const coap_address_t *b) { + if (a->size != b->size || a->addr.sa.sa_family != b->addr.sa.sa_family) + return 0; + + /* need to compare only relevant parts of sockaddr_in6 */ + switch (a->addr.sa.sa_family) { + case AF_INET: + return + a->addr.sin.sin_port == b->addr.sin.sin_port && + memcmp(&a->addr.sin.sin_addr, &b->addr.sin.sin_addr, + sizeof(struct in_addr)) == 0; + case AF_INET6: + return a->addr.sin6.sin6_port == b->addr.sin6.sin6_port && + memcmp(&a->addr.sin6.sin6_addr, &b->addr.sin6.sin6_addr, + sizeof(struct in6_addr)) == 0; + default: /* fall through and signal error */ + ; + } + return 0; +} + +static inline int +_coap_is_mcast_impl(const coap_address_t *a) { + if (!a) + return 0; + + switch (a->addr.sa.sa_family) { + case AF_INET: + return IN_MULTICAST(a->addr.sin.sin_addr.s_addr); +case AF_INET6: + return IN6_IS_ADDR_MULTICAST(&a->addr.sin6.sin6_addr); + default: /* fall through and signal error */ + ; + } + return 0; +} + +#endif /* WITH_POSIX */ + +#ifdef WITH_ARDUINO +typedef OCDevAddr coap_address_t; + +static inline int +_coap_address_equals_impl(const coap_address_t *a, + const coap_address_t *b) { + uint32_t i; + + if ((a == NULL) || (b == NULL)) + return 0; + + if (a->size != b->size) + return 0; + + for (i = 0; i < a->size; i++) + { + if (a->addr[i] != b->addr[i]) + return 0; + } + return 1; +} + +static inline int +_coap_is_mcast_impl(const coap_address_t *a) { + if (!a) + return 0; + + /* TODO */ + return 0; +} + +#endif /* WITH_ARDUINO */ + +/** + * Resets the given coap_address_t object @p addr to its default + * values. In particular, the member size must be initialized to the + * available size for storing addresses. + * + * @param addr The coap_address_t object to initialize. + */ +static inline void +coap_address_init(coap_address_t *addr) { + assert(addr); + memset(addr, 0, sizeof(coap_address_t)); +#ifndef WITH_LWIP + /* lwip has constandt address sizes and doesn't need the .size part */ + addr->size = sizeof(addr->addr); +#endif +} + +/** + * Compares given address objects @p a and @p b. This function returns + * @c 1 if addresses are equal, @c 0 otherwise. The parameters @p a + * and @p b must not be @c NULL; + */ +static inline int +coap_address_equals(const coap_address_t *a, const coap_address_t *b) { + assert(a); assert(b); + return _coap_address_equals_impl(a, b); +} + +/** + * Checks if given address @p a denotes a multicast address. This + * function returns @c 1 if @p a is multicast, @c 0 otherwise. + */ +static inline int +coap_is_mcast(const coap_address_t *a) { + return a && _coap_is_mcast_impl(a); +} + +#ifdef __cplusplus +} +#endif + +#endif /* _COAP_ADDRESS_H_ */ diff --git a/resource/csdk/libcoap-4.1.1/async.c b/resource/csdk/libcoap-4.1.1/async.c new file mode 100644 index 000000000..976bf6331 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/async.c @@ -0,0 +1,101 @@ +/* async.c -- state management for asynchronous messages + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file async.c + * @brief state management for asynchronous messages + */ + +#ifndef WITHOUT_ASYNC + +#include "config.h" + +#include "utlist.h" + +#include "mem.h" +#include "debug.h" +#include "async.h" + +coap_async_state_t * +coap_register_async(coap_context_t *context, coap_address_t *peer, + coap_pdu_t *request, unsigned char flags, void *data) { + coap_async_state_t *s; + coap_tid_t id; + + coap_transaction_id(peer, request, &id); + LL_SEARCH_SCALAR(context->async_state,s,id,id); + + if (s != NULL) { + /* We must return NULL here as the caller must know that he is + * responsible for releasing @p data. */ + debug("asynchronous state for transaction %d already registered\n", id); + return NULL; + } + + /* store information for handling the asynchronous task */ + s = (coap_async_state_t *)coap_malloc(sizeof(coap_async_state_t) + + request->hdr->token_length); + if (!s) { + coap_log(LOG_CRIT, "coap_register_async: insufficient memory\n"); + return NULL; + } + + memset(s, 0, sizeof(coap_async_state_t) + request->hdr->token_length); + + /* set COAP_ASYNC_CONFIRM according to request's type */ + s->flags = flags & ~COAP_ASYNC_CONFIRM; + if (request->hdr->type == COAP_MESSAGE_CON) + s->flags |= COAP_ASYNC_CONFIRM; + + s->appdata = data; + + memcpy(&s->peer, peer, sizeof(coap_address_t)); + + if (request->hdr->token_length) { + s->tokenlen = request->hdr->token_length; + memcpy(s->token, request->hdr->token, request->hdr->token_length); + } + + memcpy(&s->id, &id, sizeof(coap_tid_t)); + + coap_touch_async(s); + + LL_PREPEND(context->async_state, s); + + return s; +} + +coap_async_state_t * +coap_find_async(coap_context_t *context, coap_tid_t id) { + coap_async_state_t *tmp; + LL_SEARCH_SCALAR(context->async_state,tmp,id,id); + return tmp; +} + +int +coap_remove_async(coap_context_t *context, coap_tid_t id, + coap_async_state_t **s) { + coap_async_state_t *tmp = coap_find_async(context, id); + + if (tmp) + LL_DELETE(context->async_state,tmp); + + *s = tmp; + return tmp != NULL; +} + +void +coap_free_async(coap_async_state_t *s) { + if (s && (s->flags & COAP_ASYNC_RELEASE_DATA) != 0) + coap_free(s->appdata); + coap_free(s); +} + +#else +void does_not_exist(); /* make some compilers happy */ +#endif /* WITHOUT_ASYNC */ diff --git a/resource/csdk/libcoap-4.1.1/async.h b/resource/csdk/libcoap-4.1.1/async.h new file mode 100644 index 000000000..cf0554b47 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/async.h @@ -0,0 +1,154 @@ +/* async.h -- state management for asynchronous messages + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file async.h + * @brief state management for asynchronous messages + */ + + +#ifndef _COAP_ASYNC_H_ +#define _COAP_ASYNC_H_ + +#include "config.h" +#include "net.h" + +#ifndef WITHOUT_ASYNC + +/** + * @defgroup coap_async Asynchronous Messaging + * @{ + * Structure for managing asynchronous state of CoAP resources. A + * coap_resource_t object holds a list of coap_async_state_t objects + * that can be used to generate a separate response in case a result + * of an operation cannot be delivered in time, or the resource has + * been explicitly subscribed to with the option @c observe. + */ +typedef struct coap_async_state_t { + unsigned char flags; /**< holds the flags to control behaviour */ + + /** + * Holds the internal time when the object was registered with a + * resource. This field will be updated whenever + * coap_register_async() is called for a specific resource. + */ + coap_tick_t created; + + /** + * This field can be used to register opaque application data with + * the asynchronous state object. */ + void *appdata; + + unsigned short message_id; /**< id of last message seen */ + coap_tid_t id; /**< transaction id */ + + struct coap_async_state_t *next; /**< internally used for linking */ + + coap_address_t peer; /**< the peer to notify */ + size_t tokenlen; /**< length of the token */ +#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-pedantic" +#endif + __extension__ unsigned char token[]; /**< the token to use in a response */ +#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) +#pragma GCC diagnostic pop +#endif +} coap_async_state_t; + +/* Definitions for Async Status Flags These flags can be used to + * control the behaviour of asynchronous response generation. */ +#define COAP_ASYNC_CONFIRM 0x01 /**< send confirmable response */ +#define COAP_ASYNC_SEPARATE 0x02 /**< send separate response */ +#define COAP_ASYNC_OBSERVED 0x04 /**< the resource is being observed */ + +/** release application data on destruction */ +#define COAP_ASYNC_RELEASE_DATA 0x08 + +/** + * Allocates a new coap_async_state_t object and fills its fields + * according to the given @p request. The @p flags are used to control + * generation of empty ACK responses to stop retransmissions and to + * release registered @p data when the resource is deleted by + * coap_free_async(). This function returns a pointer to the registered + * coap_async_t object or @c NULL on error. Note that this function will + * return @c NULL in case that an object with the same identifier is + * already registered. + * + * @param context The context to use. + * @param peer The remote peer that is to be asynchronously notified. + * @param request The request that is handled asynchronously. + * @param flags Flags to control state management. + * @param data Opaque application data to register. Note that the + * storage occupied by @p data is released on destruction + * only if flag COAP_ASYNC_RELEASE_DATA is set. + * + * @return A pointer to the registered coap_async_state_t object or + * @c NULL in case of an error. + */ +coap_async_state_t * +coap_register_async(coap_context_t *context, coap_address_t *peer, + coap_pdu_t *request, unsigned char flags, void *data); + +/** + * Removes the state object identified by @p id from @p context. The + * removed object is returned in @p s, if found. Otherwise, @p s is + * undefined. This function returns @c 1 if the object was removed, @c + * 0 otherwise. Note that the storage allocated for the stored object + * is not released by this functions. You will have to call + * coap_free_async() to do so. + * + * @param context The context where the async object is registered. + * @param id The identifier of the asynchronous transaction. + * @param s Will be set to the object identified by @p id + * after removal. + * + * @return @c 1 if object was removed and @p s updated, or @c 0 if no + * object was found with the given id. @p s is valid only if the + * return value is @c 1. + */ +int coap_remove_async(coap_context_t *context, coap_tid_t id, + coap_async_state_t **s); + +/** + * Releases the memory that was allocated by coap_async_state_init() + * for the object @p s. The registered application data will be + * released automatically if COAP_ASYNC_RELEASE_DATA is set. + * + * @param s The object to delete. + */ +void +coap_free_async(coap_async_state_t *state); + +/** + * Retrieves the object identified by @p id from the list of asynchronous + * transactions that are registered with @p context. This function returns + * a pointer to that object or @c NULL if not found. + * + * @param context The context where the asynchronous objects are + * registered with. + * @param id The id of the object to retrieve. + * + * @return A pointer to the object identified by @p id or @c NULL if + * not found. + */ +coap_async_state_t *coap_find_async(coap_context_t *context, coap_tid_t id); + +/** + * Updates the time stamp of @p s. + * + * @param s The state object to update. + */ +static inline void +coap_touch_async(coap_async_state_t *s) { coap_ticks(&s->created); } + +/** @} */ + +#endif /* WITHOUT_ASYNC */ + +#endif /* _COAP_ASYNC_H_ */ diff --git a/resource/csdk/libcoap-4.1.1/bits.h b/resource/csdk/libcoap-4.1.1/bits.h new file mode 100644 index 000000000..6569c7564 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/bits.h @@ -0,0 +1,89 @@ +/* + * bits.h -- bit vector manipulation + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file bits.h + * @brief bit vector manipulation + */ + +#ifndef _BITS_H_ +#define _BITS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#include + +/** + * Sets the bit @p bit in bit-vector @p vec. This function returns @c + * 1 if bit was set or @c -1 on error (i.e. when the given bit does + * not fit in the vector). + * + * @param vec The bit-vector to change. + * @param size The size of @p vec in bytes. + * @param bit The bit to set in @p vec. + * + * @return @c -1 if @p bit does not fit into @p vec, @c 1 otherwise. + */ +inline static int +bits_setb(uint8_t *vec, size_t size, uint16_t bit) { + if (size <= (size_t)(bit >> 3)) + return -1; + + *(vec + (bit >> 3)) |= (uint8_t)(1 << (bit & 0x07)); + return 1; +} + +/** + * Clears the bit @p bit from bit-vector @p vec. This function returns + * @c 1 if bit was cleared or @c -1 on error (i.e. when the given bit + * does not fit in the vector). + * + * @param vec The bit-vector to change. + * @param size The size of @p vec in bytes. + * @param bit The bit to clear from @p vec. + * + * @return @c -1 if @p bit does not fit into @p vec, @c 1 otherwise. + */ +inline static int +bits_clrb(uint8_t *vec, size_t size, uint16_t bit) { + if (size <= (size_t)(bit >> 3)) + return -1; + + *(vec + (bit >> 3)) &= (uint8_t)(~(1 << (bit & 0x07))); + return 1; +} + +/** + * Gets the status of bit @p bit from bit-vector @p vec. This function returns + * @c 1 if the bit is set, @c 0 otherwise (even in case of an error).. + * + * @param vec The bit-vector to read from.. + * @param size The size of @p vec in bytes. + * @param bit The bit to get from @p vec. + * + * @return @c 1 if the bit is set, @c 0 otherwise. + */ +inline static int +bits_getb(const uint8_t *vec, size_t size, uint16_t bit) { + if (size <= (size_t)(bit >> 3)) + return -1; + + return (*(vec + (bit >> 3)) & (1 << (bit & 0x07))) != 0; +} + +#ifdef __cplusplus +} +#endif + +#endif /* _BITS_H_ */ diff --git a/resource/csdk/libcoap-4.1.1/block.c b/resource/csdk/libcoap-4.1.1/block.c new file mode 100644 index 000000000..402fd8ce2 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/block.c @@ -0,0 +1,138 @@ +/* block.c -- block transfer + * + * Copyright (C) 2010--2012 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "config.h" + +#if defined(HAVE_ASSERT_H) && !defined(assert) +# include +#endif + +#ifdef WITH_ARDUINO +/* On Arduino the abort function, needed for assert, is defined in std lib */ +#include +#endif + +#include "debug.h" +#include "block.h" + +#define min(a,b) ((a) < (b) ? (a) : (b)) + +#ifndef WITHOUT_BLOCK +unsigned int +coap_opt_block_num(const coap_opt_t *block_opt) { + unsigned int num = 0; + unsigned short len; + + len = coap_opt_length(block_opt); + + if (len == 0) { + return 0; + } + + if (len > 1) { + num = coap_decode_var_bytes(COAP_OPT_VALUE(block_opt), + COAP_OPT_LENGTH(block_opt) - 1); + } + + return (num << 4) | ((*COAP_OPT_BLOCK_LAST(block_opt) & 0xF0) >> 4); +} + +int +coap_get_block(coap_pdu_t *pdu, unsigned short type, coap_block_t *block) { + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + + assert(block); + memset(block, 0, sizeof(coap_block_t)); + + if (pdu && (option = coap_check_option(pdu, type, &opt_iter))) { + block->szx = COAP_OPT_BLOCK_SZX(option); + if (COAP_OPT_BLOCK_MORE(option)) + block->m = 1; + block->num = coap_opt_block_num(option); + return 1; + } + + return 0; +} + +int +coap_write_block_opt(coap_block_t *block, unsigned short type, + coap_pdu_t *pdu, size_t data_length) { + size_t start, want, avail; + unsigned char buf[3]; + + assert(pdu); + + /* Block2 */ + if (type != COAP_OPTION_BLOCK2) { + warn("coap_write_block_opt: skipped unknown option\n"); + return -1; + } + + start = block->num << (block->szx + 4); + if (data_length <= start) { + debug("illegal block requested\n"); + return -2; + } + + avail = pdu->max_size - pdu->length - 4; + want = 1 << (block->szx + 4); + + /* check if entire block fits in message */ + if (want <= avail) { + block->m = want < data_length - start; + } else { + /* Sender has requested a block that is larger than the remaining + * space in pdu. This is ok if the remaining data fits into the pdu + * anyway. The block size needs to be adjusted only if there is more + * data left that cannot be delivered in this message. */ + + if (data_length - start <= avail) { + + /* it's the final block and everything fits in the message */ + block->m = 0; + } else { + unsigned char szx; + + /* we need to decrease the block size */ + if (avail < 16) { /* bad luck, this is the smallest block size */ + debug("not enough space, even the smallest block does not fit"); + return -3; + } + debug("decrease block size for %d to %d\n", avail, coap_fls(avail) - 5); + szx = block->szx; + block->szx = coap_fls(avail) - 5; + block->m = 1; + block->num <<= szx - block->szx; + } + } + + /* to re-encode the block option */ + coap_add_option(pdu, type, coap_encode_var_bytes(buf, ((block->num << 4) | + (block->m << 3) | + block->szx)), + buf); + + return 1; +} + +int +coap_add_block(coap_pdu_t *pdu, unsigned int len, const unsigned char *data, + unsigned int block_num, unsigned char block_szx) { + size_t start; + start = block_num << (block_szx + 4); + + if (len <= start) + return 0; + + return coap_add_data(pdu, + min(len - start, (unsigned int)(1 << (block_szx + 4))), + data + start); +} +#endif /* WITHOUT_BLOCK */ diff --git a/resource/csdk/libcoap-4.1.1/block.h b/resource/csdk/libcoap-4.1.1/block.h new file mode 100644 index 000000000..ee2d5a946 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/block.h @@ -0,0 +1,145 @@ +/* block.h -- block transfer + * + * Copyright (C) 2010--2012,2014 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef _COAP_BLOCK_H_ +#define _COAP_BLOCK_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "option.h" +#include "encode.h" +#include "pdu.h" + +/** + * @defgroup block Block Transfer + * @{ + */ + +#ifndef COAP_MAX_BLOCK_SZX +/** + * The largest value for the SZX component in a Block option. Note + * that 1 << (COAP_MAX_BLOCK_SZX + 4) should not exceed + * COAP_MAX_PDU_SIZE. + */ +#define COAP_MAX_BLOCK_SZX 4 +#endif /* COAP_MAX_BLOCK_SZX */ + +#if (COAP_MAX_PDU_SIZE - 6) < (1 << (COAP_MAX_BLOCK_SZX + 4)) +#error "COAP_MAX_BLOCK_SZX too large" +#endif + +/** + * Structure of Block options. + */ +typedef struct { + unsigned int num:20; /**< block number */ + unsigned int m:1; /**< 1 if more blocks follow, 0 otherwise */ + unsigned int szx:3; /**< block size */ +} coap_block_t; + +/** + * Returns the value of the least significant byte of a Block option @p opt. + * For zero-length options (i.e. num == m == szx == 0), COAP_OPT_BLOCK_LAST + * returns @c NULL. + */ +#define COAP_OPT_BLOCK_LAST(opt) \ + (COAP_OPT_LENGTH(opt) ? (COAP_OPT_VALUE(opt) + (COAP_OPT_LENGTH(opt)-1)) : 0) + +/** Returns the value of the More-bit of a Block option @p opt. */ +#define COAP_OPT_BLOCK_MORE(opt) \ + (COAP_OPT_LENGTH(opt) ? (*COAP_OPT_BLOCK_LAST(opt) & 0x08) : 0) + +/** Returns the value of the SZX-field of a Block option @p opt. */ +#define COAP_OPT_BLOCK_SZX(opt) \ + (COAP_OPT_LENGTH(opt) ? (*COAP_OPT_BLOCK_LAST(opt) & 0x07) : 0) + +/** + * Returns the value of field @c num in the given block option @p + * block_opt. + */ +unsigned int coap_opt_block_num(const coap_opt_t *block_opt); + +/** + * Checks if more than @p num blocks are required to deliver @p data_len + * bytes of data for a block size of 1 << (@p szx + 4). + */ +static inline int +coap_more_blocks(size_t data_len, unsigned int num, unsigned short szx) { + return ((num+1) << (szx + 4)) < data_len; +} + +/** Sets the More-bit in @p block_opt */ +static inline void +coap_opt_block_set_m(coap_opt_t *block_opt, int m) { + if (m) + *(COAP_OPT_VALUE(block_opt) + (COAP_OPT_LENGTH(block_opt) - 1)) |= 0x08; + else + *(COAP_OPT_VALUE(block_opt) + (COAP_OPT_LENGTH(block_opt) - 1)) &= ~0x08; +} + +/** + * Initializes @p block from @p pdu. @p type must be either COAP_OPTION_BLOCK1 + * or COAP_OPTION_BLOCK2. When option @p type was found in @p pdu, @p block + * is initialized with values from this option and the function returns the + * value @c 1. Otherwise, @c 0 is returned. + * + * @param pdu The pdu to search for option @p type. + * @param type The option to search for (must be COAP_OPTION_BLOCK1 or + * COAP_OPTION_BLOCK2) + * @param block The block structure to initilize. + * @return @c 1 on success, @c 0 otherwise. + */ +int coap_get_block(coap_pdu_t *pdu, unsigned short type, coap_block_t *block); + +/** + * Writes a block option of type @p type to message @p pdu. If the + * requested block size is too large to fit in @p pdu, it is reduced + * accordingly. An exception is made for the final block when less + * space is required. The actual length of the resource is specified + * in @p data_length. + * + * This function may change *block to reflect the values written to + * @p pdu. As the function takes into consideration the remaining space + * @p pdu, no more options should be added after coap_write_block_opt() + * has returned. + * + * @param block The block structure to use. On return, this object + * is updated according to the values that have been + * written to @p pdu. + * @param type COAP_OPTION_BLOCK1 or COAP_OPTION_BLOCK2 + * @param pdu The message where the block option should be + * written. + * @param data_length The length of the actual data that will be added + * the @p pdu by calling coap_add_block(). + * @return @c 1 on success, or a negative value on error. + */ +int coap_write_block_opt(coap_block_t *block, unsigned short type, + coap_pdu_t *pdu, size_t data_length); + +/** + * Adds the @p block_num block of size 1 << (@p block_szx + 4) from + * source @p data to @p pdu. + * + * @param pdu The message to add the block + * @param len The length of @p data. + * @param data The source data to fill the block with + * @param block_num The actual block number + * @param block_szx Encoded size of block @p block_number + * @return @c 1 on success, @c 0 otherwise. + */ +int coap_add_block(coap_pdu_t *pdu, unsigned int len, const unsigned char *data, + unsigned int block_num, unsigned char block_szx); +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _COAP_BLOCK_H_ */ diff --git a/resource/csdk/libcoap-4.1.1/coap.h b/resource/csdk/libcoap-4.1.1/coap.h new file mode 100644 index 000000000..2e7440a67 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/coap.h @@ -0,0 +1,36 @@ +/* coap.h -- main header file for CoAP stack + * + * Copyright (C) 2010--2012 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef _COAP_H_ +#define _COAP_H_ + +#include "net.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "config.h" +#include "debug.h" +#include "mem.h" +#include "coap_list.h" +#include "pdu.h" +#include "option.h" +#include "encode.h" +#include "str.h" +#include "uri.h" +#include "async.h" +#include "t_list.h" +#include "subscribe.h" +#include "block.h" + +#ifdef __cplusplus +} +#endif + +#endif /* _COAP_H_ */ diff --git a/resource/csdk/libcoap-4.1.1/coap_list.c b/resource/csdk/libcoap-4.1.1/coap_list.c new file mode 100644 index 000000000..e147a17b2 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/coap_list.c @@ -0,0 +1,96 @@ +/* coap_list.c -- CoAP list structures + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "config.h" + +#include +#include + +#include "debug.h" +#include "mem.h" +#include "coap_list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int +coap_insert(coap_list_t **queue, coap_list_t *node, + int (*order)(void *, void *node) ) { + coap_list_t *p, *q; + if ( !queue || !node ) + return 0; + + /* set queue head if empty */ + if ( !*queue ) { + *queue = node; + return 1; + } + + /* replace queue head if new node has to be added before the existing queue head */ + q = *queue; + if ( order( node->data, q->data ) < 0) { + node->next = q; + *queue = node; + return 1; + } + + /* search for right place to insert */ + do { + p = q; + q = q->next; + } while ( q && order( node->data, q->data ) >= 0); + + /* insert new item */ + node->next = q; + p->next = node; + return 1; +} + +int +coap_delete(coap_list_t *node) { + if ( !node ) + return 0; + + if ( node->delete_func ) + node->delete_func( node->data ); + coap_free( node->data ); + coap_free( node ); + + return 1; +} + +void +coap_delete_list(coap_list_t *queue) { + if ( !queue ) + return; + + coap_delete_list( queue->next ); + coap_delete( queue ); +} + +coap_list_t * +coap_new_listnode(void *data, void (*delete_func)(void *) ) { + coap_list_t *node = (coap_list_t*)coap_malloc( sizeof(coap_list_t) ); + if ( ! node ) { +#ifndef NDEBUG + coap_log(LOG_CRIT, "coap_new_listnode: malloc\n"); +#endif + return NULL; + } + + memset(node, 0, sizeof(coap_list_t)); + node->data = data; + node->delete_func = delete_func; + return node; +} + +#ifdef __cplusplus +} +#endif + diff --git a/resource/csdk/libcoap-4.1.1/coap_list.h b/resource/csdk/libcoap-4.1.1/coap_list.h new file mode 100644 index 000000000..9e47b2668 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/coap_list.h @@ -0,0 +1,53 @@ +/* coap_list.h -- CoAP list structures + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef _COAP_LIST_H_ +#define _COAP_LIST_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct coap_linkedlistnode { + struct coap_linkedlistnode *next; + void *data; + + /** + * Callback function that is called from coap_delete to release + * additional memory allocated by data Set to NULL if you do not + * need this. Note that data is free'd automatically. */ + void (*delete_func)(void *); +}; + +typedef struct coap_linkedlistnode coap_list_t; + +/** + * Adds node to given queue, ordered by specified order function. Returns 1 + * when insert was successful, 0 otherwise. + */ +int coap_insert(coap_list_t **queue, coap_list_t *node, + int (*order)(void *, void *) ); + +/* destroys specified node */ +int coap_delete(coap_list_t *node); + +/* removes all items from given queue and frees the allocated storage */ +void coap_delete_list(coap_list_t *queue); + +/** + * Creates a new list node and adds the given data object. The memory allocated + * by data will be released by coap_delete() with the new node. Returns the + * new list node. + */ +coap_list_t *coap_new_listnode(void *data, void (*delete_func)(void *) ); + +#ifdef __cplusplus +} +#endif + +#endif /* _COAP_LIST_H_ */ diff --git a/resource/csdk/libcoap-4.1.1/coap_time.h b/resource/csdk/libcoap-4.1.1/coap_time.h new file mode 100644 index 000000000..6255eb86f --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/coap_time.h @@ -0,0 +1,193 @@ +/* coap_time.h -- Clock Handling + * + * Copyright (C) 2010--2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file coap_time.h + * @brief Clock Handling + */ + +#ifndef _COAP_TIME_H_ +#define _COAP_TIME_H_ + +/* +** Make sure we can call this stuff from C++. +*/ +#ifdef __cplusplus +extern "C" { +#endif + + +#include "config.h" + +/** + * @defgroup clock Clock Handling + * Default implementation of internal clock. You should redefine this if + * you do not have time() and gettimeofday(). + * @{ + */ + +#ifdef WITH_LWIP + +#include +#include + +/* lwIP provides ms in sys_now */ +#define COAP_TICKS_PER_SECOND 1000 + +typedef uint32_t coap_tick_t; + +static inline void coap_ticks_impl(coap_tick_t *t) +{ + *t = sys_now(); +} + +static inline void coap_clock_init_impl(void) +{ +} + +#define coap_clock_init coap_clock_init_impl + +#define coap_ticks coap_ticks_impl + +#endif +#ifdef WITH_CONTIKI +#include "clock.h" + +typedef clock_time_t coap_tick_t; + +/** + * This data type is used to represent the difference between two + * clock_tick_t values. This data type must have the same size in + * memory as coap_tick_t to allow wrapping. + */ +typedef int coap_tick_diff_t; + +#define COAP_TICKS_PER_SECOND CLOCK_SECOND + +/** Set at startup to initialize the internal clock (time in seconds). */ +extern clock_time_t clock_offset; + +static inline void +contiki_clock_init_impl(void) { + clock_init(); + clock_offset = clock_time(); +} + +#define coap_clock_init contiki_clock_init_impl + +static inline void +contiki_ticks_impl(coap_tick_t *t) { + *t = clock_time(); +} + +#define coap_ticks contiki_ticks_impl + +#endif /* WITH_CONTIKI */ +#ifdef WITH_POSIX +typedef unsigned int coap_tick_t; + +/** + * This data type is used to represent the difference between two + * clock_tick_t values. This data type must have the same size in + * memory as coap_tick_t to allow wrapping. + */ +typedef int coap_tick_diff_t; + +#define COAP_TICKS_PER_SECOND 1024 + +/** Set at startup to initialize the internal clock (time in seconds). */ +extern time_t clock_offset; +#endif /* WITH_POSIX */ + +#ifdef WITH_ARDUINO +#include "Time.h" +typedef time_t coap_tick_t; + +/** + * This data type is used to represent the difference between two + * clock_tick_t values. This data type must have the same size in + * memory as coap_tick_t to allow wrapping. + */ +typedef int coap_tick_diff_t; + +/* TODO: Ticks per second value for Arduino needs verification from + * documentation */ +#define COAP_TICKS_PER_SECOND 1000 + +extern time_t clock_offset; + +#endif /* WITH_ARDUINO */ + +#ifndef coap_clock_init +static inline void +coap_clock_init_impl(void) { +#ifdef HAVE_TIME_H + clock_offset = time(NULL); +#else +# ifdef WITH_ARDUINO + clock_offset = now(); +# else +# ifdef __GNUC__ + /* Issue a warning when using gcc. Other prepropressors do + * not seem to have a similar feature. */ +# warning "cannot initialize clock" +# endif + clock_offset = 0; +# endif /* WITH_ARDUINO */ +#endif /* HAVE_TIME */ +} +#define coap_clock_init coap_clock_init_impl +#endif /* coap_clock_init */ + +#ifndef coap_ticks +static inline void +coap_ticks_impl(coap_tick_t *t) { +#ifdef HAVE_SYS_TIME_H + struct timeval tv; + gettimeofday(&tv, NULL); + *t = (tv.tv_sec - clock_offset) * COAP_TICKS_PER_SECOND + + (tv.tv_usec * COAP_TICKS_PER_SECOND / 1000000); +#else +# ifdef WITH_ARDUINO + coap_tick_t tv; + tv = now(); + *t = (tv - clock_offset)*COAP_TICKS_PER_SECOND; +# else +# error "clock not implemented" +# endif /* WITH_ARDUINO */ +#endif /* HAVE_SYS_TIME_H */ +} +#define coap_ticks coap_ticks_impl +#endif /* coap_ticks */ + +/** + * Returns @c 1 if and only if @p a is less than @p b where less is + * defined on a signed data type. + */ +static inline +int coap_time_lt(coap_tick_t a, coap_tick_t b) { + return ((coap_tick_diff_t)(a - b)) < 0; +} + +/** + * Returns @c 1 if and only if @p a is less than or equal @p b where + * less is defined on a signed data type. + */ +static inline +int coap_time_le(coap_tick_t a, coap_tick_t b) { + return a == b || coap_time_lt(a,b); +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + + +#endif /* _COAP_TIME_H_ */ diff --git a/resource/csdk/libcoap-4.1.1/config.h b/resource/csdk/libcoap-4.1.1/config.h new file mode 100644 index 000000000..91d21d666 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/config.h @@ -0,0 +1,150 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define to 1 if you have the header file. */ +#ifndef WITH_ARDUINO +#define HAVE_ARPA_INET_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `getaddrinfo' function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `coap' library (-lcoap). */ +/* #undef HAVE_LIBCOAP */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#define HAVE_MALLOC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#ifndef WITH_ARDUINO +#define HAVE_NETINET_IN_H 1 +#endif + +/* Define to 1 if you have the `select' function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strnlen' function. */ +#define HAVE_STRNLEN 1 + +/* Define to 1 if you have the `strrchr' function. */ +#define HAVE_STRRCHR 1 + +/* Define to 1 if you have the header file. */ +#ifndef WITH_ARDUINO +#define HAVE_SYSLOG_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef WITH_ARDUINO +#define HAVE_SYS_SOCKET_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#ifndef WITH_ARDUINO +#define HAVE_SYS_TIME_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef WITH_ARDUINO +#define HAVE_SYS_TYPES_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef WITH_ARDUINO +#define HAVE_SYS_UNISTD_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef WITH_ARDUINO +#define HAVE_TIME_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef WITH_ARDUINO +#define HAVE_UNISTD_H 1 +#endif + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "libcoap" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "libcoap 4.1.1" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "libcoap" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "4.1.1" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Define to rpl_malloc if the replacement function should be used. */ +/* #undef malloc */ + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* Define to `int' if does not define. */ +/* #undef ssize_t */ diff --git a/resource/csdk/libcoap-4.1.1/config.h.in b/resource/csdk/libcoap-4.1.1/config.h.in new file mode 100644 index 000000000..4a0f3c6a3 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/config.h.in @@ -0,0 +1,131 @@ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define if building universal (internal helper macro) */ +#undef AC_APPLE_UNIVERSAL_BUILD + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_INET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ASSERT_H + +/* Define to 1 if you have the `getaddrinfo' function. */ +#undef HAVE_GETADDRINFO + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `coap' library (-lcoap). */ +#undef HAVE_LIBCOAP + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#undef HAVE_MALLOC + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `memset' function. */ +#undef HAVE_MEMSET + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the `select' function. */ +#undef HAVE_SELECT + +/* Define to 1 if you have the `socket' function. */ +#undef HAVE_SOCKET + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strcasecmp' function. */ +#undef HAVE_STRCASECMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strnlen' function. */ +#undef HAVE_STRNLEN + +/* Define to 1 if you have the `strrchr' function. */ +#undef HAVE_STRRCHR + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYSLOG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UNISTD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# undef WORDS_BIGENDIAN +# endif +#endif + +/* Define to rpl_malloc if the replacement function should be used. */ +#undef malloc + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define to `int' if does not define. */ +#undef ssize_t diff --git a/resource/csdk/libcoap-4.1.1/configure b/resource/csdk/libcoap-4.1.1/configure new file mode 100755 index 000000000..b6f5dadb5 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/configure @@ -0,0 +1,5411 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for libcoap 4.1.1. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='libcoap' +PACKAGE_TARNAME='libcoap' +PACKAGE_VERSION='4.1.1' +PACKAGE_STRING='libcoap 4.1.1' +PACKAGE_BUGREPORT='' +PACKAGE_URL='' + +ac_unique_file="coap.h" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='LTLIBOBJS +BUILD_SO +TESTS +LIBOBJS +EGREP +GREP +CPP +ETAGS +DOXYGEN +RANLIB +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +SET_MAKE +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +with_contiki +with_debug +with_async +with_block +with_observe +with_query_filter +with_tests +with_shared +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures libcoap 4.1.1 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/libcoap] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of libcoap 4.1.1:";; + esac + cat <<\_ACEOF + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-contiki build libcoap for the Contiki OS + --without-debug disable all debug output and assertions + --without-async disable handling of asynchronous transactions and + observe + --without-block disable block transfer + --without-observe disable resource observation + --without-query-filter disable support for filters on /.well-known/core + --with-tests enable unit tests (requires cunit) + --with-shared build shared library + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +libcoap configure 4.1.1 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by libcoap $as_me 4.1.1, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + +# First check for Contiki build to quit configure before any other test + +# Check whether --with-contiki was given. +if test "${with_contiki+set}" = set; then : + withval=$with_contiki; cp -p Makefile.contiki Makefile + cp -p config.h.contiki config.h + { $as_echo "$as_me:${as_lineno-$LINENO}: Contiki build prepared" >&5 +$as_echo "$as_me: Contiki build prepared" >&6;} + exit 0 +fi + + +# Checks for programs. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +# Extract the first word of "doxygen", so it can be a program name with args. +set dummy doxygen; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_DOXYGEN+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $DOXYGEN in + [\\/]* | ?:[\\/]*) + ac_cv_path_DOXYGEN="$DOXYGEN" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_DOXYGEN="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_DOXYGEN" && ac_cv_path_DOXYGEN=":" + ;; +esac +fi +DOXYGEN=$ac_cv_path_DOXYGEN +if test -n "$DOXYGEN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DOXYGEN" >&5 +$as_echo "$DOXYGEN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "etags", so it can be a program name with args. +set dummy etags; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ETAGS+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ETAGS in + [\\/]* | ?:[\\/]*) + ac_cv_path_ETAGS="$ETAGS" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ETAGS="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_ETAGS" && ac_cv_path_ETAGS="/bin/false" + ;; +esac +fi +ETAGS=$ac_cv_path_ETAGS +if test -n "$ETAGS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ETAGS" >&5 +$as_echo "$ETAGS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; + +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) + +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error $? "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac + + +# Checks for libraries. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for coap_new_pdu in -lcoap" >&5 +$as_echo_n "checking for coap_new_pdu in -lcoap... " >&6; } +if ${ac_cv_lib_coap_coap_new_pdu+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcoap $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char coap_new_pdu (); +int +main () +{ +return coap_new_pdu (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_coap_coap_new_pdu=yes +else + ac_cv_lib_coap_coap_new_pdu=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_coap_coap_new_pdu" >&5 +$as_echo "$ac_cv_lib_coap_coap_new_pdu" >&6; } +if test "x$ac_cv_lib_coap_coap_new_pdu" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBCOAP 1 +_ACEOF + + LIBS="-lcoap $LIBS" + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5 +$as_echo_n "checking for library containing gethostbyname... " >&6; } +if ${ac_cv_search_gethostbyname+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +for ac_lib in '' nsl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_gethostbyname=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_gethostbyname+:} false; then : + break +fi +done +if ${ac_cv_search_gethostbyname+:} false; then : + +else + ac_cv_search_gethostbyname=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5 +$as_echo "$ac_cv_search_gethostbyname" >&6; } +ac_res=$ac_cv_search_gethostbyname +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5 +$as_echo_n "checking for library containing socket... " >&6; } +if ${ac_cv_search_socket+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char socket (); +int +main () +{ +return socket (); + ; + return 0; +} +_ACEOF +for ac_lib in '' socket; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_socket=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_socket+:} false; then : + break +fi +done +if ${ac_cv_search_socket+:} false; then : + +else + ac_cv_search_socket=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5 +$as_echo "$ac_cv_search_socket" >&6; } +ac_res=$ac_cv_search_socket +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + +# configuration options that may change compile flags + +# Check whether --with-debug was given. +if test "${with_debug+set}" = set; then : + withval=$with_debug; CPPFLAGS="${CPPFLAGS} -DNDEBUG" +fi + + + +# Check whether --with-async was given. +if test "${with_async+set}" = set; then : + withval=$with_async; CPPFLAGS="${CPPFLAGS} -DWITHOUT_ASYNC" +fi + + + +# Check whether --with-block was given. +if test "${with_block+set}" = set; then : + withval=$with_block; CPPFLAGS="${CPPFLAGS} -DWITHOUT_BLOCK" +fi + + + +# Check whether --with-observe was given. +if test "${with_observe+set}" = set; then : + withval=$with_observe; CPPFLAGS="${CPPFLAGS} -DWITHOUT_OBSERVE" +fi + + + +# Check whether --with-query-filter was given. +if test "${with_query_filter+set}" = set; then : + withval=$with_query_filter; CPPFLAGS="${CPPFLAGS} -DWITHOUT_QUERY_FILTER" +fi + + + +# Check whether --with-tests was given. +if test "${with_tests+set}" = set; then : + withval=$with_tests; TESTS="tests" +fi + + + +# Check whether --with-shared was given. +if test "${with_shared+set}" = set; then : + withval=$with_shared; BUILD_SO="BUILD_SO=1" +fi + + +# disambiguate between autoconf generated setups and contiki / lwip setups +# which use explicit config.h.* files +CPPFLAGS="${CPPFLAGS} -DWITH_POSIX" + +# Checks for header files. +for ac_header in assert.h arpa/inet.h limits.h netdb.h netinet/in.h stdlib.h string.h strings.h sys/socket.h sys/time.h time.h unistd.h sys/unistd.h syslog.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +# Checks for typedefs, structures, and compiler characteristics. +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default" +if test "x$ac_cv_type_ssize_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define ssize_t int +_ACEOF + +fi + + +# Checks for library functions. +for ac_header in stdlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" +if test "x$ac_cv_header_stdlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDLIB_H 1 +_ACEOF + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 +$as_echo_n "checking for GNU libc compatible malloc... " >&6; } +if ${ac_cv_func_malloc_0_nonnull+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_malloc_0_nonnull=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if defined STDC_HEADERS || defined HAVE_STDLIB_H +# include +#else +char *malloc (); +#endif + +int +main () +{ +return ! malloc (0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_malloc_0_nonnull=yes +else + ac_cv_func_malloc_0_nonnull=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 +$as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } +if test $ac_cv_func_malloc_0_nonnull = yes; then : + +$as_echo "#define HAVE_MALLOC 1" >>confdefs.h + +else + $as_echo "#define HAVE_MALLOC 0" >>confdefs.h + + case " $LIBOBJS " in + *" malloc.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS malloc.$ac_objext" + ;; +esac + + +$as_echo "#define malloc rpl_malloc" >>confdefs.h + +fi + + +for ac_func in memset select socket strcasecmp strrchr getaddrinfo strnlen +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + +ac_config_headers="$ac_config_headers config.h" + + +ac_config_files="$ac_config_files Makefile doc/Makefile doc/Doxyfile examples/Makefile tests/Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by libcoap $as_me 4.1.1, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +libcoap config.status 4.1.1 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; + "doc/Doxyfile") CONFIG_FILES="$CONFIG_FILES doc/Doxyfile" ;; + "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;; + "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/resource/csdk/libcoap-4.1.1/configure.in b/resource/csdk/libcoap-4.1.1/configure.in new file mode 100644 index 000000000..77f6c8f37 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/configure.in @@ -0,0 +1,98 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. +# +# Copyright (C) 2010--2014 Olaf Bergmann +# +# This file is part of the CoAP library libcoap. Please see +# README for terms of use. + +AC_PREREQ([2.65]) +AC_INIT([libcoap], [4.1.1]) +AC_CONFIG_SRCDIR([coap.h]) + +# First check for Contiki build to quit configure before any other test +AC_ARG_WITH(contiki, + [AS_HELP_STRING([--with-contiki],[build libcoap for the Contiki OS])], + [cp -p Makefile.contiki Makefile + cp -p config.h.contiki config.h + AC_MSG_NOTICE([Contiki build prepared]) + exit 0], + []) + +# Checks for programs. +AC_PROG_MAKE_SET +AC_PROG_CC +AC_PROG_RANLIB +AC_PATH_PROG(DOXYGEN, doxygen, [:]) +AC_PATH_PROG(ETAGS, etags, [/bin/false]) + +AC_C_BIGENDIAN + +# Checks for libraries. +AC_CHECK_LIB([coap], [coap_new_pdu]) + +AC_SEARCH_LIBS([gethostbyname], [nsl]) +AC_SEARCH_LIBS([socket], [socket]) + +# configuration options that may change compile flags +AC_ARG_WITH(debug, + [AS_HELP_STRING([--without-debug],[disable all debug output and assertions])], + [CPPFLAGS="${CPPFLAGS} -DNDEBUG"], + []) + +AC_ARG_WITH(async, + [AS_HELP_STRING([--without-async],[disable handling of asynchronous transactions and observe])], + [CPPFLAGS="${CPPFLAGS} -DWITHOUT_ASYNC"], + []) + +AC_ARG_WITH(block, + [AS_HELP_STRING([--without-block],[disable block transfer])], + [CPPFLAGS="${CPPFLAGS} -DWITHOUT_BLOCK"], + []) + +AC_ARG_WITH(observe, + [AS_HELP_STRING([--without-observe],[disable resource observation])], + [CPPFLAGS="${CPPFLAGS} -DWITHOUT_OBSERVE"], + []) + +AC_ARG_WITH(query-filter, + [AS_HELP_STRING([--without-query-filter],[disable support for filters on /.well-known/core])], + [CPPFLAGS="${CPPFLAGS} -DWITHOUT_QUERY_FILTER"], + []) + +AC_ARG_WITH(tests, + [AS_HELP_STRING([--with-tests],[enable unit tests (requires cunit)])], + [TESTS="tests"], + []) + +AC_ARG_WITH(shared, + [AS_HELP_STRING([--with-shared],[build shared library])], + [BUILD_SO="BUILD_SO=1"], + []) + +# disambiguate between autoconf generated setups and contiki / lwip setups +# which use explicit config.h.* files +CPPFLAGS="${CPPFLAGS} -DWITH_POSIX" + +# Checks for header files. +AC_CHECK_HEADERS([assert.h arpa/inet.h limits.h netdb.h netinet/in.h stdlib.h string.h strings.h sys/socket.h sys/time.h time.h unistd.h sys/unistd.h syslog.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_TYPE_SIZE_T +AC_TYPE_SSIZE_T + +# Checks for library functions. +AC_FUNC_MALLOC +AC_CHECK_FUNCS([memset select socket strcasecmp strrchr getaddrinfo strnlen]) + +AC_SUBST(TESTS) +AC_SUBST(BUILD_SO) + +AC_CONFIG_HEADERS([config.h]) + +AC_CONFIG_FILES([Makefile + doc/Makefile + doc/Doxyfile + examples/Makefile + tests/Makefile]) +AC_OUTPUT diff --git a/resource/csdk/libcoap-4.1.1/debug.c b/resource/csdk/libcoap-4.1.1/debug.c new file mode 100644 index 000000000..3a0380661 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/debug.c @@ -0,0 +1,383 @@ +/* debug.c -- debug utilities + * + * Copyright (C) 2010--2012 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "config.h" + +#if defined(HAVE_ASSERT_H) && !defined(assert) +# include +#endif + +#include +#include +#include +#include + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_TIME_H +#include +#endif + +#include "debug.h" +#include "net.h" + +#ifdef WITH_CONTIKI +# ifndef DEBUG +# define DEBUG DEBUG_PRINT +# endif /* DEBUG */ +#include "net/uip-debug.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +static coap_log_t maxlog = LOG_WARNING; /* default maximum log level */ + +coap_log_t +coap_get_log_level() { + return maxlog; +} + +void +coap_set_log_level(coap_log_t level) { + maxlog = level; +} + +/* this array has the same order as the type log_t */ +static char *loglevels[] = { + "EMRG", "ALRT", "CRIT", "ERR", "WARN", "NOTE", "INFO", "DEBG" +}; + +#ifdef HAVE_TIME_H + +static inline size_t +print_timestamp(char *s, size_t len, coap_tick_t t) { + struct tm *tmp; + time_t now = clock_offset + (t / COAP_TICKS_PER_SECOND); + tmp = localtime(&now); + return strftime(s, len, "%b %d %H:%M:%S", tmp); +} + +#else /* alternative implementation: just print the timestamp */ + +static inline size_t +print_timestamp(char *s, size_t len, coap_tick_t t) { +#ifdef HAVE_SNPRINTF + return snprintf(s, len, "%u.%03u", + (unsigned int)(clock_offset + (t / COAP_TICKS_PER_SECOND)), + (unsigned int)(t % COAP_TICKS_PER_SECOND)); +#else /* HAVE_SNPRINTF */ + /* @todo do manual conversion of timestamp */ + return 0; +#endif /* HAVE_SNPRINTF */ +} + +#endif /* HAVE_TIME_H */ + +#ifndef NDEBUG + +#ifndef HAVE_STRNLEN +/** + * A length-safe strlen() fake. + * + * @param s The string to count characters != 0. + * @param maxlen The maximum length of @p s. + * + * @return The length of @p s. + */ +static inline size_t +strnlen(const char *s, size_t maxlen) { + size_t n = 0; + while(*s++ && n < maxlen) + ++n; + return n; +} +#endif /* HAVE_STRNLEN */ + +unsigned int +print_readable( const unsigned char *data, unsigned int len, + unsigned char *result, unsigned int buflen, int encode_always ) { + const unsigned char hex[] = "0123456789ABCDEF"; + unsigned int cnt = 0; + assert(data || len == 0); + + if (buflen == 0 || len == 0) + return 0; + + while (len) { + if (!encode_always && isprint(*data)) { + if (cnt == buflen) + break; + *result++ = *data; + ++cnt; + } else { + if (cnt+4 < buflen) { + *result++ = '\\'; + *result++ = 'x'; + *result++ = hex[(*data & 0xf0) >> 4]; + *result++ = hex[*data & 0x0f]; + cnt += 4; + } else + break; + } + + ++data; --len; + } + + *result = '\0'; + return cnt; +} + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +size_t +coap_print_addr(const coap_address_t *addr, unsigned char *buf, size_t len) { +TODO(FIX: Fix this) + (void)addr; + (void)buf; + (void)len; +#if 0 +#ifdef HAVE_ARPA_INET_H + const void *addrptr = NULL; + in_port_t port; + unsigned char *p = buf; + + switch (addr->addr.sa.sa_family) { + case AF_INET: + addrptr = &addr->addr.sin.sin_addr; + port = ntohs(addr->addr.sin.sin_port); + break; + case AF_INET6: + if (len < 7) /* do not proceed if buffer is even too short for [::]:0 */ + return 0; + + *p++ = '['; + + addrptr = &addr->addr.sin6.sin6_addr; + port = ntohs(addr->addr.sin6.sin6_port); + + break; + default: + memcpy(buf, "(unknown address type)", min(22, len)); + return min(22, len); + } + + if (inet_ntop(addr->addr.sa.sa_family, addrptr, (char *)p, len) == 0) { + perror("coap_print_addr"); + return 0; + } + + p += strnlen((char *)p, len); + + if (addr->addr.sa.sa_family == AF_INET6) { + if (p < buf + len) { + *p++ = ']'; + } else + return 0; + } + + p += snprintf((char *)p, buf + len - p + 1, ":%d", port); + + return buf + len - p; +#else /* HAVE_ARPA_INET_H */ +# if WITH_CONTIKI + unsigned char *p = buf; + uint8_t i; +# if WITH_UIP6 + const unsigned char hex[] = "0123456789ABCDEF"; + + if (len < 41) + return 0; + + *p++ = '['; + + for (i=0; i < 16; i += 2) { + if (i) { + *p++ = ':'; + } + *p++ = hex[(addr->addr.u8[i] & 0xf0) >> 4]; + *p++ = hex[(addr->addr.u8[i] & 0x0f)]; + *p++ = hex[(addr->addr.u8[i+1] & 0xf0) >> 4]; + *p++ = hex[(addr->addr.u8[i+1] & 0x0f)]; + } + *p++ = ']'; +# else /* WITH_UIP6 */ +# warning "IPv4 network addresses will not be included in debug output" + + if (len < 21) + return 0; +# endif /* WITH_UIP6 */ + if (buf + len - p < 6) + return 0; + +#ifdef HAVE_SNPRINTF + p += snprintf((char *)p, buf + len - p + 1, ":%d", uip_htons(addr->port)); +#else /* HAVE_SNPRINTF */ + /* @todo manual conversion of port number */ +#endif /* HAVE_SNPRINTF */ + + return p - buf; +# else /* WITH_CONTIKI */ + /* TODO: output addresses manually */ +# warning "inet_ntop() not available, network addresses will not be included in debug output" +# endif /* WITH_CONTIKI */ + return 0; +#endif +#endif //if 0 +} + +#ifndef WITH_CONTIKI +void +coap_show_pdu(const coap_pdu_t *pdu) { + unsigned char buf[COAP_MAX_PDU_SIZE]; /* need some space for output creation */ + int encode = 0, have_options = 0; + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + + fprintf(COAP_DEBUG_FD, "v:%d t:%d tkl:%d c:%d id:%u", + pdu->hdr->version, pdu->hdr->type, + pdu->hdr->token_length, + pdu->hdr->code, ntohs(pdu->hdr->id)); + + /* show options, if any */ + coap_option_iterator_init((coap_pdu_t *)pdu, &opt_iter, COAP_OPT_ALL); + + while ((option = coap_option_next(&opt_iter))) { + if (!have_options) { + have_options = 1; + fprintf(COAP_DEBUG_FD, " o: ["); + } else { + fprintf(COAP_DEBUG_FD, ","); + } + + if (opt_iter.type == COAP_OPTION_URI_PATH || + opt_iter.type == COAP_OPTION_PROXY_URI || + opt_iter.type == COAP_OPTION_URI_HOST || + opt_iter.type == COAP_OPTION_LOCATION_PATH || + opt_iter.type == COAP_OPTION_LOCATION_QUERY || + opt_iter.type == COAP_OPTION_URI_PATH || + opt_iter.type == COAP_OPTION_OBSERVE || + opt_iter.type == COAP_OPTION_URI_QUERY) { + encode = 0; + } else { + encode = 1; + } + + if (print_readable(COAP_OPT_VALUE(option), + COAP_OPT_LENGTH(option), + buf, sizeof(buf), encode )) + fprintf(COAP_DEBUG_FD, " %d:'%s'", opt_iter.type, buf); + } + + if (have_options) + fprintf(COAP_DEBUG_FD, " ]"); + + if (pdu->data) { + assert(pdu->data < (unsigned char *)pdu->hdr + pdu->length); + print_readable(pdu->data, + (unsigned char *)pdu->hdr + pdu->length - pdu->data, + buf, sizeof(buf), 0 ); + fprintf(COAP_DEBUG_FD, " d:%s", buf); + } + fprintf(COAP_DEBUG_FD, "\n"); + fflush(COAP_DEBUG_FD); +} + +#else /* WITH_CONTIKI */ + +void +coap_show_pdu(const coap_pdu_t *pdu) { + unsigned char buf[80]; /* need some space for output creation */ + + PRINTF("v:%d t:%d oc:%d c:%d id:%u", + pdu->hdr->version, pdu->hdr->type, + pdu->hdr->optcnt, pdu->hdr->code, uip_ntohs(pdu->hdr->id)); + + /* show options, if any */ + if (pdu->hdr->optcnt) { + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + coap_option_iterator_init((coap_pdu_t *)pdu, &opt_iter, COAP_OPT_ALL); + + PRINTF(" o:"); + while ((option = coap_option_next(&opt_iter))) { + + if (print_readable(COAP_OPT_VALUE(option), + COAP_OPT_LENGTH(option), + buf, sizeof(buf), 0)) + PRINTF(" %d:%s", opt_iter.type, buf); + } + } + + if (pdu->data < (unsigned char *)pdu->hdr + pdu->length) { + print_readable(pdu->data, + (unsigned char *)pdu->hdr + pdu->length - pdu->data, + buf, sizeof(buf), 0 ); + PRINTF(" d:%s", buf); + } + PRINTF("\r\n"); +} +#endif /* WITH_CONTIKI */ + +#endif /* NDEBUG */ + +#ifndef WITH_CONTIKI +void +coap_log_impl(coap_log_t level, const char *format, ...) { + char timebuf[32]; + coap_tick_t now; + va_list ap; + FILE *log_fd; + + if (maxlog < level) + return; + + log_fd = level <= LOG_CRIT ? COAP_ERR_FD : COAP_DEBUG_FD; + + coap_ticks(&now); + if (print_timestamp(timebuf,sizeof(timebuf), now)) + fprintf(log_fd, "%s ", timebuf); + + if (level <= LOG_DEBUG) + fprintf(log_fd, "%s ", loglevels[level]); + + va_start(ap, format); + vfprintf(log_fd, format, ap); + va_end(ap); + fflush(log_fd); +} +#else /* WITH_CONTIKI */ +void +coap_log_impl(coap_log_t level, const char *format, ...) { + char timebuf[32]; + coap_tick_t now; + va_list ap; + + if (maxlog < level) + return; + + coap_ticks(&now); + if (print_timestamp(timebuf,sizeof(timebuf), now)) + PRINTF("%s ", timebuf); + + if (level <= LOG_DEBUG) + PRINTF("%s ", loglevels[level]); + + va_start(ap, format); + PRINTF(format, ap); + va_end(ap); +} +#endif /* WITH_CONTIKI */ +#ifdef __cplusplus +} +#endif diff --git a/resource/csdk/libcoap-4.1.1/debug.h b/resource/csdk/libcoap-4.1.1/debug.h new file mode 100644 index 000000000..d599e1bcd --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/debug.h @@ -0,0 +1,93 @@ +/* debug.h -- debug utilities + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef _COAP_DEBUG_H_ +#define _COAP_DEBUG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "config.h" + +#ifndef COAP_DEBUG_FD +#define COAP_DEBUG_FD stdout +#endif + +#ifndef COAP_ERR_FD +#define COAP_ERR_FD stderr +#endif + +#ifdef HAVE_SYSLOG_H +#include +typedef short coap_log_t; +#else +/** Pre-defined log levels akin to what is used in \b syslog. */ +typedef enum { LOG_EMERG=0, LOG_ALERT, LOG_CRIT, LOG_WARNING, + LOG_NOTICE, LOG_INFO, LOG_DEBUG +} coap_log_t; +#endif + + + +/** Returns the current log level. */ +coap_log_t coap_get_log_level(); + +/** Sets the log level to the specified value. */ +void coap_set_log_level(coap_log_t level); + +/** + * Writes the given text to @c COAP_ERR_FD (for @p level <= @c + * LOG_CRIT) or @c COAP_DEBUG_FD (for @p level >= @c LOG_WARNING). The + * text is output only when @p level is below or equal to the log + * level that set by coap_set_log_level(). + */ +void coap_log_impl(coap_log_t level, const char *format, ...); + +#ifndef coap_log +#define coap_log(...) coap_log_impl(__VA_ARGS__) +#endif + +#if !defined(TB_LOG) && !defined(NDEBUG) +#define NDEBUG +#endif + +#ifndef NDEBUG + +/* A set of convenience macros for common log levels. */ +#define info(...) coap_log(LOG_INFO, __VA_ARGS__) +#define warn(...) coap_log(LOG_WARNING, __VA_ARGS__) +#define debug(...) coap_log(LOG_DEBUG, __VA_ARGS__) + +#define DO_PRAGMA(x) _Pragma (#x) +#define TODO(x) DO_PRAGMA(message ("TODO - " #x)) + +#include "pdu.h" +void coap_show_pdu(const coap_pdu_t *); + +#include "address.h" +size_t coap_print_addr(const coap_address_t *, unsigned char *, size_t); + + +#else + +#define debug(...) +#define info(...) +#define warn(...) + +#define TODO(x) +#define coap_show_pdu(x) +#define coap_print_addr(...) + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _COAP_DEBUG_H_ */ diff --git a/resource/csdk/libcoap-4.1.1/doc/Doxyfile b/resource/csdk/libcoap-4.1.1/doc/Doxyfile new file mode 100644 index 000000000..053479db0 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/doc/Doxyfile @@ -0,0 +1,1551 @@ +# Doxyfile 1.6.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = libcoap + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 4.1.1 + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it parses. +# With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this tag. +# The format is ext=language, where ext is a file extension, and language is one of +# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, +# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by +# doxygen. The layout file controls the global structure of the generated output files +# in an output format independent way. The create the layout file that represents +# doxygen's defaults, run doxygen with the -l option. You can optionally specify a +# file name after the option, if omitted DoxygenLayout.xml will be used as the name +# of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = .. ../examples + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER +# are set, an additional index file will be generated that can be used as input for +# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated +# HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. +# For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's +# filter section matches. +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be implemented using a PHP enabled web server instead of at the web client using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server based approach is that it scales better to large projects and allows full text search. The disadvances is that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = NO + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/resource/csdk/libcoap-4.1.1/doc/Doxyfile.in b/resource/csdk/libcoap-4.1.1/doc/Doxyfile.in new file mode 100644 index 000000000..6a6203954 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/doc/Doxyfile.in @@ -0,0 +1,1551 @@ +# Doxyfile 1.6.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = @PACKAGE_NAME@ + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = @PACKAGE_VERSION@ + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it parses. +# With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this tag. +# The format is ext=language, where ext is a file extension, and language is one of +# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, +# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by +# doxygen. The layout file controls the global structure of the generated output files +# in an output format independent way. The create the layout file that represents +# doxygen's defaults, run doxygen with the -l option. You can optionally specify a +# file name after the option, if omitted DoxygenLayout.xml will be used as the name +# of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = .. ../examples + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER +# are set, an additional index file will be generated that can be used as input for +# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated +# HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. +# For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's +# filter section matches. +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be implemented using a PHP enabled web server instead of at the web client using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server based approach is that it scales better to large projects and allows full text search. The disadvances is that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = NO + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/resource/csdk/libcoap-4.1.1/doc/Makefile.in b/resource/csdk/libcoap-4.1.1/doc/Makefile.in new file mode 100644 index 000000000..df72d6a4a --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/doc/Makefile.in @@ -0,0 +1,45 @@ +# Makefile for libcoap +# +# Copyright (C) 2010 Olaf Bergmann +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# the library's version +VERSION:=@PACKAGE_VERSION@ + +# tools +@SET_MAKE@ +SHELL = /bin/sh +MKDIR = mkdir +DOXYGEN= @DOXYGEN@ + +top_builddir = @top_builddir@ + +DISTDIR?=$(top_builddir)/@PACKAGE_TARNAME@-@PACKAGE_VERSION@ +FILES:=Makefile.in Doxyfile.in html + +doc: Doxyfile + $(DOXYGEN) $< >./doxygen.out 2>&1 + +clean: + @rm -rf html + +distclean: clean + @rm -rf $(DISTDIR) + @rm -f *~ + +dist: doc + test -d $(DISTDIR)/doc || mkdir $(DISTDIR)/doc + cp -r $(FILES) $(DISTDIR)/doc diff --git a/resource/csdk/libcoap-4.1.1/doc/makefile b/resource/csdk/libcoap-4.1.1/doc/makefile new file mode 100644 index 000000000..5105c9ddd --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/doc/makefile @@ -0,0 +1,66 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +# Makefile for libcoap +# +# Copyright (C) 2010 Olaf Bergmann +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# the library's version +VERSION:=4.1.1 + +# tools + +SHELL = /bin/sh +MKDIR = mkdir +DOXYGEN= /usr/bin/doxygen + +top_builddir = .. + +DISTDIR?=$(top_builddir)/libcoap-4.1.1 +FILES:=Makefile.in Doxyfile.in html + +doc: Doxyfile + @mkdir html + $(DOXYGEN) $< >./doxygen.out 2>&1 + +clean: + @rm -rf html doxygen.out + +distclean: clean + @rm -rf $(DISTDIR) + @rm -f *~ + +dist: doc + test -d $(DISTDIR)/doc || mkdir $(DISTDIR)/doc + cp -r $(FILES) $(DISTDIR)/doc diff --git a/resource/csdk/libcoap-4.1.1/encode.c b/resource/csdk/libcoap-4.1.1/encode.c new file mode 100644 index 000000000..b034b6bb1 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/encode.c @@ -0,0 +1,48 @@ +/* encode.c -- encoding and decoding of CoAP data types + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef NDEBUG +# include +#endif + +#include "config.h" +#include "encode.h" + +/* Carsten suggested this when fls() is not available: */ +int coap_fls(unsigned int i) { + int n; + for (n = 0; i; n++) + i >>= 1; + return n; +} + +unsigned int +coap_decode_var_bytes(unsigned char *buf,unsigned int len) { + unsigned int i, n = 0; + for (i = 0; i < len; ++i) + n = (n << 8) + buf[i]; + + return n; +} + +unsigned int +coap_encode_var_bytes(unsigned char *buf, unsigned int val) { + unsigned int n, i; + + for (n = 0, i = val; i && n < sizeof(val); ++n) + i >>= 8; + + i = n; + while (i--) { + buf[i] = val & 0xff; + val >>= 8; + } + + return n; +} + diff --git a/resource/csdk/libcoap-4.1.1/encode.h b/resource/csdk/libcoap-4.1.1/encode.h new file mode 100644 index 000000000..bcc9e17cc --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/encode.h @@ -0,0 +1,62 @@ +/* encode.h -- encoding and decoding of CoAP data types + * + * Copyright (C) 2010--2012 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef _COAP_ENCODE_H_ +#define _COAP_ENCODE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if (BSD >= 199103) || defined(WITH_CONTIKI) +# include +#else +#ifndef WITH_ARDUINO +# include +#endif +#endif + +#define Nn 8 /* duplicate definition of N if built on sky motes */ +#define E 4 +#define HIBIT (1 << (Nn - 1)) +#define EMASK ((1 << E) - 1) +#define MMASK ((1 << Nn) - 1 - EMASK) +#define MAX_VALUE ( (1 << Nn) - (1 << E) ) * (1 << ((1 << E) - 1)) + +#define COAP_PSEUDOFP_DECODE_8_4(r) (r < HIBIT ? r : (r & MMASK) << (r & EMASK)) + +#ifndef HAVE_FLS +/* include this only if fls() is not available */ +extern int coap_fls(unsigned int i); +#else +#define coap_fls(i) fls(i) +#endif + +/* ls and s must be integer variables */ +#define COAP_PSEUDOFP_ENCODE_8_4_DOWN(v,ls) (v < HIBIT ? v : (ls = coap_fls(v) - Nn, (v >> ls) & MMASK) + ls) +#define COAP_PSEUDOFP_ENCODE_8_4_UP(v,ls,s) (v < HIBIT ? v : (ls = coap_fls(v) - Nn, (s = (((v + ((1<> ls) & MMASK)), s == 0 ? HIBIT + ls + 1 : s + ls)) + +/** + * Decodes multiple-length byte sequences. buf points to an input byte + * sequence of length len. Returns the decoded value. + */ +unsigned int coap_decode_var_bytes(unsigned char *buf,unsigned int len); + +/** + * Encodes multiple-length byte sequences. buf points to an output + * buffer of sufficient length to store the encoded bytes. val is + * the value to encode. Returns the number of bytes used to encode + * val or 0 on error. + */ +unsigned int coap_encode_var_bytes(unsigned char *buf, unsigned int val); + +#ifdef __cplusplus +} +#endif + +#endif /* _COAP_ENCODE_H_ */ diff --git a/resource/csdk/libcoap-4.1.1/examples/client.c b/resource/csdk/libcoap-4.1.1/examples/client.c new file mode 100644 index 000000000..29b592214 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/examples/client.c @@ -0,0 +1,1177 @@ +/* coap-client -- simple CoAP client + * + * Copyright (C) 2010--2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "coap.h" + +int flags = 0; + +static unsigned char _token_data[8]; +str the_token = { 0, _token_data }; + +#define MOD_NAME ("CoAP-Client") +#define FLAGS_BLOCK 0x01 + +static coap_list_t *optlist = NULL; +/* Request URI. + * TODO: associate the resources with transaction id and make it expireable */ +static coap_uri_t uri; +static str proxy = { 0, NULL }; +static unsigned short proxy_port = COAP_DEFAULT_PORT; + +/* reading is done when this flag is set */ +static int ready = 0; + +static str output_file = { 0, NULL }; /* output file name */ +static FILE *file = NULL; /* output file stream */ + +static str payload = { 0, NULL }; /* optional payload to send */ + +unsigned char msgtype = COAP_MESSAGE_CON; /* usually, requests are sent confirmable */ + +typedef unsigned char method_t; +method_t method = 1; /* the method we are using in our requests */ + +coap_block_t block = { .num = 0, .m = 0, .szx = 6 }; + +unsigned int wait_seconds = 90; /* default timeout in seconds */ +coap_tick_t max_wait; /* global timeout (changed by set_timeout()) */ + +unsigned int obs_seconds = 30; /* default observe time */ +coap_tick_t obs_wait = 0; /* timeout for current subscription */ + +#define min(a,b) ((a) < (b) ? (a) : (b)) + +static inline void +set_timeout(coap_tick_t *timer, const unsigned int seconds) { + coap_ticks(timer); + *timer += seconds * COAP_TICKS_PER_SECOND; +} + +int +append_to_output(const unsigned char *data, size_t len) { + size_t written; + + if (!file) { + if (!output_file.s || (output_file.length && output_file.s[0] == '-')) + file = stdout; + else { + if (!(file = fopen((char *)output_file.s, "w"))) { + perror("fopen"); + return -1; + } + } + } + + do { + written = fwrite(data, 1, len, file); + len -= written; + data += written; + } while ( written && len ); + fflush(file); + + return 0; +} + +void +close_output() { + if (file) { + + /* add a newline before closing in case were writing to stdout */ + if (!output_file.s || (output_file.length && output_file.s[0] == '-')) + fwrite("\n", 1, 1, file); + + fflush(file); + fclose(file); + } +} + +coap_pdu_t * +new_ack( coap_context_t *ctx, coap_queue_t *node ) { + coap_pdu_t *pdu = coap_new_pdu(); + (void)ctx; + + if (pdu) { + pdu->hdr->type = COAP_MESSAGE_ACK; + pdu->hdr->code = 0; + pdu->hdr->id = node->pdu->hdr->id; + } + + return pdu; +} + +coap_pdu_t * +new_response( coap_context_t *ctx, coap_queue_t *node, unsigned int code ) { + coap_pdu_t *pdu = new_ack(ctx, node); + + if (pdu) + pdu->hdr->code = code; + + return pdu; +} + +coap_pdu_t * +coap_new_request(coap_context_t *ctx, method_t m, coap_list_t *options ) { + coap_pdu_t *pdu; + coap_list_t *opt; + + if ( ! ( pdu = coap_new_pdu() ) ) + return NULL; + + pdu->hdr->type = msgtype; + pdu->hdr->id = coap_new_message_id(ctx); + pdu->hdr->code = m; + + pdu->hdr->token_length = the_token.length; + if ( !coap_add_token(pdu, the_token.length, the_token.s)) { + debug("cannot add token to request\n"); + } + coap_show_pdu(pdu); + + for (opt = options; opt; opt = opt->next) { + coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option *)opt->data), + COAP_OPTION_LENGTH(*(coap_option *)opt->data), + COAP_OPTION_DATA(*(coap_option *)opt->data)); + } + + if (payload.length) { + if ((flags & FLAGS_BLOCK) == 0) + coap_add_data(pdu, payload.length, payload.s); + else + coap_add_block(pdu, payload.length, payload.s, block.num, block.szx); + } + + return pdu; +} + +coap_tid_t +clear_obs(coap_context_t *ctx, const coap_address_t *remote) { + coap_list_t *option; + coap_pdu_t *pdu; + coap_tid_t tid = COAP_INVALID_TID; + + /* create bare PDU w/o any option */ + pdu = coap_new_request(ctx, COAP_REQUEST_GET, NULL); + + if (pdu) { + /* FIXME: add token */ + /* add URI components from optlist */ + for (option = optlist; option; option = option->next ) { + switch (COAP_OPTION_KEY(*(coap_option *)option->data)) { + case COAP_OPTION_URI_HOST : + case COAP_OPTION_URI_PORT : + case COAP_OPTION_URI_PATH : + case COAP_OPTION_URI_QUERY : + coap_add_option ( pdu, COAP_OPTION_KEY(*(coap_option *)option->data), + COAP_OPTION_LENGTH(*(coap_option *)option->data), + COAP_OPTION_DATA(*(coap_option *)option->data) ); + break; + default: + ; /* skip other options */ + } + } + + if (pdu->hdr->type == COAP_MESSAGE_CON) + tid = coap_send_confirmed(ctx, remote, pdu); + else + tid = coap_send(ctx, remote, pdu); + + if (tid == COAP_INVALID_TID) { + debug("clear_obs: error sending new request"); + coap_delete_pdu(pdu); + } else if (pdu->hdr->type != COAP_MESSAGE_CON) + coap_delete_pdu(pdu); + } + return tid; +} + +int +resolve_address(const str *server, struct sockaddr *dst) { + + struct addrinfo *res, *ainfo; + struct addrinfo hints; + static char addrstr[256]; + int error, len=-1; + + + memset(addrstr, 0, sizeof(addrstr)); + if (server->length) + memcpy(addrstr, server->s, server->length); + else + memcpy(addrstr, "localhost", 9); + + OC_LOG_V(DEBUG, MOD_NAME, "Line %d, server %s", __LINE__, addrstr); + + memset ((char *)&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_DGRAM; + hints.ai_family = AF_UNSPEC; + + error = getaddrinfo(addrstr, NULL, &hints, &res); + + if (error != 0) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error)); + return error; + } + + for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) { + switch (ainfo->ai_family) { + case AF_INET6: + case AF_INET: + len = ainfo->ai_addrlen; + memcpy(dst, ainfo->ai_addr, len); + goto finish; + default: + ; + } + } + + finish: + freeaddrinfo(res); + return len; +} + +static inline coap_opt_t * +get_block(coap_pdu_t *pdu, coap_opt_iterator_t *opt_iter) { + coap_opt_filter_t f; + + assert(pdu); + + memset(f, 0, sizeof(coap_opt_filter_t)); + coap_option_setb(f, COAP_OPTION_BLOCK1); + coap_option_setb(f, COAP_OPTION_BLOCK2); + + coap_option_iterator_init(pdu, opt_iter, f); + return coap_option_next(opt_iter); +} + +#define HANDLE_BLOCK1(Pdu) \ + ((method == COAP_REQUEST_PUT || method == COAP_REQUEST_POST) && \ + ((flags & FLAGS_BLOCK) == 0) && \ + ((Pdu)->hdr->code == COAP_RESPONSE_CODE(201) || \ + (Pdu)->hdr->code == COAP_RESPONSE_CODE(204))) + +inline int +check_token(coap_pdu_t *received) { + return received->hdr->token_length == the_token.length && + memcmp(received->hdr->token, the_token.s, the_token.length) == 0; +} + +void +message_handler(struct coap_context_t *ctx, + const coap_address_t *remote, + coap_pdu_t *sent, + coap_pdu_t *received, + const coap_tid_t id) { + + coap_pdu_t *pdu = NULL; + coap_opt_t *block_opt; + coap_opt_iterator_t opt_iter; + unsigned char buf[4]; + coap_list_t *option; + size_t len; + unsigned char *databuf; + coap_tid_t tid; + (void)id; + +#ifndef NDEBUG + if (LOG_DEBUG <= coap_get_log_level()) { + debug("** process incoming %d.%02d response:\n", + (received->hdr->code >> 5), received->hdr->code & 0x1F); + coap_show_pdu(received); + } +#endif + + /* check if this is a response to our original request */ + if (!check_token(received)) { + /* drop if this was just some message, or send RST in case of notification */ + if (!sent && (received->hdr->type == COAP_MESSAGE_CON || + received->hdr->type == COAP_MESSAGE_NON)) + coap_send_rst(ctx, remote, received); + return; + } + + switch (received->hdr->type) { + case COAP_MESSAGE_CON: + /* acknowledge received response if confirmable (TODO: check Token) */ + coap_send_ack(ctx, remote, received); + break; + case COAP_MESSAGE_RST: + info("got RST\n"); + return; + default: + ; + } + + /* output the received data, if any */ + if (received->hdr->code == COAP_RESPONSE_CODE(205)) { + + /* set obs timer if we have successfully subscribed a resource */ + if (sent && coap_check_option(received, COAP_OPTION_SUBSCRIPTION, &opt_iter)) { + debug("observation relationship established, set timeout to %d\n", obs_seconds); + set_timeout(&obs_wait, obs_seconds); + } + + /* Got some data, check if block option is set. Behavior is undefined if + * both, Block1 and Block2 are present. */ + block_opt = get_block(received, &opt_iter); + if (!block_opt) { + /* There is no block option set, just read the data and we are done. */ + if (coap_get_data(received, &len, &databuf)) + append_to_output(databuf, len); + } else { + unsigned short blktype = opt_iter.type; + + /* TODO: check if we are looking at the correct block number */ + if (coap_get_data(received, &len, &databuf)) + append_to_output(databuf, len); + + if (COAP_OPT_BLOCK_MORE(block_opt)) { + /* more bit is set */ + debug("found the M bit, block size is %u, block nr. %u\n", + COAP_OPT_BLOCK_SZX(block_opt), coap_opt_block_num(block_opt)); + + /* create pdu with request for next block */ + pdu = coap_new_request(ctx, method, NULL); /* first, create bare PDU w/o any option */ + if ( pdu ) { + /* add URI components from optlist */ + for (option = optlist; option; option = option->next ) { + switch (COAP_OPTION_KEY(*(coap_option *)option->data)) { + case COAP_OPTION_URI_HOST : + case COAP_OPTION_URI_PORT : + case COAP_OPTION_URI_PATH : + case COAP_OPTION_URI_QUERY : + coap_add_option ( pdu, COAP_OPTION_KEY(*(coap_option *)option->data), + COAP_OPTION_LENGTH(*(coap_option *)option->data), + COAP_OPTION_DATA(*(coap_option *)option->data) ); + break; + default: + ; /* skip other options */ + } + } + + /* finally add updated block option from response, clear M bit */ + /* blocknr = (blocknr & 0xfffffff7) + 0x10; */ + debug("query block %d\n", (coap_opt_block_num(block_opt) + 1)); + coap_add_option(pdu, blktype, coap_encode_var_bytes(buf, + ((coap_opt_block_num(block_opt) + 1) << 4) | + COAP_OPT_BLOCK_SZX(block_opt)), buf); + + if (received->hdr->type == COAP_MESSAGE_CON) + tid = coap_send_confirmed(ctx, remote, pdu); + else + tid = coap_send(ctx, remote, pdu); + + if (tid == COAP_INVALID_TID) { + debug("message_handler: error sending new request"); + coap_delete_pdu(pdu); + } else { + set_timeout(&max_wait, wait_seconds); + if (received->hdr->type != COAP_MESSAGE_CON) + coap_delete_pdu(pdu); + } + + return; + } + } + } + } else { /* no 2.05 */ + + /* check if an error was signaled and output payload if so */ + if (COAP_RESPONSE_CLASS(received->hdr->code) >= 4) { + fprintf(stderr, "%d.%02d", + (received->hdr->code >> 5), received->hdr->code & 0x1F); + if (coap_get_data(received, &len, &databuf)) { + fprintf(stderr, " "); + while(len--) + fprintf(stderr, "%c", *databuf++); + } + fprintf(stderr, "\n"); + } + + } + + /* finally send new request, if needed */ + if (pdu && coap_send(ctx, remote, pdu) == COAP_INVALID_TID) { + debug("message_handler: error sending response"); + } + coap_delete_pdu(pdu); + + /* our job is done, we can exit at any time */ + ready = coap_check_option(received, COAP_OPTION_SUBSCRIPTION, &opt_iter) == NULL; +} + +void +usage( const char *program, const char *version) { + const char *p; + + p = strrchr( program, '/' ); + if ( p ) + program = ++p; + + fprintf( stderr, "%s v%s -- a small CoAP implementation\n" + "(c) 2010-2013 Olaf Bergmann \n\n" + "usage: %s [-A type...] [-t type] [-b [num,]size] [-B seconds] [-e text]\n" + "\t\t[-g group] [-m method] [-N] [-o file] [-P addr[:port]] [-p port]\n" + "\t\t[-s duration] [-O num,text] [-T string] [-v num] URI\n\n" + "\tURI can be an absolute or relative coap URI,\n" + "\t-A type...\taccepted media types as comma-separated list of\n" + "\t\t\tsymbolic or numeric values\n" + "\t-t type\t\tcontent type for given resource for PUT/POST\n" + "\t-b [num,]size\tblock size to be used in GET/PUT/POST requests\n" + "\t \t\t(value must be a multiple of 16 not larger than 1024)\n" + "\t \t\tIf num is present, the request chain will start at\n" + "\t \t\tblock num\n" + "\t-B seconds\tbreak operation after waiting given seconds\n" + "\t\t\t(default is %d)\n" + "\t-e text\t\tinclude text as payload (use percent-encoding for\n" + "\t\t\tnon-ASCII characters)\n" + "\t-f file\t\tfile to send with PUT/POST (use '-' for STDIN)\n" + "\t-g group\tjoin the given multicast group\n" + "\t-m method\trequest method (get|put|post|delete), default is 'get'\n" + "\t-N\t\tsend NON-confirmable message\n" + "\t-o file\t\toutput received data to this file (use '-' for STDOUT)\n" + "\t-p port\t\tlisten on specified port\n" + "\t-s duration\tsubscribe for given duration [s]\n" + "\t-v num\t\tverbosity level (default: 3)\n" + "\t-O num,text\tadd option num with contents text to request\n" + "\t-P addr[:port]\tuse proxy (automatically adds Proxy-Uri option to\n" + "\t\t\trequest)\n" + "\t-T token\tinclude specified token\n" + "\n" + "examples:\n" + "\tcoap-client -m get coap://[::1]/\n" + "\tcoap-client -m get coap://[::1]/.well-known/core\n" + "\tcoap-client -m get -T cafe coap://[::1]/time\n" + "\techo 1000 | coap-client -m put -T cafe coap://[::1]/time -f -\n" + ,program, version, program, wait_seconds); +} + +int +join( coap_context_t *ctx, char *group_name ){ + struct ipv6_mreq mreq; + struct addrinfo *reslocal = NULL, *resmulti = NULL, hints, *ainfo; + int result = -1; + + /* we have to resolve the link-local interface to get the interface id */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_DGRAM; + + result = getaddrinfo("::", NULL, &hints, &reslocal); + if ( result < 0 ) { + fprintf(stderr, "join: cannot resolve link-local interface: %s\n", + gai_strerror(result)); + goto finish; + } + + /* get the first suitable interface identifier */ + for (ainfo = reslocal; ainfo != NULL; ainfo = ainfo->ai_next) { + if ( ainfo->ai_family == AF_INET6 ) { + mreq.ipv6mr_interface = + ((struct sockaddr_in6 *)ainfo->ai_addr)->sin6_scope_id; + break; + } + } + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_DGRAM; + + /* resolve the multicast group address */ + result = getaddrinfo(group_name, NULL, &hints, &resmulti); + + if ( result < 0 ) { + fprintf(stderr, "join: cannot resolve multicast address: %s\n", + gai_strerror(result)); + goto finish; + } + + for (ainfo = resmulti; ainfo != NULL; ainfo = ainfo->ai_next) { + if ( ainfo->ai_family == AF_INET6 ) { + mreq.ipv6mr_multiaddr = + ((struct sockaddr_in6 *)ainfo->ai_addr)->sin6_addr; + break; + } + } + + result = setsockopt( ctx->sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP, + (char *)&mreq, sizeof(mreq) ); + if ( result < 0 ) + perror("join: setsockopt"); + + finish: + freeaddrinfo(resmulti); + freeaddrinfo(reslocal); + + return result; +} + +int +order_opts(void *a, void *b) { + if (!a || !b) + return a < b ? -1 : 1; + + if (COAP_OPTION_KEY(*(coap_option *)a) < COAP_OPTION_KEY(*(coap_option *)b)) + return -1; + + return COAP_OPTION_KEY(*(coap_option *)a) == COAP_OPTION_KEY(*(coap_option *)b); +} + + +coap_list_t * +new_option_node(unsigned short key, unsigned int length, unsigned char *data) { + coap_option *option; + coap_list_t *node; + + option = coap_malloc(sizeof(coap_option) + length); + if ( !option ) + goto error; + + COAP_OPTION_KEY(*option) = key; + COAP_OPTION_LENGTH(*option) = length; + memcpy(COAP_OPTION_DATA(*option), data, length); + + /* we can pass NULL here as delete function since option is released automatically */ + node = coap_new_listnode(option, NULL); + + if ( node ) + return node; + + error: + perror("new_option_node: malloc"); + coap_free( option ); + return NULL; +} + +typedef struct { + unsigned char code; + char *media_type; +} content_type_t; + +void +cmdline_content_type(char *arg, unsigned short key) { + static content_type_t content_types[] = { + { 0, "plain" }, + { 0, "text/plain" }, + { 40, "link" }, + { 40, "link-format" }, + { 40, "application/link-format" }, + { 41, "xml" }, + { 42, "binary" }, + { 42, "octet-stream" }, + { 42, "application/octet-stream" }, + { 47, "exi" }, + { 47, "application/exi" }, + { 50, "json" }, + { 50, "application/json" }, + { 255, NULL } + }; + coap_list_t *node; + unsigned char i, value[10]; + int valcnt = 0; + unsigned char buf[2]; + char *p, *q = arg; + + while (q && *q) { + p = strchr(q, ','); + + if (isdigit(*q)) { + if (p) + *p = '\0'; + value[valcnt++] = atoi(q); + } else { + for (i=0; content_types[i].media_type && + strncmp(q,content_types[i].media_type, p ? p-q : strlen(q)) != 0 ; + ++i) + ; + + if (content_types[i].media_type) { + value[valcnt] = content_types[i].code; + valcnt++; + } else { + warn("W: unknown content-type '%s'\n",arg); + } + } + + if (!p || key == COAP_OPTION_CONTENT_TYPE) + break; + + q = p+1; + } + + for (i = 0; i < valcnt; ++i) { + node = new_option_node(key, coap_encode_var_bytes(buf, value[i]), buf); + if (node) + coap_insert( &optlist, node, order_opts ); + } +} + +void +cmdline_uri(char *arg) { + unsigned char portbuf[2]; +#define BUFSIZE 40 + unsigned char _buf[BUFSIZE]; + unsigned char *buf = _buf; + size_t buflen; + int res; + + if (proxy.length) { /* create Proxy-Uri from argument */ + size_t len = strlen(arg); + while (len > 270) { + coap_insert(&optlist, + new_option_node(COAP_OPTION_PROXY_URI, + 270, (unsigned char *)arg), + order_opts); + len -= 270; + arg += 270; + } + + coap_insert(&optlist, + new_option_node(COAP_OPTION_PROXY_URI, + len, (unsigned char *)arg), + order_opts); + } else { /* split arg into Uri-* options */ + coap_split_uri((unsigned char *)arg, strlen(arg), &uri ); + + if (uri.port != COAP_DEFAULT_PORT) { + coap_insert( &optlist, + new_option_node(COAP_OPTION_URI_PORT, + coap_encode_var_bytes(portbuf, uri.port), + portbuf), + order_opts); + } + + if (uri.path.length) { + buflen = BUFSIZE; + res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); + + while (res--) { + coap_insert(&optlist, new_option_node(COAP_OPTION_URI_PATH, + COAP_OPT_LENGTH(buf), + COAP_OPT_VALUE(buf)), + order_opts); + + buf += COAP_OPT_SIZE(buf); + } + } + + if (uri.query.length) { + buflen = BUFSIZE; + buf = _buf; + res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen); + + while (res--) { + coap_insert(&optlist, new_option_node(COAP_OPTION_URI_QUERY, + COAP_OPT_LENGTH(buf), + COAP_OPT_VALUE(buf)), + order_opts); + + buf += COAP_OPT_SIZE(buf); + } + } + } +} + +int +cmdline_blocksize(char *arg) { + unsigned short size; + + again: + size = 0; + while(*arg && *arg != ',') + size = size * 10 + (*arg++ - '0'); + + if (*arg == ',') { + arg++; + block.num = size; + goto again; + } + + if (size) + block.szx = (coap_fls(size >> 4) - 1) & 0x07; + + flags |= FLAGS_BLOCK; + return 1; +} + +/* Called after processing the options from the commandline to set + * Block1 or Block2 depending on method. */ +void +set_blocksize() { + static unsigned char buf[4]; /* hack: temporarily take encoded bytes */ + unsigned short opt; + + if (method != COAP_REQUEST_DELETE) { + opt = method == COAP_REQUEST_GET ? COAP_OPTION_BLOCK2 : COAP_OPTION_BLOCK1; + + coap_insert(&optlist, new_option_node(opt, + coap_encode_var_bytes(buf, (block.num << 4 | block.szx)), buf), + order_opts); + } +} + +void +cmdline_subscribe(char *arg) { + (void)arg; + obs_seconds = atoi(optarg); + coap_insert(&optlist, new_option_node(COAP_OPTION_SUBSCRIPTION, 0, NULL), + order_opts); +} + +int +cmdline_proxy(char *arg) { + char *proxy_port_str = strrchr((const char *)arg, ':'); /* explicit port ? */ + if (proxy_port_str) { + char *ipv6_delimiter = strrchr((const char *)arg, ']'); + if (!ipv6_delimiter) { + if (proxy_port_str == strchr((const char *)arg, ':')) { + /* host:port format - host not in ipv6 hexadecimal string format */ + *proxy_port_str++ = '\0'; /* split */ + proxy_port = atoi(proxy_port_str); + } + } else { + arg = strchr((const char *)arg, '['); + if (!arg) return 0; + arg++; + *ipv6_delimiter = '\0'; /* split */ + if (ipv6_delimiter + 1 == proxy_port_str++) { + /* [ipv6 address]:port */ + proxy_port = atoi(proxy_port_str); + } + } + } + + proxy.length = strlen(arg); + if ( (proxy.s = coap_malloc(proxy.length + 1)) == NULL) { + proxy.length = 0; + return 0; + } + + memcpy(proxy.s, arg, proxy.length+1); + return 1; +} + +inline void +cmdline_token(char *arg) { + strncpy((char *)the_token.s, arg, min(sizeof(_token_data), strlen(arg))); + the_token.length = strlen(arg); +} + +void +cmdline_option(char *arg) { + unsigned int num = 0; + + while (*arg && *arg != ',') { + num = num * 10 + (*arg - '0'); + ++arg; + } + if (*arg == ',') + ++arg; + + coap_insert( &optlist, new_option_node(num, + strlen(arg), + (unsigned char *)arg), order_opts); +} + +extern int check_segment(const unsigned char *s, size_t length); +extern void decode_segment(const unsigned char *seg, size_t length, unsigned char *buf); + +int +cmdline_input(char *text, str *buf) { + int len; + len = check_segment((unsigned char *)text, strlen(text)); + + if (len < 0) + return 0; + + buf->s = (unsigned char *)coap_malloc(len); + if (!buf->s) + return 0; + + buf->length = len; + decode_segment((unsigned char *)text, strlen(text), buf->s); + return 1; +} + +int +cmdline_input_from_file(char *filename, str *buf) { + FILE *inputfile = NULL; + size_t len; + int result = 1; + struct stat statbuf; + + if (!filename || !buf) + return 0; + + if (filename[0] == '-' && !filename[1]) { /* read from stdin */ + buf->length = 20000; + buf->s = (unsigned char *)coap_malloc(buf->length); + if (!buf->s) + return 0; + + inputfile = stdin; + } else { + /* read from specified input file */ + if (stat(filename, &statbuf) < 0) { + perror("cmdline_input_from_file: stat"); + return 0; + } + + buf->length = statbuf.st_size; + buf->s = (unsigned char *)coap_malloc(buf->length); + if (!buf->s) + return 0; + + inputfile = fopen(filename, "r"); + if ( !inputfile ) { + perror("cmdline_input_from_file: fopen"); + coap_free(buf->s); + return 0; + } + } + + len = fread(buf->s, 1, buf->length, inputfile); + + if (len < buf->length) { + if (ferror(inputfile) != 0) { + perror("cmdline_input_from_file: fread"); + coap_free(buf->s); + buf->length = 0; + buf->s = NULL; + result = 0; + } else { + buf->length = len; + } + } + + if (inputfile != stdin) + fclose(inputfile); + + return result; +} + +method_t +cmdline_method(char *arg) { + static char *methods[] = + { 0, "get", "post", "put", "delete", 0}; + unsigned char i; + + for (i=1; methods[i] && strcasecmp(arg,methods[i]) != 0 ; ++i) + ; + + return i; /* note that we do not prevent illegal methods */ +} + +coap_context_t * +get_context(const char *node, const char *port) { + coap_context_t *ctx = NULL; + int s; + struct addrinfo hints; + struct addrinfo *result, *rp; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */ +#ifndef __ANDROID__ + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV | AI_ALL; +#endif //__ANDROID__ + + + OC_LOG_V(DEBUG, MOD_NAME, "Line %d, node %s, port %d", __LINE__, node, port); + s = getaddrinfo(node, port, &hints, &result); + if ( s != 0 ) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); + return NULL; + } + + /* iterate through results until success */ + for (rp = result; rp != NULL; rp = rp->ai_next) { + coap_address_t addr; + + if (rp->ai_addrlen <= sizeof(addr.addr)) { + coap_address_init(&addr); + addr.size = rp->ai_addrlen; + memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen); + + ctx = coap_new_context(&addr); + if (ctx) { + /* TODO: output address:port for successful binding */ + goto finish; + } + } + } + + fprintf(stderr, "no context available for interface '%s'\n", node); + + finish: + freeaddrinfo(result); + return ctx; +} + +int +main(int argc, char **argv) { + coap_context_t *ctx = NULL; + coap_address_t dst; + static char addr[INET6_ADDRSTRLEN]; + void *addrptr = NULL; + fd_set readfds; + struct timeval tv; + int result; + coap_tick_t now; + coap_queue_t *nextpdu; + coap_pdu_t *pdu; + static str server; + unsigned short port = COAP_DEFAULT_PORT; + char port_str[NI_MAXSERV] = "0"; + int opt, res; + char *group = NULL; + coap_log_t log_level = LOG_WARNING; + coap_tid_t tid = COAP_INVALID_TID; + + while ((opt = getopt(argc, argv, "Nb:e:f:g:m:p:s:t:o:v:A:B:O:P:T:")) != -1) { + switch (opt) { + case 'b' : + cmdline_blocksize(optarg); + break; + case 'B' : + wait_seconds = atoi(optarg); + break; + case 'e' : + if (!cmdline_input(optarg,&payload)) + payload.length = 0; + break; + case 'f' : + if (!cmdline_input_from_file(optarg,&payload)) + payload.length = 0; + break; + case 'g' : + group = optarg; + break; + case 'p' : + strncpy(port_str, optarg, NI_MAXSERV-1); + port_str[NI_MAXSERV - 1] = '\0'; + break; + case 'm' : + method = cmdline_method(optarg); + break; + case 'N' : + msgtype = COAP_MESSAGE_NON; + break; + case 's' : + cmdline_subscribe(optarg); + break; + case 'o' : + output_file.length = strlen(optarg); + output_file.s = (unsigned char *)coap_malloc(output_file.length + 1); + + if (!output_file.s) { + fprintf(stderr, "cannot set output file: insufficient memory\n"); + exit(-1); + } else { + /* copy filename including trailing zero */ + memcpy(output_file.s, optarg, output_file.length + 1); + } + break; + case 'A' : + cmdline_content_type(optarg,COAP_OPTION_ACCEPT); + break; + case 't' : + cmdline_content_type(optarg,COAP_OPTION_CONTENT_TYPE); + break; + case 'O' : + cmdline_option(optarg); + break; + case 'P' : + if (!cmdline_proxy(optarg)) { + fprintf(stderr, "error specifying proxy address\n"); + exit(-1); + } + break; + case 'T' : + cmdline_token(optarg); + break; + case 'v' : + log_level = strtol(optarg, NULL, 10); + break; + default: + usage( argv[0], PACKAGE_VERSION ); + exit( 1 ); + } + } + + coap_set_log_level(log_level); + + if ( optind < argc ) + cmdline_uri( argv[optind] ); + else { + usage( argv[0], PACKAGE_VERSION ); + exit( 1 ); + } + + if (proxy.length) { + server = proxy; + port = proxy_port; + } else { + server = uri.host; + port = uri.port; + } + + /* resolve destination address where server should be sent */ + res = resolve_address(&server, &dst.addr.sa); + + if (res < 0) { + fprintf(stderr, "failed to resolve address\n"); + exit(-1); + } + + dst.size = res; + dst.addr.sin.sin_port = htons(port); + + /* add Uri-Host if server address differs from uri.host */ + + switch (dst.addr.sa.sa_family) { + case AF_INET: + addrptr = &dst.addr.sin.sin_addr; + + /* create context for IPv4 */ + ctx = get_context("0.0.0.0", port_str); + break; + case AF_INET6: + addrptr = &dst.addr.sin6.sin6_addr; + + /* create context for IPv6 */ + ctx = get_context("::", port_str); + break; + default: + ; + } + + if (!ctx) { + coap_log(LOG_EMERG, "cannot create context\n"); + return -1; + } + + coap_register_option(ctx, COAP_OPTION_BLOCK2); + coap_register_response_handler(ctx, message_handler); + + /* join multicast group if requested at command line */ + if (group) + join(ctx, group); + + /* construct CoAP message */ + + if (!proxy.length && addrptr + && (inet_ntop(dst.addr.sa.sa_family, addrptr, addr, sizeof(addr)) != 0) + && (strlen(addr) != uri.host.length + || memcmp(addr, uri.host.s, uri.host.length) != 0)) { + /* add Uri-Host */ + + coap_insert(&optlist, new_option_node(COAP_OPTION_URI_HOST, + uri.host.length, uri.host.s), + order_opts); + } + + /* set block option if requested at commandline */ + if (flags & FLAGS_BLOCK) + set_blocksize(); + + if (! (pdu = coap_new_request(ctx, method, optlist))) + return -1; + +#ifndef NDEBUG + if (LOG_DEBUG <= coap_get_log_level()) { + debug("sending CoAP request:\n"); + coap_show_pdu(pdu); + } +#endif + + if (pdu->hdr->type == COAP_MESSAGE_CON) + tid = coap_send_confirmed(ctx, &dst, pdu); + else + tid = coap_send(ctx, &dst, pdu); + + if (pdu->hdr->type != COAP_MESSAGE_CON || tid == COAP_INVALID_TID) + coap_delete_pdu(pdu); + + set_timeout(&max_wait, wait_seconds); + debug("timeout is set to %d seconds\n", wait_seconds); + + while ( !(ready && coap_can_exit(ctx)) ) { + FD_ZERO(&readfds); + FD_SET( ctx->sockfd, &readfds ); + + nextpdu = coap_peek_next( ctx ); + + coap_ticks(&now); + while (nextpdu && nextpdu->t <= now - ctx->sendqueue_basetime) { + coap_retransmit( ctx, coap_pop_next( ctx )); + nextpdu = coap_peek_next( ctx ); + } + + if (nextpdu && nextpdu->t < min(obs_wait ? obs_wait : max_wait, max_wait) - now) { + /* set timeout if there is a pdu to send */ + tv.tv_usec = ((nextpdu->t) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND; + tv.tv_sec = (nextpdu->t) / COAP_TICKS_PER_SECOND; + } else { + /* check if obs_wait fires before max_wait */ + if (obs_wait && obs_wait < max_wait) { + tv.tv_usec = ((obs_wait - now) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND; + tv.tv_sec = (obs_wait - now) / COAP_TICKS_PER_SECOND; + } else { + tv.tv_usec = ((max_wait - now) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND; + tv.tv_sec = (max_wait - now) / COAP_TICKS_PER_SECOND; + } + } + + result = select(ctx->sockfd + 1, &readfds, 0, 0, &tv); + + if ( result < 0 ) { /* error */ + perror("select"); + } else if ( result > 0 ) { /* read from socket */ + if ( FD_ISSET( ctx->sockfd, &readfds ) ) { + coap_read( ctx, ctx->sockfd ); /* read received data */ + coap_dispatch( ctx ); /* and dispatch PDUs from receivequeue */ + } + } else { /* timeout */ + coap_ticks(&now); + if (max_wait <= now) { + info("timeout\n"); + break; + } + if (obs_wait && obs_wait <= now) { + debug("clear observation relationship\n"); + clear_obs(ctx, &dst); /* FIXME: handle error case COAP_TID_INVALID */ + + /* make sure that the obs timer does not fire again */ + obs_wait = 0; + obs_seconds = 0; + } + } + } + + close_output(); + + coap_free_context( ctx ); + + return 0; +} diff --git a/resource/csdk/libcoap-4.1.1/examples/makefile b/resource/csdk/libcoap-4.1.1/examples/makefile new file mode 100644 index 000000000..0d1988795 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/examples/makefile @@ -0,0 +1,82 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +VERSION:=4.1.1 + +#other options are android, arduino +PLATFORM=linux + +ROOT_DIR = ../.. +OCSOCK_DIR = $(ROOT_DIR)/ocsocket +LOGGER_DIR = $(ROOT_DIR)/logger +RANDOM_DIR = $(ROOT_DIR)/ocrandom +OBJ_DIR = ./ +INC_DIRS = -I.. -I$(OCSOCK_DIR)/include/ -I$(LOGGER_DIR)/include -I$(RANDOM_DIR)/include + +ifeq ($(PLATFORM),android) + CXX=arm-linux-androideabi-g++ + CC=arm-linux-androideabi-gcc + AR=arm-linux-androideabi-ar + RANLIB=arm-linux-androideabi-ranlib + CFLAGS_ANDROID = -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 + LDFLAGS_ANDROID = -march=armv7-a -Wl,--fix-cortex-a8 -llog +else ifeq ($(PLATFORM),linux) + CXX=g++ + CC=gcc + AR=ar + RANLIB=ranlib +else + $(error Wrong value for PLATFORM !!) +endif + +DEP_LIBS = ../libcoap.a + +CFLAGS += -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions \ + -Wextra -Wno-variadic-macros -pedantic -std=gnu99 -DWITH_POSIX + +PROGRAMS = coap-server coap-client + +SOURCES:= client.c server.c + +OBJECTS:= $(patsubst %.c, %.o, $(SOURCES)) + +all: $(PROGRAMS) + +%.o: %.c + $(CC) -c $(CFLAGS) $(CFLAGS_ANDROID) $(INC_DIRS) $< -o $@ + +coap-client: client.o $(DEP_LIBS) + $(CC) -Os -Wl,--gc-sections $(LDFLAGS_ANDROID) $^ -o $@ + +coap-server: server.o $(DEP_LIBS) + $(CC) -Os -Wl,--gc-sections $(LDFLAGS_ANDROID) $^ -o $@ + +install: all + @echo "Installing for PLATFORM $(PLATFORM)" +ifeq ($(PLATFORM),android) + adb push coap-client /data/local/tmp/ + adb push coap-server /data/local/tmp/ +endif + +.PHONY: clean + +clean: + rm -f *.o $(PROGRAMS) + diff --git a/resource/csdk/libcoap-4.1.1/examples/rd.c b/resource/csdk/libcoap-4.1.1/examples/rd.c new file mode 100644 index 000000000..271a78c2d --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/examples/rd.c @@ -0,0 +1,705 @@ +/* coap -- simple implementation of the Constrained Application Protocol (CoAP) + * as defined in draft-ietf-core-coap + * + * Copyright (C) 2010--2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + + +/** + * @file rd.c + * @brief CoRE resource directory + * + * @see http://tools.ietf.org/id/draft-shelby-core-resource-directory + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "utlist.h" +#include "resource.h" +#include "coap.h" + +#define COAP_RESOURCE_CHECK_TIME 2 + +#define RD_ROOT_STR ((unsigned char *)"rd") +#define RD_ROOT_SIZE 2 + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +typedef struct rd_t { + UT_hash_handle hh; /**< hash handle (for internal use only) */ + coap_key_t key; /**< the actual key bytes for this resource */ + + size_t etag_len; /**< actual length of @c etag */ + unsigned char etag[8]; /**< ETag for current description */ + + str data; /**< points to the resource description */ +} rd_t; + +rd_t *resources = NULL; + +inline rd_t * +rd_new() { + rd_t *rd; + rd = (rd_t *)coap_malloc(sizeof(rd_t)); + if (rd) + memset(rd, 0, sizeof(rd_t)); + + return rd; +} + +inline void +rd_delete(rd_t *rd) { + if (rd) { + coap_free(rd->data.s); + coap_free(rd); + } +} + +/* temporary storage for dynamic resource representations */ +static int quit = 0; + +/* SIGINT handler: set quit to 1 for graceful termination */ +void +handle_sigint(int signum) { + quit = 1; +} + +void +hnd_get_resource(coap_context_t *ctx, struct coap_resource_t *resource, + coap_address_t *peer, coap_pdu_t *request, str *token, + coap_pdu_t *response) { + rd_t *rd = NULL; + unsigned char buf[3]; + + HASH_FIND(hh, resources, resource->key, sizeof(coap_key_t), rd); + + response->hdr->code = COAP_RESPONSE_CODE(205); + + coap_add_option(response, COAP_OPTION_CONTENT_TYPE, + coap_encode_var_bytes(buf, COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), buf); + + if (rd && rd->etag_len) + coap_add_option(response, COAP_OPTION_ETAG, rd->etag_len, rd->etag); + + if (rd && rd->data.s) + coap_add_data(response, rd->data.length, rd->data.s); +} + +void +hnd_put_resource(coap_context_t *ctx, struct coap_resource_t *resource, + coap_address_t *peer, coap_pdu_t *request, str *token, + coap_pdu_t *response) { +#if 1 + response->hdr->code = COAP_RESPONSE_CODE(501); +#else /* FIXME */ + coap_opt_iterator_t opt_iter; + coap_opt_t *token, *etag; + coap_pdu_t *response; + size_t size = sizeof(coap_hdr_t); + int type = (request->hdr->type == COAP_MESSAGE_CON) + ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON; + rd_t *rd = NULL; + unsigned char code; /* result code */ + unsigned char *data; + str tmp; + + HASH_FIND(hh, resources, resource->key, sizeof(coap_key_t), rd); + if (rd) { + /* found resource object, now check Etag */ + etag = coap_check_option(request, COAP_OPTION_ETAG, &opt_iter); + if (!etag || (COAP_OPT_LENGTH(etag) != rd->etag_len) + || memcmp(COAP_OPT_VALUE(etag), rd->etag, rd->etag_len) != 0) { + + if (coap_get_data(request, &tmp.length, &data)) { + + tmp.s = (unsigned char *)coap_malloc(tmp.length); + if (!tmp.s) { + debug("hnd_put_rd: cannot allocate storage for new rd\n"); + code = COAP_RESPONSE_CODE(503); + goto finish; + } + + coap_free(rd->data.s); + rd->data.s = tmp.s; + rd->data.length = tmp.length; + memcpy(rd->data.s, data, rd->data.length); + } + } + + if (etag) { + rd->etag_len = min(COAP_OPT_LENGTH(etag), sizeof(rd->etag)); + memcpy(rd->etag, COAP_OPT_VALUE(etag), rd->etag_len); + } + + code = COAP_RESPONSE_CODE(204); + /* FIXME: update lifetime */ + + } else { + + code = COAP_RESPONSE_CODE(503); + } + + finish: + /* FIXME: do not create a new response but use the old one instead */ + response = coap_pdu_init(type, code, request->hdr->id, size); + + if (!response) { + debug("cannot create response for message %d\n", request->hdr->id); + return; + } + + if (request->hdr->token_length) + coap_add_token(response, request->hdr->token_length, request->hdr->token); + + if (coap_send(ctx, peer, response) == COAP_INVALID_TID) { + debug("hnd_get_rd: cannot send response for message %d\n", + request->hdr->id); + } + coap_delete_pdu(response); +#endif +} + +void +hnd_delete_resource(coap_context_t *ctx, struct coap_resource_t *resource, + coap_address_t *peer, coap_pdu_t *request, str *token, + coap_pdu_t *response) { + rd_t *rd = NULL; + + HASH_FIND(hh, resources, resource->key, sizeof(coap_key_t), rd); + if (rd) { + HASH_DELETE(hh, resources, rd); + rd_delete(rd); + } + /* FIXME: link attributes for resource have been created dynamically + * using coap_malloc() and must be released. */ + coap_delete_resource(ctx, resource->key); + + response->hdr->code = COAP_RESPONSE_CODE(202); +} + +void +hnd_get_rd(coap_context_t *ctx, struct coap_resource_t *resource, + coap_address_t *peer, coap_pdu_t *request, str *token, + coap_pdu_t *response) { + unsigned char buf[3]; + + response->hdr->code = COAP_RESPONSE_CODE(205); + + coap_add_option(response, COAP_OPTION_CONTENT_TYPE, + coap_encode_var_bytes(buf, COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), buf); + + coap_add_option(response, COAP_OPTION_MAXAGE, + coap_encode_var_bytes(buf, 0x2ffff), buf); +} + +int +parse_param(unsigned char *search, size_t search_len, + unsigned char *data, size_t data_len, str *result) { + + if (result) + memset(result, 0, sizeof(str)); + + if (!search_len) + return 0; + + while (search_len <= data_len) { + + /* handle parameter if found */ + if (memcmp(search, data, search_len) == 0) { + data += search_len; + data_len -= search_len; + + /* key is only valid if we are at end of string or delimiter follows */ + if (!data_len || *data == '=' || *data == '&') { + while (data_len && *data != '=') { + ++data; --data_len; + } + + if (data_len > 1 && result) { + /* value begins after '=' */ + + result->s = ++data; + while (--data_len && *data != '&') { + ++data; result->length++; + } + } + + return 1; + } + } + + /* otherwise proceed to next */ + while (--data_len && *data++ != '&') + ; + } + + return 0; +} + +void +add_source_address(struct coap_resource_t *resource, coap_address_t *peer) { +#define BUFSIZE 64 + char *buf; + size_t n = 1; + + buf = (char *)coap_malloc(BUFSIZE); + if (!buf) + return; + + buf[0] = '"'; + + switch(peer->addr.sa.sa_family) { + + case AF_INET: + /* FIXME */ + break; + + case AF_INET6: + n += snprintf(buf + n, BUFSIZE - n, + "[%02x%02x:%02x%02x:%02x%02x:%02x%02x" \ + ":%02x%02x:%02x%02x:%02x%02x:%02x%02x]", + peer->addr.sin6.sin6_addr.s6_addr[0], + peer->addr.sin6.sin6_addr.s6_addr[1], + peer->addr.sin6.sin6_addr.s6_addr[2], + peer->addr.sin6.sin6_addr.s6_addr[3], + peer->addr.sin6.sin6_addr.s6_addr[4], + peer->addr.sin6.sin6_addr.s6_addr[5], + peer->addr.sin6.sin6_addr.s6_addr[6], + peer->addr.sin6.sin6_addr.s6_addr[7], + peer->addr.sin6.sin6_addr.s6_addr[8], + peer->addr.sin6.sin6_addr.s6_addr[9], + peer->addr.sin6.sin6_addr.s6_addr[10], + peer->addr.sin6.sin6_addr.s6_addr[11], + peer->addr.sin6.sin6_addr.s6_addr[12], + peer->addr.sin6.sin6_addr.s6_addr[13], + peer->addr.sin6.sin6_addr.s6_addr[14], + peer->addr.sin6.sin6_addr.s6_addr[15]); + + if (peer->addr.sin6.sin6_port != htons(COAP_DEFAULT_PORT)) { + n += + snprintf(buf + n, BUFSIZE - n, ":%d", peer->addr.sin6.sin6_port); + } + break; + default: + ; + } + + if (n < BUFSIZE) + buf[n++] = '"'; + + coap_add_attr(resource, (unsigned char *)"A", 1, (unsigned char *)buf, n, COAP_ATTR_FLAGS_RELEASE_VALUE); +#undef BUFSIZE +} + + +rd_t * +make_rd(coap_address_t *peer, coap_pdu_t *pdu) { + rd_t *rd; + unsigned char *data; + coap_opt_iterator_t opt_iter; + coap_opt_t *etag; + + rd = rd_new(); + + if (!rd) { + debug("hnd_get_rd: cannot allocate storage for rd\n"); + return NULL; + } + + if (coap_get_data(pdu, &rd->data.length, &data)) { + rd->data.s = (unsigned char *)coap_malloc(rd->data.length); + if (!rd->data.s) { + debug("hnd_get_rd: cannot allocate storage for rd->data\n"); + rd_delete(rd); + return NULL; + } + memcpy(rd->data.s, data, rd->data.length); + } + + etag = coap_check_option(pdu, COAP_OPTION_ETAG, &opt_iter); + if (etag) { + rd->etag_len = min(COAP_OPT_LENGTH(etag), sizeof(rd->etag)); + memcpy(rd->etag, COAP_OPT_VALUE(etag), rd->etag_len); + } + + return rd; +} + +void +hnd_post_rd(coap_context_t *ctx, struct coap_resource_t *resource, + coap_address_t *peer, coap_pdu_t *request, str *token, + coap_pdu_t *response) { + coap_resource_t *r; + coap_opt_iterator_t opt_iter; + coap_opt_t *query; +#define LOCSIZE 68 + unsigned char *loc; + size_t loc_size; + str h = {0, NULL}, ins = {0, NULL}, rt = {0, NULL}, lt = {0, NULL}; /* store query parameters */ + unsigned char *buf; + + loc = (unsigned char *)coap_malloc(LOCSIZE); + if (!loc) { + response->hdr->code = COAP_RESPONSE_CODE(500); + return; + } + memcpy(loc, RD_ROOT_STR, RD_ROOT_SIZE); + + loc_size = RD_ROOT_SIZE; + loc[loc_size++] = '/'; + + /* store query parameters for later use */ + query = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter); + if (query) { + parse_param((unsigned char *)"h", 1, + COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), &h); + parse_param((unsigned char *)"ins", 3, + COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), &ins); + parse_param((unsigned char *)"lt", 2, + COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), <); + parse_param((unsigned char *)"rt", 2, + COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), &rt); + } + + if (h.length) { /* client has specified a node name */ + memcpy(loc + loc_size, h.s, min(h.length, LOCSIZE - loc_size - 1)); + loc_size += min(h.length, LOCSIZE - loc_size - 1); + + if (ins.length && loc_size > 1) { + loc[loc_size++] = '-'; + memcpy((char *)(loc + loc_size), + ins.s, min(ins.length, LOCSIZE - loc_size - 1)); + loc_size += min(ins.length, LOCSIZE - loc_size - 1); + } + + } else { /* generate node identifier */ + loc_size += + snprintf((char *)(loc + loc_size), LOCSIZE - loc_size - 1, + "%x", request->hdr->id); + + if (loc_size > 1) { + if (ins.length) { + loc[loc_size++] = '-'; + memcpy((char *)(loc + loc_size), + ins.s, min(ins.length, LOCSIZE - loc_size - 1)); + loc_size += min(ins.length, LOCSIZE - loc_size - 1); + } else { + coap_tick_t now; + coap_ticks(&now); + + loc_size += + snprintf((char *)(loc + loc_size), LOCSIZE - loc_size - 1, + "-%x", now); + } + } + } + + /* TODO: + * - use lt to check expiration + */ + + r = coap_resource_init(loc, loc_size, COAP_RESOURCE_FLAGS_RELEASE_URI); + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_resource); + coap_register_handler(r, COAP_REQUEST_PUT, hnd_put_resource); + coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_resource); + + if (ins.s) { + buf = (unsigned char *)coap_malloc(ins.length + 2); + if (buf) { + /* add missing quotes */ + buf[0] = '"'; + memcpy(buf + 1, ins.s, ins.length); + buf[ins.length + 1] = '"'; + coap_add_attr(r, (unsigned char *)"ins", 3, buf, ins.length + 2, COAP_ATTR_FLAGS_RELEASE_VALUE); + } + } + + if (rt.s) { + buf = (unsigned char *)coap_malloc(rt.length + 2); + if (buf) { + /* add missing quotes */ + buf[0] = '"'; + memcpy(buf + 1, rt.s, rt.length); + buf[rt.length + 1] = '"'; + coap_add_attr(r, (unsigned char *)"rt", 2, buf, rt.length + 2, COAP_ATTR_FLAGS_RELEASE_VALUE); + } + } + + add_source_address(r, peer); + + { + rd_t *rd; + rd = make_rd(peer, request); + if (rd) { + coap_hash_path(loc, loc_size, rd->key); + HASH_ADD(hh, resources, key, sizeof(coap_key_t), rd); + } else { + /* FIXME: send error response and delete r */ + } + } + + coap_add_resource(ctx, r); + + + /* create response */ + + response->hdr->code = COAP_RESPONSE_CODE(201); + + { /* split path into segments and add Location-Path options */ + unsigned char _b[LOCSIZE]; + unsigned char *b = _b; + size_t buflen = sizeof(_b); + int nseg; + + nseg = coap_split_path(loc, loc_size, b, &buflen); + while (nseg--) { + coap_add_option(response, COAP_OPTION_LOCATION_PATH, + COAP_OPT_LENGTH(b), COAP_OPT_VALUE(b)); + b += COAP_OPT_SIZE(b); + } + } +} + +void +init_resources(coap_context_t *ctx) { + coap_resource_t *r; + + r = coap_resource_init(RD_ROOT_STR, RD_ROOT_SIZE, 0); + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_rd); + coap_register_handler(r, COAP_REQUEST_POST, hnd_post_rd); + + coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"40", 2, 0); + coap_add_attr(r, (unsigned char *)"rt", 2, (unsigned char *)"\"core-rd\"", 9, 0); + coap_add_attr(r, (unsigned char *)"ins", 2, (unsigned char *)"\"default\"", 9, 0); + + coap_add_resource(ctx, r); + +} + +void +usage( const char *program, const char *version) { + const char *p; + + p = strrchr( program, '/' ); + if ( p ) + program = ++p; + + fprintf( stderr, "%s v%s -- CoRE Resource Directory implementation\n" + "(c) 2011-2012 Olaf Bergmann \n\n" + "usage: %s [-A address] [-p port]\n\n" + "\t-A address\tinterface address to bind to\n" + "\t-p port\t\tlisten on specified port\n" + "\t-v num\t\tverbosity level (default: 3)\n", + program, version, program ); +} + +coap_context_t * +get_context(const char *node, const char *port) { + coap_context_t *ctx = NULL; + int s; + struct addrinfo hints; + struct addrinfo *result, *rp; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */ + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; + + s = getaddrinfo(node, port, &hints, &result); + if ( s != 0 ) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); + return NULL; + } + + /* iterate through results until success */ + for (rp = result; rp != NULL; rp = rp->ai_next) { + coap_address_t addr; + + if (rp->ai_addrlen <= sizeof(addr.addr)) { + coap_address_init(&addr); + addr.size = rp->ai_addrlen; + memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen); + + ctx = coap_new_context(&addr); + if (ctx) { + /* TODO: output address:port for successful binding */ + goto finish; + } + } + } + + fprintf(stderr, "no context available for interface '%s'\n", node); + + finish: + freeaddrinfo(result); + return ctx; +} + +int +join(coap_context_t *ctx, char *group_name) { + struct ipv6_mreq mreq; + struct addrinfo *reslocal = NULL, *resmulti = NULL, hints, *ainfo; + int result = -1; + + /* we have to resolve the link-local interface to get the interface id */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_DGRAM; + + result = getaddrinfo("::", NULL, &hints, &reslocal); + if ( result < 0 ) { + perror("join: cannot resolve link-local interface"); + goto finish; + } + + /* get the first suitable interface identifier */ + for (ainfo = reslocal; ainfo != NULL; ainfo = ainfo->ai_next) { + if ( ainfo->ai_family == AF_INET6 ) { + mreq.ipv6mr_interface = + ((struct sockaddr_in6 *)ainfo->ai_addr)->sin6_scope_id; + break; + } + } + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_DGRAM; + + /* resolve the multicast group address */ + result = getaddrinfo(group_name, NULL, &hints, &resmulti); + + if ( result < 0 ) { + perror("join: cannot resolve multicast address"); + goto finish; + } + + for (ainfo = resmulti; ainfo != NULL; ainfo = ainfo->ai_next) { + if ( ainfo->ai_family == AF_INET6 ) { + mreq.ipv6mr_multiaddr = + ((struct sockaddr_in6 *)ainfo->ai_addr)->sin6_addr; + break; + } + } + + result = setsockopt( ctx->sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP, + (char *)&mreq, sizeof(mreq) ); + if ( result < 0 ) + perror("join: setsockopt"); + + finish: + freeaddrinfo(resmulti); + freeaddrinfo(reslocal); + + return result; +} + +int +main(int argc, char **argv) { + coap_context_t *ctx; + fd_set readfds; + struct timeval tv, *timeout; + int result; + coap_tick_t now; + coap_queue_t *nextpdu; + char addr_str[NI_MAXHOST] = "::"; + char port_str[NI_MAXSERV] = "5683"; + char *group = NULL; + int opt; + coap_log_t log_level = LOG_WARNING; + + while ((opt = getopt(argc, argv, "A:g:p:v:")) != -1) { + switch (opt) { + case 'A' : + strncpy(addr_str, optarg, NI_MAXHOST-1); + addr_str[NI_MAXHOST - 1] = '\0'; + break; + case 'g' : + group = optarg; + break; + case 'p' : + strncpy(port_str, optarg, NI_MAXSERV-1); + port_str[NI_MAXSERV - 1] = '\0'; + break; + case 'v' : + log_level = strtol(optarg, NULL, 10); + break; + default: + usage( argv[0], PACKAGE_VERSION ); + exit( 1 ); + } + } + + coap_set_log_level(log_level); + + ctx = get_context(addr_str, port_str); + if (!ctx) + return -1; + + if (group) + join(ctx, group); + + init_resources(ctx); + + signal(SIGINT, handle_sigint); + + while ( !quit ) { + FD_ZERO(&readfds); + FD_SET( ctx->sockfd, &readfds ); + + nextpdu = coap_peek_next( ctx ); + + coap_ticks(&now); + while ( nextpdu && nextpdu->t <= now ) { + coap_retransmit( ctx, coap_pop_next( ctx ) ); + nextpdu = coap_peek_next( ctx ); + } + + if ( nextpdu && nextpdu->t <= now + COAP_RESOURCE_CHECK_TIME ) { + /* set timeout if there is a pdu to send before our automatic timeout occurs */ + tv.tv_usec = ((nextpdu->t - now) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND; + tv.tv_sec = (nextpdu->t - now) / COAP_TICKS_PER_SECOND; + timeout = &tv; + } else { + tv.tv_usec = 0; + tv.tv_sec = COAP_RESOURCE_CHECK_TIME; + timeout = &tv; + } + result = select( FD_SETSIZE, &readfds, 0, 0, timeout ); + + if ( result < 0 ) { /* error */ + if (errno != EINTR) + perror("select"); + } else if ( result > 0 ) { /* read from socket */ + if ( FD_ISSET( ctx->sockfd, &readfds ) ) { + coap_read( ctx ); /* read received data */ + coap_dispatch( ctx ); /* and dispatch PDUs from receivequeue */ + } + } else { /* timeout */ + /* coap_check_resource_list( ctx ); */ + } + } + + coap_free_context( ctx ); + + return 0; +} diff --git a/resource/csdk/libcoap-4.1.1/examples/server.c b/resource/csdk/libcoap-4.1.1/examples/server.c new file mode 100644 index 000000000..ee4d73f57 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/examples/server.c @@ -0,0 +1,490 @@ +/* coap -- simple implementation of the Constrained Application Protocol (CoAP) + * as defined in draft-ietf-core-coap + * + * Copyright (C) 2010--2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "resource.h" +#include "coap.h" +#include +#include + +#define COAP_RESOURCE_CHECK_TIME 2 + +#define MOD_NAME ("CoAP-Server") +static uint8_t coap_wellknown_addr[] = {224,0,1,187}; +static short coap_def_port = 5683; + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/* temporary storage for dynamic resource representations */ +static int quit = 0; + +/* changeable clock base (see handle_put_time()) */ +static time_t my_clock_base = 0; + +struct coap_resource_t *time_resource = NULL; + +#ifndef WITHOUT_ASYNC +/* This variable is used to mimic long-running tasks that require + * asynchronous responses. */ +static coap_async_state_t *async = NULL; +#endif /* WITHOUT_ASYNC */ + +/* SIGINT handler: set quit to 1 for graceful termination */ +void +handle_sigint(int signum) { + (void)signum; + quit = 1; +} + +#define INDEX "This is a test server made with libcoap (see http://libcoap.sf.net)\n" \ + "Copyright (C) 2010--2013 Olaf Bergmann \n\n" + +void +hnd_get_index(coap_context_t *ctx, struct coap_resource_t *resource, + coap_address_t *peer, coap_pdu_t *request, str *token, + coap_pdu_t *response) { + unsigned char buf[3]; + (void)ctx; + (void)resource; + (void)peer; + (void)request; + (void)token; + + response->hdr->code = COAP_RESPONSE_CODE(205); + + coap_add_option(response, COAP_OPTION_CONTENT_TYPE, + coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); + + coap_add_option(response, COAP_OPTION_MAXAGE, + coap_encode_var_bytes(buf, 0x2ffff), buf); + + coap_add_data(response, strlen(INDEX), (unsigned char *)INDEX); +} + +void +hnd_get_time(coap_context_t *ctx, struct coap_resource_t *resource, + coap_address_t *peer, coap_pdu_t *request, str *token, + coap_pdu_t *response) { + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + unsigned char buf[40]; + size_t len; + time_t now; + coap_tick_t t; + coap_subscription_t *subscription; + + /* FIXME: return time, e.g. in human-readable by default and ticks + * when query ?ticks is given. */ + + /* if my_clock_base was deleted, we pretend to have no such resource */ + response->hdr->code = + my_clock_base ? COAP_RESPONSE_CODE(205) : COAP_RESPONSE_CODE(404); + + if (request != NULL && + coap_check_option(request, COAP_OPTION_OBSERVE, &opt_iter)) { + subscription = coap_add_observer(resource, peer, token); + if (subscription) { + subscription->non = request->hdr->type == COAP_MESSAGE_NON; + coap_add_option(response, COAP_OPTION_OBSERVE, 0, NULL); + } + } + if (resource->dirty == 1) + coap_add_option(response, COAP_OPTION_OBSERVE, + coap_encode_var_bytes(buf, ctx->observe), buf); + + + if (my_clock_base) + coap_add_option(response, COAP_OPTION_CONTENT_FORMAT, + coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); + + coap_add_option(response, COAP_OPTION_MAXAGE, + coap_encode_var_bytes(buf, 0x01), buf); + + if (my_clock_base) { + + /* calculate current time */ + coap_ticks(&t); + now = my_clock_base + (t / COAP_TICKS_PER_SECOND); + + if (request != NULL + && (option = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter)) + && memcmp(COAP_OPT_VALUE(option), "ticks", + min(5, COAP_OPT_LENGTH(option))) == 0) { + /* output ticks */ + len = snprintf((char *)buf, + min(sizeof(buf), response->max_size - response->length), + "%u", (unsigned int)now); + coap_add_data(response, len, buf); + + } else { /* output human-readable time */ + struct tm *tmp; + tmp = gmtime(&now); + len = strftime((char *)buf, + min(sizeof(buf), response->max_size - response->length), + "%b %d %H:%M:%S", tmp); + coap_add_data(response, len, buf); + } + } +} + +void +hnd_put_time(coap_context_t *ctx, struct coap_resource_t *resource, + coap_address_t *peer, coap_pdu_t *request, str *token, + coap_pdu_t *response) { + coap_tick_t t; + size_t size; + unsigned char *data; + (void)ctx; + (void)peer; + (void)token; + + /* FIXME: re-set my_clock_base to clock_offset if my_clock_base == 0 + * and request is empty. When not empty, set to value in request payload + * (insist on query ?ticks). Return Created or Ok. + */ + + /* if my_clock_base was deleted, we pretend to have no such resource */ + response->hdr->code = + my_clock_base ? COAP_RESPONSE_CODE(204) : COAP_RESPONSE_CODE(201); + + resource->dirty = 1; + + coap_get_data(request, &size, &data); + + if (size == 0) /* re-init */ + my_clock_base = clock_offset; + else { + my_clock_base = 0; + coap_ticks(&t); + while(size--) + my_clock_base = my_clock_base * 10 + *data++; + my_clock_base -= t / COAP_TICKS_PER_SECOND; + } +} + +void +hnd_delete_time(coap_context_t *ctx, struct coap_resource_t *resource, + coap_address_t *peer, coap_pdu_t *request, str *token, + coap_pdu_t *response) { + (void)ctx; + (void)resource; + (void)peer; + (void)request; + (void)token; + (void)response; + my_clock_base = 0; /* mark clock as "deleted" */ + + /* type = request->hdr->type == COAP_MESSAGE_CON */ + /* ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON; */ +} + +#ifndef WITHOUT_ASYNC +void +hnd_get_async(coap_context_t *ctx, struct coap_resource_t *resource, + coap_address_t *peer, coap_pdu_t *request, str *token, + coap_pdu_t *response) { + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + unsigned long delay = 5; + size_t size; + (void)resource; + (void)token; + + if (async) { + if (async->id != request->hdr->id) { + coap_opt_filter_t f; + coap_option_filter_clear(f); + response->hdr->code = COAP_RESPONSE_CODE(503); + } + return; + } + + option = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter); + if (option) { + unsigned char *p = COAP_OPT_VALUE(option); + + delay = 0; + for (size = COAP_OPT_LENGTH(option); size; --size, ++p) + delay = delay * 10 + (*p - '0'); + } + + async = coap_register_async(ctx, peer, request, + COAP_ASYNC_SEPARATE | COAP_ASYNC_CONFIRM, + (void *)(COAP_TICKS_PER_SECOND * delay)); +} + +void +check_async(coap_context_t *ctx, coap_tick_t now) { + coap_pdu_t *response; + coap_async_state_t *tmp; + + size_t size = sizeof(coap_hdr_t) + 8; + + if (!async || now < async->created + (unsigned long)async->appdata) + return; + + response = coap_pdu_init(async->flags & COAP_ASYNC_CONFIRM + ? COAP_MESSAGE_CON + : COAP_MESSAGE_NON, + COAP_RESPONSE_CODE(205), 0, size); + if (!response) { + debug("check_async: insufficient memory, we'll try later\n"); + async->appdata = + (void *)((unsigned long)async->appdata + 15 * COAP_TICKS_PER_SECOND); + return; + } + + response->hdr->id = coap_new_message_id(ctx); + + if (async->tokenlen) + coap_add_token(response, async->tokenlen, async->token); + + coap_add_data(response, 4, (unsigned char *)"done"); + + if (coap_send(ctx, &async->peer, response) == COAP_INVALID_TID) { + debug("check_async: cannot send response for message %d\n", + response->hdr->id); + } + coap_delete_pdu(response); + coap_remove_async(ctx, async->id, &tmp); + coap_free_async(async); + async = NULL; +} +#endif /* WITHOUT_ASYNC */ + +void +init_resources(coap_context_t *ctx) { + coap_resource_t *r; + + r = coap_resource_init(NULL, 0, 0); + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_index); + + coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0); + coap_add_attr(r, (unsigned char *)"title", 5, (unsigned char *)"\"General Info\"", 14, 0); + coap_add_resource(ctx, r); + + /* store clock base to use in /time */ + my_clock_base = clock_offset; + + r = coap_resource_init((unsigned char *)"time", 4, 0); + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_time); + coap_register_handler(r, COAP_REQUEST_PUT, hnd_put_time); + coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_time); + + coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0); + coap_add_attr(r, (unsigned char *)"title", 5, (unsigned char *)"\"Internal Clock\"", 16, 0); + coap_add_attr(r, (unsigned char *)"rt", 2, (unsigned char *)"\"Ticks\"", 7, 0); + r->observable = 1; + coap_add_attr(r, (unsigned char *)"if", 2, (unsigned char *)"\"clock\"", 7, 0); + + coap_add_resource(ctx, r); + time_resource = r; + +#ifndef WITHOUT_ASYNC + r = coap_resource_init((unsigned char *)"async", 5, 0); + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_async); + + coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0); + coap_add_resource(ctx, r); +#endif /* WITHOUT_ASYNC */ +} + +void +usage( const char *program, const char *version) { + const char *p; + + p = strrchr( program, '/' ); + if ( p ) + program = ++p; + + fprintf( stderr, "%s v%s -- a small CoAP implementation\n" + "(c) 2010,2011 Olaf Bergmann \n\n" + "usage: %s [-A address] [-p port]\n\n" + "\t-A address\tinterface address to bind to\n" + "\t-p port\t\tlisten on specified port\n" + "\t-v num\t\tverbosity level (default: 3)\n", + program, version, program ); +} + +coap_context_t * +get_context(const char *node, const char *port) { + coap_context_t *ctx = NULL; + int s; + struct addrinfo hints; + struct addrinfo *result, *rp; + OCDevAddr mcast_addr; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */ + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; + + s = getaddrinfo(node, port, &hints, &result); + if ( s != 0 ) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); + return NULL; + } + + /* iterate through results until success */ + for (rp = result; rp != NULL; rp = rp->ai_next) { + coap_address_t addr; + + if (rp->ai_addrlen <= sizeof(addr.addr)) { + coap_address_init(&addr); + addr.size = rp->ai_addrlen; + memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen); + OC_LOG_BUFFER(DEBUG, MOD_NAME, (uint8_t *)&addr, addr.size + 4 ); + + ctx = coap_new_context(&addr); + if (ctx) { + /* TODO: output address:port for successful binding */ + OCBuildIPv4Address(coap_wellknown_addr[0], coap_wellknown_addr[1], + coap_wellknown_addr[2], coap_wellknown_addr[3], coap_def_port, &mcast_addr); + if (coap_join_wellknown_group(ctx, (coap_address_t*)&mcast_addr) != 0) { + OC_LOG(ERROR, MOD_NAME, PCF("Unable to join to wellknown multicast group") ); + } + goto finish; + } + } + } + + fprintf(stderr, "no context available for interface '%s'\n", node); + + finish: + freeaddrinfo(result); + return ctx; +} + +int +main(int argc, char **argv) { + coap_context_t *ctx; + fd_set readfds; + struct timeval tv, *timeout; + int result; + coap_tick_t now; + coap_queue_t *nextpdu; + char addr_str[NI_MAXHOST] = "::"; + char port_str[NI_MAXSERV] = "5683"; + int opt; + coap_log_t log_level = LOG_WARNING; + + while ((opt = getopt(argc, argv, "A:p:v:")) != -1) { + switch (opt) { + case 'A' : + strncpy(addr_str, optarg, NI_MAXHOST-1); + addr_str[NI_MAXHOST - 1] = '\0'; + break; + case 'p' : + strncpy(port_str, optarg, NI_MAXSERV-1); + port_str[NI_MAXSERV - 1] = '\0'; + break; + case 'v' : + log_level = strtol(optarg, NULL, 10); + break; + default: + usage( argv[0], PACKAGE_VERSION ); + exit( 1 ); + } + } + + coap_set_log_level(log_level); + + ctx = get_context(addr_str, port_str); + if (!ctx) + return -1; + + init_resources(ctx); + + signal(SIGINT, handle_sigint); + + while ( !quit ) { + FD_ZERO(&readfds); + FD_SET( ctx->sockfd, &readfds ); + if (ctx->sockfd_wellknown != -1) { + FD_SET( ctx->sockfd_wellknown, &readfds ); + } + + + nextpdu = coap_peek_next( ctx ); + + coap_ticks(&now); + while (nextpdu && nextpdu->t <= now - ctx->sendqueue_basetime) { + coap_retransmit( ctx, coap_pop_next( ctx ) ); + nextpdu = coap_peek_next( ctx ); + } + + if ( nextpdu && nextpdu->t <= COAP_RESOURCE_CHECK_TIME ) { + /* set timeout if there is a pdu to send before our automatic timeout occurs */ + tv.tv_usec = ((nextpdu->t) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND; + tv.tv_sec = (nextpdu->t) / COAP_TICKS_PER_SECOND; + timeout = &tv; + } else { + tv.tv_usec = 0; + tv.tv_sec = COAP_RESOURCE_CHECK_TIME; + timeout = &tv; + } + result = select( FD_SETSIZE, &readfds, 0, 0, timeout ); + + if ( result < 0 ) { /* error */ + if (errno != EINTR) + perror("select"); + } else if ( result > 0 ) { /* read from unicast socket */ + if ( FD_ISSET( ctx->sockfd, &readfds ) ) { + coap_read( ctx, ctx->sockfd ); /* read received data */ + coap_dispatch( ctx ); /* and dispatch PDUs from receivequeue */ + } + + if (ctx->sockfd_wellknown != -1) { + if ( FD_ISSET( ctx->sockfd_wellknown, &readfds ) ) { /* read from multicast socket */ + + OC_LOG(DEBUG, MOD_NAME, PCF("Device Discovery request at well-known address !!")); + coap_read( ctx, ctx->sockfd_wellknown ); /* read received data */ + TODO("Do we need to call coap_dispatch separately for unicast and multicast sockets") + coap_dispatch( ctx ); /* and dispatch PDUs from receivequeue */ + } + } + } else { /* timeout */ + if (time_resource) { + time_resource->dirty = 1; + } + } + +#ifndef WITHOUT_ASYNC + /* check if we have to send asynchronous responses */ + check_async(ctx, now); +#endif /* WITHOUT_ASYNC */ + +#ifndef WITHOUT_OBSERVE + /* check if we have to send observe notifications */ + coap_check_notify(ctx); +#endif /* WITHOUT_OBSERVE */ + } + + coap_free_context( ctx ); + + return 0; +} diff --git a/resource/csdk/libcoap-4.1.1/examples/tiny.c b/resource/csdk/libcoap-4.1.1/examples/tiny.c new file mode 100644 index 000000000..0583c28e6 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/examples/tiny.c @@ -0,0 +1,149 @@ +/* tiny -- tiny sender + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../coap.h" + +static coap_tid_t id; + +coap_pdu_t * +make_pdu( unsigned int value ) { + coap_pdu_t *pdu; + unsigned char enc; + static unsigned char buf[20]; + int len, ls; + + if ( ! ( pdu = coap_new_pdu() ) ) + return NULL; + + pdu->hdr->type = COAP_MESSAGE_NON; + pdu->hdr->code = COAP_REQUEST_POST; + pdu->hdr->id = htons(id++); + + enc = COAP_PSEUDOFP_ENCODE_8_4_DOWN(value,ls); + coap_add_data( pdu, 1, &enc); + + len = snprintf((char *)buf, sizeof(buf), "%u", COAP_PSEUDOFP_DECODE_8_4(enc)); + if ( len > 0 ) { + coap_add_data( pdu, len, buf ); + } + + return pdu; +} + +void +usage( const char *program ) { + const char *p; + + p = strrchr( program, '/' ); + if ( p ) + program = ++p; + + fprintf( stderr, "%s -- tiny fake sensor\n" + "(c) 2010 Olaf Bergmann \n\n" + "usage: %s [group address]\n" + "\n\nSends some fake sensor values to specified multicast group\n", + program, program ); +} + +coap_context_t * +get_context(const char *node, const char *port) { + coap_context_t *ctx = NULL; + int s; + struct addrinfo hints; + struct addrinfo *result, *rp; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */ + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV | AI_ALL; + + s = getaddrinfo(node, port, &hints, &result); + if ( s != 0 ) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); + return NULL; + } + + /* iterate through results until success */ + for (rp = result; rp != NULL; rp = rp->ai_next) { + ctx = coap_new_context(rp->ai_addr, rp->ai_addrlen); + if (ctx) { + /* TODO: output address:port for successful binding */ + goto finish; + } + } + + fprintf(stderr, "no context available for interface '%s'\n", node); + + finish: + freeaddrinfo(result); + return ctx; +} + +int +main(int argc, char **argv) { + coap_context_t *ctx; + struct timeval tv; + coap_pdu_t *pdu; + struct sockaddr_in6 dst; + int hops = 16; + + if ( argc > 1 && strncmp(argv[1], "-h", 2) == 0 ) { + usage( argv[0] ); + exit( 1 ); + } + + ctx = get_context("::", NULL); + if ( !ctx ) + return -1; + + id = rand() & INT_MAX; + + memset(&dst, 0, sizeof(struct sockaddr_in6 )); + dst.sin6_family = AF_INET6; + inet_pton( AF_INET6, argc > 1 ? argv[1] : "::1", &dst.sin6_addr ); + dst.sin6_port = htons( COAP_DEFAULT_PORT ); + + if ( IN6_IS_ADDR_MULTICAST(&dst.sin6_addr) ) { + /* set socket options for multicast */ + + if ( setsockopt( ctx->sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, + (char *)&hops, sizeof(hops) ) < 0 ) + perror("setsockopt: IPV6_MULTICAST_HOPS"); + + } + + while ( 1 ) { + + if (! (pdu = make_pdu( rand() & 0xfff ) ) ) + return -1; + + coap_send( ctx, (struct sockaddr *)&dst, sizeof(dst), pdu ); + coap_delete_pdu(pdu); + + tv.tv_sec = 5; tv.tv_usec = 0; + + select( 0, 0, 0, 0, &tv ); + + } + + coap_free_context( ctx ); + + return 0; +} diff --git a/resource/csdk/libcoap-4.1.1/hashkey.c b/resource/csdk/libcoap-4.1.1/hashkey.c new file mode 100644 index 000000000..828b5194d --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/hashkey.c @@ -0,0 +1,29 @@ +/* hashkey.c -- definition of hash key type and helper functions + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "hashkey.h" + +/* Caution: When changing this, update COAP_DEFAULT_WKC_HASHKEY + * accordingly (see int coap_hash_path()); + */ +void +coap_hash_impl(const unsigned char *s, unsigned int len, coap_key_t h) { + size_t j; + + while (len--) { + j = sizeof(coap_key_t)-1; + + while (j) { + h[j] = ((h[j] << 7) | (h[j-1] >> 1)) + h[j]; + --j; + } + + h[0] = (h[0] << 7) + h[0] + *s++; + } +} + diff --git a/resource/csdk/libcoap-4.1.1/hashkey.h b/resource/csdk/libcoap-4.1.1/hashkey.h new file mode 100644 index 000000000..abce9ac2a --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/hashkey.h @@ -0,0 +1,65 @@ +/* hashkey.h -- definition of hash key type and helper functions + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file hashkey.h + * @brief definition of hash key type and helper functions + */ + +#ifndef _COAP_HASHKEY_H_ +#define _COAP_HASHKEY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "str.h" + +typedef unsigned char coap_key_t[4]; + +#ifndef coap_hash +/** + * Calculates a fast hash over the given string @p s of length @p len + * and stores the result into @p h. Depending on the exact + * implementation, this function cannot be used as one-way function to + * check message integrity or simlar. + * + * @param s The string used for hash calculation. + * @param len The length of @p s. + * @param h The result buffer to store the calculated hash key. + */ +void coap_hash_impl(const unsigned char *s, unsigned int len, coap_key_t h); + +#define coap_hash(String,Length,Result) \ + coap_hash_impl((String),(Length),(Result)) + +/* This is used to control the pre-set hash-keys for resources. */ +#define __COAP_DEFAULT_HASH +#else +#undef __COAP_DEFAULT_HASH +#endif /* coap_hash */ + +/** + * Calls coap_hash() with given @c str object as parameter. + * + * @param Str Must contain a pointer to a coap string object. + * @param H A coap_key_t object to store the result. + * + * @hideinitializer + */ +#define coap_str_hash(Str,H) { \ + assert(Str); \ + memset((H), 0, sizeof(coap_key_t)); \ + coap_hash((H), (Str)->s, (Str)->length); \ + } + +#ifdef __cplusplus +} +#endif + +#endif /* _COAP_HASHKEY_H_ */ diff --git a/resource/csdk/libcoap-4.1.1/makefile b/resource/csdk/libcoap-4.1.1/makefile new file mode 100644 index 000000000..ddf4fec04 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/makefile @@ -0,0 +1,151 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +# override with `make BUILD=debug` +# override with `make PLATFORM=arduinomega` or `make PLATFORM=arduinodue` +# default to release build +# default to build for linux +BUILD := release +#other options are arduinomega, arduinodue +PLATFORM=linux +#other options are arduino +PLATFORM_TYPE=linux +# override with `make PLATFORM=arduinomega ARDUINOWIFI=1` to enable Arduino WiFi shield +ARDUINOWIFI := 0 + +ifeq ($(ROOT_DIR), ) + ROOT_DIR = .. +endif +ifeq ($(PLATFORM), "") + PLATFORM := "linux" +endif + +OCSOCK_DIR = $(ROOT_DIR)/ocsocket +OC_LOG_DIR = $(ROOT_DIR)/../oc_logger +LOGGER_DIR = $(ROOT_DIR)/logger +RANDOM_DIR = $(ROOT_DIR)/ocrandom +STACK_DIR = $(ROOT_DIR)/stack +OCMALLOC_DIR = $(ROOT_DIR)/ocmalloc +EXTLIBS_DIR = $(ROOT_DIR)/../../extlibs +TINYDTLS_DIR = $(EXTLIBS_DIR)/tinydtls +INC_DIRS = -I$(OCSOCK_DIR)/include/ -I$(LOGGER_DIR)/include -I$(RANDOM_DIR)/include \ + -I$(OCMALLOC_DIR)/include -I$(OC_LOG_DIR)/include -I$(STACK_DIR)/include + +# Note for Arduino: The CC flag is set to the C++ compiler since Arduino build +# includes Time.h header file which has C++ style definitions. +ifeq ($(PLATFORM),android) + CXX=arm-linux-androideabi-g++ + CC=arm-linux-androideabi-gcc + AR=arm-linux-androideabi-ar + RANLIB=arm-linux-androideabi-ranlib + CFLAGS_PLATFORM = -DWITH_POSIX -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 + LDFLAGS_PLATFORM = -march=armv7-a -Wl,--fix-cortex-a8 -llog +else ifeq ($(PLATFORM),linux) + PLATFORM_TYPE:=linux + CXX=g++ + CC=gcc + AR=ar + RANLIB=ranlib + CFLAGS_PLATFORM = -std=gnu99 -DWITH_POSIX +else ifeq ($(PLATFORM),arduinomega) + PLATFORM_TYPE:=arduino + include $(ROOT_DIR)/local.properties + include $(ROOT_DIR)/$(PLATFORM).properties + CC=$(ARDUINO_TOOLS_DIR)/avr-g++ +else ifeq ($(PLATFORM),arduinodue) + PLATFORM_TYPE:=arduino + include $(ROOT_DIR)/local.properties + include $(ROOT_DIR)/$(PLATFORM).properties + CC=$(ARDUINO_TOOLS_DIR)/arm-none-eabi-g++ +else + $(error Wrong value for PLATFORM !!) +endif + +ifeq ($(PLATFORM_TYPE),arduino) + ifeq ($(ARDUINOWIFI),1) + SOURCES += ocsocket_arduino_wifi.c + ARDUINO_SHIELD_TYPE := "/wifi_shield" + else + SOURCES += ocsocket_arduino.c + ARDUINO_SHIELD_TYPE := "/ethernet_shield" + endif + SOURCESCPP:= Time.cpp + OBJECTSCPP:= $(patsubst %.cpp, %.o, $(SOURCESCPP)) + VPATH := $(SDIR_ARD_TIME) +else + SOURCES += ocsocket.c +endif + +OUT_DIR := ./$(PLATFORM)$(ARDUINO_SHIELD_TYPE)/$(BUILD) +OBJ_DIR := $(OUT_DIR)/obj + +CC_FLAGS.debug := -O0 -g3 -Wall -ffunction-sections -fdata-sections -fno-exceptions -pedantic \ +-DTB_LOG +CC_FLAGS.release := -Os -Wall -ffunction-sections -fdata-sections -fno-exceptions + +SOURCES+= pdu.c net.c debug.c encode.c uri.c coap_list.c hashkey.c \ + str.c option.c async.c subscribe.c block.c logger.c ocrandom.c ocmalloc.c \ + oc_logger.c oc_console_logger.c +VPATH += $(OCSOCK_DIR)/src:$(LOGGER_DIR)/src:$(RANDOM_DIR)/src:$(OCMALLOC_DIR)/src\ + :$(OC_LOG_DIR)/c + +ifeq ($(PLATFORM),linux) +ifneq ($(wildcard $(TINYDTLS_DIR)/libtinydtls.a),) + $(info "Building libcoap with DTLS support") + SOURCES += netdtls.c + VPATH += sec + NETDTLS_DIR = sec + INC_DIRS += -I$(TINYDTLS_DIR) -I$(NETDTLS_DIR) -I. + CC_FLAGS.debug += -DWITH_DTLS + CC_FLAGS.release += -DWITH_DTLS +endif +endif + +OBJECTS:= $(patsubst %.c, %.o, $(SOURCES)) + +all: prep_dirs libcoap.a + +prep_dirs: + -mkdir -p $(PLATFORM) + -mkdir -p $(OUT_DIR) + -mkdir -p $(OBJ_DIR) + +%.o: %.c + $(CC) -c $(CC_FLAGS.$(BUILD)) $(CFLAGS_PLATFORM) $(INC_DIRS) $(INC_DIR_PLATFORM) $< -o $(OBJ_DIR)/$@ + +%.o: %.cpp + $(CXX) -c $(CC_FLAGS.$(BUILD)) $(CFLAGS_PLATFORM) $(INC_DIRS) $(INC_DIR_PLATFORM) $< -o $(OBJ_DIR)/$@ + +libcoap.a: $(OBJECTS) $(OBJECTSCPP) + $(AR) rcs $(OUT_DIR)/$@ $(addprefix $(OBJ_DIR)/,$^) + $(RANLIB) $(OUT_DIR)/$@ + +.PHONY: clean + +clean: legacy_clean + -rm -rf linux + -rm -rf arduinomega + -rm -rf arduinodue + +legacy_clean: + rm -f *.o libcoap.a + rm -rf release + rm -rf debug + diff --git a/resource/csdk/libcoap-4.1.1/mem.h b/resource/csdk/libcoap-4.1.1/mem.h new file mode 100644 index 000000000..2b0d27de4 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/mem.h @@ -0,0 +1,26 @@ +/* mem.h -- CoAP memory handling + * Currently, this is just a dummy for malloc/free + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef _COAP_MEM_H_ +#define _COAP_MEM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ocmalloc.h" + +#define coap_malloc(size) OCMalloc(size) +#define coap_free(ptr) OCFree(ptr) + +#ifdef __cplusplus +} +#endif + +#endif /* _COAP_MEM_H_ */ diff --git a/resource/csdk/libcoap-4.1.1/net.c b/resource/csdk/libcoap-4.1.1/net.c new file mode 100644 index 000000000..d36b0e230 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/net.c @@ -0,0 +1,1642 @@ +/* net.c -- CoAP network interface + * + * Copyright (C) 2010--2014 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "config.h" + +#include +#include +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#elif HAVE_SYS_UNISTD_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef WITH_LWIP +#include +#include +#include +#endif + +#include "debug.h" +#include "mem.h" +#include "str.h" +#include "async.h" +#include "option.h" +#include "encode.h" +#include "block.h" +#include "net.h" + +#if defined(WITH_POSIX) || defined(WITH_ARDUINO) + +#include +#include +#if defined(WITH_DTLS) +#include "netdtls.h" +#endif /* WITH_DTLS */ + +#define MOD_NAME ("net.c") + +time_t clock_offset; + +static inline coap_queue_t * +coap_malloc_node() { + return (coap_queue_t *)coap_malloc(sizeof(coap_queue_t)); +} + +static inline void +coap_free_node(coap_queue_t *node) { + coap_free(node); +} +#endif /* WITH_POSIX || WITH_ARDUINO */ +#ifdef WITH_LWIP + +#include + +static void coap_retransmittimer_execute(void *arg); +static void coap_retransmittimer_restart(coap_context_t *ctx); + +static inline coap_queue_t * +coap_malloc_node() { + return (coap_queue_t *)memp_malloc(MEMP_COAP_NODE); +} + +static inline void +coap_free_node(coap_queue_t *node) { + memp_free(MEMP_COAP_NODE, node); +} + +#endif /* WITH_LWIP */ +#ifdef WITH_CONTIKI +# ifndef DEBUG +# define DEBUG DEBUG_PRINT +# endif /* DEBUG */ + +#include "memb.h" +#include "net/uip-debug.h" + +clock_time_t clock_offset; + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN]) + +void coap_resources_init(); +void coap_pdu_resources_init(); + +unsigned char initialized = 0; +coap_context_t the_coap_context; + +MEMB(node_storage, coap_queue_t, COAP_PDU_MAXCNT); + +PROCESS(coap_retransmit_process, "message retransmit process"); + +static inline coap_queue_t * +coap_malloc_node() { + return (coap_queue_t *)memb_alloc(&node_storage); +} + +static inline void +coap_free_node(coap_queue_t *node) { + memb_free(&node_storage, node); +} +#endif /* WITH_CONTIKI */ +#ifdef WITH_LWIP + +/** Callback to udp_recv when using lwIP. Gets called by lwIP on arriving + * packages, places a reference in context->pending_package, and calls + * coap_read to process the package. Thus, coap_read needs not be called in + * lwIP main loops. (When modifying this for thread-like operation, ie. if you + * remove the coap_read call from this, make sure that coap_read gets a chance + * to run before this callback is entered the next time.) + */ +static void received_package(void *arg, struct udp_pcb *upcb, struct pbuf *p, ip_addr_t *addr, u16_t port) +{ + struct coap_context_t *context = (coap_context_t *)arg; + + LWIP_ASSERT("pending_package was not cleared.", context->pending_package == NULL); + + context->pending_package = p; /* we don't free it, coap_read has to do that */ + context->pending_address.addr = addr->addr; /* FIXME: this has to become address-type independent, probably there'll be an lwip function for that */ + context->pending_port = port; + + coap_read(context, -1); /* we want to read from unicast socket */ +} + +#endif /* WITH_LWIP */ + +unsigned int coap_adjust_basetime(coap_context_t *ctx, coap_tick_t now) { + unsigned int result = 0; + coap_tick_diff_t delta = now - ctx->sendqueue_basetime; + + if (ctx->sendqueue) { + /* delta < 0 means that the new time stamp is before the old. */ + if (delta <= 0) { + ctx->sendqueue->t -= delta; + } else { + /* This case is more complex: The time must be advanced forward, + * thus possibly leading to timed out elements at the queue's + * start. For every element that has timed out, its relative + * time is set to zero and the result counter is increased. */ + + coap_queue_t *q = ctx->sendqueue; + coap_tick_t t = 0; + while (q && (t + q->t < (coap_tick_t) delta)) { + t += q->t; + q->t = 0; + result++; + q = q->next; + } + + /* finally adjust the first element that has not expired */ + if (q) { + q->t = (coap_tick_t) delta - t; + } + } + } + + /* adjust basetime */ + ctx->sendqueue_basetime += delta; + + return result; +} + +int coap_insert_node(coap_queue_t **queue, coap_queue_t *node) { + coap_queue_t *p, *q; + if (!queue || !node) + return 0; + + /* set queue head if empty */ + if (!*queue) { + *queue = node; + return 1; + } + + /* replace queue head if PDU's time is less than head's time */ + q = *queue; + if (node->t < q->t) { + node->next = q; + *queue = node; + q->t -= node->t; /* make q->t relative to node->t */ + return 1; + } + + /* search for right place to insert */ + do { + node->t -= q->t; /* make node-> relative to q->t */ + p = q; + q = q->next; + } while (q && q->t <= node->t); + + /* insert new item */ + if (q) { + q->t -= node->t; /* make q->t relative to node->t */ + } + node->next = q; + p->next = node; + return 1; +} + +int coap_delete_node(coap_queue_t *node) { + if (!node) + return 0; + + coap_delete_pdu(node->pdu); + coap_free_node(node); + + return 1; +} + +void coap_delete_all(coap_queue_t *queue) { + if (!queue) + return; + + coap_delete_all(queue->next); + coap_delete_node(queue); +} + +coap_queue_t * +coap_new_node() { + coap_queue_t *node; + node = coap_malloc_node(); + + if (!node) { +#ifndef NDEBUG + coap_log(LOG_WARNING, "coap_new_node: malloc\n"); +#endif + return NULL; + } + + memset(node, 0, sizeof *node); + return node; +} + +coap_queue_t * +coap_peek_next(coap_context_t *context) { + if (!context || !context->sendqueue) + return NULL; + + return context->sendqueue; +} + +coap_queue_t * +coap_pop_next(coap_context_t *context) { + coap_queue_t *next; + + if (!context || !context->sendqueue) + return NULL; + + next = context->sendqueue; + context->sendqueue = context->sendqueue->next; + if (context->sendqueue) { + context->sendqueue->t += next->t; + } + next->next = NULL; + return next; +} + +#ifdef COAP_DEFAULT_WKC_HASHKEY +/** Checks if @p Key is equal to the pre-defined hash key for.well-known/core. */ +#define is_wkc(Key) \ + (memcmp((Key), COAP_DEFAULT_WKC_HASHKEY, sizeof(coap_key_t)) == 0) +#else +/* Implements a singleton to store a hash key for the .wellknown/core + * resources. */ +int +is_wkc(coap_key_t k) { + static coap_key_t wkc; + static unsigned char _initialized = 0; + if (!_initialized) { + _initialized = coap_hash_path((unsigned char *)COAP_DEFAULT_URI_WELLKNOWN, + sizeof(COAP_DEFAULT_URI_WELLKNOWN) - 1, wkc); + } + return memcmp(k, wkc, sizeof(coap_key_t)) == 0; +} +#endif + +coap_context_t * +coap_new_context(uint8_t ipAddr[], uint16_t port) { + + OCDevAddr devAddr; + coap_address_t* listen_addr; + +#if defined(WITH_POSIX) || defined(WITH_ARDUINO) + coap_context_t *c = (coap_context_t*)coap_malloc( sizeof( coap_context_t ) ); + //int reuse = 1; +#endif /* WITH_POSIX || WITH_ARDUINO */ +#ifdef WITH_LWIP + coap_context_t *c = memp_malloc(MEMP_COAP_CONTEXT); +#endif /* WITH_LWIP */ +#ifdef WITH_CONTIKI + coap_context_t *c; + + if (initialized) + return NULL; +#endif /* WITH_CONTIKI */ + + OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], port, + &devAddr); + + listen_addr = (coap_address_t*) &devAddr; + + if (!listen_addr) { + coap_free(c); + coap_log(LOG_EMERG, "no listen address specified\n"); + return NULL; + } + + coap_clock_init(); +#ifdef WITH_LWIP + prng_init(LWIP_RAND()); +#else /* WITH_LWIP */ + prng_init((unsigned long)listen_addr ^ clock_offset); +#endif /* WITH_LWIP */ + +#ifndef WITH_CONTIKI + if (!c) { +#ifndef NDEBUG + coap_log(LOG_EMERG, "coap_init: malloc:\n"); +#endif + return NULL; + } +#endif /* not WITH_CONTIKI */ +#ifdef WITH_CONTIKI + coap_resources_init(); + coap_pdu_resources_init(); + + c = &the_coap_context; + initialized = 1; +#endif /* WITH_CONTIKI */ + + memset(c, 0, sizeof(coap_context_t)); + + /* set well-known sockfd to uninitialize value */ + c->sockfd_wellknown = -1; + + /* initialize message id */ + prng((unsigned char * )&c->message_id, sizeof(unsigned short)); + + /* register the critical options that we know */ + coap_register_option(c, COAP_OPTION_IF_MATCH); + coap_register_option(c, COAP_OPTION_URI_HOST); + coap_register_option(c, COAP_OPTION_IF_NONE_MATCH); + coap_register_option(c, COAP_OPTION_URI_PORT); + coap_register_option(c, COAP_OPTION_URI_PATH); + coap_register_option(c, COAP_OPTION_URI_QUERY); + coap_register_option(c, COAP_OPTION_ACCEPT); + coap_register_option(c, COAP_OPTION_PROXY_URI); + coap_register_option(c, COAP_OPTION_PROXY_SCHEME); + coap_register_option(c, COAP_OPTION_BLOCK2); + coap_register_option(c, COAP_OPTION_BLOCK1); + +#if defined(WITH_POSIX) || defined(WITH_ARDUINO) + if (OCInitUDP((OCDevAddr *)listen_addr, + (int32_t *)&(c->sockfd), OC_SOCKET_REUSEADDR) != ERR_SUCCESS) { + coap_free( c); + return NULL; + } + +#if defined(WITH_DTLS) + if (coap_dtls_init(c, ipAddr) != 0) { + coap_free( c); + return NULL; + } +#else + /* set dtls socket file descriptor to uninitialize value */ + c->sockfd_dtls = -1; +#endif /* WITH_DTLS */ + return c; + +#endif /* WITH_POSIX || WITH_ARDUINO */ +#ifdef WITH_CONTIKI + c->conn = udp_new(NULL, 0, NULL); + udp_bind(c->conn, listen_addr->port); + + process_start(&coap_retransmit_process, (char *)c); + + PROCESS_CONTEXT_BEGIN(&coap_retransmit_process); +#ifndef WITHOUT_OBSERVE + etimer_set(&c->notify_timer, COAP_RESOURCE_CHECK_TIME * COAP_TICKS_PER_SECOND); +#endif /* WITHOUT_OBSERVE */ + /* the retransmit timer must be initialized to some large value */ + etimer_set(&the_coap_context.retransmit_timer, 0xFFFF); + PROCESS_CONTEXT_END(&coap_retransmit_process); + return c; +#endif /* WITH_CONTIKI */ +#ifdef WITH_LWIP + c->pcb = udp_new(); + /* hard assert: this is not expected to fail dynamically */ + LWIP_ASSERT("Failed to allocate PCB for CoAP", c->pcb != NULL); + + udp_recv(c->pcb, received_package, (void*)c); + udp_bind(c->pcb, &listen_addr->addr, listen_addr->port); + + c->timer_configured = 0; + + return c; +#endif + return NULL; +} + +void coap_free_context(coap_context_t *context) { + if (!context) + return; + + coap_delete_all(context->recvqueue); + coap_delete_all(context->sendqueue); + +#ifdef WITH_LWIP + context->sendqueue = NULL; + coap_retransmittimer_restart(context); +#endif + +#if defined(WITH_POSIX) || defined(WITH_ARDUINO) + /* coap_delete_list(context->subscriptions); */ + OCClose( context->sockfd ); + if (context->sockfd_wellknown != -1) { + OCClose( context->sockfd_wellknown ); + } +#if defined(WITH_DTLS) + coap_dtls_deinit( context ); +#endif /* WITH_DTLS */ + coap_free( context ); +#endif +#ifdef WITH_LWIP + udp_remove(context->pcb); + memp_free(MEMP_COAP_CONTEXT, context); +#endif +#ifdef WITH_CONTIKI + memset(&the_coap_context, 0, sizeof(coap_context_t)); + initialized = 0; +#endif /* WITH_CONTIKI */ +} + +int coap_join_wellknown_group(coap_context_t *ctx, + const coap_address_t *multicast_addr) { +#if defined(WITH_POSIX) || defined(WITH_ARDUINO) + if (OCInitUDPMulticast((OCDevAddr *)multicast_addr, + (int32_t *)&(ctx->sockfd_wellknown)) != ERR_SUCCESS) { + return 1; + } + return 0; +#endif + return 0; +} + +int coap_option_check_critical(coap_context_t *ctx, coap_pdu_t *pdu, + coap_opt_filter_t unknown) { + + coap_opt_iterator_t opt_iter; + int ok = 1; + + coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL); + + while (coap_option_next(&opt_iter)) { + + /* The following condition makes use of the fact that + * coap_option_getb() returns -1 if type exceeds the bit-vector + * filter. As the vector is supposed to be large enough to hold + * the largest known option, we know that everything beyond is + * bad. + */ + if ((opt_iter.type & 0x01) + && coap_option_getb(ctx->known_options, opt_iter.type) < 1) { + debug("unknown critical option %d\n", opt_iter.type); + + ok = 0; + + /* When opt_iter.type is beyond our known option range, + * coap_option_setb() will return -1 and we are safe to leave + * this loop. */ + if (coap_option_setb(unknown, opt_iter.type) == -1) + break; + } + } + + return ok; +} + +void coap_transaction_id(const coap_address_t *peer, const coap_pdu_t *pdu, + coap_tid_t *id) { + coap_key_t h; + + memset(h, 0, sizeof(coap_key_t)); + + /* Compare the complete address structure in case of IPv4. For IPv6, + * we need to look at the transport address only. */ + +#ifdef WITH_POSIX + switch (peer->addr.sa.sa_family) { + case AF_INET: + coap_hash((const unsigned char *)&peer->addr.sa, peer->size, h); + break; + case AF_INET6: + coap_hash((const unsigned char *)&peer->addr.sin6.sin6_port, + sizeof(peer->addr.sin6.sin6_port), h); + coap_hash((const unsigned char *)&peer->addr.sin6.sin6_addr, + sizeof(peer->addr.sin6.sin6_addr), h); + break; + default: + return; + } +#endif + +#ifdef WITH_ARDUINO + coap_hash((const unsigned char *)peer->addr, peer->size, h); +#endif /* WITH_ARDUINO */ + +#if defined(WITH_LWIP) || defined(WITH_CONTIKI) + /* FIXME: with lwip, we can do better */ + coap_hash((const unsigned char *)&peer->port, sizeof(peer->port), h); + coap_hash((const unsigned char *)&peer->addr, sizeof(peer->addr), h); +#endif /* WITH_LWIP || WITH_CONTIKI */ + + coap_hash((const unsigned char * )&pdu->hdr->id, sizeof(unsigned short), h); + + *id = ((h[0] << 8) | h[1]) ^ ((h[2] << 8) | h[3]); +} + +coap_tid_t coap_send_ack(coap_context_t *context, const coap_address_t *dst, + coap_pdu_t *request, coap_send_flags_t flag) { + coap_pdu_t *response; + coap_tid_t result = COAP_INVALID_TID; + + if (request && request->hdr->type == COAP_MESSAGE_CON) { + response = coap_pdu_init(COAP_MESSAGE_ACK, 0, request->hdr->id, + sizeof(coap_pdu_t)); + if (response) { + result = coap_send(context, dst, response, flag, NULL); + coap_delete_pdu(response); + } + } + return result; +} + +#if defined(WITH_POSIX) || defined(WITH_ARDUINO) +/* releases space allocated by PDU if free_pdu is set */ +int +coap_send_impl(coap_context_t *context, + const coap_address_t *dst, + coap_pdu_t *pdu) { + + int bytes_written = -1; + + if ( !context || !dst || !pdu ) + return bytes_written; + + bytes_written = OCSendTo( context->sockfd, (uint8_t*)(pdu->hdr), pdu->length, 0, + (OCDevAddr*)dst); + debug("bytes_written %d\n", (int)bytes_written); + + return bytes_written; +} +#endif /* WITH_POSIX || WITH_ARDUINO */ +#ifdef WITH_CONTIKI +/* releases space allocated by PDU if free_pdu is set */ +coap_tid_t +coap_send_impl(coap_context_t *context, + const coap_address_t *dst, + coap_pdu_t *pdu) { + coap_tid_t id = COAP_INVALID_TID; + + if ( !context || !dst || !pdu ) + return id; + + /* FIXME: is there a way to check if send was successful? */ + uip_udp_packet_sendto(context->conn, pdu->hdr, pdu->length, + &dst->addr, dst->port); + + coap_transaction_id(dst, pdu, &id); + + return id; +} +#endif /* WITH_CONTIKI */ +#ifdef WITH_LWIP +coap_tid_t +coap_send_impl(coap_context_t *context, + const coap_address_t *dst, + coap_pdu_t *pdu) { + coap_tid_t id = COAP_INVALID_TID; + struct pbuf *p; + uint8_t err; + char *data_backup; + + if ( !context || !dst || !pdu ) + { + return id; + } + + data_backup = pdu->data; + + /* FIXME: we can't check this here with the existing infrastructure, but we + * should actually check that the pdu is not held by anyone but us. the + * respective pbuf is already exclusively owned by the pdu. */ + + p = pdu->pbuf; + LWIP_ASSERT("The PDU header is not where it is expected", pdu->hdr == p->payload + sizeof(coap_pdu_t)); + + err = pbuf_header(p, -sizeof(coap_pdu_t)); + if (err) + { + debug("coap_send_impl: pbuf_header failed\n"); + pbuf_free(p); + return id; + } + + coap_transaction_id(dst, pdu, &id); + + pbuf_realloc(p, pdu->length); + + udp_sendto(context->pcb, p, + &dst->addr, dst->port); + + pbuf_header(p, -(ptrdiff_t)((uint8_t*)pdu - (uint8_t*)p->payload) - sizeof(coap_pdu_t)); /* FIXME hack around udp_sendto not restoring; see http://lists.gnu.org/archive/html/lwip-users/2013-06/msg00008.html. for udp over ip over ethernet, this was -42; as we're doing ppp too, this has to be calculated generically */ + + err = pbuf_header(p, sizeof(coap_pdu_t)); + LWIP_ASSERT("Cannot undo pbuf_header", err == 0); + + /* restore destroyed pdu data */ + LWIP_ASSERT("PDU not restored", p->payload == pdu); + pdu->max_size = p->tot_len - sizeof(coap_pdu_t); /* reduced after pbuf_realloc */ + pdu->hdr = p->payload + sizeof(coap_pdu_t); + pdu->max_delta = 0; /* won't be used any more */ + pdu->length = pdu->max_size; + pdu->data = data_backup; + pdu->pbuf = p; + + return id; +} +#endif /* WITH_LWIP */ + +coap_tid_t coap_send_error(coap_context_t *context, coap_pdu_t *request, + const coap_address_t *dst, unsigned char code, coap_opt_filter_t opts, + coap_send_flags_t flag) { + coap_pdu_t *response; + coap_tid_t result = COAP_INVALID_TID; + + assert(request); + assert(dst); + + response = coap_new_error_response(request, code, opts); + if (response) { + result = coap_send(context, dst, response, flag, NULL); + coap_delete_pdu(response); + } + + return result; +} + +coap_tid_t coap_send_message_type(coap_context_t *context, + const coap_address_t *dst, coap_pdu_t *request, + coap_send_flags_t flag, unsigned char type) { + coap_pdu_t *response; + coap_tid_t result = COAP_INVALID_TID; + + if (request) { + response = coap_pdu_init(type, 0, request->hdr->id, sizeof(coap_pdu_t)); + if (response) { + result = coap_send(context, dst, response, flag, NULL); + coap_delete_pdu(response); + } + } + return result; +} + +coap_tid_t coap_send(coap_context_t *context, + const coap_address_t *dst, coap_pdu_t *pdu, coap_send_flags_t flag, + uint8_t *cache_flag) +{ + coap_queue_t *node = NULL; + coap_tick_t now; + coap_tid_t tid; + int bytesWritten; + unsigned int r; + + if (!context) + return COAP_INVALID_TID; + if(!(flag & SEND_RETX)){ + coap_transaction_id(dst, pdu, &tid); + } + if((flag & SEND_NOW) || (flag & SEND_RETX)) + { + goto sending; + } + + node = coap_new_node(); + if (!node) { + debug("coap_send: insufficient memory\n"); + return COAP_INVALID_TID; + } + + prng((unsigned char * )&r, sizeof(r)); + /* add randomized RESPONSE_TIMEOUT to determine retransmission timeout */ + if(flag & SEND_NOW_CON) { + node->timeout = COAP_DEFAULT_RESPONSE_TIMEOUT * COAP_TICKS_PER_SECOND + + (COAP_DEFAULT_RESPONSE_TIMEOUT >> 1) + * ((COAP_TICKS_PER_SECOND * (r & 0xFF)) >> 8); + } + else + { + node->timeout = MAX_MULTICAST_DELAY_SEC * ((COAP_TICKS_PER_SECOND * (r & 0xFF)) >> 8); + node->delayedResNeeded = 1; + } + + if (flag & SEND_SECURE_PORT) { + node->secure = 1; + } + + memcpy(&node->remote, dst, sizeof(coap_address_t)); + node->pdu = pdu; + node->id = tid; + + /* Set timer for pdu retransmission. If this is the first element in + * the retransmission queue, the base time is set to the current + * time and the retransmission time is node->timeout. If there is + * already an entry in the sendqueue, we must check if this node is + * to be retransmitted earlier. Therefore, node->timeout is first + * normalized to the base time and then inserted into the queue with + * an adjusted relative time. + */ + + coap_ticks(&now); + if (context->sendqueue == NULL) + { + node->t = node->timeout; + context->sendqueue_basetime = now; + } + else + { + /* make node->t relative to context->sendqueue_basetime */ + node->t = (now - context->sendqueue_basetime) + node->timeout; + } + coap_insert_node(&context->sendqueue, node); + + #ifdef WITH_LWIP + if (node == context->sendqueue) + /* don't bother with timer stuff if there are earlier retransmits */ + coap_retransmittimer_restart(context); + #endif + + #ifdef WITH_CONTIKI + { /* (re-)initialize retransmission timer */ + coap_queue_t *nextpdu; + + nextpdu = coap_peek_next(context); + assert(nextpdu); /* we have just inserted a node */ + + /* must set timer within the context of the retransmit process */ + PROCESS_CONTEXT_BEGIN(&coap_retransmit_process); + etimer_set(&context->retransmit_timer, nextpdu->t); + PROCESS_CONTEXT_END(&coap_retransmit_process); + } + #endif /* WITH_CONTIKI */ + + if(flag & SEND_NOW_CON) + { + goto sending; + } + return tid; + + sending: + OC_LOG_V(DEBUG, MOD_NAME, PCF("sending 0x%x"), flag); +#if defined(WITH_DTLS) + // A secure packet is first encrypted by DTLS library and then send + // over the network. + if (flag & SEND_SECURE_PORT) { + bytesWritten = coap_dtls_encrypt(context, (OCDevAddr*)dst, + pdu, &node, tid, cache_flag); + } else { + bytesWritten = coap_send_impl(context, dst, pdu); + } +#else + bytesWritten = coap_send_impl(context, dst, pdu); +#endif /* WITH_DTLS */ + if(bytesWritten > 0) { + return tid; + } + debug("coap_send_impl: error sending pdu\n"); + coap_free_node(node); + return COAP_INVALID_TID; +} + +coap_tid_t coap_retransmit(coap_context_t *context, coap_queue_t *node) { + coap_tid_t tid = COAP_INVALID_TID; + coap_send_flags_t flag; + + if (!context || !node) + return COAP_INVALID_TID; + + /* re-initialize timeout when maximum number of retransmissions are not reached yet */ + if (node->retransmit_cnt < COAP_DEFAULT_MAX_RETRANSMIT) { + node->retransmit_cnt++; + node->t = node->timeout << node->retransmit_cnt; + coap_insert_node(&context->sendqueue, node); +#ifdef WITH_LWIP + if (node == context->sendqueue) /* don't bother with timer stuff if there are earlier retransmits */ + coap_retransmittimer_restart(context); +#endif + + debug("** retransmission #%d of transaction %d\n", node->retransmit_cnt, + ntohs(node->pdu->hdr->id)); + flag = (coap_send_flags_t)(SEND_RETX | (node->secure ? SEND_SECURE_PORT : 0)); + tid = coap_send(context, (coap_address_t *)&(node->remote),node->pdu, flag, NULL); + return (tid == COAP_INVALID_TID)? COAP_INVALID_TID : node->id; + } + + /* no more retransmissions, remove node from system */ + +#ifndef WITH_CONTIKI + debug("** removed transaction %d\n", ntohs(node->id)); +#endif + + // deletion of node will happen in ocoap since we still need the info node has + return COAP_INVALID_TID; +} + +/** + * Checks if @p opt fits into the message that ends with @p maxpos. + * This function returns @c 1 on success, or @c 0 if the option @p opt + * would exceed @p maxpos. + */ +static inline int check_opt_size(coap_opt_t *opt, unsigned char *maxpos) { + if (opt && opt < maxpos) { + if (((*opt & 0x0f) < 0x0f) || (opt + 1 < maxpos)) + return opt + COAP_OPT_SIZE(opt) < maxpos; + } + return 0; +} + +int coap_read(coap_context_t *ctx, int sockfd) { +#if defined(WITH_POSIX) || defined(WITH_ARDUINO) + static char buf[COAP_MAX_PDU_SIZE]; +#endif +#if defined(WITH_LWIP) || defined(WITH_CONTIKI) + char *buf; +#endif + char *pbuf = buf; + coap_hdr_t *pdu; + int bytes_read = -1; + + coap_address_t src, dst; + coap_queue_t *node; + unsigned char delayedResNeeded = 0; + +#ifdef WITH_CONTIKI + pbuf = uip_appdata; +#endif /* WITH_CONTIKI */ +#ifdef WITH_LWIP + LWIP_ASSERT("No package pending", ctx->pending_package != NULL); + LWIP_ASSERT("Can only deal with contiguous PBUFs to read the initial details", ctx->pending_package->tot_len == ctx->pending_package->len); + pbuf = ctx->pending_package->payload; +#endif /* WITH_LWIP */ + + coap_address_init(&src); + +#if defined(WITH_POSIX) || defined(WITH_ARDUINO) + bytes_read = OCRecvFrom( sockfd, (uint8_t*)pbuf, sizeof(buf), 0, + (OCDevAddr*)&src); + + // Set the delayed response flag for responding to multicast requests + if (sockfd == ctx->sockfd_wellknown && bytes_read > 0) { + delayedResNeeded = 1; + } +#if defined(WITH_DTLS) + // Perform the DTLS decryption if packet is coming on secure port + if (sockfd == ctx->sockfd_dtls && bytes_read > 0) { + if (coap_dtls_decrypt(ctx, (OCDevAddr*)&src, (uint8_t*)pbuf, bytes_read, + (uint8_t**)&pbuf, &bytes_read) < 0) { + bytes_read = -1; + } + } +#endif /* WITH_DTLS */ + + pdu = (coap_hdr_t *) pbuf; +#endif /* WITH_POSIX || WITH_ARDUINO */ +#ifdef WITH_CONTIKI + if(uip_newdata()) { + uip_ipaddr_copy(&src.addr, &UIP_IP_BUF->srcipaddr); + src.port = UIP_UDP_BUF->srcport; + uip_ipaddr_copy(&dst.addr, &UIP_IP_BUF->destipaddr); + dst.port = UIP_UDP_BUF->destport; + + bytes_read = uip_datalen(); + ((char *)uip_appdata)[bytes_read] = 0; + PRINTF("Server received %d bytes from [", (int)bytes_read); + PRINT6ADDR(&src.addr); + PRINTF("]:%d\n", uip_ntohs(src.port)); + } +#endif /* WITH_CONTIKI */ +#ifdef WITH_LWIP + /* FIXME: use lwip address operation functions */ + src.addr.addr = ctx->pending_address.addr; + src.port = ctx->pending_port; + bytes_read = ctx->pending_package->tot_len; +#endif /* WITH_LWIP */ + + if (bytes_read < 0) { + warn("coap_read: recvfrom\n"); + goto error_early; + } + + if ((size_t) bytes_read < sizeof(coap_hdr_t)) { + debug("coap_read: discarded invalid frame\n"); + goto error_early; + } + + if (pdu->version != COAP_DEFAULT_VERSION) { + debug("coap_read: unknown protocol version\n"); + goto error_early; + } + + node = coap_new_node(); + if (!node) + goto error_early; + +#ifdef WITH_LWIP + node->pdu = coap_pdu_from_pbuf(ctx->pending_package); + ctx->pending_package = NULL; +#else + node->pdu = coap_pdu_init(0, 0, 0, bytes_read); +#endif + if (!node->pdu) + goto error; + + coap_ticks(&node->t); + memcpy(&node->local, &dst, sizeof(coap_address_t)); + memcpy(&node->remote, &src, sizeof(coap_address_t)); + + if (!coap_pdu_parse((unsigned char *) pbuf, bytes_read, node->pdu)) { + warn("discard malformed PDU"); + goto error; + } + + //set the delayed response flag + node->delayedResNeeded = delayedResNeeded; + + //set the secure flag on the received packet +#if defined(WITH_DTLS) + node->secure = (sockfd == ctx->sockfd_dtls) ? 1 : 0; +#else + node->secure = 0; +#endif /* WITH_DTLS */ + + /* and add new node to receive queue */ + coap_transaction_id(&node->remote, node->pdu, &node->id); + coap_insert_node(&ctx->recvqueue, node); + +#ifndef NDEBUG + if (LOG_DEBUG <= coap_get_log_level()) { +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 40 +#endif + unsigned char addr[INET6_ADDRSTRLEN + 8]; + + if (coap_print_addr(&src, addr, INET6_ADDRSTRLEN + 8)) + debug("** received %d bytes from %s:\n", (int )bytes_read, addr); + + coap_show_pdu(node->pdu); + } +#endif + + return bytes_read; + + error: + /* FIXME: send back RST? */ + coap_delete_node(node); + return bytes_read; + error_early: +#ifdef WITH_LWIP + /* even if there was an error, clean up */ + pbuf_free(ctx->pending_package); + ctx->pending_package = NULL; +#endif + return bytes_read; +} + +int coap_remove_from_queue(coap_queue_t **queue, coap_tid_t id, + coap_queue_t **node) { + coap_queue_t *p, *q; + + if (!queue || !*queue) + return 0; + debug("*** looking for transaction %u == %u\n", id, (*queue)->id); + + /* replace queue head if PDU's time is less than head's time */ + if (id == (*queue)->id) { /* found transaction */ + *node = *queue; + *queue = (*queue)->next; + if (*queue) { /* adjust relative time of new queue head */ + (*queue)->t += (*node)->t; + } + (*node)->next = NULL; + /* coap_delete_node( q ); */ + debug("*** removed transaction %u\n", id); + return 1; + } + + /* search transaction to remove (only first occurence will be removed) */ + q = *queue; + do { + p = q; + q = q->next; + } while (q && id != q->id); + + if (q) { /* found transaction */ + p->next = q->next; + if (p->next) { /* must update relative time of p->next */ + p->next->t += q->t; + } + q->next = NULL; + *node = q; + /* coap_delete_node( q ); */ + debug("*** removed transaction %u\n", id); + return 1; + } + + return 0; + +} + +static inline int token_match(const unsigned char *a, size_t alen, + const unsigned char *b, size_t blen) { + return alen == blen && (alen == 0 || memcmp(a, b, alen) == 0); +} + +void coap_cancel_all_messages(coap_context_t *context, + const coap_address_t *dst, const unsigned char *token, + size_t token_length) { + /* cancel all messages in sendqueue that are for dst + * and use the specified token */ + coap_queue_t *p, *q; + + debug("cancel_all_messages\n"); + while (context->sendqueue + && coap_address_equals(dst, &context->sendqueue->remote) + && token_match(token, token_length, + context->sendqueue->pdu->hdr->token, + context->sendqueue->pdu->hdr->token_length)) { + q = context->sendqueue; + context->sendqueue = q->next; + debug("**** removed transaction %d\n", ntohs(q->pdu->hdr->id)); + coap_delete_node(q); + } + + if (!context->sendqueue) + return; + + p = context->sendqueue; + q = p->next; + + /* when q is not NULL, it does not match (dst, token), so we can skip it */ + while (q) { + if (coap_address_equals(dst, &q->remote) + && token_match(token, token_length, q->pdu->hdr->token, + q->pdu->hdr->token_length)) { + p->next = q->next; + debug("**** removed transaction %d\n", ntohs(q->pdu->hdr->id)); + coap_delete_node(q); + q = p->next; + } else { + p = q; + q = q->next; + } + } +} + +coap_queue_t * +coap_find_transaction(coap_queue_t *queue, coap_tid_t id) { + while (queue && queue->id != id) + queue = queue->next; + + return queue; +} + +coap_pdu_t * +coap_new_error_response(coap_pdu_t *request, unsigned char code, + coap_opt_filter_t opts) { + coap_opt_iterator_t opt_iter; + coap_pdu_t *response; + size_t size = sizeof(coap_hdr_t) + request->hdr->token_length; + int type; + coap_opt_t *option; + unsigned short opt_type = 0; /* used for calculating delta-storage */ + +#if COAP_ERROR_PHRASE_LENGTH > 0 + const char *phrase = coap_response_phrase(code); + + /* Need some more space for the error phrase and payload start marker */ + if (phrase) + size += strlen(phrase) + 1; +#endif + + assert(request); + + /* cannot send ACK if original request was not confirmable */ + type = request->hdr->type == COAP_MESSAGE_CON ? + COAP_MESSAGE_ACK : COAP_MESSAGE_NON; + + /* Estimate how much space we need for options to copy from + * request. We always need the Token, for 4.02 the unknown critical + * options must be included as well. */ + coap_option_clrb(opts, COAP_OPTION_CONTENT_TYPE); /* we do not want this */ + + coap_option_iterator_init(request, &opt_iter, opts); + + /* Add size of each unknown critical option. As known critical + options as well as elective options are not copied, the delta + value might grow. + */ + while ((option = coap_option_next(&opt_iter))) { + unsigned short delta = opt_iter.type - opt_type; + /* calculate space required to encode (opt_iter.type - opt_type) */ + if (delta < 13) { + size++; + } else if (delta < 269) { + size += 2; + } else { + size += 3; + } + + /* add coap_opt_length(option) and the number of additional bytes + * required to encode the option length */ + + size += coap_opt_length(option); + switch (*option & 0x0f) { + case 0x0e: + size++; + /* fall through */ + continue; + case 0x0d: + size++; + break; + default: + ; + } + + opt_type = opt_iter.type; + } + + /* Now create the response and fill with options and payload data. */ + response = coap_pdu_init(type, code, request->hdr->id, size); + if (response) { + /* copy token */ + if (!coap_add_token(response, request->hdr->token_length, + request->hdr->token)) { + debug("cannot add token to error response\n"); + coap_delete_pdu(response); + return NULL; + } + + /* copy all options */ + coap_option_iterator_init(request, &opt_iter, opts); + while ((option = coap_option_next(&opt_iter))) + coap_add_option(response, opt_iter.type, COAP_OPT_LENGTH(option), + COAP_OPT_VALUE(option)); + +#if COAP_ERROR_PHRASE_LENGTH > 0 + /* note that diagnostic messages do not need a Content-Format option. */ + if (phrase) + coap_add_data(response, strlen(phrase), (unsigned char *) phrase); +#endif + } + + return response; +} + + +#define SZX_TO_BYTES(SZX) ((size_t)(1 << ((SZX) + 4))) + +#define WANT_WKC(Pdu,Key) \ + (((Pdu)->hdr->code == COAP_REQUEST_GET) && is_wkc(Key)) + +/************************************************************************************************ + * Following code will be moved to newer handle_request in the future and kept for reference + ************************************************************************************************/ +#if 0 +void +handle_request(coap_context_t *context, coap_queue_t *node) { + coap_method_handler_t h = NULL; + coap_pdu_t *response = NULL; + coap_opt_filter_t opt_filter; + coap_resource_t *resource; + coap_key_t key; + + coap_option_filter_clear(opt_filter); + + /* try to find the resource from the request URI */ + coap_hash_request_uri(node->pdu, key); + resource = coap_get_resource_from_key(context, key); + + if (!resource) { + /* The resource was not found. Check if the request URI happens to + * be the well-known URI. In that case, we generate a default + * response, otherwise, we return 4.04 */ + + switch(node->pdu->hdr->code) { + + case COAP_REQUEST_GET: + if (is_wkc(key)) { /* GET request for .well-known/core */ + info("create default response for %s\n", COAP_DEFAULT_URI_WELLKNOWN); + response = wellknown_response(context, node->pdu); + + } else { /* GET request for any another resource, return 4.04 */ + + debug("GET for unknown resource 0x%02x%02x%02x%02x, return 4.04\n", + key[0], key[1], key[2], key[3]); + response = + coap_new_error_response(node->pdu, COAP_RESPONSE_CODE(404), + opt_filter); + } + break; + + default: /* any other request type */ + + debug("unhandled request for unknown resource 0x%02x%02x%02x%02x\r\n", + key[0], key[1], key[2], key[3]); + if (!coap_is_mcast(&node->local)) + response = coap_new_error_response(node->pdu, COAP_RESPONSE_CODE(405), + opt_filter); + } + + if (response && coap_send(context, &node->remote, response) == COAP_INVALID_TID) { + warn("cannot send response for transaction %u\n", node->id); + } + coap_delete_pdu(response); + + return; + } + + /* the resource was found, check if there is a registered handler */ + if ((size_t)node->pdu->hdr->code - 1 < + sizeof(resource->handler)/sizeof(coap_method_handler_t)) + h = resource->handler[node->pdu->hdr->code - 1]; + + if (h) { + debug("call custom handler for resource 0x%02x%02x%02x%02x\n", + key[0], key[1], key[2], key[3]); + response = coap_pdu_init(node->pdu->hdr->type == COAP_MESSAGE_CON + ? COAP_MESSAGE_ACK + : COAP_MESSAGE_NON, + 0, node->pdu->hdr->id, COAP_MAX_PDU_SIZE); + + /* Implementation detail: coap_add_token() immediately returns 0 + if response == NULL */ + if (coap_add_token(response, node->pdu->hdr->token_length, + node->pdu->hdr->token)) { + str token = {node->pdu->hdr->token_length, node->pdu->hdr->token}; + + h(context, resource, &node->remote, + node->pdu, &token, response); + if (response->hdr->type != COAP_MESSAGE_NON || + (response->hdr->code >= 64 + && !coap_is_mcast(&node->local))) { + if (coap_send(context, &node->remote, response) == COAP_INVALID_TID) { + debug("cannot send response for message %d\n", node->pdu->hdr->id); + } + } + + coap_delete_pdu(response); + } else { + warn("cannot generate response\r\n"); + } + } else { + if (WANT_WKC(node->pdu, key)) { + debug("create default response for %s\n", COAP_DEFAULT_URI_WELLKNOWN); + response = wellknown_response(context, node->pdu); + } else + response = coap_new_error_response(node->pdu, COAP_RESPONSE_CODE(405), + opt_filter); + + if (!response || (coap_send(context, &node->remote, response) + == COAP_INVALID_TID)) { + debug("cannot send response for transaction %u\n", node->id); + } + coap_delete_pdu(response); + } +} +#endif +static void handle_request(coap_context_t *context, coap_queue_t *rcvd) { + /* Call application-specific reponse handler when available. If + * not, we must acknowledge confirmable messages. */ + if (context->request_handler) { + context->request_handler(context, rcvd); + } else { + coap_send_flags_t flag = SEND_NOW; + flag = (coap_send_flags_t)(flag | (rcvd->secure ? SEND_SECURE_PORT : 0)); + /* send ACK if rcvd is confirmable (i.e. a separate response) */ + coap_send_ack(context, &rcvd->remote, rcvd->pdu, flag); + } +} + +static void handle_response(coap_context_t *context, coap_queue_t *rcvd) { + /* Call application-specific reponse handler when available. If + * not, we must acknowledge confirmable messages. */ + if (context->response_handler) { + context->response_handler(context, rcvd); + } else { + coap_send_flags_t flag = SEND_NOW; + flag = (coap_send_flags_t)(flag | (rcvd->secure ? SEND_SECURE_PORT : 0)); + /* send ACK if rcvd is confirmable (i.e. a separate response) */ + coap_send_ack(context, &rcvd->remote, rcvd->pdu, flag); + } +} + +static void handle_ack_rst(coap_context_t *context, uint8_t msgType, coap_queue_t *sent) { + /* Call application-specific reponse handler when available. If + * not, we must acknowledge confirmable messages. */ + if (context->ack_rst_handler) { + context->ack_rst_handler(context, msgType, sent); + } +} + +static inline int +#ifdef __GNUC__ +handle_locally(coap_context_t *context __attribute__ ((unused)), + coap_queue_t *node __attribute__ ((unused))) { +#else /* not a GCC */ + handle_locally(coap_context_t *context, coap_queue_t *node) { +#endif /* GCC */ + /* this function can be used to check if node->pdu is really for us */ + return 1; + } + + void coap_dispatch(coap_context_t *context) { + coap_queue_t *rcvd = NULL, *sent = NULL; + coap_pdu_t *response; + coap_opt_filter_t opt_filter; + + if (!context) + return; + + memset(opt_filter, 0, sizeof(coap_opt_filter_t)); + + while (context->recvqueue) { + rcvd = context->recvqueue; + + /* remove node from recvqueue */ + context->recvqueue = context->recvqueue->next; + rcvd->next = NULL; + + if (rcvd->pdu->hdr->version != COAP_DEFAULT_VERSION) { + debug("dropped packet with unknown version %u\n", + rcvd->pdu->hdr->version); + goto cleanup; + } + + switch (rcvd->pdu->hdr->type) { + case COAP_MESSAGE_ACK: + /* find transaction in sendqueue to stop retransmission */ + if(coap_remove_from_queue(&context->sendqueue, rcvd->id, &sent)){ + handle_ack_rst(context, COAP_MESSAGE_ACK, sent); + } + + //delete empty messages, this is ACK only message no piggybacked response + if (rcvd->pdu->hdr->code == 0) + goto cleanup; + break; + + case COAP_MESSAGE_NON: /* check for unknown critical options */ + if (coap_option_check_critical(context, rcvd->pdu, opt_filter) + == 0) + goto cleanup; + break; + + case COAP_MESSAGE_CON: /* check for unknown critical options */ + if (coap_option_check_critical(context, rcvd->pdu, opt_filter) + == 0) { + /* FIXME: send response only if we have received a request. Otherwise, + * send RST. */ + response = coap_new_error_response(rcvd->pdu, + COAP_RESPONSE_CODE(402), opt_filter); + if (!response) + warn("coap_dispatch: cannot create error reponse\n"); + else { + coap_send_flags_t flag = SEND_NOW; + flag = (coap_send_flags_t)(flag | rcvd->secure ? SEND_SECURE_PORT : 0); + if (coap_send(context, &rcvd->remote, response, flag, NULL) + == COAP_INVALID_TID) { + warn("coap_dispatch: error sending reponse\n"); + } + coap_delete_pdu(response); + } + goto cleanup; + } + break; + + case COAP_MESSAGE_RST: + /* find transaction in sendqueue to stop retransmission */ + if(coap_remove_from_queue(&context->sendqueue, rcvd->id, &sent)){ + handle_ack_rst(context, COAP_MESSAGE_RST, sent); + } + goto cleanup; + break; + + default: + debug( + "TODO: Need to handle other message types in coap_dispatch"); + } + + /************************************************************************************************ + * Following code will be replaced at different parts of the stack + ************************************************************************************************/ +#if 0 + switch (rcvd->pdu->hdr->type) { + case COAP_MESSAGE_ACK: + /* find transaction in sendqueue to stop retransmission */ + coap_remove_from_queue(&context->sendqueue, rcvd->id, &sent); + + if (rcvd->pdu->hdr->code == 0) + goto cleanup; + + /* FIXME: if sent code was >= 64 the message might have been a + * notification. Then, we must flag the observer to be alive + * by setting obs->fail_cnt = 0. */ + if (sent && COAP_RESPONSE_CLASS(sent->pdu->hdr->code) == 2) { + const str token = {sent->pdu->hdr->token_length, + sent->pdu->hdr->token}; + coap_touch_observer(context, &sent->remote, &token); + } + break; + + case COAP_MESSAGE_RST: + /* We have sent something the receiver disliked, so we remove + * not only the transaction but also the subscriptions we might + * have. */ + + coap_log(LOG_ALERT, "got RST for message %u\n", + ntohs(rcvd->pdu->hdr->id)); + + /* find transaction in sendqueue to stop retransmission */ + coap_remove_from_queue(&context->sendqueue, rcvd->id, &sent); + + if (sent) + coap_handle_rst(context, sent); + goto cleanup; + + case COAP_MESSAGE_NON: /* check for unknown critical options */ + if (coap_option_check_critical(context, rcvd->pdu, opt_filter) + == 0) + goto cleanup; + break; + + case COAP_MESSAGE_CON: /* check for unknown critical options */ + if (coap_option_check_critical(context, rcvd->pdu, opt_filter) + == 0) { + + /* FIXME: send response only if we have received a request. Otherwise, + * send RST. */ + response = coap_new_error_response(rcvd->pdu, + COAP_RESPONSE_CODE(402), opt_filter); + + if (!response) + warn("coap_dispatch: cannot create error reponse\n"); + else { + if (coap_send(context, &rcvd->remote, + response) == COAP_INVALID_TID) { + warn("coap_dispatch: error sending reponse\n"); + } + coap_delete_pdu(response); + } + + goto cleanup; + } + break; + } +#endif + + /* Pass message to upper layer if a specific handler was + * registered for a request that should be handled locally. */ + if (handle_locally(context, rcvd)) { + if (COAP_MESSAGE_IS_REQUEST(rcvd->pdu->hdr)){ + handle_request(context, rcvd); + } + else if (COAP_MESSAGE_IS_RESPONSE(rcvd->pdu->hdr)){ + handle_response(context, rcvd); + } + else { + coap_send_flags_t flag; + flag = (coap_send_flags_t)(SEND_NOW | + (rcvd->secure ? SEND_SECURE_PORT : 0)); + debug("dropped message with invalid code\n"); + coap_send_message_type(context, &rcvd->remote, rcvd->pdu, + flag, COAP_MESSAGE_RST); + } + } + + // we should not retry responses..... + cleanup: + coap_delete_node(sent); + sent = NULL; + coap_delete_node(rcvd); + rcvd = NULL; + } + } + + int coap_can_exit(coap_context_t *context) { + return !context + || (context->recvqueue == NULL && context->sendqueue == NULL); + } + +#ifdef WITH_CONTIKI + + /*---------------------------------------------------------------------------*/ + /* CoAP message retransmission */ + /*---------------------------------------------------------------------------*/ + PROCESS_THREAD(coap_retransmit_process, ev, data) + { + coap_tick_t now; + coap_queue_t *nextpdu; + + PROCESS_BEGIN(); + + debug("Started retransmit process\r\n"); + + while(1) { + PROCESS_YIELD(); + if (ev == PROCESS_EVENT_TIMER) { + if (etimer_expired(&the_coap_context.retransmit_timer)) { + + nextpdu = coap_peek_next(&the_coap_context); + + coap_ticks(&now); + while (nextpdu && nextpdu->t <= now) { + coap_retransmit(&the_coap_context, coap_pop_next(&the_coap_context)); + nextpdu = coap_peek_next(&the_coap_context); + } + + /* need to set timer to some value even if no nextpdu is available */ + etimer_set(&the_coap_context.retransmit_timer, + nextpdu ? nextpdu->t - now : 0xFFFF); + } +#ifndef WITHOUT_OBSERVE + if (etimer_expired(&the_coap_context.notify_timer)) { + coap_check_notify(&the_coap_context); + etimer_reset(&the_coap_context.notify_timer); + } +#endif /* WITHOUT_OBSERVE */ + } + } + + PROCESS_END(); + } + /*---------------------------------------------------------------------------*/ + +#endif /* WITH_CONTIKI */ + +#ifdef WITH_LWIP + /* FIXME: retransmits that are not required any more due to incoming packages + * do *not* get cleared at the moment, the wakeup when the transmission is due + * is silently accepted. this is mainly due to the fact that the required + * checks are similar in two places in the code (when receiving ACK and RST) + * and that they cause more than one patch chunk, as it must be first checked + * whether the sendqueue item to be dropped is the next one pending, and later + * the restart function has to be called. nothing insurmountable, but it can + * also be implemented when things have stabilized, and the performance + * penality is minimal + * + * also, this completely ignores COAP_RESOURCE_CHECK_TIME. + * */ + + static void coap_retransmittimer_execute(void *arg) + { + coap_context_t *ctx = (coap_context_t*)arg; + coap_tick_t now; + coap_tick_t elapsed; + coap_queue_t *nextinqueue; + + ctx->timer_configured = 0; + + coap_ticks(&now); + + elapsed = now - ctx->sendqueue_basetime; /* that's positive for sure, and unless we haven't been called for a complete wrapping cycle, did not wrap */ + + nextinqueue = coap_peek_next(ctx); + while (nextinqueue != NULL) + { + if (nextinqueue->t > elapsed) { + nextinqueue->t -= elapsed; + break; + } else { + elapsed -= nextinqueue->t; + coap_retransmit(ctx, coap_pop_next(ctx)); + nextinqueue = coap_peek_next(ctx); + } + } + + ctx->sendqueue_basetime = now; + + coap_retransmittimer_restart(ctx); + } + + static void coap_retransmittimer_restart(coap_context_t *ctx) + { + coap_tick_t now, elapsed, delay; + + if (ctx->timer_configured) + { + sys_untimeout(coap_retransmittimer_execute, (void*)ctx); + ctx->timer_configured = 0; + } + if (ctx->sendqueue != NULL) + { + coap_ticks(&now); + elapsed = now - ctx->sendqueue_basetime; + if (ctx->sendqueue->t >= elapsed) { + delay = ctx->sendqueue->t - elapsed; + } else { + /* a strange situation, but not completely impossible. + * + * this happens, for example, right after + * coap_retransmittimer_execute, when a retransmission + * was *just not yet* due, and the clock ticked before + * our coap_ticks was called. + * + * not trying to retransmit anything now, as it might + * cause uncontrollable recursion; let's just try again + * with the next main loop run. + * */ + delay = 0; + } + sys_timeout(delay, coap_retransmittimer_execute, (void*)ctx); + ctx->timer_configured = 1; + } + } +#endif diff --git a/resource/csdk/libcoap-4.1.1/net.h b/resource/csdk/libcoap-4.1.1/net.h new file mode 100644 index 000000000..cec3f0a91 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/net.h @@ -0,0 +1,545 @@ +/* net.h -- CoAP network interface + * + * Copyright (C) 2010--2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef _COAP_NET_H_ +#define _COAP_NET_H_ + +#ifdef WITH_ARDUINO +#include "Time.h" +#endif /* WITH_ARDUINO */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "config.h" + +#ifdef HAVE_ASSERT_H +#include +#else +#ifndef assert +#warning "assertions are disabled" +# define assert(x) +#endif +#endif + +#include +#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#ifdef WITH_LWIP +#include +#endif + +#include "option.h" +#include "address.h" +#include "prng.h" +#include "pdu.h" +#include "coap_time.h" + +typedef enum { + SEND_NOW = (1 << 0), // Flag used when sending non-confirmable, + // ACK and RESET coap pdus, Automatically set in SendCoAPPdu + // Do not use in upper stack APIs + SEND_NOW_CON = (1 << 1), // Flag used when sending confirmable coap pdu, + // Automatically set in SendCoAPPdu, + // Do not use in upper stack APIs + SEND_DELAYED = (1 << 2), // Flag used to delay the transmission of coap pdu + SEND_RETX = (1 << 3), // Flag used to retransmit a confirmable pdu + SEND_SECURE_PORT = (1 << 4) // Flag used to indicate that PDU needs to + // be transmitted on secure port +} coap_send_flags_t; + +struct coap_queue_t; + +typedef struct coap_queue_t { + struct coap_queue_t *next; + + coap_tick_t t; /**< when to send PDU for the next time */ + unsigned char retransmit_cnt; /**< retransmission counter, will be removed when zero */ + unsigned int timeout; /**< the randomized timeout value */ + + coap_address_t local; /**< local address */ + coap_address_t remote; /**< remote address */ + coap_tid_t id; /**< unique transaction id */ + + coap_pdu_t *pdu; /**< the CoAP PDU to send */ + + unsigned char delayedResNeeded; /**< delayed response flag */ + unsigned char secure; /**< rx/tx will use secure channel (DTLS) */ +} coap_queue_t; + +/** Adds node to given queue, ordered by node->t. */ +int coap_insert_node(coap_queue_t **queue, coap_queue_t *node); + +/** Destroys specified node. */ +int coap_delete_node(coap_queue_t *node); + +/** Removes all items from given queue and frees the allocated storage. */ +void coap_delete_all(coap_queue_t *queue); + +/** Creates a new node suitable for adding to the CoAP sendqueue. */ +coap_queue_t *coap_new_node(); + +struct coap_resource_t; +struct coap_context_t; +#ifndef WITHOUT_ASYNC +struct coap_async_state_t; +#endif + +struct coap_dtls_context_t; + +/** Message handler for requests that is used as call-back in coap_context_t */ +typedef void (*coap_request_handler_t)(struct coap_context_t *, + const coap_queue_t * rcvd); + +/** Message handler for responses that is used as call-back in coap_context_t */ +typedef void (*coap_response_handler_t)(struct coap_context_t *, + const coap_queue_t * rcvd); + +/** Message handler for ack and rst that is used as call-back in coap_context_t */ +typedef void (*coap_ack_rst_handler_t)(struct coap_context_t *, uint8_t msgType, + const coap_queue_t * sent); + +#define COAP_MID_CACHE_SIZE 3 +typedef struct { + unsigned char flags[COAP_MID_CACHE_SIZE]; + coap_key_t item[COAP_MID_CACHE_SIZE]; +} coap_mid_cache_t; + +/** The CoAP stack's global state is stored in a coap_context_t object */ +typedef struct coap_context_t { + coap_opt_filter_t known_options; +#ifndef WITH_CONTIKI + struct coap_resource_t *resources; /**< hash table or list of known resources */ +#endif /* WITH_CONTIKI */ +#ifndef WITHOUT_ASYNC + /** list of asynchronous transactions */ + struct coap_async_state_t *async_state; +#endif /* WITHOUT_ASYNC */ + /** + * The time stamp in the first element of the sendqeue is relative + * to sendqueue_basetime. */ + coap_tick_t sendqueue_basetime; + coap_queue_t *sendqueue, *recvqueue; +#if defined(WITH_POSIX) || defined(WITH_ARDUINO) + int sockfd; /**< send/receive socket */ + int sockfd_wellknown; /**< well-known discovery socket */ + int sockfd_dtls; /**< secure communication happens on this socket */ + /** dtls interface */ + struct coap_dtls_context_t *coap_dtls_ctx; +#endif /* WITH_POSIX || WITH_ARDUINO */ +#ifdef WITH_CONTIKI + struct uip_udp_conn *conn; /**< uIP connection object */ + + struct etimer retransmit_timer; /**< fires when the next packet must be sent */ + struct etimer notify_timer; /**< used to check resources periodically */ +#endif /* WITH_CONTIKI */ +#ifdef WITH_LWIP + struct udp_pcb *pcb; /**< the underlying lwIP UDP PCB */ + struct pbuf *pending_package; /**< pbuf containing the last received package if not handled yet. This is only used to pass the package from the udp_recv callback into the coap_read function, which frees the pbuf and clears this field. */ + ip_addr_t pending_address; /**< the address associated with pending_package */ + u16_t pending_port; /**< the port associated with pending_package */ + + uint8_t timer_configured; /**< Set to 1 when a retransmission is scheduled using lwIP timers for this context, otherwise 0. */ +#endif /* WITH_LWIP */ + + /** + * The last message id that was used is stored in this field. The + * initial value is set by coap_new_context() and is usually a + * random value. A new message id can be created with + * coap_new_message_id(). + */ + unsigned short message_id; + + /** + * The next value to be used for Observe. This field is global for + * all resources and will be updated when notifications are created. + */ + unsigned int observe; + + coap_request_handler_t request_handler; + coap_response_handler_t response_handler; + coap_ack_rst_handler_t ack_rst_handler; +} coap_context_t; + +/** + * Registers a new message handler that is called whenever a request + * was received that matches an ongoing transaction. + * + * @param context The context to register the handler for. + * @param handler The response handler to register. + */ +static inline void +coap_register_request_handler(coap_context_t *context, + coap_request_handler_t handler) { + context->request_handler = handler; +} + +/** + * Registers a new message handler that is called whenever a response + * was received that matches an ongoing transaction. + * + * @param context The context to register the handler for. + * @param handler The response handler to register. + */ +static inline void +coap_register_response_handler(coap_context_t *context, + coap_response_handler_t handler) { + context->response_handler = handler; +} + +/** + * Registers a new message handler that is called whenever ack or rst + * was received that matches an ongoing transaction. + * + * @param context The context to register the handler for. + * @param handler The handler to register. + */ +static inline void +coap_register_ack_rst_handler(coap_context_t *context, + coap_ack_rst_handler_t handler) { + context->ack_rst_handler = handler; +} + +/** + * Registers the option type @p type with the given context object @p + * ctx. + * + * @param ctx The context to use. + * @param type The option type to register. + */ +inline static void +coap_register_option(coap_context_t *ctx, unsigned char type) { + coap_option_setb(ctx->known_options, type); +} + + +/** + * Set sendqueue_basetime in the given context object @p ctx to @p + * now. This function returns the number of elements in the queue + * head that have timed out. + */ +unsigned int coap_adjust_basetime(coap_context_t *ctx, coap_tick_t now); + +/** Returns the next pdu to send without removing from sendqeue. */ +coap_queue_t *coap_peek_next( coap_context_t *context ); + +/** Returns the next pdu to send and removes it from the sendqeue. */ +coap_queue_t *coap_pop_next( coap_context_t *context ); + +/** Creates a new coap_context_t object that will hold the CoAP stack status. */ +coap_context_t *coap_new_context(uint8_t ipAddr[], uint16_t port); + +/** Joins the CoAP stack to well-known multicast address. */ +int coap_join_wellknown_group(coap_context_t *context, + const coap_address_t *multicast_addr); + +/** + * Returns a new message id and updates @p context->message_id + * accordingly. The message id is returned in network byte order + * to make it easier to read in tracing tools. + * + * @param context the current coap_context_t object + * @return incremented message id in network byte order + */ +static inline unsigned short +coap_new_message_id(coap_context_t *context) { + ++(context->message_id); +#ifdef WITH_ARDUINO + return ((context->message_id << 8) | ((context->message_id >> 8) & (0xFF))); +#elif WITH_CONTIKI + return uip_htons(context->message_id); +#else + return htons(context->message_id); +#endif +} + +/* CoAP stack context must be released with coap_free_context() */ +void coap_free_context( coap_context_t *context ); + +/** + * Sends a confirmed CoAP message to given destination. The memory + * that is allocated by pdu will not be released by + * coap_send_confirmed(). The caller must release the memory. + * + * @param context The CoAP context to use. + * @param dst The address to send to. + * @param pdu The CoAP PDU to send. + * @return The message id of the sent message or @c COAP_INVALID_TID on error. + */ +coap_tid_t coap_send_confirmed(coap_context_t *context, + const coap_address_t *dst, + coap_pdu_t *pdu); + +/** + * Creates a new ACK PDU with specified error @p code. The options + * specified by the filter expression @p opts will be copied from the + * original request contained in @p request. Unless @c + * SHORT_ERROR_RESPONSE was defined at build time, the textual reason + * phrase for @p code will be added as payload, with Content-Type @c + * 0. This function returns a pointer to the new response message, or + * @c NULL on error. The storage allocated for the new message must be + * relased with coap_free(). + * + * @param request Specification of the received (confirmable) request. + * @param code The error code to set. + * @param opts An option filter that specifies which options to copy + * from the original request in @p node. + * + * @return A pointer to the new message or @c NULL on error. + */ +coap_pdu_t *coap_new_error_response(coap_pdu_t *request, + unsigned char code, + coap_opt_filter_t opts); +/** + * Sends a CoAP message to given destination. The memory + * that is allocated by pdu will be released by coap_send(). + * + * @param context The CoAP context to use. + * @param dst The address to send to. + * @param pdu The CoAP PDU to send. + * @param flag The flag indicating how the message will be send + * @param cache_flag When DTLS library determines that a secure session does + * not exist with the peer yet, it caches the 'pdu pointer' + * so that it can be sent later and 'coap_send' sets this + * variable to TRUE to instruct the caller of this method + * to not delete the 'pdu'. + * @return The message id of the sent message or @c COAP_INVALID_TID on error. + */ +coap_tid_t coap_send(coap_context_t *context, const coap_address_t *dst, + coap_pdu_t *pdu, + coap_send_flags_t flags, + uint8_t *cache_flag); + +/** + * Sends an error response with code @p code for request @p request to + * @p dst. @p opts will be passed to coap_new_error_response() to + * copy marked options from the request. This function returns the + * transaction id if the message was sent, or @c COAP_INVALID_TID + * otherwise. + * + * @param context The context to use. + * @param request The original request to respond to. + * @param dst The remote peer that sent the request. + * @param code The reponse code. + * @param opts A filter that specifies the options to copy from the + * @p request. + * + * @return The transaction id if the message was sent, or @c + * COAP_INVALID_TID otherwise. + */ +coap_tid_t coap_send_error(coap_context_t *context, + coap_pdu_t *request, + const coap_address_t *dst, + unsigned char code, + coap_opt_filter_t opts, + coap_send_flags_t flag); + +/** + * Helper funktion to create and send a message with @p type (usually + * ACK or RST). This function returns @c COAP_INVALID_TID when the + * message was not sent, a valid transaction id otherwise. + * + * @param context The CoAP context. + * @param dst Where to send the context. + * @param request The request that should be responded to. + * @param type Which type to set + * @param flag options for sending the message + * @return transaction id on success or @c COAP_INVALID_TID otherwise. + */ +coap_tid_t +coap_send_message_type(coap_context_t *context, + const coap_address_t *dst, + coap_pdu_t *request, + coap_send_flags_t flag, + unsigned char type); +/** + * Sends an ACK message with code @c 0 for the specified @p request to + * @p dst. This function returns the corresponding transaction id if + * the message was sent or @c COAP_INVALID_TID on error. + * + * @param context The context to use. + * @param dst The destination address. + * @param request The request to be acknowledged. + * @param flag Options for sending the acknowledgement. + * + * @return The transaction id if ACK was sent or @c COAP_INVALID_TID + * on error. + */ +coap_tid_t coap_send_ack(coap_context_t *context, + const coap_address_t *dst, + coap_pdu_t *request, + coap_send_flags_t flag); + +/** + * Sends an RST message with code @c 0 for the specified @p request to + * @p dst. This function returns the corresponding transaction id if + * the message was sent or @c COAP_INVALID_TID on error. + * + * @param context The context to use. + * @param dst The destination address. + * @param request The request to be reset. + * @param flag Options for sending the reset message. + * + * @return The transaction id if RST was sent or @c COAP_INVALID_TID + * on error. + */ +static inline coap_tid_t +coap_send_rst(coap_context_t *context, + const coap_address_t *dst, + coap_pdu_t *request, + coap_send_flags_t flag) { + return coap_send_message_type(context, dst, request, flag, COAP_MESSAGE_RST); +} + +/** Handles retransmissions of confirmable messages */ +coap_tid_t coap_retransmit( coap_context_t *context, coap_queue_t *node); + +/** + * Reads data from the network and tries to parse as CoAP PDU. On success, 0 is returned + * and a new node with the parsed PDU is added to the receive queue in the specified context + * object. + */ +int coap_read( coap_context_t *context, int sockfd ); + +/** + * Calculates a unique transaction id from given arguments @p peer and + * @p pdu. The id is returned in @p id. + * + * @param peer The remote party who sent @p pdu. + * @param pdu The message that initiated the transaction. + * @param id Set to the new id. + */ +void coap_transaction_id(const coap_address_t *peer, const coap_pdu_t *pdu, + coap_tid_t *id); + +/** + * This function removes the element with given @p id from the list + * given list. If @p id was found, @p node is updated to point to the + * removed element. Note that the storage allocated by @p node is + * @b not released. The caller must do this manually using + * coap_delete_node(). This function returns @c 1 if the element with + * id @p id was found, @c 0 otherwise. For a return value of @c 0, + * the contents of @p node is undefined. + * + * @param queue The queue to search for @p id. + * @param id The node id to look for. + * @param node If found, @p node is updated to point to the + * removed node. You must release the storage pointed to by + * @p node manually. + * + * @return @c 1 if @p id was found, @c 0 otherwise. + */ +int coap_remove_from_queue(coap_queue_t **queue, + coap_tid_t id, + coap_queue_t **node); + +/** + * Removes the transaction identified by @p id from given @p queue. + * This is a convenience function for coap_remove_from_queue() with + * automatic deletion of the removed node. + * + * @param queue The queue to search for @p id. + * @param id The transaction id. + * + * @return @c 1 if node was found, removed and destroyed, @c 0 otherwise. + */ +inline static int +coap_remove_transaction(coap_queue_t **queue, coap_tid_t id) { + coap_queue_t *node; + if (!coap_remove_from_queue(queue, id, &node)) + return 0; + + coap_delete_node(node); + return 1; +} + +/** + * Retrieves transaction from queue. + * @queue The transaction queue to be searched + * @id Unique key of the transaction to find. + * @return A pointer to the transaction object or NULL if not found + */ +coap_queue_t *coap_find_transaction(coap_queue_t *queue, coap_tid_t id); + +/** + * Cancels all outstanding messages for peer @p dst that have the + * specified token. + * + * @param context The context in use + * @param dst Destination address of the messages to remove. + * @param token Message token + * @param token_length Actual length of @p token + */ +void coap_cancel_all_messages(coap_context_t *context, + const coap_address_t *dst, + const unsigned char *token, + size_t token_length); + +/** Dispatches the PDUs from the receive queue in given context. */ +void coap_dispatch( coap_context_t *context ); + +/** Returns 1 if there are no messages to send or to dispatch in the context's queues. */ +int coap_can_exit( coap_context_t *context ); + +/** + * Returns the current value of an internal tick counter. The counter + * counts \c COAP_TICKS_PER_SECOND ticks every second. + */ +void coap_ticks(coap_tick_t *); + +/** + * Verifies that @p pdu contains no unknown critical options. Options + * must be registered at @p ctx, using the function + * coap_register_option(). A basic set of options is registered + * automatically by coap_new_context(). This function returns @c 1 if + * @p pdu is ok, @c 0 otherwise. The given filter object @p unknown + * will be updated with the unknown options. As only @c COAP_MAX_OPT + * options can be signalled this way, remaining options must be + * examined manually. + * + * @code + coap_opt_filter_t f = COAP_OPT_NONE; + coap_opt_iterator_t opt_iter; + + if (coap_option_check_critical(ctx, pdu, f) == 0) { + coap_option_iterator_init(pdu, &opt_iter, f); + + while (coap_option_next(&opt_iter)) { + if (opt_iter.type & 0x01) { + ... handle unknown critical option in opt_iter ... + } + } + } + * @endcode + * + * @param ctx The context where all known options are registered. + * @param pdu The PDU to check. + * @param unknown The output filter that will be updated to indicate the + * unknown critical options found in @p pdu. + * + * @return @c 1 if everything was ok, @c 0 otherwise. + */ +int coap_option_check_critical(coap_context_t *ctx, + coap_pdu_t *pdu, + coap_opt_filter_t unknown); + +#ifdef __cplusplus +} +#endif + +#endif /* _COAP_NET_H_ */ diff --git a/resource/csdk/libcoap-4.1.1/option.c b/resource/csdk/libcoap-4.1.1/option.c new file mode 100644 index 000000000..a03fc9e61 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/option.c @@ -0,0 +1,407 @@ +/* + * option.c -- helpers for handling options in CoAP PDUs + * + * Copyright (C) 2010-2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + + +#include "config.h" + +#if defined(HAVE_ASSERT_H) && !defined(assert) +# include +#endif + +#include +#include + +#include "option.h" +#include "debug.h" + +coap_opt_t * +options_start(coap_pdu_t *pdu) { + + if (pdu && pdu->hdr && + (pdu->hdr->token + pdu->hdr->token_length + < (unsigned char *)pdu->hdr + pdu->length)) { + + coap_opt_t *opt = pdu->hdr->token + pdu->hdr->token_length; + return (*opt == COAP_PAYLOAD_START) ? NULL : opt; + + } else + return NULL; +} + +size_t +coap_opt_parse(const coap_opt_t *opt, size_t length, coap_option_t *result) { + + const coap_opt_t *opt_start = opt; /* store where parsing starts */ + + assert(opt); assert(result); + +#define ADVANCE_OPT(o,e,step) if ((e) < step) { \ + debug("cannot advance opt past end\n"); \ + return 0; \ + } else { \ + (e) -= step; \ + (o) = ((unsigned char *)(o)) + step; \ + } + + if (length < 1) + return 0; + + result->delta = (*opt & 0xf0) >> 4; + result->length = *opt & 0x0f; + + switch(result->delta) { + case 15: + if (*opt != COAP_PAYLOAD_START) + debug("ignored reserved option delta 15\n"); + return 0; + case 14: + /* Handle two-byte value: First, the MSB + 269 is stored as delta value. + * After that, the option pointer is advanced to the LSB which is handled + * just like case delta == 13. */ + ADVANCE_OPT(opt,length,1); + result->delta = ((*opt & 0xff) << 8) + 269; + if (result->delta < 269) { + debug("delta too large\n"); + return 0; + } + /* fall through */ + case 13: + ADVANCE_OPT(opt,length,1); + result->delta += *opt & 0xff; + break; + + default: + ; + } + + switch(result->length) { + case 15: + debug("found reserved option length 15\n"); + return 0; + case 14: + /* Handle two-byte value: First, the MSB + 269 is stored as delta value. + * After that, the option pointer is advanced to the LSB which is handled + * just like case delta == 13. */ + ADVANCE_OPT(opt,length,1); + result->length = ((*opt & 0xff) << 8) + 269; + /* fall through */ + case 13: + ADVANCE_OPT(opt,length,1); + result->length += *opt & 0xff; + break; + + default: + ; + } + + ADVANCE_OPT(opt,length,1); + /* opt now points to value, if present */ + + result->value = (unsigned char *)opt; + if (length < result->length) { + debug("invalid option length\n"); + return 0; + } + +#undef ADVANCE_OPT + + return (opt + result->length) - opt_start; +} + +coap_opt_iterator_t * +coap_option_iterator_init(coap_pdu_t *pdu, coap_opt_iterator_t *oi, + const coap_opt_filter_t filter) { + assert(pdu); + assert(pdu->hdr); + assert(oi); + + memset(oi, 0, sizeof(coap_opt_iterator_t)); + + oi->next_option = (unsigned char *)pdu->hdr + sizeof(coap_hdr_t) + + pdu->hdr->token_length; + if ((unsigned char *)pdu->hdr + pdu->length <= oi->next_option) { + oi->bad = 1; + return NULL; + } + + assert((sizeof(coap_hdr_t) + pdu->hdr->token_length) <= pdu->length); + + oi->length = pdu->length - (sizeof(coap_hdr_t) + pdu->hdr->token_length); + + if (filter) { + memcpy(oi->filter, filter, sizeof(coap_opt_filter_t)); + oi->filtered = 1; + } + return oi; +} + +static inline int +opt_finished(coap_opt_iterator_t *oi) { + assert(oi); + + if (oi->bad || oi->length == 0 || + !oi->next_option || *oi->next_option == COAP_PAYLOAD_START) { + oi->bad = 1; + } + + return oi->bad; +} + +coap_opt_t * +coap_option_next(coap_opt_iterator_t *oi) { + coap_option_t option; + coap_opt_t *current_opt = NULL; + size_t optsize; + int b; /* to store result of coap_option_getb() */ + + assert(oi); + + if (opt_finished(oi)) + return NULL; + + while (1) { + /* oi->option always points to the next option to deliver; as + * opt_finished() filters out any bad conditions, we can assume that + * oi->option is valid. */ + current_opt = oi->next_option; + + /* Advance internal pointer to next option, skipping any option that + * is not included in oi->filter. */ + optsize = coap_opt_parse(oi->next_option, oi->length, &option); + if (optsize) { + assert(optsize <= oi->length); + + oi->next_option += optsize; + oi->length -= optsize; + + oi->type += option.delta; + } else { /* current option is malformed */ + oi->bad = 1; + return NULL; + } + + /* Exit the while loop when: + * - no filtering is done at all + * - the filter matches for the current option + * - the filter is too small for the current option number + */ + if (!oi->filtered || + (b = coap_option_getb(oi->filter, oi->type)) > 0) + break; + else if (b < 0) { /* filter too small, cannot proceed */ + oi->bad = 1; + return NULL; + } + } + + return current_opt; +} + +coap_opt_t * +coap_check_option(coap_pdu_t *pdu, unsigned char type, + coap_opt_iterator_t *oi) { + coap_opt_filter_t f; + + coap_option_filter_clear(f); + coap_option_setb(f, type); + + coap_option_iterator_init(pdu, oi, f); + + return coap_option_next(oi); +} + +unsigned short +coap_opt_delta(const coap_opt_t *opt) { + unsigned short n; + + n = (*opt++ & 0xf0) >> 4; + + switch (n) { + case 15: /* error */ + warn("coap_opt_delta: illegal option delta\n"); + + /* This case usually should not happen, hence we do not have a + * proper way to indicate an error. */ + return 0; + case 14: + /* Handle two-byte value: First, the MSB + 269 is stored as delta value. + * After that, the option pointer is advanced to the LSB which is handled + * just like case delta == 13. */ + n = ((*opt++ & 0xff) << 8) + 269; + /* fall through */ + case 13: + n += *opt & 0xff; + break; + default: /* n already contains the actual delta value */ + ; + } + + return n; +} + +unsigned short +coap_opt_length(const coap_opt_t *opt) { + unsigned short length; + + length = *opt & 0x0f; + switch (*opt & 0xf0) { + case 0xf0: + debug("illegal option delta\n"); + return 0; + case 0xe0: + ++opt; + /* fall through to skip another byte */ + case 0xd0: + ++opt; + /* fall through to skip another byte */ + default: + ++opt; + } + + switch (length) { + case 0x0f: + debug("illegal option length\n"); + return 0; + case 0x0e: + length = (*opt++ << 8) + 269; + /* fall through */ + case 0x0d: + length += *opt++; + break; + default: + ; + } + return length; +} + +unsigned char * +coap_opt_value(coap_opt_t *opt) { + size_t ofs = 1; + + switch (*opt & 0xf0) { + case 0xf0: + debug("illegal option delta\n"); + return 0; + case 0xe0: + ++ofs; + /* fall through */ + case 0xd0: + ++ofs; + break; + default: + ; + } + + switch (*opt & 0x0f) { + case 0x0f: + debug("illegal option length\n"); + return 0; + case 0x0e: + ++ofs; + /* fall through */ + case 0x0d: + ++ofs; + break; + default: + ; + } + + return (unsigned char *)opt + ofs; +} + +size_t +coap_opt_size(const coap_opt_t *opt) { + coap_option_t option; + + /* we must assume that opt is encoded correctly */ + return coap_opt_parse(opt, (size_t)-1, &option); +} + +size_t +coap_opt_setheader(coap_opt_t *opt, size_t maxlen, + unsigned short delta, size_t length) { + size_t skip = 0; + + assert(opt); + + if (maxlen == 0) /* need at least one byte */ + return 0; + + if (delta < 13) { + opt[0] = delta << 4; + } else if (delta < 270) { + if (maxlen < 2) { + debug("insufficient space to encode option delta %d", delta); + return 0; + } + + opt[0] = 0xd0; + opt[++skip] = delta - 13; + } else { + if (maxlen < 3) { + debug("insufficient space to encode option delta %d", delta); + return 0; + } + + opt[0] = 0xe0; + opt[++skip] = ((delta - 269) >> 8) & 0xff; + opt[++skip] = (delta - 269) & 0xff; + } + + if (length < 13) { + opt[0] |= length & 0x0f; + } else if (length < 270) { + if (maxlen < skip + 1) { + debug("insufficient space to encode option length %d", length); + return 0; + } + + opt[0] |= 0x0d; + opt[++skip] = length - 13; + } else { + if (maxlen < skip + 2) { + debug("insufficient space to encode option delta %d", delta); + return 0; + } + + opt[0] |= 0x0e; + opt[++skip] = ((length - 269) >> 8) & 0xff; + opt[++skip] = (length - 269) & 0xff; + } + + return skip + 1; +} + +size_t +coap_opt_encode(coap_opt_t *opt, size_t maxlen, unsigned short delta, + const unsigned char *val, size_t length) { + size_t l = 1; + + l = coap_opt_setheader(opt, maxlen, delta, length); + assert(l <= maxlen); + + if (!l) { + debug("coap_opt_encode: cannot set option header\n"); + return 0; + } + + maxlen -= l; + opt += l; + + if (maxlen < length) { + debug("coap_opt_encode: option too large for buffer\n"); + return 0; + } + + if (val) /* better be safe here */ + memcpy(opt, val, length); + + return l + length; +} + diff --git a/resource/csdk/libcoap-4.1.1/option.h b/resource/csdk/libcoap-4.1.1/option.h new file mode 100644 index 000000000..34cb31fc3 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/option.h @@ -0,0 +1,345 @@ +/* + * option.h -- helpers for handling options in CoAP PDUs + * + * Copyright (C) 2010-2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file option.h + * @brief helpers for handling options in CoAP PDUs + */ + +#ifndef _OPTION_H_ +#define _OPTION_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "bits.h" +#include "pdu.h" + +/** + * Use byte-oriented access methods here because sliding a complex + * struct coap_opt_t over the data buffer may cause bus error on + * certain platforms. + */ +typedef unsigned char coap_opt_t; +#define PCHAR(p) ((coap_opt_t *)(p)) + +/** Representation of CoAP options. */ +typedef struct { + unsigned short delta; + size_t length; + unsigned char *value; +} coap_option_t; + +/** + * Parses the option pointed to by @p opt into @p result. This + * function returns the number of bytes that have been parsed, or @c 0 + * on error. An error is signaled when illegal delta or length values + * are encountered or when option parsing would result in reading past + * the option (i.e. beyond opt + length). + * + * @param opt The beginning of the option to parse. + * @param length The maximum length of @p opt. + * @param result A pointer to the coap_option_t structure that is + * filled with actual values iff coap_opt_parse() > 0. + * @return The number of bytes parsed or @c 0 on error. + */ +size_t coap_opt_parse(const coap_opt_t *opt, size_t length, + coap_option_t *result); + +/** + * Returns the size of the given option, taking into account a + * possible option jump. + * + * @param opt An option jump or the beginning of the option. + * @return The number of bytes between @p opt and the end of + * the option starting at @p opt. In case of an error, + * this function returns @c 0 as options need at least + * one byte storage space. + */ +size_t coap_opt_size(const coap_opt_t *opt); + +/** @deprecated { Use coap_opt_size() instead. } */ +#define COAP_OPT_SIZE(opt) coap_opt_size(opt) + +/** + * Calculates the beginning of the PDU's option section. + * + * @param pdu The PDU containing the options. + * @return A pointer to the first option if available, or @c NULL otherwise. + */ +coap_opt_t *options_start(coap_pdu_t *pdu); + +/** + * Interprets @p opt as pointer to a CoAP option and advances to + * the next byte past this option. + * @hideinitializer + */ +#define options_next(opt) \ + ((coap_opt_t *)((unsigned char *)(opt) + COAP_OPT_SIZE(opt))) + +/** + * @defgroup opt_filter Option Filters + * @{ + */ + +/** + * Fixed-size bit-vector we use for option filtering. It is large + * enough to hold the highest option number known at build time (20 in + * the core spec). + */ +typedef unsigned char coap_opt_filter_t[(COAP_MAX_OPT >> 3) + 1]; + +/** Pre-defined filter that includes all options. */ +#define COAP_OPT_ALL NULL + +/** + * Clears filter @p f. + * + * @param f The filter to clear. + */ +static inline void +coap_option_filter_clear(coap_opt_filter_t f) { + memset(f, 0, sizeof(coap_opt_filter_t)); +} + +/** + * Sets the corresponding bit for @p type in @p filter. This function + * returns @c 1 if bit was set or @c -1 on error (i.e. when the given + * type does not fit in the filter). + * + * @param filter The filter object to change. + * @param type The type for which the bit should be set. + * + * @return @c 1 if bit was set, @c -1 otherwise. + */ +inline static int +coap_option_setb(coap_opt_filter_t filter, unsigned short type) { + return bits_setb((uint8_t *)filter, sizeof(coap_opt_filter_t), type); +} + +/** +* Sets the entire range of vendor specific options in the filter +*/ +inline static int +coap_option_setbVendor(coap_opt_filter_t filter) +{ + if ((COAP_VENDOR_OPT_START >> 3) > sizeof(coap_opt_filter_t)) + { + return -1; + } + memset((uint8_t *)filter + (COAP_VENDOR_OPT_START >> 3), 0xFF, + sizeof(coap_opt_filter_t) - (COAP_VENDOR_OPT_START >> 3)); + return 1; +} + +/** + * Clears the corresponding bit for @p type in @p filter. This function + * returns @c 1 if bit was cleared or @c -1 on error (i.e. when the given + * type does not fit in the filter). + * + * @param filter The filter object to change. + * @param type The type for which the bit should be cleared. + * + * @return @c 1 if bit was set, @c -1 otherwise. + */ +inline static int +coap_option_clrb(coap_opt_filter_t filter, unsigned short type) { + return bits_clrb((uint8_t *)filter, sizeof(coap_opt_filter_t), type); +} + +/** + * Gets the corresponding bit for @p type in @p filter. This function + * returns @c 1 if the bit is set @c 0 if not, or @c -1 on error (i.e. + * when the given type does not fit in the filter). + * + * @param filter The filter object to read bit from.. + * @param type The type for which the bit should be read. + * + * @return @c 1 if bit was set, @c 0 if not, @c -1 on error. + */ +inline static int +coap_option_getb(const coap_opt_filter_t filter, unsigned short type) { + return bits_getb((uint8_t *)filter, sizeof(coap_opt_filter_t), type); +} + +/** + * Iterator to run through PDU options. This object must be + * initialized with coap_option_iterator_init(). Call + * coap_option_next() to walk through the list of options until + * coap_option_next() returns @c NULL. + * + * @code + * coap_opt_t *option; + * coap_opt_iterator_t opt_iter; + * coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL); + * + * while ((option = coap_option_next(&opt_iter))) { + * ... do something with option ... + * } + * @endcode + */ +typedef struct { + size_t length; /**< remaining length of PDU */ + unsigned short type; /**< decoded option type */ + unsigned int bad:1; /**< iterator object is ok if not set */ + unsigned int filtered:1; /**< denotes whether or not filter is used */ + coap_opt_t *next_option; /**< pointer to the unparsed next option */ + coap_opt_filter_t filter; /**< option filter */ +} coap_opt_iterator_t; + +/** + * Initializes the given option iterator @p oi to point to the + * beginning of the @p pdu's option list. This function returns @p oi + * on success, @c NULL otherwise (i.e. when no options exist). + * Note that a length check on the option list must be performed before + * coap_option_iterator_init() is called. + * + * @param pdu The PDU the options of which should be walked through. + * @param oi An iterator object that will be initilized. + * @param filter An optional option type filter. + * With @p type != @c COAP_OPT_ALL, coap_option_next() + * will return only options matching this bitmask. + * Fence-post options @c 14, @c 28, @c 42, ... are always + * skipped. + * + * @return The iterator object @p oi on success, @c NULL otherwise. + */ +coap_opt_iterator_t *coap_option_iterator_init(coap_pdu_t *pdu, + coap_opt_iterator_t *oi, const coap_opt_filter_t filter); + +/** + * Updates the iterator @p oi to point to the next option. This + * function returns a pointer to that option or @c NULL if no more + * options exist. The contents of @p oi will be updated. In + * particular, @c oi->n specifies the current option's ordinal number + * (counted from @c 1), @c oi->type is the option's type code, and @c + * oi->option points to the beginning of the current option + * itself. When advanced past the last option, @c oi->option will be + * @c NULL. + * + * Note that options are skipped whose corresponding bits in the + * filter specified with coap_option_iterator_init() are @c 0. Options + * with type codes that do not fit in this filter hence will always be + * returned. + * + * @param oi The option iterator to update. + * + * @return The next option or @c NULL if no more options exist. + */ +coap_opt_t *coap_option_next(coap_opt_iterator_t *oi); + +/** + * Retrieves the first option of type @p type from @p pdu. @p oi must + * point to a coap_opt_iterator_t object that will be initialized by + * this function to filter only options with code @p type. This + * function returns the first option with this type, or @c NULL if not + * found. + * + * @param pdu The PDU to parse for options. + * @param type The option type code to search for. + * @param oi An iterator object to use. + * + * @return A pointer to the first option of type @p type, or @c NULL + * if not found. + */ +coap_opt_t *coap_check_option(coap_pdu_t *pdu, + unsigned char type, + coap_opt_iterator_t *oi); + +/** + * Encodes the given delta and length values into @p opt. This + * function returns the number of bytes that were required to encode + * @p delta and @p length or @c 0 on error. Note that the result + * indicates by how many bytes @p opt must be advanced to encode the + * option value. + * + * @param opt The option buffer space where @p delta and @p length are + * written + * @param maxlen The maximum length of @p opt + * @param delta The actual delta value to encode. + * @param length The actual length value to encode. + * @return The number of bytes used or @c 0 on error. + */ +size_t coap_opt_setheader(coap_opt_t *opt, size_t maxlen, + unsigned short delta, size_t length); + +/** + * Encodes option with given @p delta into @p opt. This function returns + * the number of bytes written to @p opt or @c 0 on error. This happens + * especially when @p opt does not provide sufficient space to store + * the option value, delta, and option jumps when required. + * + * @param opt The option buffer space where @p val is written + * @param n Maximum length of @p opt. + * @param delta The option delta. + * @param val The option value to copy into @p opt. + * @param len The actual length of @p val. + * @return The number of bytes that have been written to @p opt or + * @c 0 on error. The return value will always be less than @p n. + */ +size_t coap_opt_encode(coap_opt_t *opt, size_t n, unsigned short delta, + const unsigned char *val, size_t length); + +/** + * Decodes the delta value of the next option. This function returns + * the number of bytes read or @c 0 on error. The caller of this + * function must ensure that it does not read over the boundaries + * of @p opt (e.g. by calling coap_opt_check_delta(). + * + * @param opt The option to examine + * @return The number of bytes read or @c 0 on error. + */ +unsigned short coap_opt_delta(const coap_opt_t *opt); + +/** @deprecated { Use coap_opt_delta() instead. } */ +#define COAP_OPT_DELTA(opt) coap_opt_delta(opt) + +/** @deprecated { Use coap_opt_encode() instead. } */ +#define COAP_OPT_SETDELTA(opt,val) \ + coap_opt_encode((opt), COAP_MAX_PDU_SIZE, (val), NULL, 0) + +/** + * Returns the length of the given option. @p opt must point to an + * option jump or the beginning of the option. This function returns + * @c 0 when @p opt is not an option or the actual length of @p opt + * (which can be @c 0 as well). + * + * @note {The rationale for using @c 0 in case of an error is that in + * most contexts, the result of this function is used to skip the next + * coap_opt_length() bytes. } + * + * @param opt The option whose length should be returned. + * @return The option's length or @c 0 when undefined. + */ +unsigned short coap_opt_length(const coap_opt_t *opt); + +/** @deprecated { Use coap_opt_length() instead. } */ +#define COAP_OPT_LENGTH(opt) coap_opt_length(opt) + +/** + * Returns a pointer to the value of the given option. @p opt must + * point to an option jump or the beginning of the option. This + * function returns @c NULL if @p opt is not a valid option. + * + * @param opt The option whose value should be returned. + * @return A pointer to the option value or @c NULL on error. + */ +unsigned char *coap_opt_value(coap_opt_t *opt); + +/** @deprecated { Use coap_opt_value() instead. } */ +#define COAP_OPT_VALUE(opt) coap_opt_value((coap_opt_t *)opt) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* _OPTION_H_ */ diff --git a/resource/csdk/libcoap-4.1.1/pdu.c b/resource/csdk/libcoap-4.1.1/pdu.c new file mode 100644 index 000000000..109e2890d --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/pdu.c @@ -0,0 +1,406 @@ +/* pdu.c -- CoAP message structure + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "config.h" + +#if defined(HAVE_ASSERT_H) && !defined(assert) +#include +#endif + +#include +#include +#include +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#include "debug.h" +#include "pdu.h" +#include "option.h" +#include "encode.h" + +#ifdef WITH_CONTIKI +#include "memb.h" + +typedef unsigned char _pdu[sizeof(coap_pdu_t) + COAP_MAX_PDU_SIZE]; + +MEMB(pdu_storage, _pdu, COAP_PDU_MAXCNT); + +void +coap_pdu_resources_init() { + memb_init(&pdu_storage); +} +#else /* WITH_CONTIKI */ +#include "mem.h" +#endif /* WITH_CONTIKI */ + +void +coap_pdu_clear(coap_pdu_t *pdu, size_t size) { + assert(pdu); + + memset(pdu, 0, sizeof(coap_pdu_t) + size); + pdu->max_size = size; + pdu->hdr = (coap_hdr_t *)((unsigned char *)pdu + sizeof(coap_pdu_t)); + pdu->hdr->version = COAP_DEFAULT_VERSION; + + /* data is NULL unless explicitly set by coap_add_data() */ + pdu->length = sizeof(coap_hdr_t); +} + +#ifdef WITH_LWIP +coap_pdu_t * +coap_pdu_from_pbuf(struct pbuf *pbuf) +{ + LWIP_ASSERT("Can only deal with contiguous PBUFs", pbuf->tot_len == pbuf->len); + LWIP_ASSERT("coap_read needs to receive an exclusive copy of the incoming pbuf", pbuf->ref == 1); + + void *data = pbuf->payload; + coap_pdu_t *result; + + u8_t header_error = pbuf_header(pbuf, sizeof(coap_pdu_t)); + LWIP_ASSERT("CoAP PDU header does not fit in existing header space", header_error == 0); + + result = (coap_pdu_t *)pbuf->payload; + + memset(result, 0, sizeof(coap_pdu_t)); + + result->max_size = pbuf->tot_len - sizeof(coap_pdu_t); + result->length = pbuf->tot_len - sizeof(coap_pdu_t); + result->hdr = data; + result->pbuf = pbuf; + + return result; +} +#endif + +coap_pdu_t * +coap_pdu_init(unsigned char type, unsigned char code, + unsigned short id, size_t size) { + coap_pdu_t *pdu; +#ifdef WITH_LWIP + struct pbuf *p; +#endif + + assert(size <= COAP_MAX_PDU_SIZE); + /* Size must be large enough to fit the header. */ + if (size < sizeof(coap_hdr_t) || size > COAP_MAX_PDU_SIZE) + return NULL; + + /* size must be large enough for hdr */ +#if defined(WITH_POSIX) || defined(WITH_ARDUINO) + pdu = (coap_pdu_t *)coap_malloc(sizeof(coap_pdu_t) + size); +#endif +#ifdef WITH_CONTIKI + pdu = (coap_pdu_t *)memb_alloc(&pdu_storage); +#endif +#ifdef WITH_LWIP + p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); + if (p != NULL) { + u8_t header_error = pbuf_header(p, sizeof(coap_pdu_t)); + /* we could catch that case and allocate larger memory in advance, but then + * again, we'd run into greater trouble with incoming packages anyway */ + LWIP_ASSERT("CoAP PDU header does not fit in transport header", header_error == 0); + pdu = p->payload; + } else { + pdu = NULL; + } +#endif + if (pdu) { + coap_pdu_clear(pdu, size); + pdu->hdr->id = id; + pdu->hdr->type = type; + pdu->hdr->code = code; +#ifdef WITH_LWIP + pdu->pbuf = p; +#endif + } + return pdu; +} + + +void +coap_delete_pdu(coap_pdu_t *pdu) { +#if defined(WITH_POSIX) || defined(WITH_ARDUINO) + coap_free( pdu ); +#endif +#ifdef WITH_LWIP + if (pdu != NULL) /* accepting double free as the other implementation accept that too */ + pbuf_free(pdu->pbuf); +#endif +#ifdef WITH_CONTIKI + memb_free(&pdu_storage, pdu); +#endif +} + +int +coap_add_token(coap_pdu_t *pdu, size_t len, const unsigned char *data) { + const size_t HEADERLENGTH = len + 4; + /* must allow for pdu == NULL as callers may rely on this */ + if (!pdu || len > 8 || pdu->max_size < HEADERLENGTH) + return 0; + + pdu->hdr->token_length = len; + if (len) + memcpy(pdu->hdr->token, data, len); + pdu->max_delta = 0; + pdu->length = HEADERLENGTH; + pdu->data = NULL; + + return 1; +} + +/** @FIXME de-duplicate code with coap_add_option_later */ +size_t +coap_add_option(coap_pdu_t *pdu, unsigned short type, unsigned int len, const unsigned char *data) { + size_t optsize; + coap_opt_t *opt; + + assert(pdu); + pdu->data = NULL; + + if (type < pdu->max_delta) { + warn("coap_add_option: options are not in correct order\n"); + return 0; + } + + opt = (unsigned char *)pdu->hdr + pdu->length; + + /* encode option and check length */ + optsize = coap_opt_encode(opt, pdu->max_size - pdu->length, + type - pdu->max_delta, data, len); + + if (!optsize) { + warn("coap_add_option: cannot add option\n"); + /* error */ + return 0; + } else { + pdu->max_delta = type; + pdu->length += optsize; + } + + return optsize; +} + +/** @FIXME de-duplicate code with coap_add_option */ +unsigned char* +coap_add_option_later(coap_pdu_t *pdu, unsigned short type, unsigned int len) { + size_t optsize; + coap_opt_t *opt; + + assert(pdu); + pdu->data = NULL; + + if (type < pdu->max_delta) { + warn("coap_add_option: options are not in correct order\n"); + return NULL; + } + + opt = (unsigned char *)pdu->hdr + pdu->length; + + /* encode option and check length */ + optsize = coap_opt_encode(opt, pdu->max_size - pdu->length, + type - pdu->max_delta, NULL, len); + + if (!optsize) { + warn("coap_add_option: cannot add option\n"); + /* error */ + return NULL; + } else { + pdu->max_delta = type; + pdu->length += optsize; + } + + return ((unsigned char*)opt) + optsize - len; +} + +int +coap_add_data(coap_pdu_t *pdu, unsigned int len, const unsigned char *data) { + assert(pdu); + assert(pdu->data == NULL); + + if (len == 0) + return 1; + + if (pdu->length + len + 1 > pdu->max_size) { + warn("coap_add_data: cannot add: data too large for PDU\n"); + assert(pdu->data == NULL); + return 0; + } + + pdu->data = (unsigned char *)pdu->hdr + pdu->length; + *pdu->data = COAP_PAYLOAD_START; + pdu->data++; + + memcpy(pdu->data, data, len); + pdu->length += len + 1; + return 1; +} + +int +coap_get_data(coap_pdu_t *pdu, size_t *len, unsigned char **data) { + assert(pdu); + assert(len); + assert(data); + + if (pdu->data) { + *len = (unsigned char *)pdu->hdr + pdu->length - pdu->data; + *data = pdu->data; + } else { /* no data, clear everything */ + *len = 0; + *data = NULL; + } + + return *data != NULL; +} + +#ifndef SHORT_ERROR_RESPONSE +typedef struct { + unsigned char code; + const char *phrase; +} error_desc_t; + +/* if you change anything here, make sure, that the longest string does not + * exceed COAP_ERROR_PHRASE_LENGTH. */ +error_desc_t coap_error[] = { + { COAP_RESPONSE_CODE(65), "2.01 Created" }, + { COAP_RESPONSE_CODE(66), "2.02 Deleted" }, + { COAP_RESPONSE_CODE(67), "2.03 Valid" }, + { COAP_RESPONSE_CODE(68), "2.04 Changed" }, + { COAP_RESPONSE_CODE(69), "2.05 Content" }, + { COAP_RESPONSE_CODE(400), "Bad Request" }, + { COAP_RESPONSE_CODE(401), "Unauthorized" }, + { COAP_RESPONSE_CODE(402), "Bad Option" }, + { COAP_RESPONSE_CODE(403), "Forbidden" }, + { COAP_RESPONSE_CODE(404), "Not Found" }, + { COAP_RESPONSE_CODE(405), "Method Not Allowed" }, + { COAP_RESPONSE_CODE(408), "Request Entity Incomplete" }, + { COAP_RESPONSE_CODE(413), "Request Entity Too Large" }, + { COAP_RESPONSE_CODE(415), "Unsupported Media Type" }, + { COAP_RESPONSE_CODE(500), "Internal Server Error" }, + { COAP_RESPONSE_CODE(501), "Not Implemented" }, + { COAP_RESPONSE_CODE(502), "Bad Gateway" }, + { COAP_RESPONSE_CODE(503), "Service Unavailable" }, + { COAP_RESPONSE_CODE(504), "Gateway Timeout" }, + { COAP_RESPONSE_CODE(505), "Proxying Not Supported" }, + { 0, NULL } /* end marker */ +}; + +const char * +coap_response_phrase(unsigned char code) { + int i; + for (i = 0; coap_error[i].code; ++i) { + if (coap_error[i].code == code) + return coap_error[i].phrase; + } + return NULL; +} +#endif + +/** + * Advances *optp to next option if still in PDU. This function + * returns the number of bytes opt has been advanced or @c 0 + * on error. + */ +static size_t +next_option_safe(coap_opt_t **optp, size_t *length) { + coap_option_t option; + size_t optsize; + + assert(optp); assert(*optp); + assert(length); + + optsize = coap_opt_parse(*optp, *length, &option); + if (optsize) { + assert(optsize <= *length); + + *optp += optsize; + *length -= optsize; + } + + return optsize; +} + +int +coap_pdu_parse(unsigned char *data, size_t length, coap_pdu_t *pdu) { + coap_opt_t *opt; + + assert(data); + assert(pdu); + + if (pdu->max_size < length) { + debug("insufficient space to store parsed PDU\n"); + return 0; + } + + if (length < sizeof(coap_hdr_t)) { + debug("discarded invalid PDU\n"); + } + + pdu->hdr->version = data[0] >> 6; + pdu->hdr->type = (data[0] >> 4) & 0x03; + pdu->hdr->token_length = data[0] & 0x0f; + pdu->hdr->code = data[1]; + pdu->data = NULL; + + /* sanity checks */ + if (pdu->hdr->code == 0) { + if (length != sizeof(coap_hdr_t) || pdu->hdr->token_length) { + debug("coap_pdu_parse: empty message is not empty\n"); + goto discard; + } + } + + if (length < sizeof(coap_hdr_t) + pdu->hdr->token_length + || pdu->hdr->token_length > 8) { + debug("coap_pdu_parse: invalid Token\n"); + goto discard; + } + + /* Copy message id in network byte order, so we can easily write the + * response back to the network. */ + memcpy(&pdu->hdr->id, data + 2, 2); + + /* append data (including the Token) to pdu structure */ + memcpy(pdu->hdr + 1, data + sizeof(coap_hdr_t), length - sizeof(coap_hdr_t)); + pdu->length = length; + + /* Finally calculate beginning of data block and thereby check integrity + * of the PDU structure. */ + + /* skip header + token */ + length -= (pdu->hdr->token_length + sizeof(coap_hdr_t)); + opt = (unsigned char *)(pdu->hdr + 1) + pdu->hdr->token_length; + + while (length && *opt != COAP_PAYLOAD_START) { + + if (!next_option_safe(&opt, (size_t *)&length)) { + debug("coap_pdu_parse: drop\n"); + goto discard; + } + } + + /* end of packet or start marker */ + if (length) { + assert(*opt == COAP_PAYLOAD_START); + opt++; length--; + + if (!length) { + debug("coap_pdu_parse: message ending in payload start marker\n"); + goto discard; + } + + debug("set data to %p (pdu ends at %p)\n", (unsigned char *)opt, + (unsigned char *)pdu->hdr + pdu->length); + pdu->data = (unsigned char *)opt; + } + + return 1; + + discard: + return 0; +} diff --git a/resource/csdk/libcoap-4.1.1/pdu.h b/resource/csdk/libcoap-4.1.1/pdu.h new file mode 100644 index 000000000..8b76776f5 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/pdu.h @@ -0,0 +1,377 @@ +/* pdu.h -- CoAP message structure + * + * Copyright (C) 2010--2012 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef _PDU_H_ +#define _PDU_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "config.h" +#include "coap_list.h" +#include "uri.h" + +#ifdef WITH_LWIP +#include +#endif + +/* pre-defined constants that reflect defaults for CoAP */ +// This value is based on the DEFAULT_LEISURE (5 seconds) defined in RFC 7252 +#define MAX_MULTICAST_DELAY_SEC (5) + +/* response timeout in seconds, this can not be less that the delays between calls to OCProcess*/ +#define COAP_DEFAULT_RESPONSE_TIMEOUT 2 +#define COAP_DEFAULT_MAX_RETRANSMIT 4 /* max number of retransmissions */ +#define COAP_DEFAULT_PORT 5683 /* CoAP default UDP port */ +#define COAP_DEFAULT_MAX_AGE 60 /* default maximum object lifetime in seconds */ +#ifndef COAP_MAX_PDU_SIZE +#ifdef WITH_ARDUINO +#define COAP_MAX_PDU_SIZE 320 /* maximum size of a CoAP PDU for embedded platforms*/ +#else +#define COAP_MAX_PDU_SIZE 1400 /* maximum size of a CoAP PDU for big platforms*/ +#endif +#endif /* COAP_MAX_PDU_SIZE */ + +#define COAP_DEFAULT_VERSION 1 /* version of CoAP supported */ +#define COAP_DEFAULT_SCHEME "coap" /* the default scheme for CoAP URIs */ + +/** well-known resources URI */ +#define COAP_DEFAULT_URI_WELLKNOWN ".well-known/core" + +#ifdef __COAP_DEFAULT_HASH +/* pre-calculated hash key for the default well-known URI */ +#define COAP_DEFAULT_WKC_HASHKEY "\345\130\144\245" +#endif + +/* CoAP message types */ + +#define COAP_MESSAGE_CON 0 /* confirmable message (requires ACK/RST) */ +#define COAP_MESSAGE_NON 1 /* non-confirmable message (one-shot message) */ +#define COAP_MESSAGE_ACK 2 /* used to acknowledge confirmable messages */ +#define COAP_MESSAGE_RST 3 /* indicates error in received messages */ + +/* CoAP request methods */ + +#define COAP_REQUEST_GET 1 +#define COAP_REQUEST_POST 2 +#define COAP_REQUEST_PUT 3 +#define COAP_REQUEST_DELETE 4 + +/* CoAP option types (be sure to update check_critical when adding options */ + +#define COAP_OPTION_IF_MATCH 1 /* C, opaque, 0-8 B, (none) */ +#define COAP_OPTION_URI_HOST 3 /* C, String, 1-255 B, destination address */ +#define COAP_OPTION_ETAG 4 /* E, opaque, 1-8 B, (none) */ +#define COAP_OPTION_IF_NONE_MATCH 5 /* empty, 0 B, (none) */ +#define COAP_OPTION_URI_PORT 7 /* C, uint, 0-2 B, destination port */ +#define COAP_OPTION_LOCATION_PATH 8 /* E, String, 0-255 B, - */ +#define COAP_OPTION_URI_PATH 11 /* C, String, 0-255 B, (none) */ +#define COAP_OPTION_CONTENT_FORMAT 12 /* E, uint, 0-2 B, (none) */ +#define COAP_OPTION_CONTENT_TYPE COAP_OPTION_CONTENT_FORMAT +#define COAP_OPTION_MAXAGE 14 /* E, uint, 0--4 B, 60 Seconds */ +#define COAP_OPTION_URI_QUERY 15 /* C, String, 1-255 B, (none) */ +#define COAP_OPTION_ACCEPT 17 /* C, uint, 0-2 B, (none) */ +#define COAP_OPTION_LOCATION_QUERY 20 /* E, String, 0-255 B, (none) */ +#define COAP_OPTION_PROXY_URI 35 /* C, String, 1-1034 B, (none) */ +#define COAP_OPTION_PROXY_SCHEME 39 /* C, String, 1-255 B, (none) */ +#define COAP_OPTION_SIZE2 28 /* E, uint, 0-4 B, (none) */ +#define COAP_OPTION_SIZE1 60 /* E, uint, 0-4 B, (none) */ + +/* option types from draft-ietf-coap-observe-09 */ + +#define COAP_OPTION_OBSERVE 6 /* E, empty/uint, 0 B/0-3 B, (none) */ +#define COAP_OPTION_SUBSCRIPTION COAP_OPTION_OBSERVE + +/* selected option types from draft-core-block-04 */ + +#define COAP_OPTION_BLOCK2 23 /* C, uint, 0--3 B, (none) */ +#define COAP_OPTION_BLOCK1 27 /* C, uint, 0--3 B, (none) */ + +#define COAP_VENDOR_OPT_START (2048) +/**< the highest option number we know + * COAP_MAX_OPT has to be larger than COAP_VENDOR_OPT_START + * however, we should keep in mind that COAP_MAX_OPT + * impacts the size of option filter as its size is about + * ceil(COAP_MAX_OPT>>3) + * Default is 3000 (just a nice round number) + */ +#define COAP_MAX_OPT (3000) + +/* CoAP result codes (HTTP-Code / 100 * 40 + HTTP-Code % 100) */ + +/* As of draft-ietf-core-coap-04, response codes are encoded to base + * 32, i.e. the three upper bits determine the response class while + * the remaining five fine-grained information specific to that class. + */ +#define COAP_RESPONSE_CODE(N) (((N)/100 << 5) | (N)%100) + +/* Determines the class of response code C */ +#define COAP_RESPONSE_CLASS(C) (((C) >> 5) & 0xFF) + +#ifndef SHORT_ERROR_RESPONSE +/** + * Returns a human-readable response phrase for the specified CoAP + * response @p code. This function returns @c NULL if not found. + * + * @param code The response code for which the literal phrase should + * be retrieved. + * + * @return A zero-terminated string describing the error, or @c NULL + * if not found. + */ +const char *coap_response_phrase(unsigned char code); + +#define COAP_ERROR_PHRASE_LENGTH 32 /**< maximum length of error phrase */ + +#else +#define coap_response_phrase(x) ((char *)NULL) + +#define COAP_ERROR_PHRASE_LENGTH 0 /**< maximum length of error phrase */ +#endif /* SHORT_ERROR_RESPONSE */ + +/* The following definitions exist for backwards compatibility */ +#if 0 /* this does not exist any more */ +#define COAP_RESPONSE_100 40 /* 100 Continue */ +#endif +#define COAP_RESPONSE_200 COAP_RESPONSE_CODE(200) /* 2.00 OK */ +#define COAP_RESPONSE_201 COAP_RESPONSE_CODE(201) /* 2.01 Created */ +#define COAP_RESPONSE_202 COAP_RESPONSE_CODE(202) /* 2.02 Deleted */ +#define COAP_RESPONSE_304 COAP_RESPONSE_CODE(203) /* 2.03 Valid */ +#define COAP_RESPONSE_400 COAP_RESPONSE_CODE(400) /* 4.00 Bad Request */ +#define COAP_RESPONSE_403 COAP_RESPONSE_CODE(403) /* 4.03 Forbidden */ +#define COAP_RESPONSE_404 COAP_RESPONSE_CODE(404) /* 4.04 Not Found */ +#define COAP_RESPONSE_405 COAP_RESPONSE_CODE(405) /* 4.05 Method Not Allowed */ +#define COAP_RESPONSE_415 COAP_RESPONSE_CODE(415) /* 4.15 Unsupported Media Type */ +#define COAP_RESPONSE_500 COAP_RESPONSE_CODE(500) /* 5.00 Internal Server Error */ +#define COAP_RESPONSE_501 COAP_RESPONSE_CODE(501) /* 5.01 Not Implemented */ +#define COAP_RESPONSE_503 COAP_RESPONSE_CODE(503) /* 5.03 Service Unavailable */ +#define COAP_RESPONSE_504 COAP_RESPONSE_CODE(504) /* 5.04 Gateway Timeout */ +#if 0 /* these response codes do not have a valid code any more */ +# define COAP_RESPONSE_X_240 240 /* Token Option required by server */ +# define COAP_RESPONSE_X_241 241 /* Uri-Authority Option required by server */ +#endif +#define COAP_RESPONSE_X_242 COAP_RESPONSE_CODE(402) /* Critical Option not supported */ + +/* CoAP media type encoding */ + +#define COAP_MEDIATYPE_TEXT_PLAIN 0 /* text/plain (UTF-8) */ +#define COAP_MEDIATYPE_APPLICATION_LINK_FORMAT 40 /* application/link-format */ +#define COAP_MEDIATYPE_APPLICATION_XML 41 /* application/xml */ +#define COAP_MEDIATYPE_APPLICATION_OCTET_STREAM 42 /* application/octet-stream */ +#define COAP_MEDIATYPE_APPLICATION_RDF_XML 43 /* application/rdf+xml */ +#define COAP_MEDIATYPE_APPLICATION_EXI 47 /* application/exi */ +#define COAP_MEDIATYPE_APPLICATION_JSON 50 /* application/json */ + +/* Note that identifiers for registered media types are in the range 0-65535. We + * use an unallocated type here and hope for the best. */ +#define COAP_MEDIATYPE_ANY 0xff /* any media type */ + +/* CoAP transaction id */ +/*typedef unsigned short coap_tid_t; */ +typedef int coap_tid_t; +#define COAP_INVALID_TID -1 + +#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-pedantic" +#endif +#ifdef WORDS_BIGENDIAN +typedef struct { + unsigned int version:2; /* protocol version */ + unsigned int type:2; /* type flag */ + unsigned int token_length:4; /* length of Token */ + unsigned int code:8; /* request method (value 1--10) or response code (value 40-255) */ + unsigned short id; /* message id */ + __extension__ unsigned char token[0]; /* the actual token, if any */ +} coap_hdr_t; +#else +typedef struct { + unsigned int token_length:4; /* length of Token */ + unsigned int type:2; /* type flag */ + unsigned int version:2; /* protocol version */ + unsigned int code:8; /* request method (value 1--10) or response code (value 40-255) */ + unsigned short id; /* transaction id (network byte order!) */ + __extension__ unsigned char token[0]; /* the actual token, if any */ +} coap_hdr_t; +#endif +#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) +#pragma GCC diagnostic pop +#endif + +#define COAP_MESSAGE_IS_EMPTY(MSG) ((MSG)->code == 0) +#define COAP_MESSAGE_IS_REQUEST(MSG) (!COAP_MESSAGE_IS_EMPTY(MSG) \ + && ((MSG)->code < 32)) +#define COAP_MESSAGE_IS_RESPONSE(MSG) ((MSG)->code >= 64 && (MSG)->code <= 191) + +#define COAP_OPT_LONG 0x0F /* OC == 0b1111 indicates that the option list in a + * CoAP message is limited by 0b11110000 marker */ + +#define COAP_OPT_END 0xF0 /* end marker */ + +#define COAP_PAYLOAD_START 0xFF /* payload marker */ + +/** + * Structures for more convenient handling of options. (To be used with ordered + * coap_list_t.) The option's data will be added to the end of the coap_option + * structure (see macro COAP_OPTION_DATA). + */ +typedef struct { + unsigned short key; /* the option key (no delta coding) */ + unsigned int length; +} coap_option; + +#define COAP_OPTION_KEY(option) (option).key +#define COAP_OPTION_LENGTH(option) (option).length +#define COAP_OPTION_DATA(option) ((unsigned char *)&(option) + sizeof(coap_option)) + +/** Header structure for CoAP PDUs */ + +typedef struct { + size_t max_size; /**< allocated storage for options and data */ + + coap_hdr_t *hdr; + unsigned short max_delta; /**< highest option number */ + unsigned short length; /**< PDU length (including header, options, data) */ + unsigned char *data; /**< payload */ + +#ifdef WITH_LWIP + struct pbuf *pbuf; /**< lwIP PBUF. The allocated coap_pdu_t will always reside inside the pbuf's payload, but the pointer has to be kept because no exact offset can be given. This field must not be accessed from outside, because the pbuf's reference count is checked to be 1 when the pbuf is assigned to the pdu, and the pbuf stays exclusive to this pdu. */ +#endif + +} coap_pdu_t; + +/** Options in coap_pdu_t are accessed with the macro COAP_OPTION. */ +#define COAP_OPTION(node) ((coap_option *)(node)->options) + +#ifdef WITH_LWIP +/** + * Creates a CoAP PDU from an lwIP @p pbuf, whose reference is passed on to + * this function. + * + * The pbuf is checked for being contiguous, for having enough head space for + * the PDU struct (which is located directly in front of the data, overwriting + * the old other headers), and for having only one reference. The reference is + * stored in the PDU and will be freed when the PDU is freed. + * + * (For now, these are errors; in future, a new pbuf might be allocated, the + * data copied and the passed pbuf freed). + * + * This behaves like coap_pdu_init(0, 0, 0, pbuf->tot_len), and afterwards + * copying the contents of the pbuf to the pdu. + * + * @return A pointer to the new PDU object or @c NULL on error. + */ +coap_pdu_t * coap_pdu_from_pbuf(struct pbuf *pbuf); +#endif + +/** + * Creates a new CoAP PDU of given @p size (must be large enough to hold the + * basic CoAP message header (coap_hdr_t). The function returns a pointer to + * the node coap_pdu_t object on success, or @c NULL on error. The storage + * allocated for the result must be released with coap_delete_pdu(). + * + * @param type The type of the PDU (one of COAP_MESSAGE_CON, + * COAP_MESSAGE_NON, COAP_MESSAGE_ACK, COAP_MESSAGE_RST). + * @param code The message code. + * @param id The message id to set or COAP_INVALID_TID if unknown. + * @param size The number of bytes to allocate for the actual message. + * + * @return A pointer to the new PDU object or @c NULL on error. + */ +coap_pdu_t * +coap_pdu_init(unsigned char type, unsigned char code, + unsigned short id, size_t size); + +/** + * Clears any contents from @p pdu and resets @c version field, @c + * length and @c data pointers. @c max_size is set to @p size, any + * other field is set to @c 0. Note that @p pdu must be a valid + * pointer to a coap_pdu_t object created e.g. by coap_pdu_init(). + */ +void coap_pdu_clear(coap_pdu_t *pdu, size_t size); + +/** + * Creates a new CoAP PDU. The object is created on the heap and must be released + * using coap_delete_pdu(); + * + * @deprecated This function allocates the maximum storage for each + * PDU. Use coap_pdu_init() instead. + */ +coap_pdu_t *coap_new_pdu(); + +void coap_delete_pdu(coap_pdu_t *); + +/** + * Parses @p data into the CoAP PDU structure given in @p result. This + * function returns @c 0 on error or a number greater than zero on + * success. + * + * @param data The raw data to parse as CoAP PDU + * @param length The actual size of @p data + * @param result The PDU structure to fill. Note that the structure must + * provide space for at least @p length bytes to hold the + * entire CoAP PDU. + * @return A value greater than zero on success or @c 0 on error. + */ +int coap_pdu_parse(unsigned char *data, size_t length, coap_pdu_t *result); + +/** + * Adds token of length @p len to @p pdu. Adding the token destroys + * any following contents of the pdu. Hence options and data must be + * added after coap_add_token() has been called. In @p pdu, length is + * set to @p len + @c 4, and max_delta is set to @c 0. This funtion + * returns @c 0 on error or a value greater than zero on success. + * + * @param pdu The PDU where the token is to be added. + * @param len The length of the new token. + * @param data The token to add. + * @return A value greater than zero on success, or @c 0 on error. + */ +int coap_add_token(coap_pdu_t *pdu, size_t len, const unsigned char *data); + +/** + * Adds option of given type to pdu that is passed as first + * parameter. coap_add_option() destroys the PDU's data, so + * coap_add_data() must be called after all options have been added. + * As coap_add_token() destroys the options following the token, + * the token must be added before coap_add_option() is called. + * This function returns the number of bytes written or @c 0 on error. + */ +size_t coap_add_option(coap_pdu_t *pdu, unsigned short type, + unsigned int len, const unsigned char *data); + +/** + * Adds option of given type to pdu that is passed as first + * parameter, but does not write a value. It works like coap_add_option with + * respect to calling sequence (i.e. after token and before data). + * This function returns a memory address to which the option data has to be + * written before the PDU can be sent, or @c NULL on error. + */ +unsigned char *coap_add_option_later(coap_pdu_t *pdu, unsigned short type, + unsigned int len); + +/** + * Adds given data to the pdu that is passed as first parameter. Note + * that the PDU's data is destroyed by coap_add_option(). coap_add_data() + * must be called only once per PDU, otherwise the result is undefined. + */ +int coap_add_data(coap_pdu_t *pdu, unsigned int len, const unsigned char *data); + +/** + * Retrieves the length and data pointer of specified PDU. Returns 0 on error + * or 1 if *len and *data have correct values. Note that these values are + * destroyed with the pdu. + */ +int coap_get_data(coap_pdu_t *pdu, size_t *len, unsigned char **data); + +#ifdef __cplusplus +} +#endif + +#endif /* _PDU_H_ */ diff --git a/resource/csdk/libcoap-4.1.1/prng.h b/resource/csdk/libcoap-4.1.1/prng.h new file mode 100644 index 000000000..50479c951 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/prng.h @@ -0,0 +1,89 @@ +/* prng.h -- Pseudo Random Numbers + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file prng.h + * @brief Pseudo Random Numbers + */ + +#ifndef _COAP_PRNG_H_ +#define _COAP_PRNG_H_ + +#include "config.h" +#include + +/** + * @defgroup prng Pseudo Random Numbers + * @{ + */ + +#ifndef WITH_CONTIKI +#include + +/** + * Fills \p buf with \p len random bytes. This is the default + * implementation for prng(). You might want to change prng() to use + * a better PRNG on your specific platform. + */ +static inline int +coap_prng_impl(unsigned char *buf, size_t len) { +#if 0 + while (len--) + *buf++ = rand() & 0xFF; +#endif + OCFillRandomMem(buf, len); + return 1; +} +#else /* WITH_CONTIKI */ +#include + +/** + * Fills \p buf with \p len random bytes. This is the default + * implementation for prng(). You might want to change prng() to use + * a better PRNG on your specific platform. + */ +static inline int +contiki_prng_impl(unsigned char *buf, size_t len) { + unsigned short v = random_rand(); + while (len > sizeof(v)) { + memcpy(buf, &v, sizeof(v)); + len -= sizeof(v); + buf += sizeof(v); + v = random_rand(); + } + + memcpy(buf, &v, len); + return 1; +} + +#define prng(Buf,Length) contiki_prng_impl((Buf), (Length)) +#define prng_init(Value) random_init((unsigned short)(Value)) +#endif /* WITH_CONTIKI */ + +#ifndef prng +/** + * Fills \p Buf with \p Length bytes of random data. + * + * @hideinitializer + */ +#define prng(Buf,Length) coap_prng_impl((Buf), (Length)) +#endif + +#ifndef prng_init +/** + * Called to set the PRNG seed. You may want to re-define this to + * allow for a better PRNG. + * + * @hideinitializer + */ +#define prng_init(Value) OCSeedRandom()//srand((unsigned long)(Value)) +#endif + +/** @} */ + +#endif /* _COAP_PRNG_H_ */ diff --git a/resource/csdk/libcoap-4.1.1/resource.c b/resource/csdk/libcoap-4.1.1/resource.c new file mode 100644 index 000000000..f723274b1 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/resource.c @@ -0,0 +1,869 @@ +/* resource.c -- generic resource handling + * + * Copyright (C) 2010--2014 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "config.h" +#include "net.h" +#include "debug.h" +#include "resource.h" +#include "subscribe.h" + +#ifdef WITH_LWIP +#include "utlist.h" +/* mem.h is only needed for the string free calls for + * COAP_ATTR_FLAGS_RELEASE_NAME / COAP_ATTR_FLAGS_RELEASE_VALUE / + * COAP_RESOURCE_FLAGS_RELEASE_URI. not sure what those lines should actually + * do on lwip. */ +#include "mem.h" + +#include + +#define COAP_MALLOC_TYPE(Type) \ + ((coap_##Type##_t *)memp_malloc(MEMP_COAP_##Type)) +#define COAP_FREE_TYPE(Type, Object) memp_free(MEMP_COAP_##Type, Object) + +#endif +#if defined(WITH_POSIX) || defined(WITH_ARDUINO) +#include "utlist.h" +#include "mem.h" + +#define COAP_MALLOC_TYPE(Type) \ + ((coap_##Type##_t *)coap_malloc(sizeof(coap_##Type##_t))) +#define COAP_FREE_TYPE(Type, Object) coap_free(Object) + +#endif /* WITH_POSIX || WITH_ARDUINO */ +#ifdef WITH_CONTIKI +#include "memb.h" + +MEMB(resource_storage, coap_resource_t, COAP_MAX_RESOURCES); +MEMB(attribute_storage, coap_attr_t, COAP_MAX_ATTRIBUTES); +MEMB(subscription_storage, coap_subscription_t, COAP_MAX_SUBSCRIBERS); + +void +coap_resources_init() { + memb_init(&resource_storage); + memb_init(&attribute_storage); + memb_init(&subscription_storage); +} + +static inline coap_subscription_t * +coap_malloc_subscription() { + return memb_alloc(&subscription_storage); +} + +static inline void +coap_free_subscription(coap_subscription_t *subscription) { + memb_free(&subscription_storage, subscription); +} +#endif /* WITH_CONTIKI */ + +#define min(a,b) ((a) < (b) ? (a) : (b)) + +/* Helper functions for conditional output of character sequences into + * a given buffer. The first Offset characters are skipped. + */ + +/** + * Adds Char to Buf if Offset is zero. Otherwise, Char is not written + * and Offset is decremented. + */ +#define PRINT_WITH_OFFSET(Buf,Offset,Char) \ + if ((Offset) == 0) { \ + (*(Buf)++) = (Char); \ + } else { \ + (Offset)--; \ + } \ + +/** + * Adds Char to Buf if Offset is zero and Buf is less than Bufend. + */ +#define PRINT_COND_WITH_OFFSET(Buf,Bufend,Offset,Char,Result) { \ + if ((Buf) < (Bufend)) { \ + PRINT_WITH_OFFSET(Buf,Offset,Char); \ + } \ + (Result)++; \ + } + +/** + * Copies at most Length characters of Str to Buf. The first Offset + * characters are skipped. Output may be truncated to Bufend - Buf + * characters. + */ +#define COPY_COND_WITH_OFFSET(Buf,Bufend,Offset,Str,Length,Result) { \ + size_t i; \ + for (i = 0; i < (Length); i++) { \ + PRINT_COND_WITH_OFFSET((Buf), (Bufend), (Offset), (Str)[i], (Result)); \ + } \ + } + +int +match(const str *text, const str *pattern, int match_prefix, int match_substring) { + assert(text); assert(pattern); + + if (text->length < pattern->length) + return 0; + + if (match_substring) { + unsigned char *next_token = text->s; + size_t remaining_length = text->length; + while (remaining_length) { + size_t token_length; + unsigned char *token = next_token; + next_token = (unsigned char *)memchr(token, ' ', remaining_length); + + if (next_token) { + token_length = next_token - token; + remaining_length -= (token_length + 1); + next_token++; + } else { + token_length = remaining_length; + remaining_length = 0; + } + + if ((match_prefix || pattern->length == token_length) && + memcmp(token, pattern->s, pattern->length) == 0) + return 1; + } + return 0; + } + + return (match_prefix || pattern->length == text->length) && + memcmp(text->s, pattern->s, pattern->length) == 0; +} + +/** + * Prints the names of all known resources to @p buf. This function + * sets @p buflen to the number of bytes actually written and returns + * @c 1 on succes. On error, the value in @p buflen is undefined and + * the return value will be @c 0. + * + * @param context The context with the resource map. + * @param buf The buffer to write the result. + * @param buflen Must be initialized to the maximum length of @p buf and will be + * set to the length of the well-known response on return. + * @param offset The offset in bytes where the output shall start and is + * shifted accordingly with the characters that have been + * processed. This parameter is used to support the block + * option. + * @param query_filter A filter query according to Link Format + * + * @return COAP_PRINT_STATUS_ERROR on error. Otherwise, the lower 28 bits are + * set to the number of bytes that have actually been written to + * @p buf. COAP_PRINT_STATUS_TRUNC is set when the output has been + * truncated. + */ +#if defined(__GNUC__) && defined(WITHOUT_QUERY_FILTER) +coap_print_status_t +print_wellknown(coap_context_t *context, unsigned char *buf, size_t *buflen, + size_t offset, + coap_opt_t *query_filter __attribute__ ((unused))) { +#else /* not a GCC */ +coap_print_status_t +print_wellknown(coap_context_t *context, unsigned char *buf, size_t *buflen, + size_t offset, coap_opt_t *query_filter) { +#endif /* GCC */ + coap_resource_t *r; + unsigned char *p = buf; + const unsigned char *bufend = buf + *buflen; + size_t left, written = 0; + coap_print_status_t result; + const size_t old_offset = offset; + int subsequent_resource = 0; +#ifndef COAP_RESOURCES_NOHASH + coap_resource_t *tmp; +#endif +#ifndef WITHOUT_QUERY_FILTER + str resource_param = { 0, NULL }, query_pattern = { 0, NULL }; + int flags = 0; /* MATCH_SUBSTRING, MATCH_PREFIX, MATCH_URI */ +#define MATCH_URI 0x01 +#define MATCH_PREFIX 0x02 +#define MATCH_SUBSTRING 0x04 + static const str _rt_attributes[] = { + {2, (unsigned char *)"rt"}, + {2, (unsigned char *)"if"}, + {3, (unsigned char *)"rel"}, + {0, NULL}}; +#endif /* WITHOUT_QUERY_FILTER */ + +#ifdef WITH_CONTIKI + int i; +#endif /* WITH_CONTIKI */ + +#ifndef WITHOUT_QUERY_FILTER + /* split query filter, if any */ + if (query_filter) { + resource_param.s = COAP_OPT_VALUE(query_filter); + while (resource_param.length < COAP_OPT_LENGTH(query_filter) + && resource_param.s[resource_param.length] != '=') + resource_param.length++; + + if (resource_param.length < COAP_OPT_LENGTH(query_filter)) { + const str *rt_attributes; + if (resource_param.length == 4 && + memcmp(resource_param.s, "href", 4) == 0) + flags |= MATCH_URI; + + for (rt_attributes = _rt_attributes; rt_attributes->s; rt_attributes++) { + if (resource_param.length == rt_attributes->length && + memcmp(resource_param.s, rt_attributes->s, rt_attributes->length) == 0) { + flags |= MATCH_SUBSTRING; + break; + } + } + + /* rest is query-pattern */ + query_pattern.s = + COAP_OPT_VALUE(query_filter) + resource_param.length + 1; + + assert((resource_param.length + 1) <= COAP_OPT_LENGTH(query_filter)); + query_pattern.length = + COAP_OPT_LENGTH(query_filter) - (resource_param.length + 1); + + if ((query_pattern.s[0] == '/') && ((flags & MATCH_URI) == MATCH_URI)) { + query_pattern.s++; + query_pattern.length--; + } + + if (query_pattern.length && + query_pattern.s[query_pattern.length-1] == '*') { + query_pattern.length--; + flags |= MATCH_PREFIX; + } + } + } +#endif /* WITHOUT_QUERY_FILTER */ + +#ifndef WITH_CONTIKI + +#ifdef COAP_RESOURCES_NOHASH + LL_FOREACH(context->resources, r) { +#else + HASH_ITER(hh, context->resources, r, tmp) { +#endif +#else /* WITH_CONTIKI */ + r = (coap_resource_t *)resource_storage.mem; + for (i = 0; i < resource_storage.num; ++i, ++r) { + if (!resource_storage.count[i]) + continue; +#endif /* WITH_CONTIKI */ + +#ifndef WITHOUT_QUERY_FILTER + if (resource_param.length) { /* there is a query filter */ + + if (flags & MATCH_URI) { /* match resource URI */ + if (!match(&r->uri, &query_pattern, (flags & MATCH_PREFIX) != 0, (flags & MATCH_SUBSTRING) != 0)) + continue; + } else { /* match attribute */ + coap_attr_t *attr; + str unquoted_val; + attr = coap_find_attr(r, resource_param.s, resource_param.length); + if (!attr) continue; + if (attr->value.s[0] == '"') { /* if attribute has a quoted value, remove double quotes */ + unquoted_val.length = attr->value.length - 2; + unquoted_val.s = attr->value.s + 1; + } else { + unquoted_val = attr->value; + } + if (!(match(&unquoted_val, &query_pattern, + (flags & MATCH_PREFIX) != 0, + (flags & MATCH_SUBSTRING) != 0))) + continue; + } + } +#endif /* WITHOUT_QUERY_FILTER */ + + if (!subsequent_resource) { /* this is the first resource */ + subsequent_resource = 1; + } else { + PRINT_COND_WITH_OFFSET(p, bufend, offset, ',', written); + } + + left = bufend - p; /* calculate available space */ + result = coap_print_link(r, p, &left, &offset); + + if (result & COAP_PRINT_STATUS_ERROR) { + break; + } + + /* coap_print_link() returns the number of characters that + * where actually written to p. Now advance to its end. */ + p += COAP_PRINT_OUTPUT_LENGTH(result); + written += left; + } + + *buflen = written; + result = p - buf; + if (result + old_offset - offset < *buflen) { + result |= COAP_PRINT_STATUS_TRUNC; + } + return result; +} + +coap_resource_t * +coap_resource_init(const unsigned char *uri, size_t len, int flags) { + coap_resource_t *r; + +#if defined(WITH_POSIX) || defined(WITH_ARDUINO) + r = (coap_resource_t *)coap_malloc(sizeof(coap_resource_t)); +#endif +#ifdef WITH_LWIP + r = (coap_resource_t *)memp_malloc(MEMP_COAP_RESOURCE); +#endif +#ifdef WITH_CONTIKI + r = (coap_resource_t *)memb_alloc(&resource_storage); +#endif + if (r) { + memset(r, 0, sizeof(coap_resource_t)); + +#ifdef WITH_CONTIKI + LIST_STRUCT_INIT(r, link_attr); +#endif /* WITH_CONTIKI */ + LIST_STRUCT_INIT(r, subscribers); + + r->uri.s = (unsigned char *)uri; + r->uri.length = len; + + coap_hash_path(r->uri.s, r->uri.length, r->key); + + r->flags = flags; + } else { + debug("coap_resource_init: no memory left\n"); + } + + return r; +} + +coap_attr_t * +coap_add_attr(coap_resource_t *resource, + const unsigned char *name, size_t nlen, + const unsigned char *val, size_t vlen, + int flags) { + coap_attr_t *attr; + + if (!resource || !name) + return NULL; + +#if defined(WITH_POSIX) || defined(WITH_ARDUINO) + attr = (coap_attr_t *)coap_malloc(sizeof(coap_attr_t)); +#endif +#ifdef WITH_LWIP + attr = (coap_attr_t *)memp_malloc(MEMP_COAP_RESOURCEATTR); +#endif +#ifdef WITH_CONTIKI + attr = (coap_attr_t *)memb_alloc(&attribute_storage); +#endif + + if (attr) { + attr->name.length = nlen; + attr->value.length = val ? vlen : 0; + + attr->name.s = (unsigned char *)name; + attr->value.s = (unsigned char *)val; + + attr->flags = flags; + + /* add attribute to resource list */ +#ifndef WITH_CONTIKI + LL_PREPEND(resource->link_attr, attr); +#else /* WITH_CONTIKI */ + list_add(resource->link_attr, attr); +#endif /* WITH_CONTIKI */ + } else { + debug("coap_add_attr: no memory left\n"); + } + + return attr; +} + +coap_attr_t * +coap_find_attr(coap_resource_t *resource, + const unsigned char *name, size_t nlen) { + coap_attr_t *attr; + + if (!resource || !name) + return NULL; + +#ifndef WITH_CONTIKI + LL_FOREACH(resource->link_attr, attr) { +#else /* WITH_CONTIKI */ + for (attr = list_head(resource->link_attr); attr; + attr = list_item_next(attr)) { +#endif /* WITH_CONTIKI */ + if (attr->name.length == nlen && + memcmp(attr->name.s, name, nlen) == 0) + return attr; + } + + return NULL; +} + +void +coap_delete_attr(coap_attr_t *attr) { + if (!attr) + return; + if (attr->flags & COAP_ATTR_FLAGS_RELEASE_NAME) + coap_free(attr->name.s); + if (attr->flags & COAP_ATTR_FLAGS_RELEASE_VALUE) + coap_free(attr->value.s); +#ifdef POSIX + coap_free(attr); +#endif +#ifdef WITH_LWIP + memp_free(MEMP_COAP_RESOURCEATTR, attr); +#endif +#ifdef WITH_CONTIKI + /* FIXME it looks like this was never implemented */ +#endif +} + +void +coap_hash_request_uri(const coap_pdu_t *request, coap_key_t key) { + coap_opt_iterator_t opt_iter; + coap_opt_filter_t filter; + coap_opt_t *option; + + memset(key, 0, sizeof(coap_key_t)); + + coap_option_filter_clear(filter); + coap_option_setb(filter, COAP_OPTION_URI_PATH); + + coap_option_iterator_init((coap_pdu_t *)request, &opt_iter, filter); + while ((option = coap_option_next(&opt_iter))) + coap_hash(COAP_OPT_VALUE(option), COAP_OPT_LENGTH(option), key); +} + +void +coap_add_resource(coap_context_t *context, coap_resource_t *resource) { +#ifndef WITH_CONTIKI +#ifdef COAP_RESOURCES_NOHASH + LL_PREPEND(context->resources, resource); +#else + HASH_ADD(hh, context->resources, key, sizeof(coap_key_t), resource); +#endif +#endif /* WITH_CONTIKI */ +} + +int +coap_delete_resource(coap_context_t *context, coap_key_t key) { + coap_resource_t *resource; + coap_attr_t *attr, *tmp; +#ifdef WITH_CONTIKI + coap_subscription_t *obs; +#endif + + if (!context) + return 0; + + resource = coap_get_resource_from_key(context, key); + + if (!resource) + return 0; + +#if defined(WITH_POSIX) || defined(WITH_LWIP) || defined(WITH_ARDUINO) +#ifdef COAP_RESOURCES_NOHASH + LL_DELETE(context->resources, resource); +#else + HASH_DELETE(hh, context->resources, resource); +#endif + + /* delete registered attributes */ + LL_FOREACH_SAFE(resource->link_attr, attr, tmp) coap_delete_attr(attr); + + if (resource->flags & COAP_RESOURCE_FLAGS_RELEASE_URI) + coap_free(resource->uri.s); + +#if defined(WITH_POSIX) || defined(WITH_ARDUINO) + coap_free(resource); +#endif +#ifdef WITH_LWIP + memp_free(MEMP_COAP_RESOURCE, resource); +#endif +#else /* not (WITH_POSIX || WITH_LWIP || WITH_ARDUINO) */ + /* delete registered attributes */ + while ( (attr = list_pop(resource->link_attr)) ) + memb_free(&attribute_storage, attr); + + /* delete subscribers */ + while ( (obs = list_pop(resource->subscribers)) ) { + /* FIXME: notify observer that its subscription has been removed */ + memb_free(&subscription_storage, obs); + } + + memb_free(&resource_storage, resource); +#endif /* WITH_CONTIKI */ + + return 1; +} + +coap_resource_t * +coap_get_resource_from_key(coap_context_t *context, coap_key_t key) { +#ifndef WITH_CONTIKI + coap_resource_t *resource; +#ifdef COAP_RESOURCES_NOHASH + resource = NULL; + LL_FOREACH(context->resources, resource) { + /* if you think you can outspart the compiler and speed things up by (eg by + * casting to uint32* and comparing alues), increment this counter: 1 */ + if (memcmp(key, resource->key, sizeof(coap_key_t)) == 0) + return resource; + } + return NULL; +#else + HASH_FIND(hh, context->resources, key, sizeof(coap_key_t), resource); + + return resource; +#endif +#else /* WITH_CONTIKI */ + int i; + coap_resource_t *ptr2; + + /* the search function is basically taken from memb.c */ + ptr2 = (coap_resource_t *)resource_storage.mem; + for (i = 0; i < resource_storage.num; ++i) { + if (resource_storage.count[i] && + (memcmp(ptr2->key, key, sizeof(coap_key_t)) == 0)) + return (coap_resource_t *)ptr2; + ++ptr2; + } + + return NULL; +#endif /* WITH_CONTIKI */ +} + +coap_print_status_t +coap_print_link(const coap_resource_t *resource, + unsigned char *buf, size_t *len, size_t *offset) { + unsigned char *p = buf; + const unsigned char *bufend = buf + *len; + coap_attr_t *attr; + coap_print_status_t result = 0; + const size_t old_offset = *offset; + + *len = 0; + PRINT_COND_WITH_OFFSET(p, bufend, *offset, '<', *len); + PRINT_COND_WITH_OFFSET(p, bufend, *offset, '/', *len); + + COPY_COND_WITH_OFFSET(p, bufend, *offset, + resource->uri.s, resource->uri.length, *len); + + PRINT_COND_WITH_OFFSET(p, bufend, *offset, '>', *len); + +#ifndef WITH_CONTIKI + LL_FOREACH(resource->link_attr, attr) { +#else /* WITH_CONTIKI */ + for (attr = list_head(resource->link_attr); attr; + attr = list_item_next(attr)) { +#endif /* WITH_CONTIKI */ + + PRINT_COND_WITH_OFFSET(p, bufend, *offset, ';', *len); + + COPY_COND_WITH_OFFSET(p, bufend, *offset, + attr->name.s, attr->name.length, *len); + + if (attr->value.s) { + PRINT_COND_WITH_OFFSET(p, bufend, *offset, '=', *len); + + COPY_COND_WITH_OFFSET(p, bufend, *offset, + attr->value.s, attr->value.length, *len); + } + + } + if (resource->observable) { + COPY_COND_WITH_OFFSET(p, bufend, *offset, ";obs", 4, *len); + } + + result = p - buf; + if (result + old_offset - *offset < *len) { + result |= COAP_PRINT_STATUS_TRUNC; + } + + return result; +} + +#ifndef WITHOUT_OBSERVE +coap_subscription_t * +coap_find_observer(coap_resource_t *resource, const coap_address_t *peer, + const str *token) { + coap_subscription_t *s; + + assert(resource); + assert(peer); + + for (s = (coap_subscription_t*)list_head(resource->subscribers); s; + s = (coap_subscription_t*)list_item_next(s)) { + if (coap_address_equals(&s->subscriber, peer) + && (!token || (token->length == s->token_length + && memcmp(token->s, s->token, token->length) == 0))) + return s; + } + + return NULL; +} + +coap_subscription_t * +coap_add_observer(coap_resource_t *resource, + const coap_address_t *observer, + const str *token) { + coap_subscription_t *s; + + assert(observer); + + /* Check if there is already a subscription for this peer. */ + s = coap_find_observer(resource, observer, token); + + /* We are done if subscription was found. */ + if (s) + return s; + + /* s points to a different subscription, so we have to create + * another one. */ + s = COAP_MALLOC_TYPE(subscription); + + if (!s) + return NULL; + + coap_subscription_init(s); + memcpy(&s->subscriber, observer, sizeof(coap_address_t)); + + if (token && token->length) { + s->token_length = token->length; + memcpy(s->token, token->s, min(s->token_length, 8)); + } + + /* add subscriber to resource */ + list_add(resource->subscribers, s); + + return s; +} + +void +coap_touch_observer(coap_context_t *context, const coap_address_t *observer, + const str *token) { + coap_resource_t *r; + coap_subscription_t *s; + +#ifndef WITH_CONTIKI +#ifdef COAP_RESOURCES_NOHASH + LL_FOREACH(context->resources, r) { +#else + coap_resource_t *tmp; + HASH_ITER(hh, context->resources, r, tmp) { +#endif + s = coap_find_observer(r, observer, token); + if (s) { + s->fail_cnt = 0; + } + } +#else /* WITH_CONTIKI */ + r = (coap_resource_t *)resource_storage.mem; + for (i = 0; i < resource_storage.num; ++i, ++r) { + if (resource_storage.count[i]) { + s = coap_find_observer(r, observer, token); + if (s) { + s->fail_cnt = 0; + } + } + } +#endif /* WITH_CONTIKI */ +} + +void +coap_delete_observer(coap_resource_t *resource, const coap_address_t *observer, + const str *token) { + coap_subscription_t *s; + + s = coap_find_observer(resource, observer, token); + + if (s) { + list_remove(resource->subscribers, s); + + COAP_FREE_TYPE(subscription,s); + } +} + +static void +coap_notify_observers(coap_context_t *context, coap_resource_t *r) { + coap_method_handler_t h; + coap_subscription_t *obs; + str token; + coap_pdu_t *response; + + if (r->observable && (r->dirty || r->partiallydirty)) { + r->partiallydirty = 0; + + /* retrieve GET handler, prepare response */ + h = r->handler[COAP_REQUEST_GET - 1]; + assert(h); /* we do not allow subscriptions if no + * GET handler is defined */ + + for (obs = (coap_subscription_t*)list_head(r->subscribers); obs; + obs = (coap_subscription_t*)list_item_next(obs)) { + if (r->dirty == 0 && obs->dirty == 0) + /* running this resource due to partiallydirty, but this observation's notification was already enqueued */ + continue; + + coap_tid_t tid = COAP_INVALID_TID; + obs->dirty = 0; + /* initialize response */ + response = coap_pdu_init(COAP_MESSAGE_CON, 0, 0, COAP_MAX_PDU_SIZE); + if (!response) { + obs->dirty = 1; + r->partiallydirty = 1; + debug("coap_check_notify: pdu init failed, resource stays partially dirty\n"); + continue; + } + + if (!coap_add_token(response, obs->token_length, obs->token)) { + obs->dirty = 1; + r->partiallydirty = 1; + debug("coap_check_notify: cannot add token, resource stays partially dirty\n"); + coap_delete_pdu(response); + continue; + } + + token.length = obs->token_length; + token.s = obs->token; + + response->hdr->id = coap_new_message_id(context); + if (obs->non && obs->non_cnt < COAP_OBS_MAX_NON) { + response->hdr->type = COAP_MESSAGE_NON; + } else { + response->hdr->type = COAP_MESSAGE_CON; + } + /* fill with observer-specific data */ + h(context, r, &obs->subscriber, NULL, &token, response); + + if (response->hdr->type == COAP_MESSAGE_CON) { + tid = coap_send(context, &obs->subscriber, response, SEND_NOW_CON); + obs->non_cnt = 0; + } else { + tid = coap_send(context, &obs->subscriber, response, SEND_NOW); + obs->non_cnt++; + } + + if (COAP_INVALID_TID == tid || response->hdr->type != COAP_MESSAGE_CON) + coap_delete_pdu(response); + if (COAP_INVALID_TID == tid) + { + debug("coap_check_notify: sending failed, resource stays partially dirty\n"); + obs->dirty = 1; + r->partiallydirty = 1; + } + + } + + /* Increment value for next Observe use. */ + context->observe++; + } + r->dirty = 0; +} + +void +coap_check_notify(coap_context_t *context) { + coap_resource_t *r; +#ifndef WITH_CONTIKI + +#ifdef COAP_RESOURCES_NOHASH + LL_FOREACH(context->resources, r) { +#else + coap_resource_t *tmp; + HASH_ITER(hh, context->resources, r, tmp) { +#endif + coap_notify_observers(context, r); + } +#else /* WITH_CONTIKI */ + int i; + + r = (coap_resource_t *)resource_storage.mem; + for (i = 0; i < resource_storage.num; ++i, ++r) { + if (resource_storage.count[i]) { + coap_notify_observers(context, r); + } + } +#endif /* WITH_CONTIKI */ +} + +/** + * Checks the failure counter for (peer, token) and removes peer from + * the list of observers for the given resource when COAP_OBS_MAX_FAIL + * is reached. + * + * @param context The CoAP context to use + * @param resource The resource to check for (peer, token) + * @param peer The observer's address + * @param token The token that has been used for subscription. + */ +static void +coap_remove_failed_observers(coap_context_t *context, + coap_resource_t *resource, + const coap_address_t *peer, + const str *token) { + coap_subscription_t *obs; + + for (obs = (coap_subscription_t*)list_head(resource->subscribers); obs; + obs = (coap_subscription_t*)list_item_next(obs)) { + if (coap_address_equals(peer, &obs->subscriber) && + token->length == obs->token_length && + memcmp(token->s, obs->token, token->length) == 0) { + + /* count failed notifies and remove when + * COAP_MAX_FAILED_NOTIFY is reached */ + if (obs->fail_cnt < COAP_OBS_MAX_FAIL) + obs->fail_cnt++; + else { + list_remove(resource->subscribers, obs); + obs->fail_cnt = 0; + +#ifndef NDEBUG + if (LOG_DEBUG <= coap_get_log_level()) { +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 40 +#endif + unsigned char addr[INET6_ADDRSTRLEN+8]; + + if (coap_print_addr(&obs->subscriber, addr, INET6_ADDRSTRLEN+8)) + debug("** removed observer %s\n", addr); + } +#endif + coap_cancel_all_messages(context, &obs->subscriber, + obs->token, obs->token_length); + + COAP_FREE_TYPE(subscription, obs); + } + } + break; /* break loop if observer was found */ + } +} + +void +coap_handle_failed_notify(coap_context_t *context, + const coap_address_t *peer, + const str *token) { + coap_resource_t *r; + +#ifndef WITH_CONTIKI + +#ifdef COAP_RESOURCES_NOHASH + LL_FOREACH(context->resources, r) { +#else + coap_resource_t *tmp; + HASH_ITER(hh, context->resources, r, tmp) { +#endif + coap_remove_failed_observers(context, r, peer, token); + } +#else /* WITH_CONTIKI */ + int i; + + r = (coap_resource_t *)resource_storage.mem; + for (i = 0; i < resource_storage.num; ++i, ++r) { + if (resource_storage.count[i]) { + coap_remove_failed_observers(context, r, peer, token); + } + } +#endif /* WITH_CONTIKI */ +} +#endif /* WITHOUT_NOTIFY */ diff --git a/resource/csdk/libcoap-4.1.1/resource.h b/resource/csdk/libcoap-4.1.1/resource.h new file mode 100644 index 000000000..ede32f579 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/resource.h @@ -0,0 +1,332 @@ +/* resource.h -- generic resource handling + * + * Copyright (C) 2010,2011,2014 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file resource.h + * @brief generic resource handling + */ + +#ifndef _COAP_RESOURCE_H_ +#define _COAP_RESOURCE_H_ + +#include "config.h" +#include "t_list.h" +#include "async.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(HAVE_ASSERT_H) && !defined(assert) +# include +#endif + +#ifndef COAP_RESOURCE_CHECK_TIME +/** The interval in seconds to check if resources have changed. */ +#define COAP_RESOURCE_CHECK_TIME 2 +#endif /* COAP_RESOURCE_CHECK_TIME */ + +#ifndef WITH_CONTIKI +# ifdef COAP_RESOURCES_NOHASH +# include "utlist.h" +# else +# include "uthash.h" +# endif +#else /* WITH_CONTIKI */ +#endif /* WITH_CONTIKI */ +#include "hashkey.h" +#include "str.h" +#include "pdu.h" +#include "net.h" +#include "subscribe.h" + +/** Definition of message handler function (@sa coap_resource_t). */ +typedef void (*coap_method_handler_t) + (coap_context_t *, struct coap_resource_t *, coap_address_t *, coap_pdu_t *, + str * /* token */, coap_pdu_t * /* response */); + +#define COAP_ATTR_FLAGS_RELEASE_NAME 0x1 +#define COAP_ATTR_FLAGS_RELEASE_VALUE 0x2 + +typedef struct coap_attr_t { + struct coap_attr_t *next; + str name; + str value; + int flags; +} coap_attr_t; + +#define COAP_RESOURCE_FLAGS_RELEASE_URI 0x1 + +typedef struct coap_resource_t { + unsigned int dirty:1; /**< set to 1 if resource has changed */ + unsigned int partiallydirty:1; /**< set to 1 if some subscribers have not yet been notified of the last change */ + unsigned int observable:1; /**< can be observed */ + unsigned int cacheable:1; /**< can be cached */ + + /** + * Used to store handlers for the four coap methods @c GET, @c POST, + * @c PUT, and @c DELETE. coap_dispatch() will pass incoming + * requests to the handler that corresponds to its request method or + * generate a 4.05 response if no handler is available. + */ + coap_method_handler_t handler[4]; + + coap_key_t key; /**< the actual key bytes for this resource */ + +#ifndef WITH_CONTIKI +#ifdef COAP_RESOURCES_NOHASH + struct coap_resource_t *next; +#else + UT_hash_handle hh; +#endif +#endif /* WITH_CONTIKI */ + +#ifndef WITH_CONTIKI + coap_attr_t *link_attr; /**< attributes to be included with the link format */ +#else /* WITH_CONTIKI */ + LIST_STRUCT(link_attr); /**< attributes to be included with the link format */ +#endif /* WITH_CONTIKI */ + LIST_STRUCT(subscribers); /**< list of observers for this resource */ + + + /** + * Request URI for this resource. This field will point into the + * static memory. */ + str uri; + int flags; + +} coap_resource_t; + +/** + * Creates a new resource object and initializes the link field to the + * string of length @p len. This function returns the + * new coap_resource_t object. + * + * @param uri The URI path of the new resource. + * @param len The length of @p uri. + * @param flags Flags for memory management (in particular release of memory) + * + * @return A pointer to the new object or @c NULL on error. + */ +coap_resource_t *coap_resource_init(const unsigned char *uri, size_t len, int flags); + +/** + * Registers the given @p resource for @p context. The resource must + * have been created by coap_resource_init(), the storage allocated + * for the resource will be released by coap_delete_resource(). + * + * @param context The context to use. + * @param resource The resource to store. + */ +void coap_add_resource(coap_context_t *context, coap_resource_t *resource); + +/** + * Deletes a resource identified by @p key. The storage allocated for + * that resource is freed. + * + * @param context The context where the resources are stored. + * @param key The unique key for the resource to delete. + * + * @return @c 1 if the resource was found (and destroyed), @c 0 otherwise. + */ +int coap_delete_resource(coap_context_t *context, coap_key_t key); + +/** + * Registers a new attribute with the given @p resource. As the + * attributes str fields will point to @p name and @p val the + * caller must ensure that these pointers are valid during the + * attribute's lifetime. + * + * @param resource The resource to register the attribute with. + * @param name The attribute's name. + * @param nlen Length of @p name. + * @param val The attribute's value or @c NULL if none. + * @param vlen Length of @p val if specified. + * @param flags Flags for memory management (in particular release of memory) + * + * @return A pointer to the new attribute or @c NULL on error. + */ +coap_attr_t *coap_add_attr(coap_resource_t *resource, + const unsigned char *name, size_t nlen, + const unsigned char *val, size_t vlen, + int flags); + +/** + * Returns @p resource's coap_attr_t object with given @p name if + * found, @c NULL otherwise. + * + * @param resource The resource to search for attribute @p name. + * @param name Name of the requested attribute. + * @param nlen Actual length of @p name. + * @return The first attribute with specified @p name or @c NULL if + * none was found. + */ +coap_attr_t *coap_find_attr(coap_resource_t *resource, + const unsigned char *name, size_t nlen); + +/** + * Deletes an attribute + * + * @param attr Pointer to a previously created attribute + * + */ +void coap_delete_attr(coap_attr_t *attr); + +/** + * Status word to encode the result of conditional print or copy + * operations such as coap_print_link(). The lower 28 bits of + * coap_print_status_t are used to encode the number of characters + * that has actually been printed, bits 28 to 31 encode the status. + * When COAP_PRINT_STATUS_ERROR is set, an error occurred during + * output. In this case, the other bits are undefined. + * COAP_PRINT_STATUS_TRUNC indicates that the output is truncated, + * i.e. the printing would have exceeded the current buffer. + */ +typedef unsigned int coap_print_status_t; + +#define COAP_PRINT_STATUS_MASK 0xF0000000u +#define COAP_PRINT_OUTPUT_LENGTH(v) ((v) & ~COAP_PRINT_STATUS_MASK) +#define COAP_PRINT_STATUS_ERROR 0x80000000u +#define COAP_PRINT_STATUS_TRUNC 0x40000000u + +/** + * Writes a description of this resource in link-format to given text + * buffer. @p len must be initialized to the maximum length of @p buf + * and will be set to the number of characters actually written if + * successful. This function returns @c 1 on success or @c 0 on + * error. + * + * @param resource The resource to describe. + * @param buf The output buffer to write the description to. + * @param len Must be initialized to the length of @p buf and + * will be set to the length of the printed link description. + * @param offset The offset within the resource description where to + * start writing into @p buf. This is useful for dealing + * with the Block2 option. @p offset is updated during + * output as it is consumed. + * + * @return If COAP_PRINT_STATUS_ERROR is set, an error occured. Otherwise, + * the lower 28 bits will indicate the number of characters that + * have actually been output into @p buffer. The flag + * COAP_PRINT_STATUS_TRUNC indicates that the output has been + * truncated. + */ +coap_print_status_t coap_print_link(const coap_resource_t *resource, + unsigned char *buf, size_t *len, size_t *offset); + +/** + * Registers the specified @p handler as message handler for the request type + * @p method + * + * @param resource The resource for which the handler shall be registered. + * @param method The CoAP request method to handle. + * @param handler The handler to register with @p resource. + */ +static inline void +coap_register_handler(coap_resource_t *resource, + unsigned char method, coap_method_handler_t handler) { + assert(resource); + assert(method > 0 && (size_t)(method-1) < sizeof(resource->handler)/sizeof(coap_method_handler_t)); + resource->handler[method-1] = handler; +} + +/** + * Returns the resource identified by the unique string @p key. If no + * resource was found, this function returns @c NULL. + * + * @param context The context to look for this resource. + * @param key The unique key of the resource. + * + * @return A pointer to the resource or @c NULL if not found. + */ +coap_resource_t *coap_get_resource_from_key(coap_context_t *context, + coap_key_t key); + +/** + * Calculates the hash key for the resource requested by the + * Uri-Options of @p request. This function calls coap_hash() for + * every path segment. + * + * @param request The requesting pdu. + * @param key The resulting hash is stored in @p key + */ +void coap_hash_request_uri(const coap_pdu_t *request, coap_key_t key); + +/** + * @addtogroup observe + */ + +/** + * Adds the specified peer as observer for @p resource. The + * subscription is identified by the given @p token. This function + * returns the registered subscription information if the @p observer + * has been added, or @c NULL on error. + * + * @param resource The observed resource. + * @param observer The remote peer that wants to received status updates. + * @param token The token that identifies this subscription. + * @param token_length The actual length of @p token. Must be @c 0 when + * @p token is @c NULL. + * @return A pointer to the added/updated subscription information or + * @c NULL on error. + */ +coap_subscription_t *coap_add_observer(coap_resource_t *resource, + const coap_address_t *observer, + const str *token); + +/** + * Returns a subscription object for given @p peer. + * + * @param resource The observed resource. + * @param peer The address to search for. + * @param token The token that identifies this subscription or @c NULL for any + * token. + * @return A valid subscription if exists or @c NULL otherwise. + */ +coap_subscription_t *coap_find_observer(coap_resource_t *resource, + const coap_address_t *peer, + const str *token); + +/** + * Marks an observer as alive. + * + * @param context The CoAP context to use + * @param observer The transport address of the observer + * @param token The corresponding token that has been used for + * the subscription + */ +void coap_touch_observer(coap_context_t *context, + const coap_address_t *observer, + const str *token); + +/** + * Removes any subscription for @p observer from @p resource and releases + * the allocated storage. + * + * @param resource The observed resource. + * @param observer The observer's address. + * @param token The token that identifies this subscription or @c NULL for any + * token. + */ +void coap_delete_observer(coap_resource_t *resource, + const coap_address_t *observer, + const str *token); + +/** + * Checks for all known resources, if they are dirty and notifies + * subscribed observers. + */ +void coap_check_notify(coap_context_t *context); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* _COAP_RESOURCE_H_ */ diff --git a/resource/csdk/libcoap-4.1.1/sec/netdtls.c b/resource/csdk/libcoap-4.1.1/sec/netdtls.c new file mode 100644 index 000000000..e90e64b6b --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/sec/netdtls.c @@ -0,0 +1,548 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "netdtls.h" +#include "dtls.h" +#include "alert.h" +#include "debug.h" +#include "logger.h" +#include "mem.h" +#include "ocsecurityconfig.h" + +#define MOD_NAME ("netdtls.c") + +#define get_dtls_ctx(coap_ctx) (coap_ctx->coap_dtls_ctx->dtls_ctx) + +extern void OCGetDtlsPskCredentials(OCDtlsPskCredsBlob **credInfo); + +/** + * An internal method to invoke tinyDTLS library 'dtls_write' method. + * Return value from this method will indicate if data was successfully sent + * to peer OR a new DTLS handshake session was invoked OR some error happened + * while processing. + * + */ +static dtls_ret coap_dtls_encrypt_internal(coap_context_t *ctx, OCDevAddr* dst, + uint8_t *pt, uint16_t ptLen) { + int ret; + if (ptLen == 0) + return DTLS_OK; + + ret = dtls_write(get_dtls_ctx(ctx), (session_t*)dst, pt, ptLen); + if (ret == 0) { + // A new DTLS session was initiated by tinyDTLS library + return DTLS_SESSION_INITIATED; + } + + if (ret == ptLen) { + // tinyDTLS library successfully encrypted the data and + // sent it to the peer. + return DTLS_OK; + } + + return DTLS_FAIL; +} + +/** + * An internal method to invoke tinyDTLS library 'dtls_handle_message' method + * to decrypt packet received on secure port. + * Return value from this method will indicate if a valid application pdu was + * decypted OR a DTLS handshake message was received OR some error happened + * while processing. + * + */ +static dtls_ret coap_dtls_decrypt_internal(coap_context_t *ctx, OCDevAddr* src, + uint8_t* ct, int ctLen, uint8_t** pt, int* ptLen) { + dtls_ret ret = DTLS_FAIL; + pt_info_t ptinfo; + + ptinfo.pt =NULL; + ptinfo.ptlen = 0; + ctx->coap_dtls_ctx->pt_info = &ptinfo; + + if (dtls_handle_message(get_dtls_ctx(ctx), (session_t*)src, ct, ctLen) == 0) { + ret = DTLS_HS_MSG; + if (ptinfo.pt && ptinfo.ptlen) { + *pt = ptinfo.pt; + *ptLen = ptinfo.ptlen; + ret = DTLS_OK; + } + } + return ret; +} + + +/** + * If tinyDTLS library starts a new DTLS handshake session with a peer, the pdu + * which was requested by application to encrypt will need to be cached until + * DTLS session is established. This method caches the pdu in cachedqueue. + * + */ +static int coap_cache_pdu(coap_context_t *ctx, + coap_queue_t* existing_node, + OCDevAddr *dst, + coap_pdu_t *pdu, + coap_tid_t tid) +{ + coap_queue_t *node; + coap_tick_t now; + + if (!ctx) + return -1; + /* Create a new node for caching the PDU in cachedqueue until + * DTLS session is established with peer. + */ + node = coap_new_node(); + if (!node) { + OC_LOG(DEBUG, MOD_NAME, PCF("Unable to allocate memory")); + return -1; + } + + memcpy(&node->remote, dst, sizeof(coap_address_t)); + node->pdu = pdu; + node->id = tid; + node->secure = 1; + + coap_ticks(&now); + node->t = now + (COAP_DEFAULT_RESPONSE_TIMEOUT *2) * COAP_TICKS_PER_SECOND; + + if (existing_node) { + node->timeout = existing_node->timeout; + node->delayedResNeeded = existing_node->delayedResNeeded; + } + + // Add the node in cachedqueue list + // TODO : Do we need to add some limits on how many packets can be cached ? + if (ctx->coap_dtls_ctx->cachedqueue) { + coap_queue_t *p = ctx->coap_dtls_ctx->cachedqueue; + while(p->next != NULL) { + p = p->next; + } + p->next = node; + } else { + ctx->coap_dtls_ctx->cachedqueue = node; + } + + return 0; +} + +/** + * Once a DTLS session is established and cached pdu is send, this pdu needs to + * be saved in 'sendqueue' if this is a CON pdu for re-transmission purposes. + * + */ +static void save_cached_con_pdu(coap_context_t *ctx, + coap_queue_t *node) +{ + coap_tick_t now; + + coap_ticks(&now); + if (ctx->sendqueue == NULL) + { + node->t = node->timeout; + ctx->sendqueue_basetime = now; + } + else + { + /* make node->t relative to context->sendqueue_basetime */ + node->t = (now - ctx->sendqueue_basetime) + node->timeout; + } + + node->delayedResNeeded = 0; + node->next = NULL; + coap_insert_node(&ctx->sendqueue, node); +} + +/** + * Once a DTLS session is established, this method is invoked to retrieve any + * pdu's available in cachedqueue to be sent to the peer. + * + */ +static coap_queue_t* get_cached_pdu( coap_context_t *ctx, + const coap_address_t *dst) +{ + coap_queue_t *node, *prev; + + node = ctx->coap_dtls_ctx->cachedqueue; + prev = NULL; + while(node) { + if (coap_address_equals(dst, &node->remote)) { + //disconnect the node from cachedqueue + if (node == ctx->coap_dtls_ctx->cachedqueue) + ctx->coap_dtls_ctx->cachedqueue = node->next; + else if (node->next == NULL) + prev->next = NULL; + else + prev->next = node->next; + + node->next = NULL; + return node; + } + prev = node; + node = node->next; + } + return NULL; +} + +/** + * Once a DTLS session is established, this method takes care of sending + * pdu's available in cachedqueue to the peer. + * + */ +static void coap_send_cached_pdu( coap_context_t *ctx, + const coap_address_t *dst ) +{ + coap_queue_t *node; + + if (!ctx) + return ; + + for (;(node=get_cached_pdu(ctx, dst));) { + OC_LOG(DEBUG, MOD_NAME, PCF("Sending cached PDU")); + OC_LOG_BUFFER(DEBUG, MOD_NAME, (uint8_t*)node->pdu->hdr, node->pdu->length); + // Send this PDU to DTLS library for encryption + dtls_ret ret = coap_dtls_encrypt_internal(ctx, (OCDevAddr*)dst, + (uint8_t*)node->pdu->hdr, node->pdu->length); + if (ret == DTLS_OK) { + OC_LOG(DEBUG, MOD_NAME, PCF("coap_send_cached_pdu: successully send cached pdu")); + } else { + OC_LOG(DEBUG, MOD_NAME, PCF("coap_send_cached_pdu: sending cached pdu failed.")); + //TODO Notify application that packet send failed. + } + + /* Add cache node in sendqueue if it is CON pdu, + * as it may be needed for retransmission + * else, delete it + */ + if (node->pdu->hdr->type == COAP_MESSAGE_CON) { + save_cached_con_pdu(ctx, node); + } else { + coap_delete_node(node); + } + } +} + + +/** + * This is the tinyDTLS 'read' callback. + * It is invoked by tinyDTLS to provide the decrypted pdu. + * + */ +static int read_decrypted_payload(dtls_context_t *dtls_ctx, + session_t *session, + uint8_t *buf, + size_t len ) +{ + if (!dtls_ctx) + return -1; + + coap_dtls_context_t* coap_dtls_ctx = + ((coap_context_t*)dtls_get_app_data(dtls_ctx))->coap_dtls_ctx; + + if (coap_dtls_ctx && coap_dtls_ctx->pt_info) { + coap_dtls_ctx->pt_info->pt = buf; + coap_dtls_ctx->pt_info->ptlen = len; + return len; + } + + return -1; +} + +/** + * This is the tinyDTLS 'write' callback. + * It is invoked by tinyDTLS to send encrypted data or handshake message to peer. + * + */ +static int send_secure_data(dtls_context_t *dtls_ctx, + session_t *session, + uint8_t* buf, + size_t buflen) +{ + if (!dtls_ctx) + return -1; + + return OCSendTo( ((coap_context_t*)dtls_get_app_data(dtls_ctx))->sockfd_dtls, + buf, buflen, 0, (OCDevAddr*)session); +} + + +/** + * This is the tinyDTLS 'event' callback. + * It is invoked by tinyDTLS to notify any DTLS events or alerts. + * + */ +static int handle_secure_event(dtls_context_t *dtls_ctx, + session_t *session, + dtls_alert_level_t level, + unsigned short code) +{ + if (!dtls_ctx) + return -1; + + OC_LOG_V(DEBUG, MOD_NAME, "level %d, code %u", level, code); + + //Notify stack of any errors/connection state changes to upper layer + //application + if (!level && (code == DTLS_EVENT_CONNECTED)) + { + coap_send_cached_pdu( (coap_context_t*)dtls_get_app_data(dtls_ctx), + (coap_address_t*)session); + } + return 0; +} + +/** + * This is the tinyDTLS 'get_psk_info' callback. + * It is invoked by tinyDTLS to retrieve identity/credentials. + * This is currently a test version using stationary keys. + * + */ +static int get_psk_credentials(dtls_context_t *ctx, + const session_t *session, + dtls_credentials_type_t type, + const unsigned char *desc, size_t desc_len, + unsigned char *result, size_t result_len) +{ + int ret = -1; + OCDtlsPskCredsBlob *creds_blob = NULL; + + //Retrieve the credentials blob from security module + OCGetDtlsPskCredentials(&creds_blob); + + if (!creds_blob) + return ret; + + if ((type == DTLS_PSK_HINT) || (type == DTLS_PSK_IDENTITY)) { + if (DTLS_PSK_ID_LEN <= result_len){ + memcpy(result, creds_blob->identity, DTLS_PSK_ID_LEN); + ret = DTLS_PSK_ID_LEN; + } + } + + if ((type == DTLS_PSK_KEY) && (desc) && (desc_len == DTLS_PSK_PSK_LEN)) { + //Check if we have the credentials for the device with which we + //are trying to perform a handshake + for (int i =0; i < creds_blob->num; i++) { + if (memcmp(desc, creds_blob->creds[i].id, DTLS_PSK_ID_LEN) == 0) + { + memcpy(result, creds_blob->creds[i].psk, DTLS_PSK_PSK_LEN); + ret = DTLS_PSK_PSK_LEN; + } + } + } + + return ret; +} + + +/** + * Open secure port and initialize tinyDTLS library. + * + * @param ctx - handle to global coap_context_t. + * + * @param ipAddr - ip address. + * + * @return A value less than zero on error, greater or + * equal otherwise. + */ +int coap_dtls_init(coap_context_t *ctx, uint8_t ipAddr[]) { + + int ret = -1; + coap_dtls_context_t *coap_dtls_ctx = NULL; + OCDevAddr dev_addr; + + if (!ctx) + goto exit; + + coap_dtls_ctx = + (coap_dtls_context_t*)coap_malloc(sizeof(coap_dtls_context_t)); + + if (!coap_dtls_ctx) + goto exit; + memset(coap_dtls_ctx, 0, sizeof(coap_dtls_ctx)); + ctx->sockfd_dtls = -1; + + OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], + COAP_DTLS_DEFAULT_PORT, &dev_addr); + if (OCInitUDP((OCDevAddr *)&dev_addr, (int32_t *)&(ctx->sockfd_dtls), 0) != ERR_SUCCESS) { + OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], + COAP_DTLS_RANDOM_PORT, &dev_addr); + if (OCInitUDP((OCDevAddr *)&dev_addr, (int32_t *)&(ctx->sockfd_dtls), 0) != ERR_SUCCESS) { + goto exit; + } + } + + // Initialize clock, crypto and other global vars in tinyDTLS library + dtls_init(); + + coap_dtls_ctx->dtls_ctx = dtls_new_context(ctx); + if (!coap_dtls_ctx->dtls_ctx) + goto exit; + + coap_dtls_ctx->callbacks.write = send_secure_data; + coap_dtls_ctx->callbacks.read = read_decrypted_payload; + coap_dtls_ctx->callbacks.event = handle_secure_event; + coap_dtls_ctx->callbacks.get_psk_info = get_psk_credentials; + + dtls_set_handler(coap_dtls_ctx->dtls_ctx, &(coap_dtls_ctx->callbacks)); + ctx->coap_dtls_ctx = coap_dtls_ctx; + ret = 0; + +exit: + if (ret == -1) { + coap_dtls_deinit(ctx); + } + return ret; +} + + +/** + * Closes secure port and de-inits tinyDTLS library. + * + * @param ctx - handle to global coap_context_t. + * + */ +void coap_dtls_deinit(coap_context_t *ctx) { + + if (!ctx || !ctx->coap_dtls_ctx) + return; + + coap_dtls_context_t *coap_dtls_ctx = ctx->coap_dtls_ctx; + + coap_delete_all(coap_dtls_ctx->cachedqueue); + + dtls_free_context(coap_dtls_ctx->dtls_ctx); + coap_dtls_ctx->dtls_ctx = NULL; + + if (ctx->sockfd_dtls != -1) + OCClose(ctx->sockfd_dtls); + + coap_free(coap_dtls_ctx); + ctx->coap_dtls_ctx = NULL; +} + + +/** + * Performs DTLS encryption of the CoAP PDU. If a + * DTLS session does not exist yet with the @dst, + * a DTLS handshake will be started. In case where + * a new DTLS handshake is started, pdu info is + * cached to be send when session setup is finished. + * + * @param ctx - handle to global coap_context_t. + * @param dst - address of the receiver of the pdu. + * @param pdu - pointer to CoAP pdu. + * @param node - address of the node holding pdu. + * @param tid - tid of the pdu. + * @param cached - output variable to indicate if pdu + * is cached and inform the caller to + * NOT free the memory holding pdu. + * + * @return A value less than zero on error, greater or + * equal otherwise. + */ +int coap_dtls_encrypt(coap_context_t *ctx, + OCDevAddr *dst, + coap_pdu_t *pdu, + coap_queue_t **node, + coap_tid_t tid, + uint8_t *cache_flag) { + OC_LOG(DEBUG, MOD_NAME, PCF("coap_dtls_encrypt")); + + if (!dst || !pdu) + return -1; + + dtls_ret ret = coap_dtls_encrypt_internal( ctx, dst, + (uint8_t*)pdu->hdr, pdu->length); + + if (ret == DTLS_SESSION_INITIATED) { + OC_LOG(DEBUG, MOD_NAME, PCF("Initiated new DTLS session")); + if (cache_flag && coap_cache_pdu(ctx, *node, dst, pdu, tid) == 0) { + /* Delete the node from sendqueue list as it has been + * added in cachedqueue list. It will be added + * again in sendqueue list when DTLS session is established + */ + if (*node) { + coap_queue_t* removed_node = NULL; + coap_remove_from_queue(&(ctx->sendqueue), + (*node)->id, &removed_node); + if (removed_node == *node) { + coap_free(*node); + *node = NULL; + OC_LOG(DEBUG, MOD_NAME, PCF("coap_dtls_encrypt -- Removed correct node")); + } + } + *cache_flag = 1; + } + return pdu->length; + } + + if (ret == DTLS_OK) { + OC_LOG(DEBUG, MOD_NAME, PCF("Encrypted App PDU and send to peer")); + return pdu->length; + } + return -1; +} + + +/** + * Performs DTLS decryption of the CoAP PDU received on + * secure port. This method performs in-place decryption + * of the cipher-text buffer. If a DTLS handshake message + * is received or decryption failure happens, this method + * returns -1. If a valid CoAP pdu is received, it returns the + * length of the decrypted pdu. + * + * @param ctx - handle to global coap_context_t. + * @param src - address of the sender of the pdu. + * @param ct - pointer to the cipher text buffer. + * @param ctlen - length of the ciphertext buffer. + * @param pt - output variable to store the starting address + * of decrypted plaintext. + * @param ptlen - output variable to store the length of + * decrypted plaintext. + * + * @return A value less than zero on error, greater or + * equal otherwise. + */ +int coap_dtls_decrypt(coap_context_t *ctx, + OCDevAddr* src, + uint8_t* ct, + int ctlen, + uint8_t** pt, + int* ptlen) { + OC_LOG(DEBUG, MOD_NAME, PCF("coap_dtls_decrypt")); + + if (!src || !ct || !pt || !ptlen) + return -1; + + dtls_ret ret = coap_dtls_decrypt_internal(ctx, src, ct, ctlen, + pt, ptlen); + + if (ret == DTLS_OK) + return *ptlen; + + if (ret == DTLS_HS_MSG) + OC_LOG(DEBUG, MOD_NAME, PCF("coap_dtls_decrypt : Handshake msg recvd ")); + if (ret == DTLS_FAIL) + OC_LOG(DEBUG, MOD_NAME, PCF("coap_dtls_decrypt : Decryption failure ")); + + return -1; +} diff --git a/resource/csdk/libcoap-4.1.1/sec/netdtls.h b/resource/csdk/libcoap-4.1.1/sec/netdtls.h new file mode 100644 index 000000000..1348bba99 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/sec/netdtls.h @@ -0,0 +1,138 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef _NET_DTLS_H +#define _NET_DTLS_H + +#include "net.h" +#include "address.h" +#include "pdu.h" +#include "dtls.h" + +#define COAP_DTLS_DEFAULT_PORT 5684 +#define COAP_DTLS_RANDOM_PORT 0 + +/** + * Data structure for holding the tinyDTLS interface + * related info. + */ +typedef struct coap_dtls_context_t { + coap_queue_t *cachedqueue; /**< pdu's are cached until DTLS session is formed */ + struct dtls_context_t *dtls_ctx; /**< pointer to tinyDTLS context */ + struct pt_info_t *pt_info; /**< used by callback during + decryption to hold address/length */ + dtls_handler_t callbacks; /**< pointer to callbacks needed by tinyDTLS */ +}coap_dtls_context_t; + +/** + * Data structure for holding the decrypted data address + * and length provided by tinyDTLS callback interface. + */ +typedef struct pt_info_t { + uint8_t *pt; + uint16_t ptlen; +}pt_info_t; + +/** + * Declares DTLS errors and return values. Currently used internally only. + */ +typedef enum +{ + DTLS_OK = 0, + DTLS_FAIL, + DTLS_SESSION_INITIATED, + DTLS_HS_MSG +} dtls_ret; + +/** + * Open secure port and initialize tinyDTLS library. + * + * @param ctx - handle to global coap_context_t. + * + * @param ipAddr - ip address. + * + * @return A value less than zero on error, greater or + * equal otherwise. + */ +int coap_dtls_init(coap_context_t *ctx, uint8_t ipAddr[]); + +/** + * Closes secure port and de-inits tinyDTLS library. + * + * @param ctx - handle to global coap_context_t. + * + */ +void coap_dtls_deinit(coap_context_t *ctx); + +/** + * Performs DTLS encryption of the CoAP PDU. If a + * DTLS session does not exist yet with the @dst, + * a DTLS handshake will be started. In case where + * a new DTLS handshake is started, pdu info is + * cached to be send when session setup is finished. + * + * @param ctx - handle to global coap_context_t. + * @param dst - address of the receiver of the pdu. + * @param pdu - pointer to CoAP pdu. + * @param node - address of the node holding pdu. + * @param tid - tid of the pdu. + * @param cache_flag - output variable to indicate if pdu + * is cached and inform the caller to + * NOT free the memory holding pdu. + * + * @return A value less than zero on error, greater or + * equal otherwise. + */ +int coap_dtls_encrypt(coap_context_t *ctx, + OCDevAddr* dst, + coap_pdu_t *pdu, + coap_queue_t **node, + coap_tid_t tid, + uint8_t *cache_flag); + +/** + * Performs DTLS decryption of the CoAP PDU received on + * secure port. This method performs in-place decryption + * of the cipher-text buffer. If a DTLS handshake message + * is received or decryption failure happens, this method + * returns -1. If a valid application PDU is decrypted, it + * returns the length of the decrypted pdu. + * + * @param ctx - handle to global coap_context_t. + * @param src - address of the sender of the pdu. + * @param ct - pointer to the cipher text buffer. + * @param ctlen - length of the ciphertext buffer. + * @param pt - output variable to store the starting address + * of decrypted plaintext. + * @param ptlen - output variable to store the length of + * decrypted plaintext. + * + * @return A value less than zero on error, greater or + * equal otherwise. + */ +int coap_dtls_decrypt(coap_context_t *ctx, + OCDevAddr* src, + uint8_t* ct, + int ctlen, + uint8_t** pt, + int* ptlen); + +#endif //_NET_DTLS_H + diff --git a/resource/csdk/libcoap-4.1.1/str.c b/resource/csdk/libcoap-4.1.1/str.c new file mode 100644 index 000000000..e251bc42b --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/str.c @@ -0,0 +1,34 @@ +/* str.c -- strings to be used in the CoAP library + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "config.h" + +#include + +#include "debug.h" +#include "mem.h" +#include "str.h" + +str *coap_new_string(size_t size) { + str *s = (str*)coap_malloc(sizeof(str) + size + 1); + if ( !s ) { +#ifndef NDEBUG + coap_log(LOG_CRIT, "coap_new_string: malloc\n"); +#endif + return NULL; + } + + memset(s, 0, sizeof(str)); + s->s = ((unsigned char *)s) + sizeof(str); + return s; +} + +void coap_delete_string(str *s) { + coap_free(s); +} + diff --git a/resource/csdk/libcoap-4.1.1/str.h b/resource/csdk/libcoap-4.1.1/str.h new file mode 100644 index 000000000..7c10ce8a6 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/str.h @@ -0,0 +1,30 @@ +/* str.h -- strings to be used in the CoAP library + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef _COAP_STR_H_ +#define _COAP_STR_H_ + +#include + +typedef struct { + size_t length; /* length of string */ + unsigned char *s; /* string data */ +} str; + +#define COAP_SET_STR(st,l,v) { (st)->length = (l), (st)->s = (v); } + +/** + * Returns a new string object with at least size bytes storage + * allocated. The string must be released using coap_delete_string(); + */ +str *coap_new_string(size_t size); + +/** Deletes the given string and releases any memory allocated. */ +void coap_delete_string(str *); + +#endif /* _COAP_STR_H_ */ diff --git a/resource/csdk/libcoap-4.1.1/subscribe.c b/resource/csdk/libcoap-4.1.1/subscribe.c new file mode 100644 index 000000000..d6834198d --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/subscribe.c @@ -0,0 +1,401 @@ +/* subscribe.c -- subscription handling for CoAP + * see draft-ietf-coap-observe-09 + * + * Copyright (C) 2010--2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "config.h" + +#if defined(HAVE_ASSERT_H) && !defined(assert) +# include +#endif + +#include +#include +#ifdef HAVE_ARPA_INET_H +# include +#endif + +/* #include "resource.h" */ + +#include "mem.h" +#include "encode.h" +#include "debug.h" +#include "subscribe.h" + +void +coap_subscription_init(coap_subscription_t *s) { + assert(s); + memset(s, 0, sizeof(coap_subscription_t)); +} + +#if 0 +#define HMASK (ULONG_MAX >> 1) + +void +notify(coap_context_t *context, coap_resource_t *res, + coap_subscription_t *sub, unsigned int duration, int code) { +#if 0 + coap_pdu_t *pdu; + int ls, finished=0; + unsigned char ct, d; + unsigned int length; +#ifndef NDEBUG + char addr[INET6_ADDRSTRLEN]; +#endif + + if ( !context || !res || !sub || !(pdu = coap_new_pdu()) ) + return; + + pdu->hdr->type = COAP_MESSAGE_CON; + pdu->hdr->id = rand(); /* use a random transaction id */ + pdu->hdr->code = code; + + /* FIXME: content-type and data (how about block?) */ + if (res->uri->host.length) + coap_add_option (pdu, COAP_OPTION_URI_HOST, + res->uri->host.length, + res->uri->host.s ); + + if (res->uri->path.length) + coap_add_option (pdu, COAP_OPTION_URI_PATH, + res->uri->path.length, + res->uri->path.s); + + d = COAP_PSEUDOFP_ENCODE_8_4_DOWN(duration, ls); + + coap_add_option ( pdu, COAP_OPTION_SUBSCRIPTION, 1, &d ); + + if (sub->token.length) { + coap_add_option (pdu, COAP_OPTION_TOKEN, + sub->token.length, + sub->token.s); + } + + if (res->uri->query.length) + coap_add_option (pdu, COAP_OPTION_URI_QUERY, + res->uri->query.length, + res->uri->query.s ); + + if (res->data) { + length = (unsigned char *)pdu->hdr + COAP_MAX_PDU_SIZE - pdu->data; + ct = res->mediatype; + res->data(res->uri, &ct, 0, pdu->data, &length, &finished); + pdu->length += length; + + /* TODO: add block option if not finished */ + /* TODO: add mediatype */ + } + +#ifndef NDEBUG + if ( inet_ntop(sub->subscriber.addr.sa.sa_family, + &sub->subscriber.addr, addr, sizeof(addr)) ) { + debug("*** notify for %s to [%s]\n", res->uri->path.s, addr); + } +#endif + if (pdu && coap_send_confirmed(context, + &sub->subscriber.addr.sa, + sub->subscriber.size, pdu) + == COAP_INVALID_TID) { +#ifndef NDEBUG + debug("coap_check_resource_list: error sending notification\n"); +#endif + coap_delete_pdu(pdu); + } +#endif +} + +void +coap_check_resource_list(coap_context_t *context) { + coap_resource_t *res, *tmp; + coap_list_t *sub; + coap_key_t key; + time_t now; + + if ( !context || !context->resources /* || !context->subscribers */) + return; + + time(&now); /* FIXME: use coap_ticks() */ + + HASH_ITER(hh, context->resources, res, tmp) { + if (res->dirty) { + debug("FIXME: notify subscribers\n"); +#if 0 + key = coap_uri_hash( COAP_RESOURCE(res)->uri ) ; + + /* is subscribed? */ + for (sub = context->subscriptions; sub; sub = sub->next) { + if ( COAP_SUBSCRIPTION(sub)->resource == key ) { + /* notify subscriber */ + notify(context, COAP_RESOURCE(res), COAP_SUBSCRIPTION(sub), + COAP_SUBSCRIPTION(sub)->expires - now, COAP_RESPONSE_200); + } + + } + + COAP_RESOURCE(res)->dirty = 0; +#endif + } + } +} + +#if 0 +coap_resource_t * +coap_get_resource_from_key(coap_context_t *ctx, coap_key_t key) { + coap_list_t *node; + + if (ctx) { + /* TODO: use hash table for resources with key to access */ + for (node = ctx->resources; node; node = node->next) { + printf("check %ux\n", coap_uri_hash(COAP_RESOURCE(node)->uri)); + if ( key == coap_uri_hash(COAP_RESOURCE(node)->uri) ) { + printf("found\n"); + return COAP_RESOURCE(node); + } + } + } + + printf("not found\n"); + return NULL; +} + +coap_resource_t * +coap_get_resource(coap_context_t *ctx, coap_uri_t *uri) { +#ifndef NDEBUG + int i; + printf("search resource %ux", coap_uri_hash(uri)); + for (i=0; i < uri->path.length; ++i) { + printf(" %02x", uri->path.s[i]); + } + printf("\n"); +#endif + return uri ? coap_get_resource_from_key(ctx, coap_uri_hash(uri)) : NULL; +} +#endif + +void +coap_check_subscriptions(coap_context_t *context) { + time_t now; + coap_list_t *node; +#ifndef NDEBUG + char addr[INET6_ADDRSTRLEN]; +#endif + + if ( !context ) + return; + + time(&now); + + node = context->subscriptions; + while ( node && COAP_SUBSCRIPTION(node)->expires < now ) { +#ifndef NDEBUG + if (inet_ntop(COAP_SUBSCRIPTION(node)->subscriber.addr.sa.sa_family, + &COAP_SUBSCRIPTION(node)->subscriber.addr, + addr, sizeof(addr))) { + + debug("** removed expired subscription from [%s]\n", addr); + } +#endif +#if 0 + notify(context, + coap_get_resource_from_key(context, COAP_SUBSCRIPTION(node)->resource), + COAP_SUBSCRIPTION(node), + 0, COAP_RESPONSE_400); +#endif + context->subscriptions = node->next; + coap_delete(node); + node = context->subscriptions; + } +} + +void +coap_free_resource(void *res) { + if ( res ) { +#if 0 + coap_free(((coap_resource_t *)res)->uri); + coap_delete_string(((coap_resource_t *)res)->name); +#endif + } +} + +#if 0 +/** + * Deletes the resource that is identified by key. Returns 1 if the resource was + * removed, 0 on error (e.g. if no such resource exists). + */ +int +coap_delete_resource(coap_context_t *context, coap_key_t key) { + coap_list_t *prev, *node; + + if (!context || key == COAP_INVALID_HASHKEY) + return 0; + + for (prev = NULL, node = context->resources; node; + prev = node, node = node->next) { + if (coap_uri_hash(COAP_RESOURCE(node)->uri) == key) { +#ifndef NDEBUG + debug("removed key %lu (%s)\n",key,COAP_RESOURCE(node)->uri->path.s); +#endif + if (!prev) + context->resources = node->next; + else + prev->next = node->next; + + coap_delete(node); + return 1; + } + } + return 0; +} +#endif + +coap_subscription_t * +coap_new_subscription(coap_context_t *context, const coap_uri_t *resource, + const struct sockaddr *addr, socklen_t addrlen, time_t expiry) { + coap_subscription_t *result; + + if ( !context || !resource || !addr + || !(result = coap_malloc(sizeof(coap_subscription_t)))) + return NULL; + + result->resource = coap_uri_hash(resource); + result->expires = expiry; + memcpy(&result->subscriber.addr.sa, addr, addrlen); + + memset(&result->token, 0, sizeof(str)); + + return result; + +} + +coap_list_t * +coap_list_push_first(coap_list_t **list, void *data, void (*delete_func)(void *) ) { + coap_list_t *node; + node = coap_new_listnode(data, delete_func); + if ( !node || !list ) + return NULL; + + if ( !*list ) { + *list = node; + } else { + node->next = *list; + *list = node; + } + + return node; +} + +int +_order_subscription(void *a, void *b) { + if ( !a || !b ) + return a < b ? -1 : 1; + + return ((coap_subscription_t *)a)->expires < ((coap_subscription_t *)b)->expires ? -1 : 1; +} + +coap_key_t +coap_subscription_hash(coap_subscription_t *subscription) { + if ( !subscription ) + return COAP_INVALID_HASHKEY; + + return _hash2( subscription->resource, (unsigned char *)&subscription->subscriber, + sizeof(subscription->subscriber) ); +} + +coap_key_t +coap_add_subscription(coap_context_t *context, + coap_subscription_t *subscription) { + coap_list_t *node; + if ( !context || !subscription ) + return COAP_INVALID_HASHKEY; + + if ( !(node = coap_new_listnode(subscription, NULL)) ) + return COAP_INVALID_HASHKEY; + + if ( !coap_insert(&context->subscriptions, node, _order_subscription ) ) { + coap_free( node ); /* do not call coap_delete(), so subscription object will survive */ + return COAP_INVALID_HASHKEY; + } + + return coap_subscription_hash(subscription); +} + +coap_subscription_t * +coap_find_subscription(coap_context_t *context, + coap_key_t hashkey, + struct sockaddr *addr, + str *token) { +#if 0 + coap_list_t *node; +#endif + + if (!context || !addr || hashkey == COAP_INVALID_HASHKEY) + return NULL; + + /* FIXME: I do not like the way subscriptions work right now. To be fixed. */ + +#if 0 + for (node = context->subscriptions; node; node = node->next) { + if (COAP_SUBSCRIPTION(node)->resource == hashkey) { + + if (token) { /* do not proceed if tokens do not match */ + if (token->length != COAP_SUBSCRIPTION(node)->token.length || + memcmp(token->s, COAP_SUBSCRIPTION(node)->token.s, + token->length) != 0) + continue; + } + + if (subscriber->sin6_port == COAP_SUBSCRIPTION(node)->subscriber.sin6_port + && memcmp(&subscriber->sin6_addr, + &COAP_SUBSCRIPTION(node)->subscriber.sin6_addr, + sizeof(struct in6_addr)) == 0) + return COAP_SUBSCRIPTION(node); + } + } +#endif + return NULL; +} + +int +coap_delete_subscription(coap_context_t *context, + coap_key_t key, + struct sockaddr *addr) { +#if 0 + coap_list_t *prev, *node; +#endif + + if (!context || !addr || key == COAP_INVALID_HASHKEY) + return 0; + + /* FIXME: I do not like the way subscriptions work right now. To be fixed. */ + +#if 0 + for (prev = NULL, node = context->subscriptions; node; + prev = node, node = node->next) { + if (COAP_SUBSCRIPTION(node)->resource == key) { + if (subscriber->sin6_port == COAP_SUBSCRIPTION(node)->subscriber.sin6_port + && memcmp(&subscriber->sin6_addr, + &COAP_SUBSCRIPTION(node)->subscriber.sin6_addr, + sizeof(struct in6_addr)) == 0) { + + if (!prev) { + context->subscriptions = node->next; + coap_free(COAP_SUBSCRIPTION(node)->token.s); + coap_delete(node); + } else { + prev->next = node->next; + coap_free(COAP_SUBSCRIPTION(node)->token.s); + coap_delete(node); + } + return 1; + } + } + } +#endif + + return 0; +} +#endif diff --git a/resource/csdk/libcoap-4.1.1/subscribe.h b/resource/csdk/libcoap-4.1.1/subscribe.h new file mode 100644 index 000000000..7eda74ffe --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/subscribe.h @@ -0,0 +1,200 @@ +/* subscribe.h -- subscription handling for CoAP + * see draft-hartke-coap-observe-03 + * + * Copyright (C) 2010--2012 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + + +#ifndef _COAP_SUBSCRIBE_H_ +#define _COAP_SUBSCRIBE_H_ + +#include "config.h" +#include "address.h" + +/** + * @defgroup observe Resource observation + * @{ + */ + +#ifndef COAP_OBS_MAX_NON +/** + * Number of notifications that may be sent non-confirmable before a + * confirmable message is sent to detect if observers are alive. The + * maximum allowed value here is @c 15. + */ +#define COAP_OBS_MAX_NON 5 +#endif /* COAP_OBS_MAX_NON */ + +#ifndef COAP_OBS_MAX_FAIL +/** + * Number of confirmable notifications that may fail (i.e. time out + * without being ACKed) before an observer is removed. The maximum + * value for COAP_OBS_MAX_FAIL is @c 3. + */ +#define COAP_OBS_MAX_FAIL 3 +#endif /* COAP_OBS_MAX_FAIL */ + +/** Subscriber information */ +typedef struct coap_subscription_t { + struct coap_subscription_t *next; /**< next element in linked list */ + coap_address_t subscriber; /**< address and port of subscriber */ + + unsigned int non:1; /**< send non-confirmable notifies if @c 1 */ + unsigned int non_cnt:4; /**< up to 15 non-confirmable notifies allowed */ + unsigned int fail_cnt:2; /**< up to 3 confirmable notifies can fail */ + unsigned int dirty:1; /**< set if the notification temporarily could not be sent (in that case, the resource's partiallydirty flag is set too) */ + + size_t token_length; /**< actual length of token */ + unsigned char token[8]; /**< token used for subscription */ + /* @todo CON/NON flag, block size */ +} coap_subscription_t; + +void coap_subscription_init(coap_subscription_t *); + +#if 0 +#include "uthash.h" +#include "uri.h" +#include "list.h" +#include "pdu.h" +#include "net.h" + +#if 0 +typedef unsigned long coap_key_t; + +/** Used to indicate that a hashkey is invalid. */ +#define COAP_INVALID_HASHKEY ((coap_key_t)-1) + +typedef struct { + coap_uri_t *uri; /* unique identifier; memory is released by coap_delete_resource() */ + UT_hash_handle hh; /**< hash handle (for internal use only) */ + str *name; /* display name of the resource */ + unsigned char mediatype; /* media type for resource representation */ + unsigned int dirty:1; /* set to 1 if resource has changed */ + unsigned int writable:1; /* set to 1 if resource can be changed using PUT */ + + /* cache-control */ + unsigned char etag[4]; /* version identifier for this resource + * (zero terminated, first byte is zero if not set). */ + unsigned int maxage; /* maximum cache time (zero means no Max-age option) */ + + /** + * Callback function that copies the resource representation into the provided data + * buffer (PDU payload). finished is set to 1 to indicate that this was the last block + * of buflen data for this resource representation, 0 means that data is not finished + * and a subsequent call with offset updated by buflen would yield more data (i.e. + * the M-bit of CoAP's block option must be set if offset and buflen are selected + * accordingly. + * When called, buflen must be set to the maximum length of buf that is to be filled + * with the mediatype representation of the resource identified by uri. + * The mediatype must be set to the requested mediatype of COAP_MEDIATYPE_ANY if + * none was given. On return, the mediatype will be set to the type that is + * actually used. + * The return value indicates the result code that should be used in a response to + * this function. + */ + int (*data)(coap_uri_t *uri, unsigned char *mediatype, unsigned int offset, unsigned char *buf, unsigned int *buflen, int *finished); +} coap_resource_t; +#endif + +typedef struct { + coap_key_t resource; /* hash key for subscribed resource */ + time_t expires; /* expiry time of subscription */ + + coap_address_t subscriber; /**< subscriber's address */ + + str token; /**< subscription token */ +} coap_subscription_t; + +#define COAP_RESOURCE(node) ((coap_resource_t *)(node)->data) +#define COAP_SUBSCRIPTION(node) ((coap_subscription_t *)(node)->data) + +/** Checks subscribed resources for updates and notifies subscribers of changes. */ +void coap_check_resource_list(coap_context_t *context); + +/** Removes expired subscriptions. */ +void coap_check_subscriptions(coap_context_t *context); + +#if 0 +/** + * Adds specified resource to the resource observation list. Returns a + * unique key for the resource. The alloceted memory is released when + * the resource is destroyed with coap_delete_resource(). + */ +coap_key_t coap_add_resource(coap_context_t *context, coap_resource_t *); + +/** + * Deletes the resource that is identified by key. Returns 1 if the resource was + * removed, 0 on error (e.g. if no such resource exists). + */ +int coap_delete_resource(coap_context_t *context, coap_key_t key); +#endif +/** + * Creates a new subscription object filled with the given data. The storage + * allocated for this object must be released using coap_free(). */ +coap_subscription_t *coap_new_subscription(coap_context_t *context, + const coap_uri_t *resource, + const struct sockaddr *subscriber, + socklen_t addrlen, + time_t expiry); + +/** + * Adds the given subsription object to the observer list. + * @param context The CoAP context + * @param subscription A new subscription oobject created with coap_new_subscription() + * @return A unique hash key for this resource or COAP_INVALID_HASHKEY on error. + * The storage allocated for the subscription object is released when it is + * removed from the subscription list, unless the function has returned + * COAP_INVALID_HASHKEY. In this case, the storage must be released by the + * caller of this function. +*/ +coap_key_t coap_add_subscription(coap_context_t *context, + coap_subscription_t *subscription); + +/** + * Returns the subscription from subscriber for the resource identified + * by hashkey. When token is not NULL the subscription must have the + * same token. + * @param context The CoAP context + * @param hashkey The unique key that identifies the subscription + * @param subscriber The subscriber's transport address + * @param token If not NULL, this specifies a token given by the + * subscriber to identify its subscription. + * @return The requested subscription object or NULL when not found. + */ +coap_subscription_t * coap_find_subscription(coap_context_t *context, + coap_key_t hashkey, + struct sockaddr *subscriber, + str *token); +/** + * Removes a subscription from the subscription list stored in context and + * releases the storage that was allocated for this subscription. + * @param context The CoAP context. + * @param haskey The unique key that identifies the subscription to remove. + * @return 1 if a subscription was removed, 0 otherwise. + */ +int coap_delete_subscription(coap_context_t *context, + coap_key_t hashkey, + struct sockaddr *subscriber); + +/** Returns a unique hash for the specified URI or COAP_INVALID_HASHKEY on error. */ +coap_key_t coap_uri_hash(const coap_uri_t *uri); + + +/** Returns a unique hash for the specified subscription or COAP_INVALID_HASHKEY on error. */ +coap_key_t coap_subscription_hash(coap_subscription_t *subscription); +#if 0 +/** Returns the resource identified by key or NULL if not found. */ +coap_resource_t *coap_get_resource_from_key(coap_context_t *ctx, coap_key_t key); + +/** Returns the resource identified by uri or NULL if not found. */ +coap_resource_t *coap_get_resource(coap_context_t *ctx, coap_uri_t *uri); +#endif + +#endif + +/** @} */ + +#endif /* _COAP_SUBSCRIBE_H_ */ diff --git a/resource/csdk/libcoap-4.1.1/t_list.h b/resource/csdk/libcoap-4.1.1/t_list.h new file mode 100644 index 000000000..ebbd70f02 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/t_list.h @@ -0,0 +1,146 @@ +/* t_list -- tinydtls lists + * + * Copyright (C) 2012 Olaf Bergmann + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file t_list.h + * @brief Wrappers for list structures and functions + */ + +#ifndef _DTLS_LIST_H_ +#define _DTLS_LIST_H_ + +#ifndef WITH_CONTIKI +#include "uthash.h" +#include "utlist.h" + +/* We define list structures and utility functions to be compatible + * with Contiki list structures. The Contiki list API is part of the + * Contiki operating system, and therefore the following licensing + * terms apply (taken from contiki/core/lib/list.h): + * + * Copyright (c) 2004, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * Author: Adam Dunkels + * + * $ Id: list.h,v 1.5 2010/09/13 13:31:00 adamdunkels Exp $ + */ + +typedef void **list_t; +struct list { + struct list *next; +}; + +#define LIST_CONCAT(s1, s2) s1##s2 + +#define LIST_STRUCT(name) \ + void *LIST_CONCAT(name, _list); \ + list_t name + +#define LIST_STRUCT_INIT(struct_ptr, name) { \ + (struct_ptr)->name = &((struct_ptr)->LIST_CONCAT(name,_list)); \ + (struct_ptr)->LIST_CONCAT(name,_list) = NULL; \ + } + +static inline void * +list_head(list_t the_list) { + return *the_list; +} + +static inline void +list_remove(list_t the_list, void *item) { + if (list_head(the_list)) + LL_DELETE(*(struct list **)the_list, (struct list *)item); +} + +static inline void +list_add(list_t the_list, void *item) { + list_remove(the_list, item); + LL_APPEND(*(struct list **)the_list, (struct list *)item); +} + +static inline void +list_push(list_t the_list, void *item) { + LL_PREPEND(*(struct list **)the_list, (struct list *)item); +} + +static inline void * +list_pop(list_t the_list) { + struct list *l; + l = (struct list*)*the_list; + if(l) + list_remove(the_list, l); + + return l; +} + +static inline void +list_insert(list_t the_list, void *previtem, void *newitem) { + if(previtem == NULL) { + list_push(the_list, newitem); + } else { + ((struct list *)newitem)->next = ((struct list *)previtem)->next; + ((struct list *)previtem)->next = (struct list*)newitem; + } +} + +static inline void * +list_item_next(void *item) +{ + return item == NULL? NULL: ((struct list *)item)->next; +} + +#else /* WITH_CONTIKI */ +#include "list.h" +#endif /* WITH_CONTIKI */ + +#endif /* _DTLS_LIST_H_ */ + diff --git a/resource/csdk/libcoap-4.1.1/uri.c b/resource/csdk/libcoap-4.1.1/uri.c new file mode 100644 index 000000000..96624c52a --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/uri.c @@ -0,0 +1,529 @@ +/* uri.c -- helper functions for URI treatment + * + * Copyright (C) 2010--2012 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "config.h" + +#if defined(HAVE_ASSERT_H) && !defined(assert) +# include +#endif + +#include +#include +#include + +#include "mem.h" +#include "debug.h" +#include "pdu.h" +#include "option.h" +#include "uri.h" + +/** + * A length-safe version of strchr(). This function returns a pointer + * to the first occurrence of @p c in @p s, or @c NULL if not found. + * + * @param s The string to search for @p c. + * @param len The length of @p s. + * @param c The character to search. + * + * @return A pointer to the first occurence of @p c, or @c NULL + * if not found. + */ +static inline unsigned char * +strnchr(unsigned char *s, size_t len, unsigned char c) { + while (len && *s++ != c) + --len; + + return len ? s : NULL; +} + +int +coap_split_uri(unsigned char *str_var, size_t len, coap_uri_t *uri) { + unsigned char *p, *q; + int secure = 0, res = 0; + + if (!str_var || !uri) + return -1; + + memset(uri, 0, sizeof(coap_uri_t)); + uri->port = COAP_DEFAULT_PORT; + + /* search for scheme */ + p = str_var; + if (*p == '/') { + q = p; + goto path; + } + + q = (unsigned char *)COAP_DEFAULT_SCHEME; + while (len && *q && tolower(*p) == *q) { + ++p; ++q; --len; + } + + /* If q does not point to the string end marker '\0', the schema + * identifier is wrong. */ + if (*q) { + res = -1; + goto error; + } + + /* There might be an additional 's', indicating the secure version: */ + if (len && (secure = tolower(*p) == 's')) { + ++p; --len; + uri->secure = 1; + } + + q = (unsigned char *)"://"; + while (len && *q && tolower(*p) == *q) { + ++p; ++q; --len; + } + + if (*q) { + res = -2; + goto error; + } + + /* p points to beginning of Uri-Host */ + q = p; + if (len && *p == '[') { /* IPv6 address reference */ + ++p; + + while (len && *q != ']') { + ++q; --len; + } + + if (!len || *q != ']' || p == q) { + res = -3; + goto error; + } + + COAP_SET_STR(&uri->host, q - p, p); + ++q; --len; + } else { /* IPv4 address or FQDN */ + while (len && *q != ':' && *q != '/' && *q != '?') { + *q = tolower(*q); + ++q; + --len; + } + + if (p == q) { + res = -3; + goto error; + } + + COAP_SET_STR(&uri->host, q - p, p); + } + + /* check for Uri-Port */ + if (len && *q == ':') { + p = ++q; + --len; + + while (len && isdigit(*q)) { + ++q; + --len; + } + + if (p < q) { /* explicit port number given */ + int uri_port = 0; + + while (p < q) + uri_port = uri_port * 10 + (*p++ - '0'); + + uri->port = uri_port; + } + } + + path: /* at this point, p must point to an absolute path */ + + if (!len) + goto end; + + if (*q == '/') { + p = ++q; + --len; + + while (len && *q != '?') { + ++q; + --len; + } + + if (p < q) { + COAP_SET_STR(&uri->path, q - p, p); + p = q; + } + } + + /* Uri_Query */ + if (len && *p == '?') { + ++p; + --len; + COAP_SET_STR(&uri->query, len, p); + len = 0; + } + + end: + return len ? -1 : 0; + + error: + return res; +} + +/** + * Calculates decimal value from hexadecimal ASCII character given in + * @p c. The caller must ensure that @p c actually represents a valid + * heaxdecimal character, e.g. with isxdigit(3). + * + * @hideinitializer + */ +#define hexchar_to_dec(c) ((c) & 0x40 ? ((c) & 0x0F) + 9 : ((c) & 0x0F)) + +/** + * Decodes percent-encoded characters while copying the string @p seg + * of size @p length to @p buf. The caller of this function must + * ensure that the percent-encodings are correct (i.e. the character + * '%' is always followed by two hex digits. and that @p buf provides + * sufficient space to hold the result. This function is supposed to + * be called by make_decoded_option() only. + * + * @param seg The segment to decode and copy. + * @param length Length of @p seg. + * @param buf The result buffer. + */ +void +decode_segment(const unsigned char *seg, size_t length, unsigned char *buf) { + + while (length--) { + + if (*seg == '%') { + *buf = (hexchar_to_dec(seg[1]) << 4) + hexchar_to_dec(seg[2]); + + seg += 2; length -= 2; + } else { + *buf = *seg; + } + + ++buf; ++seg; + } +} + +/** + * Runs through the given path (or query) segment and checks if + * percent-encodings are correct. This function returns @c -1 on error + * or the length of @p s when decoded. + */ +int +check_segment(const unsigned char *s, size_t length) { + + size_t n = 0; + + while (length) { + if (*s == '%') { + if (length < 2 || !(isxdigit(s[1]) && isxdigit(s[2]))) + return -1; + + s += 2; + length -= 2; + } + + ++s; ++n; --length; + } + + return n; +} + +/** + * Writes a coap option from given string @p s to @p buf. @p s should + * point to a (percent-encoded) path or query segment of a coap_uri_t + * object. The created option will have type @c 0, and the length + * parameter will be set according to the size of the decoded string. + * On success, this function returns the option's size, or a value + * less than zero on error. This function must be called from + * coap_split_path_impl() only. + * + * @param s The string to decode. + * @param length The size of the percent-encoded string @p s. + * @param buf The buffer to store the new coap option. + * @param buflen The maximum size of @p buf. + * + * @return The option's size, or @c -1 on error. + * + * @bug This function does not split segments that are bigger than 270 + * bytes. + */ +int +make_decoded_option(const unsigned char *s, size_t length, + unsigned char *buf, size_t buflen) { + int res; + size_t written; + + if (!buflen) { + debug("make_decoded_option(): buflen is 0!\n"); + return -1; + } + + res = check_segment(s, length); + if (res < 0) + return -1; + + /* write option header using delta 0 and length res */ + written = coap_opt_setheader(buf, buflen, 0, res); + + assert(written <= buflen); + + if (!written) /* encoding error */ + return -1; + + buf += written; /* advance past option type/length */ + buflen -= written; + + if (buflen < (size_t)res) { + debug("buffer too small for option\n"); + return -1; + } + + decode_segment(s, length, buf); + + return written + res; +} + + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +typedef void (*segment_handler_t)(unsigned char *, size_t, void *); + +/** + * Splits the given string into segments. You should call one of the + * macros coap_split_path() or coap_split_query() instead. + * + * @param parse_iter The iterator used for tokenizing. + * @param h A handler that is called with every token. + * @param data Opaque data that is passed to @p h when called. + * + * @return The number of characters that have been parsed from @p s. + */ +size_t +coap_split_path_impl(coap_parse_iterator_t *parse_iter, + segment_handler_t h, void *data) { + unsigned char *seg; + size_t length; + + assert(parse_iter); + assert(h); + + length = parse_iter->n; + + while ( (seg = coap_parse_next(parse_iter)) ) { + + /* any valid path segment is handled here: */ + h(seg, parse_iter->segment_length, data); + } + + return length - (parse_iter->n - parse_iter->segment_length); +} + +struct cnt_str { + str buf; + int n; +}; + +void +write_option(unsigned char *s, size_t len, void *data) { + struct cnt_str *state = (struct cnt_str *)data; + int res; + assert(state); + + /* skip empty segments and those that consist of only one or two dots */ + if (memcmp(s, "..", min(len,2)) == 0) + return; + + res = make_decoded_option(s, len, state->buf.s, state->buf.length); + if (res > 0) { + state->buf.s += res; + state->buf.length -= res; + state->n++; + } +} + +int +coap_split_path(const unsigned char *s, size_t length, + unsigned char *buf, size_t *buflen) { + struct cnt_str tmp = { { *buflen, buf }, 0 }; + coap_parse_iterator_t pi; + + coap_parse_iterator_init((unsigned char *)s, length, + '/', (unsigned char *)"?#", 2, &pi); + coap_split_path_impl(&pi, write_option, &tmp); + + *buflen = *buflen - tmp.buf.length; + return tmp.n; +} + +int +coap_split_query(const unsigned char *s, size_t length, + unsigned char *buf, size_t *buflen) { + struct cnt_str tmp = { { *buflen, buf }, 0 }; + coap_parse_iterator_t pi; + + coap_parse_iterator_init((unsigned char *)s, length, + '&', (unsigned char *)"#", 1, &pi); + + coap_split_path_impl(&pi, write_option, &tmp); + + *buflen = tmp.buf.length; + return tmp.n; +} + +#define URI_DATA(uriobj) ((unsigned char *)(uriobj) + sizeof(coap_uri_t)) + +coap_uri_t * +coap_new_uri(const unsigned char *uri, unsigned int length) { + unsigned char *result; + + result = (unsigned char*)coap_malloc(length + 1 + sizeof(coap_uri_t)); + + if (!result) + return NULL; + + memcpy(URI_DATA(result), uri, length); + URI_DATA(result)[length] = '\0'; /* make it zero-terminated */ + + if (coap_split_uri(URI_DATA(result), length, (coap_uri_t *)result) < 0) { + coap_free(result); + return NULL; + } + return (coap_uri_t *)result; +} + +coap_uri_t * +coap_clone_uri(const coap_uri_t *uri) { + coap_uri_t *result; + + if ( !uri ) + return NULL; + + result = (coap_uri_t *)coap_malloc( uri->query.length + uri->host.length + + uri->path.length + sizeof(coap_uri_t) + 1); + + if ( !result ) + return NULL; + + memset( result, 0, sizeof(coap_uri_t) ); + + result->port = uri->port; + + if ( uri->host.length ) { + result->host.s = URI_DATA(result); + result->host.length = uri->host.length; + + memcpy(result->host.s, uri->host.s, uri->host.length); + } + + if ( uri->path.length ) { + result->path.s = URI_DATA(result) + uri->host.length; + result->path.length = uri->path.length; + + memcpy(result->path.s, uri->path.s, uri->path.length); + } + + if ( uri->query.length ) { + result->query.s = URI_DATA(result) + uri->host.length + uri->path.length; + result->query.length = uri->query.length; + + memcpy(result->query.s, uri->query.s, uri->query.length); + } + + return result; +} + +/* hash URI path segments */ + +/* The function signature of coap_hash() is different from + * segment_handler_t hence we use this wrapper as safe typecast. */ +static inline void +hash_segment(unsigned char *s, size_t len, void *data) { + coap_hash(s, len, (unsigned char*)data); +} + +int +coap_hash_path(const unsigned char *path, size_t len, coap_key_t key) { + coap_parse_iterator_t pi; + + if (!path) + return 0; + + memset(key, 0, sizeof(coap_key_t)); + + coap_parse_iterator_init((unsigned char *)path, len, + '/', (unsigned char *)"?#", 2, &pi); + coap_split_path_impl(&pi, hash_segment, key); + + return 1; +} + +/* iterator functions */ + +coap_parse_iterator_t * +coap_parse_iterator_init(unsigned char *s, size_t n, + unsigned char separator, + unsigned char *delim, size_t dlen, + coap_parse_iterator_t *pi) { + assert(pi); + assert(separator); + + pi->separator = separator; + pi->delim = delim; + pi->dlen = dlen; + pi->pos = s; + pi->n = n; + pi->segment_length = 0; + + return pi; +} + +unsigned char * +coap_parse_next(coap_parse_iterator_t *pi) { + unsigned char *p; + + if (!pi) + return NULL; + + /* proceed to the next segment */ + pi->n -= pi->segment_length; + pi->pos += pi->segment_length; + pi->segment_length = 0; + + /* last segment? */ + if (!pi->n || strnchr(pi->delim, pi->dlen, *pi->pos)) { + pi->pos = NULL; + return NULL; + } + + /* skip following separator (the first segment might not have one) */ + if (*pi->pos == pi->separator) { + ++pi->pos; + --pi->n; + } + + p = pi->pos; + + while (pi->segment_length < pi->n && *p != pi->separator && + !strnchr(pi->delim, pi->dlen, *p)) { + ++p; + ++pi->segment_length; + } + + if (!pi->n) { + pi->pos = NULL; + pi->segment_length = 0; + } + + return pi->pos; +} + diff --git a/resource/csdk/libcoap-4.1.1/uri.h b/resource/csdk/libcoap-4.1.1/uri.h new file mode 100644 index 000000000..31ee38654 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/uri.h @@ -0,0 +1,174 @@ +/* uri.h -- helper functions for URI treatment + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef _COAP_URI_H_ +#define _COAP_URI_H_ + +#include "hashkey.h" +#include "str.h" + +/** Representation of parsed URI. Components may be filled from a + * string with coap_split_uri() and can be used as input for + * option-creation functions. */ +typedef struct { + str host; /**< host part of the URI */ + unsigned short port; /**< The port in host byte order */ + str path; /**< Beginning of the first path segment. + Use coap_split_path() to create Uri-Path options */ + str query; /**< The query part if present */ + unsigned char secure; /**< uses coaps URI schema */ +} coap_uri_t; + +/** + * Creates a new coap_uri_t object from the specified URI. Returns the new + * object or NULL on error. The memory allocated by the new coap_uri_t + * must be released using coap_free(). + * @param uri The URI path to copy. + * @para length The length of uri. + * + * @return New URI object or NULL on error. + */ +coap_uri_t *coap_new_uri(const unsigned char *uri, unsigned int length); + +/** + * Clones the specified coap_uri_t object. Thie function allocates sufficient + * memory to hold the coap_uri_t structure and its contents. The object must + * be released with coap_free(). */ +coap_uri_t *coap_clone_uri(const coap_uri_t *uri); + +/** + * Calculates a hash over the given path and stores the result in + * @p key. This function returns @c 0 on error or @c 1 on success. + * + * @param path The URI path to generate hash for. + * @param len The length of @p path. + * @param key The output buffer. + * + * @return @c 1 if @p key was set, @c 0 otherwise. + */ +int coap_hash_path(const unsigned char *path, size_t len, coap_key_t key); + +/** + * @defgroup uri_parse URI Parsing Functions + * + * CoAP PDUs contain normalized URIs with their path and query split into + * multiple segments. The functions in this module help splitting strings. + * @{ + */ + +/** + * Iterator to for tokenizing a URI path or query. This structure must + * be initialized with coap_parse_iterator_init(). Call + * coap_parse_next() to walk through the tokens. + * + * @code + * unsigned char *token; + * coap_parse_iterator_t pi; + * coap_parse_iterator_init(uri.path.s, uri.path.length, '/', "?#", 2, &pi); + * + * while ((token = coap_parse_next(&pi))) { + * ... do something with token ... + * } + * @endcode + */ +typedef struct { + size_t n; /**< number of remaining characters in buffer */ + unsigned char separator; /**< segment separators */ + unsigned char *delim; /**< delimiters where to split the string */ + size_t dlen; /**< length of separator */ + unsigned char *pos; /**< current position in buffer */ + size_t segment_length; /**< length of current segment */ +} coap_parse_iterator_t; + +/** + * Initializes the given iterator @p pi. + * + * @param s The string to tokenize. + * @param n The length of @p s. + * @param separator The separator character that delimits tokens. + * @param delim A set of characters that delimit @s. + * @param dlen The length of @p delim. + * @param pi The iterator object to initialize. + * + * @return The initialized iterator object @p pi. + */ +coap_parse_iterator_t * +coap_parse_iterator_init(unsigned char *s, size_t n, + unsigned char separator, + unsigned char *delim, size_t dlen, + coap_parse_iterator_t *pi); + +/** + * Updates the iterator @p pi to point to the next token. This + * function returns a pointer to that token or @c NULL if no more + * tokens exist. The contents of @p pi will be updated. In particular, + * @c pi->segment_length specifies the length of the current token, @c + * pi->pos points to its beginning. + * + * @param pi The iterator to update. + * + * @return The next token or @c NULL if no more tokens exist. + */ +unsigned char *coap_parse_next(coap_parse_iterator_t *pi); + +/** + * Parses a given string into URI components. The identified syntactic + * components are stored in the result parameter @p uri. Optional URI + * components that are not specified will be set to { 0, 0 }, except + * for the port which is set to @c COAP_DEFAULT_PORT. This function + * returns @p 0 if parsing succeeded, a value less than zero + * otherwise. + * + * @param str_var The string to split up. + * @param len The actual length of @p str_var + * @param uri The coap_uri_t object to store the result. + * @return @c 0 on success, or < 0 on error. + * + * @note The host name part will be converted to lower case by this + * function. + */ +int +coap_split_uri(unsigned char *str_var, size_t len, coap_uri_t *uri); + +/** + * Splits the given URI path into segments. Each segment is preceded + * by an option pseudo-header with delta-value 0 and the actual length + * of the respective segment after percent-decoding. + * + * @param s The path string to split. + * @param length The actual length of @p s. + * @param buf Result buffer for parsed segments. + * @param buflen Maximum length of @p buf. Will be set to the actual number + * of bytes written into buf on success. + * + * @return The number of segments created or @c -1 on error. + */ +int coap_split_path(const unsigned char *s, size_t length, + unsigned char *buf, size_t *buflen); + +/** + * Splits the given URI query into segments. Each segment is preceded + * by an option pseudo-header with delta-value 0 and the actual length + * of the respective query term. + * + * @param s The query string to split. + * @param length The actual length of @p s. + * @param buf Result buffer for parsed segments. + * @param buflen Maximum length of @p buf. Will be set to the actual number + * of bytes written into buf on success. + * + * @return The number of segments created or @c -1 on error. + * + * @bug This function does not reserve additional space for delta > 12. + */ +int coap_split_query(const unsigned char *s, size_t length, + unsigned char *buf, size_t *buflen); + +/** @} */ + +#endif /* _COAP_URI_H_ */ diff --git a/resource/csdk/libcoap-4.1.1/uthash.h b/resource/csdk/libcoap-4.1.1/uthash.h new file mode 100644 index 000000000..d2da6e541 --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/uthash.h @@ -0,0 +1,977 @@ +/* +Copyright (c) 2003-2010, Troy D. Hanson http://uthash.sourceforge.net +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef UTHASH_H +#define UTHASH_H + +#include /* memcmp,strlen */ +#include /* ptrdiff_t */ + +#include "ocmalloc.h" + +/* These macros use decltype or the earlier __typeof GNU extension. + As decltype is only available in newer compilers (VS2010 or gcc 4.3+ + when compiling c++ source) this code uses whatever method is needed + or, for VS2008 where neither is available, uses casting workarounds. */ +#ifdef _MSC_VER /* MS compiler */ +#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ +#define DECLTYPE(x) (decltype(x)) +#else /* VS2008 or older (or VS2010 in C mode) */ +#define NO_DECLTYPE +#define DECLTYPE(x) +#endif +#else /* GNU, Sun and other compilers */ +#define DECLTYPE(x) (__typeof(x)) +#endif + +#ifdef NO_DECLTYPE +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + char **_da_dst = (char**)(&(dst)); \ + *_da_dst = (char*)(src); \ +} while(0) +#else +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + (dst) = DECLTYPE(dst)(src); \ +} while(0) +#endif + +/* a number of the hash function use uint32_t which isn't defined on win32 */ +#ifdef _MSC_VER +typedef unsigned int uint32_t; +#else +#include /* uint32_t */ +#endif + +#define UTHASH_VERSION 1.9.3 + +#ifndef uthash_fatal +#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */ +#endif + +#define uthash_malloc(sz) OCMalloc(sz) +#define uthash_free(ptr,sz) OCFree(ptr) + +#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ +#define uthash_expand_fyi(tbl) /* can be defined to log expands */ + +/* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */ +#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */ + +/* calculate the element whose hash handle address is hhe */ +#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) + +#define HASH_FIND(hh,head,keyptr,keylen,out) \ +do { \ + unsigned _hf_bkt,_hf_hashv; \ + out=NULL; \ + if (head) { \ + HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \ + if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \ + HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \ + keyptr,keylen,out); \ + } \ + } \ +} while (0) + +#ifdef HASH_BLOOM +#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM) +#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0) +#define HASH_BLOOM_MAKE(tbl) \ +do { \ + (tbl)->bloom_nbits = HASH_BLOOM; \ + (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ + if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \ + memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \ + (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ +} while (0); + +#define HASH_BLOOM_FREE(tbl) \ +do { \ + uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ +} while (0); + +#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8))) +#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8))) + +#define HASH_BLOOM_ADD(tbl,hashv) \ + HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) + +#define HASH_BLOOM_TEST(tbl,hashv) \ + HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) + +#else +#define HASH_BLOOM_MAKE(tbl) +#define HASH_BLOOM_FREE(tbl) +#define HASH_BLOOM_ADD(tbl,hashv) +#define HASH_BLOOM_TEST(tbl,hashv) (1) +#endif + +#define HASH_MAKE_TABLE(hh,head) \ +do { \ + (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \ + sizeof(UT_hash_table)); \ + if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \ + memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \ + (head)->hh.tbl->tail = &((head)->hh); \ + (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ + (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ + (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ + (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ + HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ + if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \ + memset((head)->hh.tbl->buckets, 0, \ + HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ + HASH_BLOOM_MAKE((head)->hh.tbl); \ + (head)->hh.tbl->signature = HASH_SIGNATURE; \ +} while(0) + +#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ + HASH_ADD_KEYPTR(hh,head,&add->fieldname,keylen_in,add) + +#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ +do { \ + unsigned _ha_bkt; \ + (add)->hh.next = NULL; \ + (add)->hh.key = (char*)keyptr; \ + (add)->hh.keylen = keylen_in; \ + if (!(head)) { \ + head = (add); \ + (head)->hh.prev = NULL; \ + HASH_MAKE_TABLE(hh,head); \ + } else { \ + (head)->hh.tbl->tail->next = (add); \ + (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ + (head)->hh.tbl->tail = &((add)->hh); \ + } \ + (head)->hh.tbl->num_items++; \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \ + (add)->hh.hashv, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \ + HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \ + HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \ + HASH_FSCK(hh,head); \ +} while(0) + +#define HASH_TO_BKT( hashv, num_bkts, bkt ) \ +do { \ + bkt = ((hashv) & ((num_bkts) - 1)); \ +} while(0) + +/* delete "delptr" from the hash table. + * "the usual" patch-up process for the app-order doubly-linked-list. + * The use of _hd_hh_del below deserves special explanation. + * These used to be expressed using (delptr) but that led to a bug + * if someone used the same symbol for the head and deletee, like + * HASH_DELETE(hh,users,users); + * We want that to work, but by changing the head (users) below + * we were forfeiting our ability to further refer to the deletee (users) + * in the patch-up process. Solution: use scratch space to + * copy the deletee pointer, then the latter references are via that + * scratch pointer rather than through the repointed (users) symbol. + */ +#define HASH_DELETE(hh,head,delptr) \ +do { \ + unsigned _hd_bkt; \ + struct UT_hash_handle *_hd_hh_del; \ + if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + head = NULL; \ + } else { \ + _hd_hh_del = &((delptr)->hh); \ + if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \ + (head)->hh.tbl->tail = \ + (UT_hash_handle*)((char*)((delptr)->hh.prev) + \ + (head)->hh.tbl->hho); \ + } \ + if ((delptr)->hh.prev) { \ + ((UT_hash_handle*)((char*)((delptr)->hh.prev) + \ + (head)->hh.tbl->hho))->next = (delptr)->hh.next; \ + } else { \ + DECLTYPE_ASSIGN(head,(delptr)->hh.next); \ + } \ + if (_hd_hh_del->next) { \ + ((UT_hash_handle*)((char*)_hd_hh_del->next + \ + (head)->hh.tbl->hho))->prev = \ + _hd_hh_del->prev; \ + } \ + HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ + HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ + (head)->hh.tbl->num_items--; \ + } \ + HASH_FSCK(hh,head); \ +} while (0) + + +/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ +#define HASH_FIND_STR(head,findstr,out) \ + HASH_FIND(hh,head,findstr,strlen(findstr),out) +#define HASH_ADD_STR(head,strfield,add) \ + HASH_ADD(hh,head,strfield,strlen(add->strfield),add) +#define HASH_FIND_INT(head,findint,out) \ + HASH_FIND(hh,head,findint,sizeof(int),out) +#define HASH_ADD_INT(head,intfield,add) \ + HASH_ADD(hh,head,intfield,sizeof(int),add) +#define HASH_FIND_PTR(head,findptr,out) \ + HASH_FIND(hh,head,findptr,sizeof(void *),out) +#define HASH_ADD_PTR(head,ptrfield,add) \ + HASH_ADD(hh,head,ptrfield,sizeof(void *),add) +#define HASH_DEL(head,delptr) \ + HASH_DELETE(hh,head,delptr) + +/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. + * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. + */ +#ifdef HASH_DEBUG +#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0) +#define HASH_FSCK(hh,head) \ +do { \ + unsigned _bkt_i; \ + unsigned _count, _bkt_count; \ + char *_prev; \ + struct UT_hash_handle *_thh; \ + if (head) { \ + _count = 0; \ + for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \ + _bkt_count = 0; \ + _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ + _prev = NULL; \ + while (_thh) { \ + if (_prev != (char*)(_thh->hh_prev)) { \ + HASH_OOPS("invalid hh_prev %p, actual %p\n", \ + _thh->hh_prev, _prev ); \ + } \ + _bkt_count++; \ + _prev = (char*)(_thh); \ + _thh = _thh->hh_next; \ + } \ + _count += _bkt_count; \ + if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ + HASH_OOPS("invalid bucket count %d, actual %d\n", \ + (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ + } \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("invalid hh item count %d, actual %d\n", \ + (head)->hh.tbl->num_items, _count ); \ + } \ + /* traverse hh in app order; check next/prev integrity, count */ \ + _count = 0; \ + _prev = NULL; \ + _thh = &(head)->hh; \ + while (_thh) { \ + _count++; \ + if (_prev !=(char*)(_thh->prev)) { \ + HASH_OOPS("invalid prev %p, actual %p\n", \ + _thh->prev, _prev ); \ + } \ + _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ + _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \ + (head)->hh.tbl->hho) : NULL ); \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("invalid app item count %d, actual %d\n", \ + (head)->hh.tbl->num_items, _count ); \ + } \ + } \ +} while (0) +#else +#define HASH_FSCK(hh,head) +#endif + +/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to + * the descriptor to which this macro is defined for tuning the hash function. + * The app can #include to get the prototype for write(2). */ +#ifdef HASH_EMIT_KEYS +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ +do { \ + unsigned _klen = fieldlen; \ + write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ + write(HASH_EMIT_KEYS, keyptr, fieldlen); \ +} while (0) +#else +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) +#endif + +/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */ +#ifdef HASH_FUNCTION +#define HASH_FCN HASH_FUNCTION +#else +#define HASH_FCN HASH_JEN +#endif + +/* The Bernstein hash function, used in Perl prior to v5.6 */ +#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \ +do { \ + unsigned _hb_keylen=keylen; \ + char *_hb_key=(char*)(key); \ + (hashv) = 0; \ + while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \ + bkt = (hashv) & (num_bkts-1); \ +} while (0) + + +/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at + * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */ +#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \ +do { \ + unsigned _sx_i; \ + char *_hs_key=(char*)(key); \ + hashv = 0; \ + for(_sx_i=0; _sx_i < keylen; _sx_i++) \ + hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ + bkt = hashv & (num_bkts-1); \ +} while (0) + +#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \ +do { \ + unsigned _fn_i; \ + char *_hf_key=(char*)(key); \ + hashv = 2166136261UL; \ + for(_fn_i=0; _fn_i < keylen; _fn_i++) \ + hashv = (hashv * 16777619) ^ _hf_key[_fn_i]; \ + bkt = hashv & (num_bkts-1); \ +} while(0); + +#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \ +do { \ + unsigned _ho_i; \ + char *_ho_key=(char*)(key); \ + hashv = 0; \ + for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ + hashv += _ho_key[_ho_i]; \ + hashv += (hashv << 10); \ + hashv ^= (hashv >> 6); \ + } \ + hashv += (hashv << 3); \ + hashv ^= (hashv >> 11); \ + hashv += (hashv << 15); \ + bkt = hashv & (num_bkts-1); \ +} while(0) + +#define HASH_JEN_MIX(a,b,c) \ +do { \ + a -= b; a -= c; a ^= ( c >> 13 ); \ + b -= c; b -= a; b ^= ( a << 8 ); \ + c -= a; c -= b; c ^= ( b >> 13 ); \ + a -= b; a -= c; a ^= ( c >> 12 ); \ + b -= c; b -= a; b ^= ( a << 16 ); \ + c -= a; c -= b; c ^= ( b >> 5 ); \ + a -= b; a -= c; a ^= ( c >> 3 ); \ + b -= c; b -= a; b ^= ( a << 10 ); \ + c -= a; c -= b; c ^= ( b >> 15 ); \ +} while (0) + +#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \ +do { \ + unsigned _hj_i,_hj_j,_hj_k; \ + char *_hj_key=(char*)(key); \ + hashv = 0xfeedbeef; \ + _hj_i = _hj_j = 0x9e3779b9; \ + _hj_k = keylen; \ + while (_hj_k >= 12) { \ + _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ + + ( (unsigned)_hj_key[2] << 16 ) \ + + ( (unsigned)_hj_key[3] << 24 ) ); \ + _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ + + ( (unsigned)_hj_key[6] << 16 ) \ + + ( (unsigned)_hj_key[7] << 24 ) ); \ + hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ + + ( (unsigned)_hj_key[10] << 16 ) \ + + ( (unsigned)_hj_key[11] << 24 ) ); \ + \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ + \ + _hj_key += 12; \ + _hj_k -= 12; \ + } \ + hashv += keylen; \ + switch ( _hj_k ) { \ + case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \ + case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \ + case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \ + case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \ + case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \ + case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \ + case 5: _hj_j += _hj_key[4]; \ + case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \ + case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \ + case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \ + case 1: _hj_i += _hj_key[0]; \ + } \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ + bkt = hashv & (num_bkts-1); \ +} while(0) + +/* The Paul Hsieh hash function */ +#undef get16bits +#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ + || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) +#define get16bits(d) (*((const uint16_t *) (d))) +#endif + +#if !defined (get16bits) +#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ + +(uint32_t)(((const uint8_t *)(d))[0]) ) +#endif +#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \ +do { \ + char *_sfh_key=(char*)(key); \ + uint32_t _sfh_tmp, _sfh_len = keylen; \ + \ + int _sfh_rem = _sfh_len & 3; \ + _sfh_len >>= 2; \ + hashv = 0xcafebabe; \ + \ + /* Main loop */ \ + for (;_sfh_len > 0; _sfh_len--) { \ + hashv += get16bits (_sfh_key); \ + _sfh_tmp = (get16bits (_sfh_key+2) << 11) ^ hashv; \ + hashv = (hashv << 16) ^ _sfh_tmp; \ + _sfh_key += 2*sizeof (uint16_t); \ + hashv += hashv >> 11; \ + } \ + \ + /* Handle end cases */ \ + switch (_sfh_rem) { \ + case 3: hashv += get16bits (_sfh_key); \ + hashv ^= hashv << 16; \ + hashv ^= _sfh_key[sizeof (uint16_t)] << 18; \ + hashv += hashv >> 11; \ + break; \ + case 2: hashv += get16bits (_sfh_key); \ + hashv ^= hashv << 11; \ + hashv += hashv >> 17; \ + break; \ + case 1: hashv += *_sfh_key; \ + hashv ^= hashv << 10; \ + hashv += hashv >> 1; \ + } \ + \ + /* Force "avalanching" of final 127 bits */ \ + hashv ^= hashv << 3; \ + hashv += hashv >> 5; \ + hashv ^= hashv << 4; \ + hashv += hashv >> 17; \ + hashv ^= hashv << 25; \ + hashv += hashv >> 6; \ + bkt = hashv & (num_bkts-1); \ +} while(0); + +#ifdef HASH_USING_NO_STRICT_ALIASING +/* The MurmurHash exploits some CPU's (e.g. x86) tolerance for unaligned reads. + * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error. + * So MurmurHash comes in two versions, the faster unaligned one and the slower + * aligned one. We only use the faster one on CPU's where we know it's safe. + * + * Note the preprocessor built-in defines can be emitted using: + * + * gcc -m64 -dM -E - < /dev/null (on gcc) + * cc -## a.c (where a.c is a simple test file) (Sun Studio) + */ +#if (defined(__i386__) || defined(__x86_64__)) +#define HASH_MUR HASH_MUR_UNALIGNED +#else +#define HASH_MUR HASH_MUR_ALIGNED +#endif + +/* Appleby's MurmurHash fast version for unaligned-tolerant archs like i386 */ +#define HASH_MUR_UNALIGNED(key,keylen,num_bkts,hashv,bkt) \ +do { \ + const unsigned int _mur_m = 0x5bd1e995; \ + const int _mur_r = 24; \ + hashv = 0xcafebabe ^ keylen; \ + char *_mur_key = (char *)(key); \ + uint32_t _mur_tmp, _mur_len = keylen; \ + \ + for (;_mur_len >= 4; _mur_len-=4) { \ + _mur_tmp = *(uint32_t *)_mur_key; \ + _mur_tmp *= _mur_m; \ + _mur_tmp ^= _mur_tmp >> _mur_r; \ + _mur_tmp *= _mur_m; \ + hashv *= _mur_m; \ + hashv ^= _mur_tmp; \ + _mur_key += 4; \ + } \ + \ + switch(_mur_len) \ + { \ + case 3: hashv ^= _mur_key[2] << 16; \ + case 2: hashv ^= _mur_key[1] << 8; \ + case 1: hashv ^= _mur_key[0]; \ + hashv *= _mur_m; \ + }; \ + \ + hashv ^= hashv >> 13; \ + hashv *= _mur_m; \ + hashv ^= hashv >> 15; \ + \ + bkt = hashv & (num_bkts-1); \ +} while(0) + +/* Appleby's MurmurHash version for alignment-sensitive archs like Sparc */ +#define HASH_MUR_ALIGNED(key,keylen,num_bkts,hashv,bkt) \ +do { \ + const unsigned int _mur_m = 0x5bd1e995; \ + const int _mur_r = 24; \ + hashv = 0xcafebabe ^ (keylen); \ + char *_mur_key = (char *)(key); \ + uint32_t _mur_len = keylen; \ + int _mur_align = (int)_mur_key & 3; \ + \ + if (_mur_align && (_mur_len >= 4)) { \ + unsigned _mur_t = 0, _mur_d = 0; \ + switch(_mur_align) { \ + case 1: _mur_t |= _mur_key[2] << 16; \ + case 2: _mur_t |= _mur_key[1] << 8; \ + case 3: _mur_t |= _mur_key[0]; \ + } \ + _mur_t <<= (8 * _mur_align); \ + _mur_key += 4-_mur_align; \ + _mur_len -= 4-_mur_align; \ + int _mur_sl = 8 * (4-_mur_align); \ + int _mur_sr = 8 * _mur_align; \ + \ + for (;_mur_len >= 4; _mur_len-=4) { \ + _mur_d = *(unsigned *)_mur_key; \ + _mur_t = (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \ + unsigned _mur_k = _mur_t; \ + _mur_k *= _mur_m; \ + _mur_k ^= _mur_k >> _mur_r; \ + _mur_k *= _mur_m; \ + hashv *= _mur_m; \ + hashv ^= _mur_k; \ + _mur_t = _mur_d; \ + _mur_key += 4; \ + } \ + _mur_d = 0; \ + if(_mur_len >= _mur_align) { \ + switch(_mur_align) { \ + case 3: _mur_d |= _mur_key[2] << 16; \ + case 2: _mur_d |= _mur_key[1] << 8; \ + case 1: _mur_d |= _mur_key[0]; \ + } \ + unsigned _mur_k = (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \ + _mur_k *= _mur_m; \ + _mur_k ^= _mur_k >> _mur_r; \ + _mur_k *= _mur_m; \ + hashv *= _mur_m; \ + hashv ^= _mur_k; \ + _mur_k += _mur_align; \ + _mur_len -= _mur_align; \ + \ + switch(_mur_len) \ + { \ + case 3: hashv ^= _mur_key[2] << 16; \ + case 2: hashv ^= _mur_key[1] << 8; \ + case 1: hashv ^= _mur_key[0]; \ + hashv *= _mur_m; \ + } \ + } else { \ + switch(_mur_len) \ + { \ + case 3: _mur_d ^= _mur_key[2] << 16; \ + case 2: _mur_d ^= _mur_key[1] << 8; \ + case 1: _mur_d ^= _mur_key[0]; \ + case 0: hashv ^= (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \ + hashv *= _mur_m; \ + } \ + } \ + \ + hashv ^= hashv >> 13; \ + hashv *= _mur_m; \ + hashv ^= hashv >> 15; \ + } else { \ + for (;_mur_len >= 4; _mur_len-=4) { \ + unsigned _mur_k = *(unsigned*)_mur_key; \ + _mur_k *= _mur_m; \ + _mur_k ^= _mur_k >> _mur_r; \ + _mur_k *= _mur_m; \ + hashv *= _mur_m; \ + hashv ^= _mur_k; \ + _mur_key += 4; \ + } \ + switch(_mur_len) \ + { \ + case 3: hashv ^= _mur_key[2] << 16; \ + case 2: hashv ^= _mur_key[1] << 8; \ + case 1: hashv ^= _mur_key[0]; \ + hashv *= _mur_m; \ + } \ + \ + hashv ^= hashv >> 13; \ + hashv *= _mur_m; \ + hashv ^= hashv >> 15; \ + } \ + bkt = hashv & (num_bkts-1); \ +} while(0) +#endif /* HASH_USING_NO_STRICT_ALIASING */ + +/* key comparison function; return 0 if keys equal */ +#define HASH_KEYCMP(a,b,len) memcmp(a,b,len) + +/* iterate over items in a known bucket to find desired item */ +#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \ +do { \ + if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \ + else out=NULL; \ + while (out) { \ + if (out->hh.keylen == keylen_in) { \ + if ((HASH_KEYCMP(out->hh.key,keyptr,keylen_in)) == 0) break; \ + } \ + if (out->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,out->hh.hh_next)); \ + else out = NULL; \ + } \ +} while(0) + +/* add an item to a bucket */ +#define HASH_ADD_TO_BKT(head,addhh) \ +do { \ + head.count++; \ + (addhh)->hh_next = head.hh_head; \ + (addhh)->hh_prev = NULL; \ + if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \ + (head).hh_head=addhh; \ + if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \ + && (addhh)->tbl->noexpand != 1) { \ + HASH_EXPAND_BUCKETS((addhh)->tbl); \ + } \ +} while(0) + +/* remove an item from a given bucket */ +#define HASH_DEL_IN_BKT(hh,head,hh_del) \ + (head).count--; \ + if ((head).hh_head == hh_del) { \ + (head).hh_head = hh_del->hh_next; \ + } \ + if (hh_del->hh_prev) { \ + hh_del->hh_prev->hh_next = hh_del->hh_next; \ + } \ + if (hh_del->hh_next) { \ + hh_del->hh_next->hh_prev = hh_del->hh_prev; \ + } + +/* Bucket expansion has the effect of doubling the number of buckets + * and redistributing the items into the new buckets. Ideally the + * items will distribute more or less evenly into the new buckets + * (the extent to which this is true is a measure of the quality of + * the hash function as it applies to the key domain). + * + * With the items distributed into more buckets, the chain length + * (item count) in each bucket is reduced. Thus by expanding buckets + * the hash keeps a bound on the chain length. This bounded chain + * length is the essence of how a hash provides constant time lookup. + * + * The calculation of tbl->ideal_chain_maxlen below deserves some + * explanation. First, keep in mind that we're calculating the ideal + * maximum chain length based on the *new* (doubled) bucket count. + * In fractions this is just n/b (n=number of items,b=new num buckets). + * Since the ideal chain length is an integer, we want to calculate + * ceil(n/b). We don't depend on floating point arithmetic in this + * hash, so to calculate ceil(n/b) with integers we could write + * + * ceil(n/b) = (n/b) + ((n%b)?1:0) + * + * and in fact a previous version of this hash did just that. + * But now we have improved things a bit by recognizing that b is + * always a power of two. We keep its base 2 log handy (call it lb), + * so now we can write this with a bit shift and logical AND: + * + * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) + * + */ +#define HASH_EXPAND_BUCKETS(tbl) \ +do { \ + unsigned _he_bkt; \ + unsigned _he_bkt_i; \ + struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ + UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ + _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ + 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \ + memset(_he_new_buckets, 0, \ + 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + tbl->ideal_chain_maxlen = \ + (tbl->num_items >> (tbl->log2_num_buckets+1)) + \ + ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \ + tbl->nonideal_items = 0; \ + for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \ + { \ + _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \ + while (_he_thh) { \ + _he_hh_nxt = _he_thh->hh_next; \ + HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \ + _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \ + if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \ + tbl->nonideal_items++; \ + _he_newbkt->expand_mult = _he_newbkt->count / \ + tbl->ideal_chain_maxlen; \ + } \ + _he_thh->hh_prev = NULL; \ + _he_thh->hh_next = _he_newbkt->hh_head; \ + if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \ + _he_thh; \ + _he_newbkt->hh_head = _he_thh; \ + _he_thh = _he_hh_nxt; \ + } \ + } \ + uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ + tbl->num_buckets *= 2; \ + tbl->log2_num_buckets++; \ + tbl->buckets = _he_new_buckets; \ + tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \ + (tbl->ineff_expands+1) : 0; \ + if (tbl->ineff_expands > 1) { \ + tbl->noexpand=1; \ + uthash_noexpand_fyi(tbl); \ + } \ + uthash_expand_fyi(tbl); \ +} while(0) + + +/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ +/* Note that HASH_SORT assumes the hash handle name to be hh. + * HASH_SRT was added to allow the hash handle name to be passed in. */ +#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) +#define HASH_SRT(hh,head,cmpfcn) \ +do { \ + unsigned _hs_i; \ + unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ + struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ + if (head) { \ + _hs_insize = 1; \ + _hs_looping = 1; \ + _hs_list = &((head)->hh); \ + while (_hs_looping) { \ + _hs_p = _hs_list; \ + _hs_list = NULL; \ + _hs_tail = NULL; \ + _hs_nmerges = 0; \ + while (_hs_p) { \ + _hs_nmerges++; \ + _hs_q = _hs_p; \ + _hs_psize = 0; \ + for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \ + _hs_psize++; \ + _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ + ((void*)((char*)(_hs_q->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + if (! (_hs_q) ) break; \ + } \ + _hs_qsize = _hs_insize; \ + while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \ + if (_hs_psize == 0) { \ + _hs_e = _hs_q; \ + _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ + ((void*)((char*)(_hs_q->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + _hs_qsize--; \ + } else if ( (_hs_qsize == 0) || !(_hs_q) ) { \ + _hs_e = _hs_p; \ + _hs_p = (UT_hash_handle*)((_hs_p->next) ? \ + ((void*)((char*)(_hs_p->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + _hs_psize--; \ + } else if (( \ + cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \ + DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \ + ) <= 0) { \ + _hs_e = _hs_p; \ + _hs_p = (UT_hash_handle*)((_hs_p->next) ? \ + ((void*)((char*)(_hs_p->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + _hs_psize--; \ + } else { \ + _hs_e = _hs_q; \ + _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ + ((void*)((char*)(_hs_q->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + _hs_qsize--; \ + } \ + if ( _hs_tail ) { \ + _hs_tail->next = ((_hs_e) ? \ + ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \ + } else { \ + _hs_list = _hs_e; \ + } \ + _hs_e->prev = ((_hs_tail) ? \ + ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \ + _hs_tail = _hs_e; \ + } \ + _hs_p = _hs_q; \ + } \ + _hs_tail->next = NULL; \ + if ( _hs_nmerges <= 1 ) { \ + _hs_looping=0; \ + (head)->hh.tbl->tail = _hs_tail; \ + DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ + } \ + _hs_insize *= 2; \ + } \ + HASH_FSCK(hh,head); \ + } \ +} while (0) + +/* This function selects items from one hash into another hash. + * The end result is that the selected items have dual presence + * in both hashes. There is no copy of the items made; rather + * they are added into the new hash through a secondary hash + * hash handle that must be present in the structure. */ +#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ +do { \ + unsigned _src_bkt, _dst_bkt; \ + void *_last_elt=NULL, *_elt; \ + UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ + ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ + if (src) { \ + for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ + for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ + _src_hh; \ + _src_hh = _src_hh->hh_next) { \ + _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ + if (cond(_elt)) { \ + _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \ + _dst_hh->key = _src_hh->key; \ + _dst_hh->keylen = _src_hh->keylen; \ + _dst_hh->hashv = _src_hh->hashv; \ + _dst_hh->prev = _last_elt; \ + _dst_hh->next = NULL; \ + if (_last_elt_hh) { _last_elt_hh->next = _elt; } \ + if (!dst) { \ + DECLTYPE_ASSIGN(dst,_elt); \ + HASH_MAKE_TABLE(hh_dst,dst); \ + } else { \ + _dst_hh->tbl = (dst)->hh_dst.tbl; \ + } \ + HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ + HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \ + (dst)->hh_dst.tbl->num_items++; \ + _last_elt = _elt; \ + _last_elt_hh = _dst_hh; \ + } \ + } \ + } \ + } \ + HASH_FSCK(hh_dst,dst); \ +} while (0) + +#define HASH_CLEAR(hh,head) \ +do { \ + if (head) { \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head)=NULL; \ + } \ +} while(0) + +#ifdef NO_DECLTYPE +#define HASH_ITER(hh,head,el,tmp) \ +for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \ + el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL)) +#else +#define HASH_ITER(hh,head,el,tmp) \ +for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \ + el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL)) +#endif + +/* obtain a count of items in the hash */ +#define HASH_COUNT(head) HASH_CNT(hh,head) +#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0) + +typedef struct UT_hash_bucket { + struct UT_hash_handle *hh_head; + unsigned count; + + /* expand_mult is normally set to 0. In this situation, the max chain length + * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If + * the bucket's chain exceeds this length, bucket expansion is triggered). + * However, setting expand_mult to a non-zero value delays bucket expansion + * (that would be triggered by additions to this particular bucket) + * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. + * (The multiplier is simply expand_mult+1). The whole idea of this + * multiplier is to reduce bucket expansions, since they are expensive, in + * situations where we know that a particular bucket tends to be overused. + * It is better to let its chain length grow to a longer yet-still-bounded + * value, than to do an O(n) bucket expansion too often. + */ + unsigned expand_mult; + +} UT_hash_bucket; + +/* random signature used only to find hash tables in external analysis */ +#define HASH_SIGNATURE 0xa0111fe1 +#define HASH_BLOOM_SIGNATURE 0xb12220f2 + +typedef struct UT_hash_table { + UT_hash_bucket *buckets; + unsigned num_buckets, log2_num_buckets; + unsigned num_items; + struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ + ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ + + /* in an ideal situation (all buckets used equally), no bucket would have + * more than ceil(#items/#buckets) items. that's the ideal chain length. */ + unsigned ideal_chain_maxlen; + + /* nonideal_items is the number of items in the hash whose chain position + * exceeds the ideal chain maxlen. these items pay the penalty for an uneven + * hash distribution; reaching them in a chain traversal takes >ideal steps */ + unsigned nonideal_items; + + /* ineffective expands occur when a bucket doubling was performed, but + * afterward, more than half the items in the hash had nonideal chain + * positions. If this happens on two consecutive expansions we inhibit any + * further expansion, as it's not helping; this happens when the hash + * function isn't a good fit for the key domain. When expansion is inhibited + * the hash will still work, albeit no longer in constant time. */ + unsigned ineff_expands, noexpand; + + uint32_t signature; /* used only to find hash tables in external analysis */ +#ifdef HASH_BLOOM + uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ + uint8_t *bloom_bv; + char bloom_nbits; +#endif + +} UT_hash_table; + +typedef struct UT_hash_handle { + struct UT_hash_table *tbl; + void *prev; /* prev element in app order */ + void *next; /* next element in app order */ + struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ + struct UT_hash_handle *hh_next; /* next hh in bucket order */ + void *key; /* ptr to enclosing struct's key */ + unsigned keylen; /* enclosing struct's key len */ + unsigned hashv; /* result of hash-fcn(key) */ +} UT_hash_handle; + +#endif /* UTHASH_H */ diff --git a/resource/csdk/libcoap-4.1.1/utlist.h b/resource/csdk/libcoap-4.1.1/utlist.h new file mode 100644 index 000000000..35fc9dbba --- /dev/null +++ b/resource/csdk/libcoap-4.1.1/utlist.h @@ -0,0 +1,490 @@ +/* +Copyright (c) 2007-2010, Troy D. Hanson http://uthash.sourceforge.net +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef UTLIST_H +#define UTLIST_H + +#define UTLIST_VERSION 1.9.1 + +/* + * This file contains macros to manipulate singly and doubly-linked lists. + * + * 1. LL_ macros: singly-linked lists. + * 2. DL_ macros: doubly-linked lists. + * 3. CDL_ macros: circular doubly-linked lists. + * + * To use singly-linked lists, your structure must have a "next" pointer. + * To use doubly-linked lists, your structure must "prev" and "next" pointers. + * Either way, the pointer to the head of the list must be initialized to NULL. + * + * ----------------.EXAMPLE ------------------------- + * struct item { + * int id; + * struct item *prev, *next; + * } + * + * struct item *list = NULL: + * + * int main() { + * struct item *item; + * ... allocate and populate item ... + * DL_APPEND(list, item); + * } + * -------------------------------------------------- + * + * For doubly-linked lists, the append and delete macros are O(1) + * For singly-linked lists, append and delete are O(n) but prepend is O(1) + * The sort macro is O(n log(n)) for all types of single/double/circular lists. + */ + +/* These macros use decltype or the earlier __typeof GNU extension. + As decltype is only available in newer compilers (VS2010 or gcc 4.3+ + when compiling c++ code), this code uses whatever method is needed + or, for VS2008 where neither is available, uses casting workarounds. */ +#ifdef _MSC_VER /* MS compiler */ +#if _MSC_VER >= 1600 && __cplusplus /* VS2010 and newer in C++ mode */ +#define LDECLTYPE(x) decltype(x) +#else /* VS2008 or older (or VS2010 in C mode) */ +#define NO_DECLTYPE +#define LDECLTYPE(x) char* +#endif +#else /* GNU, Sun and other compilers */ +#define LDECLTYPE(x) __typeof(x) +#endif + +/* for VS2008 we use some workarounds to get around the lack of decltype, + * namely, we always reassign our tmp variable to the list head if we need + * to dereference its prev/next pointers, and save/restore the real head.*/ +#ifdef NO_DECLTYPE +#define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); } +#define _NEXT(elt,list) ((char*)((list)->next)) +#define _NEXTASGN(elt,list,to) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); } +#define _PREV(elt,list) ((char*)((list)->prev)) +#define _PREVASGN(elt,list,to) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); } +#define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; } +#define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); } +#else +#define _SV(elt,list) +#define _NEXT(elt,list) ((elt)->next) +#define _NEXTASGN(elt,list,to) ((elt)->next)=(to) +#define _PREV(elt,list) ((elt)->prev) +#define _PREVASGN(elt,list,to) ((elt)->prev)=(to) +#define _RS(list) +#define _CASTASGN(a,b) (a)=(b) +#endif + +/****************************************************************************** + * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort * + * Unwieldy variable names used here to avoid shadowing passed-in variables. * + *****************************************************************************/ +#define LL_SORT(list, cmp) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + LDECLTYPE(list) _ls_oldhead; \ + LDECLTYPE(list) _tmp; \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + _CASTASGN(_ls_p,list); \ + _CASTASGN(_ls_oldhead,list); \ + list = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \ + } else if (_ls_qsize == 0 || !_ls_q) { \ + _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \ + } else { \ + _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \ + } \ + if (_ls_tail) { \ + _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \ + } else { \ + _CASTASGN(list,_ls_e); \ + } \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } else _tmp=NULL; /* quiet gcc unused variable warning */ \ +} while (0) + +#define DL_SORT(list, cmp) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + LDECLTYPE(list) _ls_oldhead; \ + LDECLTYPE(list) _tmp; \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + _CASTASGN(_ls_p,list); \ + _CASTASGN(_ls_oldhead,list); \ + list = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \ + } else if (_ls_qsize == 0 || !_ls_q) { \ + _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \ + } else { \ + _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \ + } \ + if (_ls_tail) { \ + _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \ + } else { \ + _CASTASGN(list,_ls_e); \ + } \ + _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + _CASTASGN(list->prev, _ls_tail); \ + _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } else _tmp=NULL; /* quiet gcc unused variable warning */ \ +} while (0) + +#define CDL_SORT(list, cmp) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + LDECLTYPE(list) _ls_oldhead; \ + LDECLTYPE(list) _tmp; \ + LDECLTYPE(list) _tmp2; \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + _CASTASGN(_ls_p,list); \ + _CASTASGN(_ls_oldhead,list); \ + list = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + _SV(_ls_q,list); \ + if (_NEXT(_ls_q,list) == _ls_oldhead) { \ + _ls_q = NULL; \ + } else { \ + _ls_q = _NEXT(_ls_q,list); \ + } \ + _RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \ + if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ + } else if (_ls_qsize == 0 || !_ls_q) { \ + _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \ + if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \ + if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ + } else { \ + _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \ + if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ + } \ + if (_ls_tail) { \ + _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \ + } else { \ + _CASTASGN(list,_ls_e); \ + } \ + _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + _CASTASGN(list->prev,_ls_tail); \ + _CASTASGN(_tmp2,list); \ + _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp2); _RS(list); \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } else _tmp=NULL; /* quiet gcc unused variable warning */ \ +} while (0) + +/****************************************************************************** + * singly linked list macros (non-circular) * + *****************************************************************************/ +#define LL_PREPEND(head,add) \ +do { \ + (add)->next = head; \ + head = add; \ +} while (0) + +#define LL_APPEND(head,add) \ +do { \ + LDECLTYPE(head) _tmp; \ + (add)->next=NULL; \ + if (head) { \ + _tmp = head; \ + while (_tmp->next) { _tmp = _tmp->next; } \ + _tmp->next=(add); \ + } else { \ + (head)=(add); \ + } \ +} while (0) + +#define LL_DELETE(head,del) \ +do { \ + LDECLTYPE(head) _tmp; \ + if ((head) == (del)) { \ + (head)=(head)->next; \ + } else { \ + _tmp = head; \ + while (_tmp->next && (_tmp->next != (del))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = ((del)->next); \ + } \ + } \ +} while (0) + +/* Here are VS2008 replacements for LL_APPEND and LL_DELETE */ +#define LL_APPEND_VS2008(head,add) \ +do { \ + if (head) { \ + (add)->next = head; /* use add->next as a temp variable */ \ + while ((add)->next->next) { (add)->next = (add)->next->next; } \ + (add)->next->next=(add); \ + } else { \ + (head)=(add); \ + } \ + (add)->next=NULL; \ +} while (0) + +#define LL_DELETE_VS2008(head,del) \ +do { \ + if ((head) == (del)) { \ + (head)=(head)->next; \ + } else { \ + char *_tmp = (char*)(head); \ + while (head->next && (head->next != (del))) { \ + head = head->next; \ + } \ + if (head->next) { \ + head->next = ((del)->next); \ + } \ + { \ + char **_head_alias = (char**)&(head); \ + *_head_alias = _tmp; \ + } \ + } \ +} while (0) +#ifdef NO_DECLTYPE +#undef LL_APPEND +#define LL_APPEND LL_APPEND_VS2008 +#undef LL_DELETE +#define LL_DELETE LL_DELETE_VS2008 +#endif +/* end VS2008 replacements */ + +#define LL_FOREACH(head,el) \ + for(el=head;el;el=el->next) + +#define LL_FOREACH_SAFE(head,el,tmp) \ + for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp) + +#define LL_SEARCH_SCALAR(head,out,field,val) \ +do { \ + LL_FOREACH(head,out) { \ + if ((out)->field == (val)) break; \ + } \ +} while(0) + +#define LL_SEARCH(head,out,elt,cmp) \ +do { \ + LL_FOREACH(head,out) { \ + if ((cmp(out,elt))==0) break; \ + } \ +} while(0) + +/****************************************************************************** + * doubly linked list macros (non-circular) * + *****************************************************************************/ +#define DL_PREPEND(head,add) \ +do { \ + (add)->next = head; \ + if (head) { \ + (add)->prev = (head)->prev; \ + (head)->prev = (add); \ + } else { \ + (add)->prev = (add); \ + } \ + (head) = (add); \ +} while (0) + +#define DL_APPEND(head,add) \ +do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (head)->prev->next = (add); \ + (head)->prev = (add); \ + (add)->next = NULL; \ + } else { \ + (head)=(add); \ + (head)->prev = (head); \ + (head)->next = NULL; \ + } \ +} while (0); + +#define DL_DELETE(head,del) \ +do { \ + if ((del)->prev == (del)) { \ + (head)=NULL; \ + } else if ((del)==(head)) { \ + (del)->next->prev = (del)->prev; \ + (head) = (del)->next; \ + } else { \ + (del)->prev->next = (del)->next; \ + if ((del)->next) { \ + (del)->next->prev = (del)->prev; \ + } else { \ + (head)->prev = (del)->prev; \ + } \ + } \ +} while (0); + + +#define DL_FOREACH(head,el) \ + for(el=head;el;el=el->next) + +/* this version is safe for deleting the elements during iteration */ +#define DL_FOREACH_SAFE(head,el,tmp) \ + for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp) + +/* these are identical to their singly-linked list counterparts */ +#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR +#define DL_SEARCH LL_SEARCH + +/****************************************************************************** + * circular doubly linked list macros * + *****************************************************************************/ +#define CDL_PREPEND(head,add) \ +do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (add)->prev->next = (add); \ + } else { \ + (add)->prev = (add); \ + (add)->next = (add); \ + } \ +(head)=(add); \ +} while (0) + +#define CDL_DELETE(head,del) \ +do { \ + if ( ((head)==(del)) && ((head)->next == (head))) { \ + (head) = 0L; \ + } else { \ + (del)->next->prev = (del)->prev; \ + (del)->prev->next = (del)->next; \ + if ((del) == (head)) (head)=(del)->next; \ + } \ +} while (0); + +#define CDL_FOREACH(head,el) \ + for(el=head;el;el=(el->next==head ? 0L : el->next)) + +#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \ + for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \ + (el) && ((tmp2)=(el)->next, 1); \ + ((el) = (((el)==(tmp1)) ? 0L : (tmp2)))) + +#define CDL_SEARCH_SCALAR(head,out,field,val) \ +do { \ + CDL_FOREACH(head,out) { \ + if ((out)->field == (val)) break; \ + } \ +} while(0) + +#define CDL_SEARCH(head,out,elt,cmp) \ +do { \ + CDL_FOREACH(head,out) { \ + if ((cmp(out,elt))==0) break; \ + } \ +} while(0) + +#endif /* UTLIST_H */ + diff --git a/resource/csdk/logger/README b/resource/csdk/logger/README new file mode 100644 index 000000000..1e024feee --- /dev/null +++ b/resource/csdk/logger/README @@ -0,0 +1,42 @@ +Build notes + +//------------------------------------------------- +// NOTICE - Transition to SCONS +//------------------------------------------------- + +The IoTivity build system is transitioning to SCONS. Although the +makefiles are still available (until v1.0) and some developers are +still using them, they are currently no longer supported. To learn more +about building using SCONS see Readme.scons.txt in the repository root +directory. The build steps used in continuous integration can be found +in auto_build.sh which is also in the the repository root directory. + +//------------------------------------------------- +// Linux +//------------------------------------------------- +To enable logging, ensure that + -D TB_LOG +is set in the compiler flags + +//------------------------------------------------- +// Android +//------------------------------------------------- +To enable logging for Android, TB_LOG should be defined in the ./jni/Android.mk file as + +LOCAL_CFLAGS := -DTB_LOG + +//------------------------------------------------- +// Arduino +//------------------------------------------------- +To enable the logger for Arduino, TB_LOG should be defined in +Properties|C/C++ Build|Settings|Tool Settings|AVR Compiler|Symbols +and +Properties|C/C++ Build|Settings|Tool Settings|AVR C++ Compiler|Symbols + +Note: when building for Arduino, force the compiler to use avr-g++ to build logger.c. Or rename logger.c to logger.cpp. + +Note: when building for Arduino, several warnings are generated when trying to place strings in +PROGMEM +"warning: only initialized variables can be placed into program memory area" +This appears to be a known gcc bug - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734 + diff --git a/resource/csdk/logger/include/logger.h b/resource/csdk/logger/include/logger.h new file mode 100644 index 000000000..9dc80cfc9 --- /dev/null +++ b/resource/csdk/logger/include/logger.h @@ -0,0 +1,182 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef LOGGER_H_ +#define LOGGER_H_ + +#include +#include +#include +#include "oc_logger.h" +#include "oc_console_logger.h" + +#ifdef __ANDROID__ + #include +#elif defined ARDUINO + #include "Arduino.h" + #include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// Use the PCF macro to wrap strings stored in FLASH on the Arduino +// Example: OC_LOG(INFO, TAG, PCF("Entering function")); +#ifdef ARDUINO + #define PCF(str) ((PROGMEM const char *)(F(str))) +#else + #define PCF(str) str +#endif + +// Max buffer size used in variable argument log function +#define MAX_LOG_V_BUFFER_SIZE (256) + +// Log levels +typedef enum { + DEBUG = 0, + INFO, + WARNING, + ERROR, + FATAL +} LogLevel; + + +#ifndef ARDUINO + + /** + * Configure logger to use a context that defines a custom logger function + * + * @param ctx - pointer to oc_log_ctx_t struct that defines custom logging functions + */ + void OCLogConfig(oc_log_ctx_t *ctx); + + /** + * Initialize the logger. Optional on Android and Linux. Configures serial port on Arduino + */ + void OCLogInit(); + + /** + * Called to Free dyamically allocated resources used with custom logging. + * Not necessary if default logging is used + * + */ + void OCLogShutdown(); + + /** + * Output a variable argument list log string with the specified priority level. + * Only defined for Linux and Android + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param format - variadic log string + */ + void OCLogv(LogLevel level, const char * tag, const char * format, ...); + + /** + * Output a log string with the specified priority level. + * Only defined for Linux and Android + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param logStr - log string + */ + void OCLog(LogLevel level, const char * tag, const char * logStr); + + /** + * Output the contents of the specified buffer (in hex) with the specified priority level. + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param buffer - pointer to buffer of bytes + * @param bufferSize - max number of byte in buffer + */ + void OCLogBuffer(LogLevel level, const char * tag, const uint8_t * buffer, uint16_t bufferSize); +#else + /** + * Initialize the serial logger for Arduino + * Only defined for Arduino + */ + void OCLogInit(); + + /** + * Output a log string with the specified priority level. + * Only defined for Arduino. Uses PROGMEM strings + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param logStr - log string + */ + void OCLog(LogLevel level, PROGMEM const char * tag, PROGMEM const char * logStr); + + /** + * Output the contents of the specified buffer (in hex) with the specified priority level. + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param buffer - pointer to buffer of bytes + * @param bufferSize - max number of byte in buffer + */ + void OCLogBuffer(LogLevel level, PROGMEM const char * tag, const uint8_t * buffer, uint16_t bufferSize); + + /** + * Output a variable argument list log string with the specified priority level. + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param format - variadic log string + */ + void OCLogv(LogLevel level, const char * tag, const char * format, ...); +#endif + +#ifdef TB_LOG + // These macros are defined for Linux, Android, and Arduino + #define OC_LOG_INIT() OCLogInit() + #define OC_LOG(level, tag, logStr) OCLog((level), (tag), (logStr)) + #define OC_LOG_BUFFER(level, tag, buffer, bufferSize) OCLogBuffer((level), (tag), (buffer), (bufferSize)) + + #ifdef ARDUINO + #define OC_LOG_CONFIG(ctx) + #define OC_LOG_SHUTDOWN() + // Use full namespace for logInit to avoid function name collision + #define OC_LOG_INIT() OCLogInit() + // Don't define variable argument log function for Arduino + #define OC_LOG_V(level, tag, ...) OCLogv((level), (tag), __VA_ARGS__) + #else + #define OC_LOG_CONFIG(ctx) OCLogConfig((ctx)) + #define OC_LOG_SHUTDOWN() OCLogShutdown() + // Define variable argument log function for Linux and Android + #define OC_LOG_V(level, tag, ...) OCLogv((level), (tag), __VA_ARGS__) + #endif + +#else + #define OC_LOG_CONFIG(ctx) + #define OC_LOG_SHUTDOWN() + #define OC_LOG(level, tag, logStr) + #define OC_LOG_V(level, tag, ...) + #define OC_LOG_BUFFER(level, tag, buffer, bufferSize) + #define OC_LOG_INIT() +#endif + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* LOGGER_H_ */ diff --git a/resource/csdk/logger/makefile b/resource/csdk/logger/makefile new file mode 100644 index 000000000..a266fd257 --- /dev/null +++ b/resource/csdk/logger/makefile @@ -0,0 +1,122 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +# override with `make BUILD=release` +# default to release build +BUILD := release +PLATFORM := linux + +ROOT_DIR = .. + +# You must create the file "local.properties" on your local machine which contains any local paths, etc +# local_settings.mk should NOT be committed to repo +include $(ROOT_DIR)/local.properties +# GTEST_DIR contains the path to Google Test libs and must be defined in local.properties +# Example: +# GTEST_DIR := /home/johndoe/utils/gtest-1.7.0 + +# NOTE: to run app, make sure that LD_LIBRARY_PATH env variable +# contains $(GTEST_DIR)/lib/.libs + +CC := gcc +CXX := g++ + +PROG := loggertest + +SRC_DIR := ./src +TEST_DIR:= ./test +INC_DIR := ./include + +CC_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c99 -fpic -DTB_LOG +CC_FLAGS.release := -Os -Wall -c -fmessage-length=0 -std=c99 -fpic +CC_FLAGS := $(CC_FLAGS.$(BUILD)) + +CXX_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c++0x -fpic -DTB_LOG +CXX_FLAGS.release := -Os -Wall -c -fmessage-length=0 -std=c++0x -fpic +CXX_FLAGS := $(CXX_FLAGS.$(BUILD)) + +INC := -I$(SRC_DIR) +INC += -I$(TEST_DIR) +INC += -I$(INC_DIR) +INC += -I$(GTEST_DIR)/include + + +# using make's computed variables to select object and bin folders +# depending on the build type +OBJ_DIR.debug := ./obj/debug +OBJ_DIR.release := ./obj/release +OBJ_DIR := $(OBJ_DIR.$(BUILD)) + +BIN_DIR.debug := ./bin/debug +BIN_DIR.release := ./bin/release +BIN_DIR := $(BIN_DIR.$(BUILD)) + +C_FILES := $(wildcard $(SRC_DIR)/*.c) +#CPP_FILES := $(wildcard $(SRC_DIR)/*.cpp) +CPP_FILES := $(wildcard $(TEST_DIR)/*.cpp) +OBJ_FILES := $(addprefix $(OBJ_DIR)/,$(notdir $(CPP_FILES:.cpp=.o) $(C_FILES:.c=.o))) +H_FILES := $(wildcard $(TEST_DIR)/*.h) +H_FILES += $(wildcard $(INC_DIR)/*.h) +LD_FLAGS := -L/usr/lib +LD_FLAGS += -L$(GTEST_DIR)/lib/.libs + + +LIBS := -lpthread +LIBS += -lgtest +LIBS += -lgtest_main + + +all: $(PROG) + +$(PROG): $(OBJ_FILES) + $(CXX) -o $@ $^ $(LD_FLAGS) $(LIBS) + mv ./$(PROG) ./$(BIN_DIR) + +#$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(SRC_DIR)/%.h $(H_FILES) +# $(CC) $(CC_FLAGS) $(INC) -c -o $@ $< + +$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(INC_DIR)/%.h $(H_FILES) + $(CC) $(CC_FLAGS) $(INC) -c -o $@ $< + +$(OBJ_DIR)/%.o: $(TEST_DIR)/%.cpp $(H_FILES) + $(CXX) $(CXX_FLAGS) $(INC) -c -o $@ $< + + +.PHONY: clean +clean : + rm -rf ./obj/debug/* + rm -rf ./obj/release/* + rm -rf ./lib/debug/* + rm -rf ./lib/release/* + rm -rf ./bin/debug/* + rm -rf ./bin/release/* + rm -rf ./test/tst_*.txt + + +.PHONY: print_vars + +print_vars: + @echo "" + @echo 'BUILD = '$(value BUILD) + @echo 'INC = '$(value INC) + @echo 'CPP_FILES = '$(value CPP_FILES) + @echo 'LIBS = '$(value LIBS) + + diff --git a/resource/csdk/logger/src/logger.c b/resource/csdk/logger/src/logger.c new file mode 100644 index 000000000..ad9afd212 --- /dev/null +++ b/resource/csdk/logger/src/logger.c @@ -0,0 +1,352 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +#include "logger.h" +#include "string.h" +#include "oc_logger.h" +#include "oc_console_logger.h" + +static oc_log_ctx_t *logCtx = 0; + +static oc_log_level LEVEL_XTABLE[] = {OC_LOG_DEBUG, OC_LOG_INFO, OC_LOG_WARNING, OC_LOG_ERROR, OC_LOG_FATAL}; + +static const uint16_t LINE_BUFFER_SIZE = (16 * 2) + 16 + 1; // Show 16 bytes, 2 chars/byte, spaces between bytes, null termination + +// Convert LogLevel to platform-specific severity level. Store in PROGMEM on Arduino +#ifdef __ANDROID__ + static android_LogPriority LEVEL[] = {ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL}; +#elif defined __linux__ + static const char * LEVEL[] __attribute__ ((unused)) = {"DEBUG", "INFO", "WARNING", "ERROR", "FATAL"}; +#elif defined ARDUINO + #include + + PROGMEM const char level0[] = "DEBUG"; + PROGMEM const char level1[] = "INFO"; + PROGMEM const char level2[] = "WARNING"; + PROGMEM const char level3[] = "ERROR"; + PROGMEM const char level4[] = "FATAL"; + + PROGMEM const char * const LEVEL[] = {level0, level1, level2, level3, level4}; + + static void OCLogString(LogLevel level, PROGMEM const char * tag, PROGMEM const char * logStr); +#ifdef ARDUINO_ARCH_AVR + //Mega2560 and other 8-bit AVR microcontrollers + #define GET_PROGMEM_BUFFER(buffer, addr) { strcpy_P(buffer, (char*)pgm_read_word(addr));} +#elif defined ARDUINO_ARCH_SAM + //Arduino Due and other 32-bit ARM micro-controllers + #define GET_PROGMEM_BUFFER(buffer, addr) { strcpy_P(buffer, (char*)pgm_read_dword(addr));} +#else + #define GET_PROGMEM_BUFFER(buffer, addr) { buffer[0] = '\0';} +#endif +#endif // __ANDROID__ + + +#ifndef ARDUINO + +void OCLogConfig(oc_log_ctx_t *ctx) { + logCtx = ctx; +} + +void OCLogInit() { + +} + +void OCLogShutdown() { +#ifdef __linux__ + if (logCtx && logCtx->destroy) + { + logCtx->destroy(logCtx); + } +#endif +} + +/** + * Output a variable argument list log string with the specified priority level. + * Only defined for Linux and Android + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param format - variadic log string + */ +void OCLogv(LogLevel level, const char * tag, const char * format, ...) { + if (!format || !tag) { + return; + } + char buffer[MAX_LOG_V_BUFFER_SIZE]; + memset(buffer, 0, sizeof buffer); + va_list args; + va_start(args, format); + vsnprintf(buffer, sizeof buffer - 1, format, args); + va_end(args); + OCLog(level, tag, buffer); +} + +/** + * Output a log string with the specified priority level. + * Only defined for Linux and Android + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param logStr - log string + */ +void OCLog(LogLevel level, const char * tag, const char * logStr) { + if (!logStr || !tag) { + return; + } + + #ifdef __ANDROID__ + __android_log_write(LEVEL[level], tag, logStr); + #elif defined __linux__ + if (logCtx && logCtx->write_level) + { + logCtx->write_level(logCtx, LEVEL_XTABLE[level], logStr); + + } + else + { + printf("%s: %s: %s\n", LEVEL[level], tag, logStr); + } + #endif +} + +/** + * Output the contents of the specified buffer (in hex) with the specified priority level. + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param buffer - pointer to buffer of bytes + * @param bufferSize - max number of byte in buffer + */ +void OCLogBuffer(LogLevel level, const char * tag, const uint8_t * buffer, uint16_t bufferSize) { + if (!buffer || !tag || (bufferSize == 0)) { + return; + } + + char lineBuffer[LINE_BUFFER_SIZE]; + memset(lineBuffer, 0, sizeof lineBuffer); + int lineIndex = 0; + int i; + for (i = 0; i < bufferSize; i++) { + // Format the buffer data into a line + snprintf(&lineBuffer[lineIndex*3], sizeof(lineBuffer)-lineIndex*3, "%02X ", buffer[i]); + lineIndex++; + // Output 16 values per line + if (((i+1)%16) == 0) { + OCLog(level, tag, lineBuffer); + memset(lineBuffer, 0, sizeof lineBuffer); + lineIndex = 0; + } + } + // Output last values in the line, if any + if (bufferSize % 16) { + OCLog(level, tag, lineBuffer); + } +} + +#else + /** + * Initialize the serial logger for Arduino + * Only defined for Arduino + */ + void OCLogInit() { + Serial.begin(115200); + } + + /** + * Output a log string with the specified priority level. + * Only defined for Arduino. Only uses PROGMEM strings + * for the tag parameter + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param logStr - log string + */ + void OCLogString(LogLevel level, PROGMEM const char * tag, const char * logStr) { + if (!logStr || !tag) { + return; + } + + char buffer[LINE_BUFFER_SIZE]; + + GET_PROGMEM_BUFFER(buffer, &(LEVEL[level])); + Serial.print(buffer); + + char c; + Serial.print(F(": ")); + while ((c = pgm_read_byte(tag))) { + Serial.write(c); + tag++; + } + Serial.print(F(": ")); + + Serial.println(logStr); + } + + /** + * Output the contents of the specified buffer (in hex) with the specified priority level. + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param buffer - pointer to buffer of bytes + * @param bufferSize - max number of byte in buffer + */ + void OCLogBuffer(LogLevel level, PROGMEM const char * tag, const uint8_t * buffer, uint16_t bufferSize) { + if (!buffer || !tag || (bufferSize == 0)) { + return; + } + + char lineBuffer[LINE_BUFFER_SIZE] = {0}; + uint8_t lineIndex = 0; + for (uint8_t i = 0; i < bufferSize; i++) { + // Format the buffer data into a line + snprintf(&lineBuffer[lineIndex*3], sizeof(lineBuffer)-lineIndex*3, "%02X ", buffer[i]); + lineIndex++; + // Output 16 values per line + if (((i+1)%16) == 0) { + OCLogString(level, tag, lineBuffer); + memset(lineBuffer, 0, sizeof lineBuffer); + lineIndex = 0; + } + } + // Output last values in the line, if any + if (bufferSize % 16) { + OCLogString(level, tag, lineBuffer); + } + } + + /** + * Output a log string with the specified priority level. + * Only defined for Arduino. Uses PROGMEM strings + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param logStr - log string + */ + void OCLog(LogLevel level, PROGMEM const char * tag, PROGMEM const char * logStr) { + if (!logStr || !tag) { + return; + } + + char buffer[LINE_BUFFER_SIZE]; + + GET_PROGMEM_BUFFER(buffer, &(LEVEL[level])); + Serial.print(buffer); + + char c; + Serial.print(F(": ")); + while ((c = pgm_read_byte(tag))) { + Serial.write(c); + tag++; + } + Serial.print(F(": ")); + + while ((c = pgm_read_byte(logStr))) { + Serial.write(c); + logStr++; + } + Serial.println(); + } + + /** + * Output a variable argument list log string with the specified priority level. + * Only defined for Arduino as depicted below. + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param format - variadic log string + */ + void OCLogv(LogLevel level, PROGMEM const char * tag, const char * format, ...) + { + char buffer[LINE_BUFFER_SIZE]; + va_list ap; + va_start(ap, format); + + GET_PROGMEM_BUFFER(buffer, &(LEVEL[level])); + Serial.print(buffer); + + char c; + Serial.print(F(": ")); + + while ((c = pgm_read_byte(tag))) { + Serial.write(c); + tag++; + } + Serial.print(F(": ")); + + vsnprintf(buffer, sizeof(buffer), format, ap); + for(char *p = &buffer[0]; *p; p++) // emulate cooked mode for newlines + { + if(*p == '\n') + { + Serial.write('\r'); + } + Serial.write(*p); + } + Serial.println(); + va_end(ap); + } + /** + * Output a variable argument list log string with the specified priority level. + * Only defined for Arduino as depicted below. + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param format - variadic log string + */ + void OCLogv(LogLevel level, PROGMEM const char * tag, const __FlashStringHelper *format, ...) + { + char buffer[LINE_BUFFER_SIZE]; + va_list ap; + va_start(ap, format); + + GET_PROGMEM_BUFFER(buffer, &(LEVEL[level])); + Serial.print(buffer); + + char c; + Serial.print(F(": ")); + + while ((c = pgm_read_byte(tag))) { + Serial.write(c); + tag++; + } + Serial.print(F(": ")); + + #ifdef __AVR__ + vsnprintf_P(buffer, sizeof(buffer), (const char *)format, ap); // progmem for AVR + #else + vsnprintf(buffer, sizeof(buffer), (const char *)format, ap); // for the rest of the world + #endif + for(char *p = &buffer[0]; *p; p++) // emulate cooked mode for newlines + { + if(*p == '\n') + { + Serial.write('\r'); + } + Serial.write(*p); + } + Serial.println(); + va_end(ap); + } + + +#endif + + diff --git a/resource/csdk/logger/test/android/README b/resource/csdk/logger/test/android/README new file mode 100644 index 000000000..4648a96b8 --- /dev/null +++ b/resource/csdk/logger/test/android/README @@ -0,0 +1,22 @@ +//--------------------------------------------------------------------- +// NOTICE - Transition to SCONS +//--------------------------------------------------------------------- + +The IoTivity build system is transitioning to SCONS. Although the +makefiles are still available (until v1.0) and some developers are +still using them, they are currently no longer supported. To learn more +about building using SCONS see Readme.scons.txt in the repository root +directory. The build steps used in continuous integration can be found +in auto_build.sh which is also in the the repository root directory. + +//--------------------------------------------------------------------- + +loggertests.cpp contain several logger tests that can be used in an Android JNI app. + +androidloggertestoutput.txt is a file capture from running loggertests.cpp in an Android JNI app. + +Note: to enable the logger for Android, TB_LOG should be defined in the ./jni/Android.mk file as + +LOCAL_CFLAGS := -DTB_LOG + + diff --git a/resource/csdk/logger/test/android/androidloggertestoutput.txt b/resource/csdk/logger/test/android/androidloggertestoutput.txt new file mode 100644 index 000000000..a1e808356 --- /dev/null +++ b/resource/csdk/logger/test/android/androidloggertestoutput.txt @@ -0,0 +1,43 @@ +05-30 12:56:28.136: I/Android(8314): Starting logger test +05-30 12:56:28.136: I/Android(8314): Android Logger Test +05-30 12:56:28.136: D/Android(8314): this is a DEBUG message +05-30 12:56:28.136: I/Android(8314): this is a INFO message +05-30 12:56:28.136: W/Android(8314): this is a WARNING message +05-30 12:56:28.136: E/Android(8314): this is a ERROR message +05-30 12:56:28.136: A/Android(8314): this is a FATAL message +05-30 12:56:28.136: D/Android(8314): this is a DEBUG message +05-30 12:56:28.136: D/Android(8314): on multiple +05-30 12:56:28.136: D/Android(8314): lines +05-30 12:56:28.136: D/Android(8314): 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F +05-30 12:56:28.136: D/Android(8314): 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F +05-30 12:56:28.136: D/Android(8314): 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F +05-30 12:56:28.136: D/Android(8314): 30 31 +05-30 12:56:28.136: D/Android(8314): 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F +05-30 12:56:28.136: D/Android(8314): 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F +05-30 12:56:28.136: D/Android(8314): 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F +05-30 12:56:28.136: D/Android(8314): 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F +05-30 12:56:28.136: D/Android(8314): 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F +05-30 12:56:28.136: D/Android(8314): 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F +05-30 12:56:28.136: D/Android(8314): 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F +05-30 12:56:28.136: D/Android(8314): 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F +05-30 12:56:28.136: D/Android(8314): 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F +05-30 12:56:28.136: D/Android(8314): 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F +05-30 12:56:28.136: D/Android(8314): 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F +05-30 12:56:28.136: D/Android(8314): 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F +05-30 12:56:28.136: D/Android(8314): 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F +05-30 12:56:28.136: D/Android(8314): 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F +05-30 12:56:28.136: D/Android(8314): 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F +05-30 12:56:28.136: D/Android(8314): 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E +05-30 12:56:28.136: D/Android(8314): 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F +05-30 12:56:28.136: D/Android(8314): 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F +05-30 12:56:28.136: D/Android(8314): 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F +05-30 12:56:28.136: D/Android(8314): 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F +05-30 12:56:28.136: D/Android(8314): 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F +05-30 12:56:28.136: D/Android(8314): 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F +05-30 12:56:28.136: D/Android(8314): 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F +05-30 12:56:28.136: D/Android(8314): 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F +05-30 12:56:28.136: D/Android(8314): 80 +05-30 12:56:28.136: D/Android(8314): this is a char: A +05-30 12:56:28.136: D/Android(8314): this is an integer: 123 +05-30 12:56:28.136: D/Android(8314): this is a string: hello +05-30 12:56:28.136: D/Android(8314): this is a float: 123.45 diff --git a/resource/csdk/logger/test/android/loggertests.cpp b/resource/csdk/logger/test/android/loggertests.cpp new file mode 100644 index 000000000..e9d264aad --- /dev/null +++ b/resource/csdk/logger/test/android/loggertests.cpp @@ -0,0 +1,123 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +extern "C" { + #include "logger.h" +} + +static const char tag[] = "Android"; +static const char msg[] = "Android Logger Test"; + +static const char debugMsg[] = "this is a DEBUG message"; +static const char infoMsg[] = "this is a INFO message"; +static const char warningMsg[] = "this is a WARNING message"; +static const char errorMsg[] = "this is a ERROR message"; +static const char fatalMsg[] = "this is a FATAL message"; + +static const char multiLineMsg[] = "this is a DEBUG message\non multiple\nlines"; + + +//----------------------------------------------------------------------------- +// Tests +//----------------------------------------------------------------------------- +static void test0() { + OC_LOG(INFO, tag, msg); +} + +static void test1() { + OC_LOG(INFO, 0, msg); +} + +static void test2() { + OC_LOG(INFO, tag, 0); +} + +static void test3() { + OC_LOG(INFO, 0, 0); +} + +static void test4() { + OC_LOG(DEBUG, tag, debugMsg); + OC_LOG(INFO, tag, infoMsg); + OC_LOG(WARNING, tag, warningMsg); + OC_LOG(ERROR, tag, errorMsg); + OC_LOG(FATAL, tag, fatalMsg); +} + +static void test5() { + OC_LOG(DEBUG, tag, multiLineMsg); +} + + +static void test6() { + // Log buffer + uint8_t buffer[50]; + for (int i = 0; i < (int)(sizeof buffer); i++) { + buffer[i] = i; + } + OC_LOG_BUFFER(DEBUG, tag, buffer, sizeof buffer); + + // Log buffer, 128 bytes is a good boundary (8 rows of 16 values) + uint8_t buffer1[128]; + for (int i = 0; i < (int)(sizeof buffer1); i++) { + buffer1[i] = i; + } + OC_LOG_BUFFER(DEBUG, tag, buffer1, sizeof buffer1); + + // 1 below 128 byte boundary + uint8_t buffer2[127]; + for (int i = 0; i < (int)(sizeof buffer2); i++) { + buffer2[i] = i; + } + OC_LOG_BUFFER(DEBUG, tag, buffer2, sizeof buffer2); + + // 1 above 128 byte boundary + uint8_t buffer3[129]; + for (int i = 0; i < (int)(sizeof buffer3); i++) { + buffer3[i] = i; + } + OC_LOG_BUFFER(DEBUG, tag, buffer3, sizeof buffer3); +} + +static void test7() { + OC_LOG_V(DEBUG, tag, "this is a char: %c", 'A'); + OC_LOG_V(DEBUG, tag, "this is an integer: %d", 123); + OC_LOG_V(DEBUG, tag, "this is a string: %s", "hello"); + OC_LOG_V(DEBUG, tag, "this is a float: %5.2f", 123.45); +} + +//----------------------------------------------------------------------------- +// loggertests +//----------------------------------------------------------------------------- +void loggertests() { + OC_LOG(INFO, tag, "Starting logger test"); + + test0(); + test1(); + test2(); + test3(); + test4(); + test5(); + test6(); + test7(); +} + + diff --git a/resource/csdk/logger/test/arduino/ArduinoLoggerTest.cpp b/resource/csdk/logger/test/arduino/ArduinoLoggerTest.cpp new file mode 100644 index 000000000..f1f89abae --- /dev/null +++ b/resource/csdk/logger/test/arduino/ArduinoLoggerTest.cpp @@ -0,0 +1,126 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +// Do not remove the include below +#include "ArduinoLoggerTest.h" +#include "logger.h" + +PROGMEM const char tag[] = "Arduino"; +PROGMEM const char msg[] = "Arduino Logger Test"; + +PROGMEM const char debugMsg[] = "this is a DEBUG message"; +PROGMEM const char infoMsg[] = "this is a INFO message"; +PROGMEM const char warningMsg[] = "this is a WARNING message"; +PROGMEM const char errorMsg[] = "this is a ERROR message"; +PROGMEM const char fatalMsg[] = "this is a FATAL message"; + +PROGMEM const char multiLineMsg[] = "this is a DEBUG message\non multiple\nlines"; + + +//----------------------------------------------------------------------------- +// Tests +//----------------------------------------------------------------------------- +void test0() { + OC_LOG(INFO, tag, msg); +} + +void test1() { + OC_LOG(INFO, 0, msg); +} + +void test2() { + OC_LOG(INFO, tag, 0); +} + +void test3() { + OC_LOG(INFO, 0, 0); +} + +void test4() { + OC_LOG(DEBUG, tag, debugMsg); + OC_LOG(INFO, tag, infoMsg); + OC_LOG(WARNING, tag, warningMsg); + OC_LOG(ERROR, tag, errorMsg); + OC_LOG(FATAL, tag, fatalMsg); +} + +void test5() { + OC_LOG(DEBUG, tag, multiLineMsg); +} + + +void test6() { + // Log buffer + uint8_t buffer[50]; + for (int i = 0; i < (int)(sizeof buffer); i++) { + buffer[i] = i; + } + OC_LOG_BUFFER(DEBUG, tag, buffer, sizeof buffer); + + // Log buffer, 128 bytes is a good boundary (8 rows of 16 values) + uint8_t buffer1[128]; + for (int i = 0; i < (int)(sizeof buffer1); i++) { + buffer1[i] = i; + } + OC_LOG_BUFFER(DEBUG, tag, buffer1, sizeof buffer1); + + // 1 below 128 byte boundary + uint8_t buffer2[127]; + for (int i = 0; i < (int)(sizeof buffer2); i++) { + buffer2[i] = i; + } + OC_LOG_BUFFER(DEBUG, tag, buffer2, sizeof buffer2); + + // 1 above 128 byte boundary + uint8_t buffer3[129]; + for (int i = 0; i < (int)(sizeof buffer3); i++) { + buffer3[i] = i; + } + OC_LOG_BUFFER(DEBUG, tag, buffer3, sizeof buffer3); +} + +//The setup function is called once at startup of the sketch +void setup() +{ + // Add your initialization code here + OC_LOG_INIT(); + + test0(); + delay(2000); + test1(); + delay(2000); + test2(); + delay(2000); + test3(); + delay(2000); + test4(); + delay(2000); + test5(); + delay(2000); + test6(); + delay(2000); +} + +// The loop function is called in an endless loop +void loop() +{ + delay(2000); +} diff --git a/resource/csdk/logger/test/arduino/ArduinoLoggerTest.h b/resource/csdk/logger/test/arduino/ArduinoLoggerTest.h new file mode 100644 index 000000000..45dd801bf --- /dev/null +++ b/resource/csdk/logger/test/arduino/ArduinoLoggerTest.h @@ -0,0 +1,50 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +// Only modify this file to include +// - function definitions (prototypes) +// - include files +// - extern variable definitions +// In the appropriate section + +#ifndef ArduinoLoggerTest_H_ +#define ArduinoLoggerTest_H_ +#include "Arduino.h" +//add your includes for the project ArduinoDummyTestFramework here + + +//end of add your includes here +#ifdef __cplusplus +extern "C" { +#endif +void loop(); +void setup(); +#ifdef __cplusplus +} // extern "C" +#endif + +//add your function definitions for the project ArduinoDummyTestFramework here + + + + +//Do not add code below this line +#endif /* LoggerTest_H_ */ diff --git a/resource/csdk/logger/test/arduino/README b/resource/csdk/logger/test/arduino/README new file mode 100644 index 000000000..8ffa9f3b0 --- /dev/null +++ b/resource/csdk/logger/test/arduino/README @@ -0,0 +1,22 @@ +ArduinoLoggerTest.cpp contains several logger tests and can be used in an +Arduino sketch. + +On Arduino, the logger outputs to the serial port using Serial.print. + +Run a serial terminal program such as CuteCom at 115200,8,N,1 to view the +log outputs. + +arduinologgertestoutput.txt contains the output captured after running ArduinoLoggerTest.cpp + +Note: to enable the logger for Arduino, TB_LOG should be defined in +Properties|C/C++ Build|Settings|Tool Settings|AVR Compiler|Symbols +and +Properties|C/C++ Build|Settings|Tool Settings|AVR C++ Compiler|Symbols + +Note: when building for Arduino, force the compiler to use avr-g++ to build logger.c. Or rename logger.c to logger.cpp. + +Note: when building for Arduino, several warnings are generated when trying to place strings in +PROGMEM +"warning: only initialized variables can be placed into program memory area" +This appears to be a known gcc bug - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734 + diff --git a/resource/csdk/logger/test/arduino/arduinologgertestoutput.txt b/resource/csdk/logger/test/arduino/arduinologgertestoutput.txt new file mode 100644 index 000000000..1f91ee928 --- /dev/null +++ b/resource/csdk/logger/test/arduino/arduinologgertestoutput.txt @@ -0,0 +1,38 @@ +INFO: Arduino: Arduino Logger Test +DEBUG: Arduino: this is a DEBUG message +INFO: Arduino: this is a INFO message +WARNING: Arduino: this is a WARNING message +ERROR: Arduino: this is a ERROR message +FATAL: Arduino: this is a FATAL message +DEBUG: Arduino: this is a DEBUG message +on multiple +lines +DEBUG: Arduino: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F +DEBUG: Arduino: 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F +DEBUG: Arduino: 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F +DEBUG: Arduino: 30 31 +DEBUG: Arduino: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F +DEBUG: Arduino: 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F +DEBUG: Arduino: 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F +DEBUG: Arduino: 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F +DEBUG: Arduino: 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F +DEBUG: Arduino: 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F +DEBUG: Arduino: 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F +DEBUG: Arduino: 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F +DEBUG: Arduino: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F +DEBUG: Arduino: 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F +DEBUG: Arduino: 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F +DEBUG: Arduino: 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F +DEBUG: Arduino: 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F +DEBUG: Arduino: 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F +DEBUG: Arduino: 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F +DEBUG: Arduino: 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E +DEBUG: Arduino: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F +DEBUG: Arduino: 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F +DEBUG: Arduino: 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F +DEBUG: Arduino: 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F +DEBUG: Arduino: 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F +DEBUG: Arduino: 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F +DEBUG: Arduino: 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F +DEBUG: Arduino: 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F +DEBUG: Arduino: 80 diff --git a/resource/csdk/logger/test/loggertests.cpp b/resource/csdk/logger/test/loggertests.cpp new file mode 100644 index 000000000..27971bae9 --- /dev/null +++ b/resource/csdk/logger/test/loggertests.cpp @@ -0,0 +1,366 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +extern "C" { + #include "logger.h" +} + + +#include "gtest/gtest.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +using namespace std; + + +//----------------------------------------------------------------------------- +// file_exist citation - +// http://stackoverflow.com/questions/230062/whats-the-best-way-to-check-if-a-file-exists-in-c-cross-platform/230070#230070 +//----------------------------------------------------------------------------- +bool file_exist(const char *filename) { + struct stat buffer; + return (stat(filename, &buffer) == 0); +} + +//----------------------------------------------------------------------------- +// stdio redirection citation - http://www.cplusplus.com/forum/general/94879/ +//----------------------------------------------------------------------------- +static int fd; +static int defout; + +bool directStdOutToFile(const char *filename) { + if (!filename) { + return false; + } + + if ((defout = dup(1)) < 0) { + fprintf(stderr, "Can't dup(2) - (%s)\n", strerror(errno)); + return false; + } + if ((fd = open(filename, O_RDWR | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR)) < 0) { + fprintf(stderr, "Can't open(2) - (%s)\n", strerror(errno)); + return false; + } + // redirect output to the file + if (dup2(fd, 1) < 0) { + fprintf(stderr, "Can't dup2(2) - (%s)\n", strerror(errno)); + return false; + } + close(fd); // Descriptor no longer needed + + fflush(stdout); // FLUSH ALL OUTPUT TO file + + return true; +} + +bool directStdOutToConsole() { + fflush(stdout); // FLUSH ALL OUTPUT TO file + + // redirect output back to stdout + if (dup2(defout, 1) < 0) { + fprintf(stderr, "Can't dup2(2) - (%s)\n", strerror(errno)); + return false; + } + close(defout); // Copy of stdout no longer needed + + return true; +} + +//----------------------------------------------------------------------------- +// CalcFileMD5 citation - http://stackoverflow.com/questions/3395690/md5sum-of-file-in-linux-c +//----------------------------------------------------------------------------- +#include +#include + +#define STR_VALUE(val) #val +#define STR(name) STR_VALUE(name) + +#define PATH_LEN 256 +#define MD5_LEN 32 + +bool CalcFileMD5(const char *file_name, char *md5_sum) { + #define MD5SUM_CMD_FMT "md5sum %." STR(PATH_LEN) "s 2>/dev/null" + char cmd[PATH_LEN + sizeof (MD5SUM_CMD_FMT)]; + snprintf(cmd, sizeof(cmd), MD5SUM_CMD_FMT, file_name); + #undef MD5SUM_CMD_FMT + + FILE *p = popen(cmd, "r"); + if (p == NULL) return 0; + + int i, ch; + for (i = 0; i < MD5_LEN && isxdigit(ch = fgetc(p)); i++) { + *md5_sum++ = ch; + } + + *md5_sum = '\0'; + pclose(p); + return (i == MD5_LEN); +} + + +//----------------------------------------------------------------------------- +// Tests +//----------------------------------------------------------------------------- +TEST(LoggerTest, StringArg) { + char testFile[] = "tst_stringarg.txt"; + char stdFile[] = "std_stringarg.txt"; + + // Try deleting test file + remove(testFile); + + directStdOutToFile(testFile); + const char *tag = "StringArg"; + OC_LOG(INFO, tag, "This is a fixed string call"); + directStdOutToConsole(); + + bool testFileExists = file_exist(testFile); + EXPECT_TRUE(testFileExists); + bool stdFileExists = file_exist(stdFile); + EXPECT_TRUE(stdFileExists); + + if (testFileExists && stdFileExists) { + char testFileMD5[MD5_LEN + 1] = {0}; + char stdFileMD5[MD5_LEN + 1] = {0}; + + EXPECT_TRUE(CalcFileMD5(testFile, testFileMD5)); + EXPECT_TRUE(CalcFileMD5(stdFile, stdFileMD5)); + + EXPECT_STREQ(stdFileMD5, testFileMD5); + } +} + +TEST(LoggerTest, StringArgNoTag) { + char testFile[] = "tst_stringargnotag.txt"; + char stdFile[] = "std_stringargnotag.txt"; + + directStdOutToFile(testFile); + OC_LOG(INFO, 0, "This is a fixed string call"); + directStdOutToConsole(); + + bool testFileExists = file_exist(testFile); + EXPECT_TRUE(testFileExists); + bool stdFileExists = file_exist(stdFile); + EXPECT_TRUE(stdFileExists); + + if (testFileExists && stdFileExists) { + char testFileMD5[MD5_LEN + 1] = {0}; + char stdFileMD5[MD5_LEN + 1] = {0}; + + EXPECT_TRUE(CalcFileMD5(testFile, testFileMD5)); + EXPECT_TRUE(CalcFileMD5(stdFile, stdFileMD5)); + + EXPECT_STREQ(stdFileMD5, testFileMD5); + } +} + +TEST(LoggerTest, StringArgNoLogStr) { + char testFile[] = "tst_stringargnologstr.txt"; + char stdFile[] = "std_stringargnologstr.txt"; + + directStdOutToFile(testFile); + const char *tag = "StringArgNoLogStr"; + OC_LOG(INFO, tag, 0); + directStdOutToConsole(); + + bool testFileExists = file_exist(testFile); + EXPECT_TRUE(testFileExists); + bool stdFileExists = file_exist(stdFile); + EXPECT_TRUE(stdFileExists); + + if (testFileExists && stdFileExists) { + char testFileMD5[MD5_LEN + 1] = {0}; + char stdFileMD5[MD5_LEN + 1] = {0}; + + EXPECT_TRUE(CalcFileMD5(testFile, testFileMD5)); + EXPECT_TRUE(CalcFileMD5(stdFile, stdFileMD5)); + + EXPECT_STREQ(stdFileMD5, testFileMD5); + } +} + +TEST(LoggerTest, StringArgNoTagNoLogStr) { + char testFile[] = "tst_stringargnotagnologstr.txt"; + char stdFile[] = "std_stringargnotagnologstr.txt"; + + directStdOutToFile(testFile); + OC_LOG(INFO, 0, 0); + directStdOutToConsole(); + + bool testFileExists = file_exist(testFile); + EXPECT_TRUE(testFileExists); + bool stdFileExists = file_exist(stdFile); + EXPECT_TRUE(stdFileExists); + + if (testFileExists && stdFileExists) { + char testFileMD5[MD5_LEN + 1] = {0}; + char stdFileMD5[MD5_LEN + 1] = {0}; + + EXPECT_TRUE(CalcFileMD5(testFile, testFileMD5)); + EXPECT_TRUE(CalcFileMD5(stdFile, stdFileMD5)); + + EXPECT_STREQ(stdFileMD5, testFileMD5); + } +} + +TEST(LoggerTest, StringArgLevels) { + char testFile[] = "tst_stringarglevels.txt"; + char stdFile[] = "std_stringarglevels.txt"; + + directStdOutToFile(testFile); + const char *tag = "StringArgLevels"; + // DEBUG, INFO, WARNING, ERROR, FATAL + OC_LOG(DEBUG, tag, "this is a DEBUG message"); + OC_LOG(INFO, tag, "this is a INFO message"); + OC_LOG(WARNING, tag, "this is a WARNING message"); + OC_LOG(ERROR, tag, "this is a ERROR message"); + OC_LOG(FATAL, tag, "this is a FATAL message"); + directStdOutToConsole(); + + bool testFileExists = file_exist(testFile); + EXPECT_TRUE(testFileExists); + bool stdFileExists = file_exist(stdFile); + EXPECT_TRUE(stdFileExists); + + if (testFileExists && stdFileExists) { + char testFileMD5[MD5_LEN + 1] = {0}; + char stdFileMD5[MD5_LEN + 1] = {0}; + + EXPECT_TRUE(CalcFileMD5(testFile, testFileMD5)); + EXPECT_TRUE(CalcFileMD5(stdFile, stdFileMD5)); + + EXPECT_STREQ(stdFileMD5, testFileMD5); + } +} + +TEST(LoggerTest, StringArgMultiline) { + char testFile[] = "tst_stringargmultiline.txt"; + char stdFile[] = "std_stringargmultiline.txt"; + + directStdOutToFile(testFile); + const char *tag = "StringArgMultiline"; + OC_LOG(DEBUG, tag, "this is a DEBUG message\non multiple\nlines"); + directStdOutToConsole(); + + bool testFileExists = file_exist(testFile); + EXPECT_TRUE(testFileExists); + bool stdFileExists = file_exist(stdFile); + EXPECT_TRUE(stdFileExists); + + if (testFileExists && stdFileExists) { + char testFileMD5[MD5_LEN + 1] = {0}; + char stdFileMD5[MD5_LEN + 1] = {0}; + + EXPECT_TRUE(CalcFileMD5(testFile, testFileMD5)); + EXPECT_TRUE(CalcFileMD5(stdFile, stdFileMD5)); + + EXPECT_STREQ(stdFileMD5, testFileMD5); + } +} + +TEST(LoggerTest, VariableArg) { + char testFile[] = "tst_variablearg.txt"; + char stdFile[] = "std_variablearg.txt"; + + directStdOutToFile(testFile); + const char *tag = "VariableArg"; + // DEBUG, INFO, WARNING, ERROR, FATAL + OC_LOG_V(DEBUG, tag, "this is a char: %c", 'A'); + OC_LOG_V(DEBUG, tag, "this is an integer: %d", 123); + OC_LOG_V(DEBUG, tag, "this is a string: %s", "hello"); + OC_LOG_V(DEBUG, tag, "this is a float: %5.2f", 123.45); + directStdOutToConsole(); + + bool testFileExists = file_exist(testFile); + EXPECT_TRUE(testFileExists); + bool stdFileExists = file_exist(stdFile); + EXPECT_TRUE(stdFileExists); + + if (testFileExists && stdFileExists) { + char testFileMD5[MD5_LEN + 1] = {0}; + char stdFileMD5[MD5_LEN + 1] = {0}; + + EXPECT_TRUE(CalcFileMD5(testFile, testFileMD5)); + EXPECT_TRUE(CalcFileMD5(stdFile, stdFileMD5)); + + EXPECT_STREQ(stdFileMD5, testFileMD5); + } +} + +TEST(LoggerTest, LogBuffer) { + char testFile[] = "tst_logbuffer.txt"; + char stdFile[] = "std_logbuffer.txt"; + + directStdOutToFile(testFile); + const char *tag = "LogBuffer"; + + // Log buffer + uint8_t buffer[50]; + for (int i = 0; i < (int)(sizeof buffer); i++) { + buffer[i] = i; + } + OC_LOG_BUFFER(DEBUG, tag, buffer, sizeof buffer); + + // Log buffer, 128 bytes is a good boundary (8 rows of 16 values) + uint8_t buffer1[128]; + for (int i = 0; i < (int)(sizeof buffer1); i++) { + buffer1[i] = i; + } + OC_LOG_BUFFER(DEBUG, tag, buffer1, sizeof buffer1); + + // 1 below 128 byte boundary + uint8_t buffer2[127]; + for (int i = 0; i < (int)(sizeof buffer2); i++) { + buffer2[i] = i; + } + OC_LOG_BUFFER(DEBUG, tag, buffer2, sizeof buffer2); + + // 1 above 128 byte boundary + uint8_t buffer3[129]; + for (int i = 0; i < (int)(sizeof buffer3); i++) { + buffer3[i] = i; + } + OC_LOG_BUFFER(DEBUG, tag, buffer3, sizeof buffer3); + + directStdOutToConsole(); + + bool testFileExists = file_exist(testFile); + EXPECT_TRUE(testFileExists); + bool stdFileExists = file_exist(stdFile); + EXPECT_TRUE(stdFileExists); + + if (testFileExists && stdFileExists) { + char testFileMD5[MD5_LEN + 1] = {0}; + char stdFileMD5[MD5_LEN + 1] = {0}; + + EXPECT_TRUE(CalcFileMD5(testFile, testFileMD5)); + EXPECT_TRUE(CalcFileMD5(stdFile, stdFileMD5)); + + EXPECT_STREQ(stdFileMD5, testFileMD5); + } +} diff --git a/resource/csdk/logger/test/std_logbuffer.txt b/resource/csdk/logger/test/std_logbuffer.txt new file mode 100644 index 000000000..743c5e0a2 --- /dev/null +++ b/resource/csdk/logger/test/std_logbuffer.txt @@ -0,0 +1,29 @@ +DEBUG: LogBuffer: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F +DEBUG: LogBuffer: 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F +DEBUG: LogBuffer: 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F +DEBUG: LogBuffer: 30 31 +DEBUG: LogBuffer: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F +DEBUG: LogBuffer: 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F +DEBUG: LogBuffer: 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F +DEBUG: LogBuffer: 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F +DEBUG: LogBuffer: 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F +DEBUG: LogBuffer: 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F +DEBUG: LogBuffer: 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F +DEBUG: LogBuffer: 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F +DEBUG: LogBuffer: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F +DEBUG: LogBuffer: 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F +DEBUG: LogBuffer: 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F +DEBUG: LogBuffer: 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F +DEBUG: LogBuffer: 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F +DEBUG: LogBuffer: 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F +DEBUG: LogBuffer: 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F +DEBUG: LogBuffer: 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E +DEBUG: LogBuffer: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F +DEBUG: LogBuffer: 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F +DEBUG: LogBuffer: 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F +DEBUG: LogBuffer: 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F +DEBUG: LogBuffer: 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F +DEBUG: LogBuffer: 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F +DEBUG: LogBuffer: 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F +DEBUG: LogBuffer: 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F +DEBUG: LogBuffer: 80 diff --git a/resource/csdk/logger/test/std_stringarg.txt b/resource/csdk/logger/test/std_stringarg.txt new file mode 100644 index 000000000..e9792196e --- /dev/null +++ b/resource/csdk/logger/test/std_stringarg.txt @@ -0,0 +1 @@ +INFO: StringArg: This is a fixed string call diff --git a/resource/csdk/logger/test/std_stringarglevels.txt b/resource/csdk/logger/test/std_stringarglevels.txt new file mode 100644 index 000000000..19b3124a3 --- /dev/null +++ b/resource/csdk/logger/test/std_stringarglevels.txt @@ -0,0 +1,5 @@ +DEBUG: StringArgLevels: this is a DEBUG message +INFO: StringArgLevels: this is a INFO message +WARNING: StringArgLevels: this is a WARNING message +ERROR: StringArgLevels: this is a ERROR message +FATAL: StringArgLevels: this is a FATAL message diff --git a/resource/csdk/logger/test/std_stringargmultiline.txt b/resource/csdk/logger/test/std_stringargmultiline.txt new file mode 100644 index 000000000..5f10ebf63 --- /dev/null +++ b/resource/csdk/logger/test/std_stringargmultiline.txt @@ -0,0 +1,3 @@ +DEBUG: StringArgMultiline: this is a DEBUG message +on multiple +lines diff --git a/resource/csdk/logger/test/std_stringargnologstr.txt b/resource/csdk/logger/test/std_stringargnologstr.txt new file mode 100644 index 000000000..e69de29bb diff --git a/resource/csdk/logger/test/std_stringargnotag.txt b/resource/csdk/logger/test/std_stringargnotag.txt new file mode 100644 index 000000000..e69de29bb diff --git a/resource/csdk/logger/test/std_stringargnotagnologstr.txt b/resource/csdk/logger/test/std_stringargnotagnologstr.txt new file mode 100644 index 000000000..e69de29bb diff --git a/resource/csdk/logger/test/std_variablearg.txt b/resource/csdk/logger/test/std_variablearg.txt new file mode 100644 index 000000000..5f919de62 --- /dev/null +++ b/resource/csdk/logger/test/std_variablearg.txt @@ -0,0 +1,4 @@ +DEBUG: VariableArg: this is a char: A +DEBUG: VariableArg: this is an integer: 123 +DEBUG: VariableArg: this is a string: hello +DEBUG: VariableArg: this is a float: 123.45 diff --git a/resource/csdk/makefile b/resource/csdk/makefile new file mode 100644 index 000000000..ca77f30c7 --- /dev/null +++ b/resource/csdk/makefile @@ -0,0 +1,206 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +# override with `make BUILD=debug` +# override with `make PLATFORM=arduinomega` or `make PLATFORM=arduinodue` +# default to release build +# default to build for linux +BUILD := release +PLATFORM := linux + +# override with `make PLATFORM=arduinomega ARDUINOWIFI=1` to enable Arduino WiFi shield +ARDUINOWIFI := 0 + +ifeq ($(ROOT_DIR), ) +ROOT_DIR = ./ +endif + +PLATFORM_TYPE = linux + +ifeq ($(PLATFORM),linux) + CXX=g++ + CC=gcc + AR=ar + RANLIB=ranlib + CFLAGS_PLATFORM = -DWITH_POSIX -std=c99 + PLATFORM_TYPE=linux +else ifeq ($(PLATFORM),arduinomega) + include local.properties + include $(PLATFORM).properties + CC=$(ARDUINO_TOOLS_DIR)/avr-g++ + ifeq ($(wildcard $(ARDUINO_DIR)/libraries/Time/Time/),) + $(error Arduino Time library needs to be moved from /libraries/Time \ + to /libraries/Time/Time. You may need to create \ + /libraries/Time/Time directory. Please refer to the wiki or readme \ + for more information) + endif + PLATFORM_TYPE=arduino +else ifeq ($(PLATFORM),arduinodue) + include local.properties + include $(PLATFORM).properties + CC=$(ARDUINO_TOOLS_DIR)/arm-none-eabi-g++ + PLATFORM_TYPE=arduino +else + $(error Wrong value for PLATFORM !!) +endif + +ifeq ($(PLATFORM_TYPE),arduino) + ifeq ($(ARDUINOWIFI),0) + ARDUINO_SHIELD_TYPE := "/ethernet_shield" + else ifeq ($(ARDUINOWIFI), 1) + ARDUINO_SHIELD_TYPE := "/wifi_shield" + endif + PLATFORM_SPECIFIC_BACKOUT:= ../../../../ +else + PLATFORM_SPECIFIC_BACKOUT := ../../../ +endif + +ifeq ($(OUT_DIR), ) +OUT_DIR = $(PLATFORM)$(ARDUINO_SHIELD_TYPE)/$(BUILD) +endif + +ifeq ($(OBJ_DIR), ) +OBJ_DIR = $(OUT_DIR)/obj +endif + +OCLOGGER_DIR = logger +OC_LOG_DIR = ../oc_logger +OCRANDOM_DIR = ocrandom +OCSOCKET_DIR = ocsocket +LCOAP_DIR = libcoap-4.1.1 +OCCOAP_DIR = occoap +OCTBSTACK_DIR = stack +OCMALLOC_DIR = ocmalloc +EXTLIBS_DIR = ../../extlibs +CJSON_DIR = $(EXTLIBS_DIR)/cjson +TINYDTLS_DIR = $(EXTLIBS_DIR)/tinydtls + +OCCOAP_SRC = $(OCCOAP_DIR)/src +OCTBSTACK_SRC = $(OCTBSTACK_DIR)/src +OCMALLOC_SRC = $(OCMALLOC_DIR)/src +CJSON_SRC = $(CJSON_DIR) + +OCLOGGER_INC = $(OCLOGGER_DIR)/include +OC_LOG_INC = $(OC_LOG_DIR)/include +OCRANDOM_INC = $(OCRANDOM_DIR)/include +OCSOCKET_INC = $(OCSOCKET_DIR)/include +LCOAP_INC = $(LCOAP_DIR) +OCCOAP_INC = $(OCCOAP_DIR)/include +OCTBSTACK_INC = $(OCTBSTACK_DIR)/include +OCMALLOC_INC = $(OCMALLOC_DIR)/include +CJSON_INC = $(CJSON_DIR) + +INC_DIRS := -I$(OCLOGGER_INC) +INC_DIRS += -I$(OC_LOG_INC) +INC_DIRS += -I$(OCRANDOM_INC) +INC_DIRS += -I$(OCSOCKET_INC) +INC_DIRS += -I$(LCOAP_INC) +INC_DIRS += -I$(OCCOAP_INC) +INC_DIRS += -I$(OCMALLOC_INC) +INC_DIRS += -I$(OCTBSTACK_INC) +INC_DIRS += -I$(OCTBSTACK_INC)/internal +INC_DIRS += -I$(CJSON_INC) + +CC_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -fpic -DTB_LOG +CC_FLAGS.release := -Os -Wall -c -fmessage-length=0 -fpic + +CFLAGS += $(CC_FLAGS.$(BUILD)) $(INC_DIRS) $(CFLAGS_PLATFORM) $(INC_DIR_PLATFORM) +LDLIBS += -lcoap + +CJSON_SOURCES := $(CJSON_SRC)/cJSON.c + +OCCOAP_SOURCES := $(OCCOAP_SRC)/occoap.c +OCCOAP_SOURCES += $(OCCOAP_SRC)/occoaphelper.c + +OCTBSTACK_SOURCES := $(OCTBSTACK_SRC)/ocstack.c +OCTBSTACK_SOURCES += $(OCTBSTACK_SRC)/occlientcb.c +OCTBSTACK_SOURCES += $(OCTBSTACK_SRC)/ocresource.c +OCTBSTACK_SOURCES += $(OCTBSTACK_SRC)/ocobserve.c +OCTBSTACK_SOURCES += $(OCTBSTACK_SRC)/ocserverrequest.c +OCTBSTACK_SOURCES += $(OCTBSTACK_SRC)/occollection.c +OCTBSTACK_SOURCES += $(OCTBSTACK_SRC)/oicgroup.c +OCTBSTACK_SOURCES += $(OCTBSTACK_SRC)/ocsecurity.c + +SOURCES := $(CJSON_SOURCES) +SOURCES += $(OCCOAP_SOURCES) +SOURCES += $(OCTBSTACK_SOURCES) + +all: make_lcoap objdirs obj_build liboctbstack.a + +buildScript_all: objdirs obj_build liboctbstack.a + +make_lcoap: + $(MAKE) -C $(LCOAP_DIR) "BUILD=$(BUILD)" "PLATFORM=$(PLATFORM)" "ARDUINOWIFI=$(ARDUINOWIFI)" + +objdirs: + mkdir -p $(PLATFORM) + mkdir -p $(PLATFORM)/$(ARDUINO_SHIELD_TYPE) + mkdir -p $(OUT_DIR) + mkdir -p $(OBJ_DIR) + +obj_build: + @echo "Building $@" + # Output all *.o files to $(OUT_DIR)/$(BUILD)/$(OBJ_DIR) + $(foreach source,$(SOURCES), $(CC) $(CFLAGS) $(source) -o $(patsubst %.c, %.o, $(patsubst %, $(OBJ_DIR)/%, $(notdir $(source))));) + +liboctbstack.a: obj_build + @echo "Building $@" + # Unpackage libcoap.a to $(OBJ_DIR)/$(BUILD). The output objects from OCStack and OCCoap are already at this location + @cd $(OBJ_DIR) && $(AR) -x $(PLATFORM_SPECIFIC_BACKOUT)$(LCOAP_DIR)/$(PLATFORM)$(ARDUINO_SHIELD_TYPE)/$(BUILD)/libcoap.a + # Repackage all the objects at this location into a single archive. This is OCStack, OCCoap, and LibCoap (LibCoap contains OCRandom, OCLogger, and OCSocket.). + $(AR) -r $(OUT_DIR)/$@ $(OBJ_DIR)/*.o + + ifeq ($(PLATFORM),linux) + ifneq ($(wildcard $(TINYDTLS_DIR)/libtinydtls.a),) + $(info "Building liboctbstack with DTLS support") + mkdir -p $(OBJ_DIR)/tinydtls + @cd $(OBJ_DIR)/tinydtls && $(AR) -x ../$(PLATFORM_SPECIFIC_BACKOUT)$(TINYDTLS_DIR)/libtinydtls.a + $(AR) -q $(OUT_DIR)/$@ $(OBJ_DIR)/tinydtls/*.o + endif + endif + +.PHONY: clean print_vars + +clean: legacy_clean + -rm -rf linux + -rm -rf arduinomega + -rm -rf arduinodue + +deepclean: legacy_deepclean + -rm -rf linux + -rm -rf arduinomega + -rm -rf arduinodue + +legacy_clean: + @echo "Cleaning all." + rm -f $(OBJ_DIR)/$(BUILD)/*.o + rm -f $(ROOT_DIR)/$(BUILD)/liboctbstack.a + rm -rf $(OBJ_DIR) + rm -rf release + rm -rf debug + +legacy_deepclean: + @echo "Deep-Cleaning all." + rm -f $(OBJ_DIR)/$(BUILD)/*.o + rm -f $(ROOT_DIR)/liboctbstack.a + rm -rf $(OBJ_DIR) + $(MAKE) clean -C $(LCOAP_DIR) + rm -rf release + rm -rf debug diff --git a/resource/csdk/occoap/README.txt b/resource/csdk/occoap/README.txt new file mode 100644 index 000000000..20e70130a --- /dev/null +++ b/resource/csdk/occoap/README.txt @@ -0,0 +1,27 @@ +#============================================================================== +# NOTICE - Transition to SCONS +#============================================================================== + +The IoTivity build system is transitioning to SCONS. Although the +makefiles are still available (until v1.0) and some developers are +still using them, they are currently no longer supported. To learn more +about building using SCONS see Readme.scons.txt in the repository root +directory. The build steps used in continuous integration can be found +in auto_build.sh which is also in the the repository root directory. + +#============================================================================== +# Build instructions for Linux +#============================================================================== + +In ./occoap directory +clean ==> make clean +build ==> make + +#============================================================================== +# Unit test instructions for Linux +#============================================================================== + +After building (make), run +./occoap/bin/debug/occoaptest + + diff --git a/resource/csdk/occoap/include/occoap.h b/resource/csdk/occoap/include/occoap.h new file mode 100644 index 000000000..31ab9f0f3 --- /dev/null +++ b/resource/csdk/occoap/include/occoap.h @@ -0,0 +1,118 @@ +//****************************************************************** +/// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OCCOAP_H_ +#define OCCOAP_H_ + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include "ocstack.h" +#include "occoaptoken.h" +#include "ocstackinternal.h" +#include "occoaphelper.h" +#include + +//----------------------------------------------------------------------------- +// Function Prototypes +//----------------------------------------------------------------------------- + +uint32_t GetTime(float afterSeconds); + +/** + * Initialize the CoAP client or server with the its IPv4 address and CoAP port + * + * @param ipAddr + * IP Address of host device + * @param port + * Port of host device + * @param mode + * Host device is client, server, or client-server + * + * @return + * 0 - success + * TBD - TBD error + */ +OCStackResult OCInitCoAP(const char *address, uint16_t port, OCMode mode); + +/** + * Discover OC resources + * + * @param method - method to perform on the resource + * @param qos - CON or NON requests + * @param token - pointer to the token data structure + * @param Uri - URI of the resource to interact with + * @param payload - CoAP PDU payload + * @param options - The address of an array containing the vendor specific + * header options to be sent with the request + * @param numOptions - The number of header options to be included + * @return + * 0 - success + * TBD - TBD error + */ +OCStackResult OCDoCoAPResource(OCMethod method, OCQualityOfService qos, OCCoAPToken * token, + const char *Uri, const char *payload, OCHeaderOption * options, uint8_t numOptions); + +/** + * Send a response to a request. + * + * @param response - pointer to OCServerProtocolResponse that contains all request and + * response info necessary to send the response to the client + * @return + * OC_STACK_OK - No errors; Success + * OC_STACK_ERROR - Error sending response + */ +OCStackResult OCDoCoAPResponse(OCServerProtocolResponse *response); + +/** + * Stop the CoAP client or server processing + * + * @return 0 - success, else - TBD error + */ +OCStackResult OCStopCoAP(); + +/** + * Called in main loop of CoAP client or server. Allows low-level CoAP processing of + * send, receive, timeout, discovery, callbacks, etc. + * + * @return 0 - success, else - TBD error + */ +OCStackResult OCProcessCoAP(); + +/** + * This method is called to generate a token of MAX_TOKEN_LENGTH. + * This token is used to co-relate client requests with server responses. + * + */ +void OCGenerateCoAPToken(OCCoAPToken * token); + +/** + * Retrieve the end-point info where resource is being hosted. + * Currently, this method only provides the IP port with which the socket + * is bound. This internal method may be extended in future to retrieve + * more info (such as IP address, transport technology) about the hosting end-point. + * + * @param resPtr - pointer to the resource + * @param info - pointer to 16-bit integer to hold port number + * @return 0 - success, else - TBD error + */ +OCStackResult OCGetResourceEndPointInfo (OCResource *resPtr, void *info); + +#endif /* OCCOAP_H_ */ diff --git a/resource/csdk/occoap/include/occoaphelper.h b/resource/csdk/occoap/include/occoaphelper.h new file mode 100644 index 000000000..8e3677697 --- /dev/null +++ b/resource/csdk/occoap/include/occoaphelper.h @@ -0,0 +1,118 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// + +#ifndef OCCOAPHELPER_H_ +#define OCCOAPHELPER_H_ + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#ifndef WITH_ARDUINO +#include +#endif +#include +#include +#include "coap.h" +#include "ocstack.h" +#include "occoaptoken.h" +#include "ocstackinternal.h" + +/** + * The Max Size of the buffer that is used to parse uri and query + * individually. + */ +#define MAX_URI_QUERY_BUF_SIZE ((MAX_URI_LENGTH) >= (MAX_QUERY_LENGTH) ?\ + (MAX_URI_LENGTH) : (MAX_QUERY_LENGTH)) + +#define COAP_WK_IPAddr_0 (224) +#define COAP_WK_IPAddr_1 (0) +#define COAP_WK_IPAddr_2 (1) +#define COAP_WK_IPAddr_3 (187) + +// checks if optionID is within vendor specific range +OCStackResult isVendorSpecific(uint16_t optionID); + +// Convert OCStack code to CoAP code +uint8_t OCToCoAPResponseCode(OCStackResult result); + +//Convert OCQualityOfService to coap NON vs CON +uint8_t OCToCoAPQoS(OCQualityOfService qos, uint8_t * ipAddr); + +// Convert CoAP code to OCStack code +OCStackResult CoAPToOCResponseCode(uint8_t coapCode); + +// Internal function to generate a coap pdu based on passed parameters +coap_pdu_t * +GenerateCoAPPdu(uint8_t msgType, uint8_t code, unsigned short id, + OCCoAPToken * token, unsigned char * payloadJSON, + coap_list_t *options); + +// Internal function to send a coap pdu, it also handles NON and CON +OCStackResult +SendCoAPPdu(coap_context_t * gCoAPCtx, coap_address_t* dst, coap_pdu_t * pdu, + coap_send_flags_t flag); + +// Call back function used by libcoap to order option in coap pdu +int OrderOptions(void *a, void *b); + +// Internal function to create an option node for coap pdu +coap_list_t * +CreateNewOptionNode(unsigned short key, unsigned int length, + unsigned char *data); + +// Internal function to retrieve Uri and Query from received coap pdu +OCStackResult ParseCoAPPdu(coap_pdu_t * pdu, unsigned char * uriBuf, + unsigned char * queryBuf, uint32_t * observeOption, + uint32_t * maxAgeOption, + uint8_t * numVendorSpecificHeaderOptions, + OCHeaderOption * vendorSpecificHeaderOptions, + coap_block_t * block1, coap_block_t * block2, + uint16_t * size1, uint16_t * size2, + unsigned char * payload); + +// Internal function to retrieve a Token from received coap pdu +void RetrieveOCCoAPToken(const coap_pdu_t * pdu, OCCoAPToken * rcvdToken); + +// Internal function to create OCResponse struct at the client from a received coap pdu +OCStackResult FormOCResponse(OCResponse * * responseLoc, ClientCB * cbNode, + uint8_t TTL, OCClientResponse * clientResponse); + +// Internal function to create OCClientResponse struct at the client from a received coap pdu +OCStackResult FormOCClientResponse(OCClientResponse * clientResponse, + OCStackResult result, OCDevAddr * remote, uint32_t seqNum, + const unsigned char * resJSONPayload); + +// Internal function to handle the queued pdus in the send queue +void HandleSendQueue(coap_context_t * gCoAPCtx); + +// Internal function to form the standard response option list +OCStackResult FormOptionList(coap_list_t * * optListLoc, uint8_t * addMediaType, + uint32_t * addMaxAge, uint32_t * observeOptionPtr, + uint16_t * addPortNumber, uint8_t uriLength, unsigned char * uri, + uint8_t queryLength, unsigned char * query, OCHeaderOption * vendorSpecificHeaderOptions, + uint8_t numVendorSpecificHeaderOptions); + +// Internal function to retransmit a queue +OCStackResult ReTXCoAPQueue(coap_context_t * ctx, coap_queue_t * queue); + +// Internal function called when sending/retransmission fails +OCStackResult HandleFailedCommunication(coap_context_t * ctx, coap_queue_t * queue); +#endif /* OCCOAPHELPER_H_ */ diff --git a/resource/csdk/occoap/include/occoaptoken.h b/resource/csdk/occoap/include/occoaptoken.h new file mode 100644 index 000000000..db171a72e --- /dev/null +++ b/resource/csdk/occoap/include/occoaptoken.h @@ -0,0 +1,35 @@ + +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// + +#ifndef OCCOAPTOKEN_H_ +#define OCCOAPTOKEN_H_ + +#include + +#define MAX_TOKEN_LENGTH (8) + +typedef struct { + uint8_t token[MAX_TOKEN_LENGTH]; + size_t tokenLength; +} OCCoAPToken; + +#endif diff --git a/resource/csdk/occoap/makefile b/resource/csdk/occoap/makefile new file mode 100644 index 000000000..a9f6cd414 --- /dev/null +++ b/resource/csdk/occoap/makefile @@ -0,0 +1,139 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +# override with `make BUILD=release` +# default to release build +BUILD := release + +# You must create the file "local.properties" on your local machine which contains any local paths, etc +# local_settings.mk should NOT be committed to repo +include ./local.properties +# GTEST_DIR contains the path to Google Test libs and must be defined in local.properties +# Example: +# GTEST_DIR := /home/johndoe/utils/gtest-1.7.0 + +# NOTE: to run app, make sure that LD_LIBRARY_PATH env variable +# contains $(GTEST_DIR)/lib/.libs + +CC := gcc +CXX := g++ + +PROG := occoaptest + +#SRC_DIR := ./src +TEST_DIR:= ./test +#INC_DIR := ./include +#LOG_DIR := ../logger +#STACK_DIR := ../stack + +CC_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c99 -fpic -DTB_LOG +CC_FLAGS.release := -Os -Wall -c -fmessage-length=0 -std=c99 -fpic +CC_FLAGS := $(CC_FLAGS.$(BUILD)) + +CXX_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c++0x -fpic -DTB_LOG +CXX_FLAGS.release := -Os -Wall -c -fmessage-length=0 -std=c++0x -fpic +CXX_FLAGS := $(CXX_FLAGS.$(BUILD)) + +#INC := -I$(SRC_DIR) +#INC += -I$(TEST_DIR) +#INC += -I$(INC_DIR) +#INC += -I$(LOG_DIR)/include +#INC += -I$(STACK_DIR)/include +INC += -I$(GTEST_DIR)/include + + +# using make's computed variables to select object and bin folders +# depending on the build type +OBJ_DIR.debug := ./obj/debug +OBJ_DIR.release := ./obj/release +OBJ_DIR := $(OBJ_DIR.$(BUILD)) + +BIN_DIR.debug := ./bin/debug +BIN_DIR.release := ./bin/release +BIN_DIR := $(BIN_DIR.$(BUILD)) + +#C_FILES := $(wildcard $(LOG_DIR)/src/*.c) +#C_FILES += $(wildcard $(SRC_DIR)/*.c) +#CPP_FILES := $(wildcard $(SRC_DIR)/*.cpp) +CPP_FILES := $(wildcard $(TEST_DIR)/*.cpp) +#CPP_FILES += $(wildcard $(LOG_DIR)/src/*.c) +OBJ_FILES := $(addprefix $(OBJ_DIR)/,$(notdir $(CPP_FILES:.cpp=.o) $(C_FILES:.c=.o))) +H_FILES := $(wildcard $(TEST_DIR)/*.h) +#H_FILES += $(wildcard $(INC_DIR)/*.h) +#H_FILES += $(wildcard $(LOG_DIR)/include/*.h) +LD_FLAGS := -L/usr/lib +LD_FLAGS += -L$(GTEST_DIR)/lib/.libs + + +LIBS := -lgtest +LIBS += -lgtest_main +LIBS += -lpthread + + +all: $(PROG) + mkdir -p ./$(OBJ_DIR) + mkdir -p ./$(BIN_DIR) + +$(PROG): $(OBJ_FILES) + $(CXX) -o $@ $^ $(LD_FLAGS) $(LIBS) + mkdir -p ./$(BIN_DIR) + mv ./$(PROG) ./$(BIN_DIR) + +#$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h $(H_FILES) +# $(CXX) $(CXX_FLAGS) $(INC) -c -o $@ $< + +#$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp $(INC_DIR)/%.h $(H_FILES) +# $(CXX) $(CXX_FLAGS) $(INC) -c -o $@ $< + +$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(INC_DIR)/%.h $(H_FILES) + mkdir -p ./$(OBJ_DIR) + $(CC) $(CC_FLAGS) $(INC) -c -o $@ $< + +$(OBJ_DIR)/%.o: $(LOG_DIR)/src/%.c $(LOG_DIR)/include/%.h $(H_FILES) + mkdir -p ./$(OBJ_DIR) + $(CC) $(CC_FLAGS) $(INC) -c -o $@ $< + +$(OBJ_DIR)/%.o: $(TEST_DIR)/%.cpp $(H_FILES) + mkdir -p ./$(OBJ_DIR) + $(CXX) $(CXX_FLAGS) $(INC) -c -o $@ $< + +.PHONY: clean +clean : + rm -rf ./obj/debug/* + rm -rf ./obj/release/* + rm -rf ./lib/* + rm -rf ./bin/debug/* + rm -rf ./bin/release/* + + +.PHONY: print_vars + +print_vars: + @echo "" + @echo 'BUILD = '$(value BUILD) + @echo 'INC = '$(value INC) + @echo 'CPP_FILES = '$(value CPP_FILES) + @echo 'C_FILES = '$(value C_FILES) + @echo 'LIBS = '$(value LIBS) + @echo 'OBJ_FILES = '$(value OBJ_FILES) + @echo 'SRC_DIR = '$(value SRC_DIR) + + + diff --git a/resource/csdk/occoap/src/occoap.c b/resource/csdk/occoap/src/occoap.c new file mode 100644 index 000000000..427ebf04d --- /dev/null +++ b/resource/csdk/occoap/src/occoap.c @@ -0,0 +1,964 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +//============================================================================= +// Includes +//============================================================================= +#define _POSIX_C_SOURCE 200112L +#include +#include "occoap.h" +#include "ocstackconfig.h" +#include "occlientcb.h" +#include "ocobserve.h" +#include "logger.h" +#include "ocmalloc.h" +#include + +#ifndef WITH_ARDUINO +#include +#endif +#include +#include + +//============================================================================= +// Macros +//============================================================================= +#define TAG PCF("OCCoAP") +#define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \ + {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} } +#define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG_V(FATAL, TAG, "%s is NULL", #arg); goto exit;} } + +//============================================================================= +// Defines +//============================================================================= +#define COAP_BLOCK_FILL_VALUE (0xFF) + +//============================================================================= +// Private Variables +//============================================================================= + +static coap_context_t *gCoAPCtx = NULL; + +//============================================================================= +// Helper Functions +//============================================================================= + +//generate a coap token +void OCGenerateCoAPToken(OCCoAPToken * token) +{ + if (token) + { + token->tokenLength = MAX_TOKEN_LENGTH; + OCFillRandomMem((uint8_t*)token->token, token->tokenLength); + } +} + +//This function is called back by libcoap when ack or rst are received +static void HandleCoAPAckRst(struct coap_context_t * ctx, uint8_t msgType, + const coap_queue_t * sentQueue){ + + // silence warnings + (void) ctx; + coap_pdu_t * sentPdu = sentQueue->pdu; + OCStackResult result = OC_STACK_ERROR; + uint32_t observationOption = OC_OBSERVE_NO_OPTION; + // {{0}} to eliminate warning for known compiler bug 53119 + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119 + OCCoAPToken sentToken = {{0}}; + + result = ParseCoAPPdu(sentPdu, NULL, NULL, &observationOption, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + VERIFY_SUCCESS(result, OC_STACK_OK); + + // fill OCCoAPToken structure + RetrieveOCCoAPToken(sentPdu, &sentToken); + + if(msgType == COAP_MESSAGE_RST) + { + if(myStackMode != OC_CLIENT) + { + result = OCStackFeedBack(&sentToken, OC_OBSERVER_NOT_INTERESTED); + if(result == OC_STACK_OK) + { + OC_LOG_V(DEBUG, TAG, + "Received RST, removing all queues associated with Token %d bytes", + sentToken.tokenLength); + OC_LOG_BUFFER(INFO, TAG, sentToken.token, sentToken.tokenLength); + coap_cancel_all_messages(ctx, &sentQueue->remote, sentToken.token, + sentToken.tokenLength); + } + } + } + else if(observationOption != OC_OBSERVE_NO_OPTION && msgType == COAP_MESSAGE_ACK) + { + OC_LOG_V(DEBUG, TAG, "Received ACK, for Token %d bytes",sentToken.tokenLength); + OC_LOG_BUFFER(INFO, TAG, sentToken.token, sentToken.tokenLength); + // now the observer is still interested + if(myStackMode != OC_CLIENT) + { + OCStackFeedBack(&sentToken, OC_OBSERVER_STILL_INTERESTED); + } + } +exit: + return; +} + +//This function is called back by libcoap when a request is received +static void HandleCoAPRequests(struct coap_context_t *ctx, + const coap_queue_t * rcvdRequest) +{ + // silence warnings + (void) ctx; + OCServerProtocolRequest protocolRequest = {(OCMethod)0}; + coap_block_t rcvdBlock1; + coap_block_t rcvdBlock2; + memset(&rcvdBlock1, COAP_BLOCK_FILL_VALUE, sizeof(coap_block_t)); + memset(&rcvdBlock2, COAP_BLOCK_FILL_VALUE, sizeof(coap_block_t)); + uint16_t rcvdSize1 = 0; + coap_pdu_t * rcvdPdu = rcvdRequest->pdu; + coap_pdu_t * sendPdu = NULL; + coap_send_flags_t sendFlag; + OCStackResult result = OC_STACK_ERROR; + OCStackResult requestResult = OC_STACK_ERROR; + + if(myStackMode == OC_CLIENT) + { + //TODO: should the client be responding to requests? + return; + } + + protocolRequest.observationOption = OC_OBSERVE_NO_OPTION; + protocolRequest.qos = (rcvdPdu->hdr->type == COAP_MESSAGE_CON) ? + OC_HIGH_QOS : OC_LOW_QOS; + protocolRequest.coapID = rcvdPdu->hdr->id; + protocolRequest.delayedResNeeded = rcvdRequest->delayedResNeeded; + protocolRequest.secured = rcvdRequest->secure; + + // fill OCCoAPToken structure + RetrieveOCCoAPToken(rcvdPdu, &protocolRequest.requestToken); + OC_LOG_V(INFO, TAG, " Token received %d bytes", + protocolRequest.requestToken.tokenLength); + OC_LOG_BUFFER(INFO, TAG, protocolRequest.requestToken.token, + protocolRequest.requestToken.tokenLength); + + // fill OCDevAddr + memcpy(&protocolRequest.requesterAddr, (OCDevAddr *) &rcvdRequest->remote, + sizeof(OCDevAddr)); + + // Retrieve Uri and Query from received coap pdu + result = ParseCoAPPdu(rcvdPdu, protocolRequest.resourceUrl, + protocolRequest.query, + &(protocolRequest.observationOption), NULL, + &(protocolRequest.numRcvdVendorSpecificHeaderOptions), + protocolRequest.rcvdVendorSpecificHeaderOptions, + &rcvdBlock1, &rcvdBlock2, &rcvdSize1, NULL, + protocolRequest.reqJSONPayload); + VERIFY_SUCCESS(result, OC_STACK_OK); + + switch (rcvdPdu->hdr->code) + { + case COAP_REQUEST_GET: + { + protocolRequest.method = OC_REST_GET; + break; + } + case COAP_REQUEST_POST: + { + protocolRequest.method = OC_REST_POST; + break; + } + case COAP_REQUEST_DELETE: + { + protocolRequest.method = OC_REST_DELETE; + break; + } + case COAP_REQUEST_PUT: + { + protocolRequest.method = OC_REST_PUT; + break; + } + default: + { + OC_LOG_V(ERROR, TAG, "Received CoAP method %d not supported", + rcvdPdu->hdr->code); + goto exit; + } + } + + if(rcvdBlock1.szx != 7) + { + protocolRequest.reqPacketSize = 1 << (rcvdBlock1.szx + 4); + protocolRequest.reqMorePacket = rcvdBlock1.m; + protocolRequest.reqPacketNum = rcvdBlock1.num; + } + else + { + // No block1 received + rcvdSize1 = strlen((const char *)protocolRequest.reqJSONPayload)+1; + protocolRequest.reqTotalSize = rcvdSize1; + } + + if(rcvdBlock2.szx != 7) + { + protocolRequest.resPacketSize = 1 << (rcvdBlock2.szx + 4); + protocolRequest.resPacketNum = rcvdBlock2.num; + } + + requestResult = HandleStackRequests(&protocolRequest); + + if(requestResult == OC_STACK_VIRTUAL_DO_NOT_HANDLE || + requestResult == OC_STACK_OK || + requestResult == OC_STACK_RESOURCE_CREATED || + requestResult == OC_STACK_RESOURCE_DELETED || + requestResult == OC_STACK_INVALID_DEVICE_INFO) + { + goto exit; + } + else if(requestResult == OC_STACK_NO_MEMORY || + requestResult == OC_STACK_ERROR || + requestResult == OC_STACK_NOTIMPL || + requestResult == OC_STACK_NO_RESOURCE || + requestResult == OC_STACK_RESOURCE_ERROR) + { + // TODO: should we send an error also when we receive a non-secured request to a secure resource? + // TODO: should we consider some sort of error response + OC_LOG(DEBUG, TAG, PCF("We should send some sort of error message")); + // generate the pdu, if the request was CON, then the response is ACK, otherwire NON + sendPdu = GenerateCoAPPdu((rcvdPdu->hdr->type == COAP_MESSAGE_CON)? COAP_MESSAGE_ACK : COAP_MESSAGE_NON, + OCToCoAPResponseCode(requestResult), rcvdPdu->hdr->id, + &protocolRequest.requestToken, NULL, NULL); + VERIFY_NON_NULL(sendPdu); + coap_show_pdu(sendPdu); + sendFlag = (coap_send_flags_t)(rcvdRequest->secure ? SEND_SECURE_PORT : 0); + if(SendCoAPPdu(gCoAPCtx, (coap_address_t*) &(rcvdRequest->remote), sendPdu, + sendFlag) + != OC_STACK_OK){ + OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu")); + } + goto exit; + } + else if(requestResult == OC_STACK_SLOW_RESOURCE) + { + if(rcvdPdu->hdr->type == COAP_MESSAGE_CON) + { + // generate the pdu, if the request was CON, then the response is ACK, otherwire NON + sendPdu = GenerateCoAPPdu(COAP_MESSAGE_ACK, 0, rcvdPdu->hdr->id, + NULL, NULL, NULL); + VERIFY_NON_NULL(sendPdu); + coap_show_pdu(sendPdu); + + sendFlag = (coap_send_flags_t)(rcvdRequest->secure ? SEND_SECURE_PORT : 0); + if(SendCoAPPdu(gCoAPCtx, (coap_address_t*) &(rcvdRequest->remote), sendPdu, + sendFlag) + != OC_STACK_OK){ + OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu")); + } + } + else + { + goto exit; + } + } +exit: + return; +} + +uint32_t GetTime(float afterSeconds) +{ + coap_tick_t now; + coap_ticks(&now); + return now + (uint32_t)(afterSeconds * COAP_TICKS_PER_SECOND); +} + +//This function is called back by libcoap when a response is received +static void HandleCoAPResponses(struct coap_context_t *ctx, + const coap_queue_t * rcvdResponse) { + OCResponse * response = NULL; + OCCoAPToken rcvdToken; + OCClientResponse clientResponse = {0}; + ClientCB * cbNode = NULL; + unsigned char bufRes[MAX_RESPONSE_LENGTH] = {0}; + uint32_t sequenceNumber = OC_OBSERVE_NO_OPTION; + uint32_t maxAge = 0; + OCStackResult result = OC_STACK_ERROR; + coap_pdu_t * sendPdu = NULL; + coap_pdu_t * recvPdu = NULL; + unsigned char rcvdUri[MAX_URI_LENGTH] = { 0 }; + uint8_t isObserveNotification = 0; + #ifdef WITH_PRESENCE + char * resourceTypeName = NULL; + uint8_t remoteIpAddr[4]; + uint16_t remotePortNu; + unsigned char fullUri[MAX_URI_LENGTH] = { 0 }; + uint8_t isPresenceNotification = 0; + uint8_t isMulticastPresence = 0; + uint32_t lowerBound; + uint32_t higherBound; + char * tok = NULL; + #endif + coap_block_t rcvdBlock1 = {COAP_BLOCK_FILL_VALUE}; + coap_block_t rcvdBlock2 = {COAP_BLOCK_FILL_VALUE}; + uint16_t rcvdSize2 = 0; + + VERIFY_NON_NULL(ctx); + VERIFY_NON_NULL(rcvdResponse); + recvPdu = rcvdResponse->pdu; + + result = ParseCoAPPdu(recvPdu, rcvdUri, NULL, &sequenceNumber, &maxAge, + &clientResponse.numRcvdVendorSpecificHeaderOptions, + clientResponse.rcvdVendorSpecificHeaderOptions, + &rcvdBlock1, &rcvdBlock2, NULL, &rcvdSize2, bufRes); + + VERIFY_SUCCESS(result, OC_STACK_OK); + + OC_LOG_V(DEBUG, TAG, "The sequenceNumber/NONCE of this response %u", sequenceNumber); + OC_LOG_V(DEBUG, TAG, "The maxAge/TTL of this response %u", maxAge); + OC_LOG_V(DEBUG, TAG, "The response received is %s", bufRes); + + if(sequenceNumber >= OC_OFFSET_SEQUENCE_NUMBER) + { + isObserveNotification = 1; + OC_LOG(INFO, TAG, PCF("Received an observe notification")); + } + + #ifdef WITH_PRESENCE + if(!strcmp((char *)rcvdUri, (char *)OC_PRESENCE_URI)){ + char* tokSavePtr; + + isPresenceNotification = 1; + OC_LOG(INFO, TAG, PCF("Received a presence notification")); + tok = strtok_r((char *)bufRes, "[:]}", &tokSavePtr); + bufRes[strlen((char *)bufRes)] = ':'; + tok = strtok_r(NULL, "[:]}", &tokSavePtr); + bufRes[strlen((char *)bufRes)] = ':'; + VERIFY_NON_NULL(tok); + sequenceNumber = (uint32_t )atol(tok); + OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", sequenceNumber); + tok = strtok_r(NULL, "[:]}", &tokSavePtr); + VERIFY_NON_NULL(tok); + maxAge = (uint32_t )atol(tok); + OC_LOG_V(DEBUG, TAG, "The received TTL is %u", maxAge); + tok = strtok_r(NULL, "[:]}", &tokSavePtr); + if(tok) { + bufRes[strlen((char *)bufRes)] = ':'; + resourceTypeName = (char *)OCMalloc(strlen(tok)); + if(!resourceTypeName) + { + goto exit; + } + strcpy(resourceTypeName, tok); + OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s", + resourceTypeName); + } + bufRes[strlen((char *)bufRes)] = ']'; + } + #endif + + // fill OCCoAPToken structure + RetrieveOCCoAPToken(recvPdu, &rcvdToken); + OC_LOG_V(INFO, TAG,"Received a pdu with Token", rcvdToken.tokenLength); + OC_LOG_BUFFER(INFO, TAG, rcvdToken.token, rcvdToken.tokenLength); + + // fill OCClientResponse structure + result = FormOCClientResponse(&clientResponse, CoAPToOCResponseCode(recvPdu->hdr->code), + (OCDevAddr *) &(rcvdResponse->remote), sequenceNumber, bufRes); + VERIFY_SUCCESS(result, OC_STACK_OK); + + cbNode = GetClientCB(&rcvdToken, NULL, NULL); + + #ifdef WITH_PRESENCE + // Check if the application subscribed for presence + if(!cbNode) + { + // get the address of the remote + OCDevAddrToIPv4Addr((OCDevAddr *) &(rcvdResponse->remote), remoteIpAddr, + remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3); + OCDevAddrToPort((OCDevAddr *) &(rcvdResponse->remote), &remotePortNu); + snprintf((char *)fullUri, sizeof(fullUri), "coap://%d.%d.%d.%d:%d%s", + remoteIpAddr[0],remoteIpAddr[1],remoteIpAddr[2],remoteIpAddr[3], + remotePortNu,rcvdUri); + cbNode = GetClientCB(NULL, NULL, fullUri); + } + + // Check if application subscribed for multicast presence + if(!cbNode) + { + snprintf((char *)fullUri, sizeof(fullUri), "%s%s", OC_MULTICAST_IP, rcvdUri); + cbNode = GetClientCB(NULL, NULL, fullUri); + isMulticastPresence = 1; + isPresenceNotification = 0; + } + #endif + + // fill OCResponse structure + result = FormOCResponse(&response, cbNode, maxAge, &clientResponse); + VERIFY_SUCCESS(result, OC_STACK_OK); + + if(cbNode) + { + if(!isObserveNotification) + { + #ifdef WITH_PRESENCE + if(!isPresenceNotification) + { + #endif + OC_LOG(INFO, TAG, PCF("Received a regular response")); + if(recvPdu->hdr->type == COAP_MESSAGE_CON) + { + sendPdu = GenerateCoAPPdu(COAP_MESSAGE_ACK, 0, + recvPdu->hdr->id, NULL, NULL, NULL); + VERIFY_NON_NULL(sendPdu); + result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote, + sendPdu, + (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0)); + } + #ifdef WITH_PRESENCE + } + #endif + } + if(isObserveNotification) + { + OC_LOG(INFO, TAG, PCF("Received an observe notification")); + if(recvPdu->hdr->type == COAP_MESSAGE_CON) + { + sendPdu = GenerateCoAPPdu(COAP_MESSAGE_ACK, 0, + recvPdu->hdr->id, NULL, NULL, NULL); + VERIFY_NON_NULL(sendPdu); + result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote, + sendPdu, + (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0)); + } + //TODO: check the standard for methods to detect wrap around condition + if(cbNode->method == OC_REST_OBSERVE && + (clientResponse.sequenceNumber <= cbNode->sequenceNumber || + (clientResponse.sequenceNumber > cbNode->sequenceNumber && + clientResponse.sequenceNumber == (MAX_SEQUENCE_NUMBER)))) + { + OC_LOG_V(DEBUG, TAG, "Observe notification came out of order. \ + Ignoring Incoming:%d Against Current:%d.", + clientResponse.sequenceNumber, cbNode->sequenceNumber); + goto exit; + } + if(clientResponse.sequenceNumber > cbNode->sequenceNumber){ + cbNode->sequenceNumber = clientResponse.sequenceNumber; + } + } + else + { + #ifdef WITH_PRESENCE + if(isPresenceNotification) + { + OC_LOG(INFO, TAG, PCF("Received a presence notification")); + if(!cbNode->presence) + { + cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence)); + VERIFY_NON_NULL(cbNode->presence); + cbNode->presence->timeOut = NULL; + cbNode->presence->timeOut = (uint32_t *) + OCMalloc(PresenceTimeOutSize * sizeof(uint32_t)); + if(!(cbNode->presence->timeOut)){ + OCFree(cbNode->presence); + goto exit; + } + } + if(maxAge == 0) + { + OC_LOG(INFO, TAG, PCF("===============Stopping presence")); + response->clientResponse->result = OC_STACK_PRESENCE_STOPPED; + if(cbNode->presence) + { + OCFree(cbNode->presence->timeOut); + OCFree(cbNode->presence); + cbNode->presence = NULL; + } + } + else + { + OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %d", GetTime(0)); + cbNode->presence->TTL = maxAge; + for(int index = 0; index < PresenceTimeOutSize; index++) + { + lowerBound = GetTime(((float)(PresenceTimeOut[index]) + /(float)100)*(float)cbNode->presence->TTL); + higherBound = GetTime(((float)(PresenceTimeOut[index + 1]) + /(float)100)*(float)cbNode->presence->TTL); + cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound); + OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout %d", lowerBound); + OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound); + OC_LOG_V(DEBUG, TAG, "----------------timeOut entry %d", cbNode->presence->timeOut[index]); + } + cbNode->presence->TTLlevel = 0; + OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel); + if(cbNode->sequenceNumber == clientResponse.sequenceNumber) + { + OC_LOG(INFO, TAG, PCF("===============No presence change")); + goto exit; + } + OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack")); + cbNode->sequenceNumber = clientResponse.sequenceNumber;; + } + + // Ensure that a filter is actually applied. + if(resourceTypeName && response->cbNode->filterResourceType) + { + if(!findResourceType(response->cbNode->filterResourceType, resourceTypeName)) + { + goto exit; + } + } + } + else if(isMulticastPresence) + { + // Check if the same nonce for a given host + OCMulticastNode* mcNode = NULL; + unsigned char senderUri[MAX_URI_LENGTH] = { 0 }; + snprintf((char *)senderUri, sizeof(senderUri), "%d.%d.%d.%d:%d", + remoteIpAddr[0],remoteIpAddr[1],remoteIpAddr[2],remoteIpAddr[3], + remotePortNu); + mcNode = GetMCPresenceNode(senderUri); + + if(maxAge == 0) + { + OC_LOG(INFO, TAG, PCF("===============Stopping presence")); + response->clientResponse->result = OC_STACK_PRESENCE_STOPPED; + if(cbNode->presence) + { + OCFree(cbNode->presence->timeOut); + OCFree(cbNode->presence); + cbNode->presence = NULL; + } + } + else if(mcNode != NULL) + { + if(mcNode->nonce == clientResponse.sequenceNumber) + { + OC_LOG(INFO, TAG, PCF("===============No presence change (Multicast)")); + goto exit; + } + mcNode->nonce = clientResponse.sequenceNumber; + } + else + { + uint32_t uriLen = strlen((char*)senderUri); + unsigned char* uri = (unsigned char *) OCMalloc(uriLen + 1); + if(uri) + { + memcpy(uri, senderUri, (uriLen + 1)); + } + else + { + OC_LOG(INFO, TAG, + PCF("===============No Memory for URI to store in the presence node")); + goto exit; + } + result = AddMCPresenceNode(&mcNode, (unsigned char*) uri, + clientResponse.sequenceNumber); + if(result == OC_STACK_NO_MEMORY) + { + OC_LOG(INFO, TAG, + PCF("===============No Memory for Multicast Presence Node")); + goto exit; + } + } + + // Ensure that a filter is actually applied. + if(resourceTypeName && response->cbNode->filterResourceType) + { + if(!findResourceType(response->cbNode->filterResourceType, resourceTypeName)) + { + goto exit; + } + } + } + #endif + } + HandleStackResponses(response); + } + else if(!cbNode && isObserveNotification) + { + OC_LOG(INFO, TAG, PCF("Received an observe notification, but I do not have callback \ + ------------ sending RESET")); + sendPdu = GenerateCoAPPdu(COAP_MESSAGE_RST, 0, + recvPdu->hdr->id, NULL, NULL, NULL); + VERIFY_NON_NULL(sendPdu); + result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote, sendPdu, + (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0)); + VERIFY_SUCCESS(result, OC_STACK_OK); + } + #ifdef WITH_PRESENCE + else if(!cbNode && isPresenceNotification) + { + OC_LOG(INFO, TAG, PCF("Received a presence notification, but I do not have callback \ + ------------ ignoring")); + } + #endif + else + { + OC_LOG(INFO, TAG, PCF("Received a response, but I do not have callback. \ + ------------ sending RESET")); + sendPdu = GenerateCoAPPdu(COAP_MESSAGE_RST, 0, + recvPdu->hdr->id, NULL, NULL, NULL); + VERIFY_NON_NULL(sendPdu); + result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote, sendPdu, + (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0)); + VERIFY_SUCCESS(result, OC_STACK_OK); + } + exit: + OCFree(resourceTypeName); + OCFree(response); +} + +//============================================================================= +// Functions +//============================================================================= + +/** + * Initialize the CoAP client or server with its IPv4 address and CoAP port + * + * @param ipAddr + * IP Address of host device + * @param port + * Port of host device + * @param mode + * Host device is client, server, or client-server + * + * @return + * 0 - success + * TBD - TBD error + */ +OCStackResult OCInitCoAP(const char *address, uint16_t port, OCMode mode) { + + OCStackResult ret = OC_STACK_ERROR; + + TODO ("Below should go away and be replaced by OC_LOG"); + coap_log_t log_level = (coap_log_t)(LOG_DEBUG + 1); + OCDevAddr mcastAddr; + uint8_t ipAddr[4] = { 0 }; + uint16_t parsedPort = 0; + + OC_LOG(INFO, TAG, PCF("Entering OCInitCoAP")); + + coap_set_log_level(log_level); + + if (address) + { + if (!ParseIPv4Address((unsigned char *) address, ipAddr, &parsedPort)) + { + ret = OC_STACK_ERROR; + goto exit; + } + + OC_LOG_V(INFO, TAG, "Parsed IP Address %d.%d.%d.%d", + ipAddr[0],ipAddr[1],ipAddr[2],ipAddr[3]); + } + + gCoAPCtx = coap_new_context(ipAddr, port); + VERIFY_NON_NULL(gCoAPCtx); + + // To allow presence notification work we need to init socket gCoAPCtx->sockfd_wellknown + // for servers as well as clients + OCBuildIPv4Address(COAP_WK_IPAddr_0, COAP_WK_IPAddr_1, COAP_WK_IPAddr_2, + COAP_WK_IPAddr_3, COAP_DEFAULT_PORT, &mcastAddr); + VERIFY_SUCCESS( + coap_join_wellknown_group(gCoAPCtx, + (coap_address_t* )&mcastAddr), 0); + + coap_register_request_handler(gCoAPCtx, HandleCoAPRequests); + coap_register_response_handler(gCoAPCtx, HandleCoAPResponses); + coap_register_ack_rst_handler(gCoAPCtx, HandleCoAPAckRst); + + ret = OC_STACK_OK; + +exit: + if (ret != OC_STACK_OK) + { + OCStopCoAP(); + } + return ret; +} + +/** + * Discover OC resources + * + * @param method - method to perform on the resource + * @param qos - Quality of Service the request will be sent on + * @param token - token which will added to the request + * @param Uri - URI of the resource to interact with + * @param payload - the request payload to be added to the request before sending + * by the stack when discovery or resource interaction is complete + * @param options - The address of an array containing the vendor specific + * header options to be sent with the request + * @return + * 0 - success + * TBD - TBD error + */ +OCStackResult OCDoCoAPResource(OCMethod method, OCQualityOfService qos, OCCoAPToken * token, + const char *Uri, const char *payload, OCHeaderOption * options, uint8_t numOptions) +{ + + OCStackResult ret = OC_STACK_ERROR; + coap_pdu_t *pdu = NULL; + coap_uri_t uri; + OCDevAddr dst; + uint8_t ipAddr[4] = { 0 }; + uint16_t port = 0; + coap_list_t *optList = NULL; + uint8_t coapMsgType; + uint8_t coapMethod; + uint32_t observeOption; + coap_send_flags_t flag = (coap_send_flags_t)0; + + OC_LOG(INFO, TAG, PCF("Entering OCDoCoAPResource")); + + if (Uri) { + OC_LOG_V(INFO, TAG, "URI = %s", Uri); + VERIFY_SUCCESS(coap_split_uri((unsigned char * )Uri, strlen(Uri), &uri), OC_STACK_OK); + + // Generate the destination address + if (uri.host.length && ParseIPv4Address(uri.host.s, ipAddr, &port)) { + OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], uri.port, + &dst); + } else { + goto exit; + } + + VERIFY_SUCCESS(FormOptionList(&optList, NULL, NULL, NULL, + (uint16_t*)&uri.port, uri.path.length, uri.path.s, uri.query.length, + uri.query.s, options, numOptions), OC_STACK_OK); + + //TODO : Investigate the scenario where there will be no uri for OCDoCoAPResource + flag = (coap_send_flags_t) (uri.secure ? SEND_SECURE_PORT : 0); + OC_LOG_V(DEBUG, TAG, "uri.host.s %s", uri.host.s); + OC_LOG_V(DEBUG, TAG, "uri.path.s %s", uri.path.s); + OC_LOG_V(DEBUG, TAG, "uri.port %d", uri.port); + OC_LOG_V(DEBUG, TAG, "uri.query.s %s", uri.query.s); + OC_LOG_V(DEBUG, TAG, "secure uri %d", uri.secure); + } + + coapMsgType = OCToCoAPQoS(qos, ipAddr); + + // Decide method type + switch (method) { + case OC_REST_GET: + #ifdef WITH_PRESENCE + case OC_REST_PRESENCE: + #endif + coapMethod = COAP_REQUEST_GET; + break; + case OC_REST_PUT: + coapMethod = COAP_REQUEST_PUT; + break; + case OC_REST_POST: + coapMethod = COAP_REQUEST_POST; + break; + case OC_REST_DELETE: + coapMethod = COAP_REQUEST_DELETE; + break; + case OC_REST_OBSERVE_ALL: + case OC_REST_OBSERVE: + case OC_REST_CANCEL_OBSERVE: + coapMethod = COAP_REQUEST_GET; + observeOption = (method == OC_REST_CANCEL_OBSERVE)? + OC_OBSERVE_DEREGISTER:OC_OBSERVE_REGISTER; + coap_insert(&optList, CreateNewOptionNode(COAP_OPTION_OBSERVE, + sizeof(observeOption), (uint8_t *)&observeOption), OrderOptions); + break; + default: + coapMethod = OC_REST_NOMETHOD; + OC_LOG(FATAL, TAG, PCF("OCDoCoAPResource only supports GET, PUT, & OBSERVE methods")); + break; + } + + VERIFY_NON_NULL(gCoAPCtx); + pdu = GenerateCoAPPdu(coapMsgType, coapMethod, + coap_new_message_id(gCoAPCtx), token, + (unsigned char*) payload, optList); + VERIFY_NON_NULL(pdu); + + ret = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &dst, pdu, flag); + +exit: + if (ret!= OC_STACK_OK) + { + OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu")); + } + return ret; +} + +OCStackResult OCDoCoAPResponse(OCServerProtocolResponse *response) +{ + OCStackResult result = OC_STACK_ERROR; + coap_pdu_t * sendPdu = NULL; + coap_list_t *optList = NULL; + uint8_t msgType = COAP_MESSAGE_NON; + uint8_t mediaType = COAP_MEDIATYPE_APPLICATION_JSON; + uint32_t maxAge = 0x2ffff; + coap_send_flags_t sendFlag = (coap_send_flags_t)0; + + //uint32_t observeOption = OC_OBSERVE_NO_OPTION; + //OCStackResult responseResult; + + OC_LOG(INFO, TAG, PCF("Entering OCDoCoAPResponse")); + + if(response->notificationFlag && response->qos == OC_HIGH_QOS) + { + msgType = COAP_MESSAGE_CON; + } + else if(response->notificationFlag && response->qos != OC_HIGH_QOS) + { + msgType = COAP_MESSAGE_NON; + } + else if(!response->notificationFlag && !response->slowFlag && response->qos == OC_HIGH_QOS) + { + msgType = COAP_MESSAGE_ACK; + } + else if(!response->notificationFlag && response->slowFlag && response->qos == OC_HIGH_QOS) + { + msgType = COAP_MESSAGE_CON; + } + else if(!response->notificationFlag) + { + msgType = COAP_MESSAGE_NON; + } + + if(response->coapID == 0) + { + response->coapID = coap_new_message_id(gCoAPCtx); + } + + if (response->observationOption != OC_OBSERVE_NO_OPTION) + { + result = FormOptionList(&optList, &mediaType, &maxAge, + &response->observationOption, NULL, + strlen((char *)response->resourceUri), response->resourceUri, + 0, NULL, + response->sendVendorSpecificHeaderOptions, + response->numSendVendorSpecificHeaderOptions); + } + else + { + result = FormOptionList(&optList, &mediaType, &maxAge, + NULL, NULL, + strlen((char *)response->resourceUri), response->resourceUri, + 0, NULL, + response->sendVendorSpecificHeaderOptions, + response->numSendVendorSpecificHeaderOptions); + } + VERIFY_SUCCESS(result, OC_STACK_OK); + + sendPdu = GenerateCoAPPdu(msgType, OCToCoAPResponseCode(response->result), + response->coapID, response->requestToken, (unsigned char *)response->payload, + optList); + + VERIFY_NON_NULL(sendPdu); + coap_show_pdu(sendPdu); + + sendFlag = (coap_send_flags_t)(response->delayedResNeeded ? SEND_DELAYED : 0); + sendFlag = (coap_send_flags_t)( sendFlag | (response->secured ? SEND_SECURE_PORT : 0)); + + if (SendCoAPPdu(gCoAPCtx, (coap_address_t *) (response->requesterAddr), sendPdu, sendFlag) + != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, PCF("A problem occurred in sending a pdu")); + return OC_STACK_ERROR; + } + + return OC_STACK_OK; + +exit: + OC_LOG(ERROR, TAG, PCF("Error formatting server response")); + return OC_STACK_ERROR; +} + + +/** + * Stop the CoAP client or server processing + * + * @return 0 - success, else - TBD error + */ +OCStackResult OCStopCoAP() { + OC_LOG(INFO, TAG, PCF("Entering OCStopCoAP")); + coap_free_context(gCoAPCtx); + gCoAPCtx = NULL; + return OC_STACK_OK; +} + +/** + * Called in main loop of CoAP client or server. Allows low-level CoAP processing of + * send, receive, timeout, discovery, callbacks, etc. + * + * @return 0 - success, else - TBD error + */ +OCStackResult OCProcessCoAP() { + + OC_LOG(INFO, TAG, PCF("Entering OCProcessCoAP")); + int read = 0; + read = coap_read(gCoAPCtx, gCoAPCtx->sockfd); + if(read > 0) { + OC_LOG(INFO, TAG, PCF("This is a Unicast<============")); + } + if (-1 != gCoAPCtx->sockfd_wellknown) { + read = coap_read(gCoAPCtx, gCoAPCtx->sockfd_wellknown); + if(read > 0) + { + OC_LOG(INFO, TAG, PCF("This is a Multicast<===========")); + } + } + if (-1 != gCoAPCtx->sockfd_dtls) { + read = coap_read(gCoAPCtx, gCoAPCtx->sockfd_dtls); + if(read > 0) + { + OC_LOG(INFO, TAG, PCF("This is a Secure packet<===========")); + } + } + coap_dispatch(gCoAPCtx); + + HandleSendQueue(gCoAPCtx); + + return OC_STACK_OK; +} + + +/** + * Retrieve the info about the end-point where resource is being hosted. + * Currently, this method only provides the IP port with which the socket + * is bound. + * + * @return 0 - success, else - TBD error + */ +OCStackResult OCGetResourceEndPointInfo (OCResource *resPtr, void *info) { + + OCStackResult result = OC_STACK_ERROR; + int sfd; + OC_LOG(INFO, TAG, PCF("Entering OCGetResourceEndPointInfo")); + VERIFY_NON_NULL(resPtr); + VERIFY_NON_NULL(info); + + sfd = (resPtr->resourceProperties & OC_SECURE) ? gCoAPCtx->sockfd_dtls : + gCoAPCtx->sockfd; + + if (OCGetSocketInfo(sfd, (uint16_t*)info) == ERR_SUCCESS) + result = OC_STACK_OK; +exit: + return result; +} + + diff --git a/resource/csdk/occoap/src/occoaphelper.c b/resource/csdk/occoap/src/occoaphelper.c new file mode 100644 index 000000000..1727c2606 --- /dev/null +++ b/resource/csdk/occoap/src/occoaphelper.c @@ -0,0 +1,714 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include "occoaphelper.h" +#include "ocstackconfig.h" +#include "logger.h" +#include "coap_time.h" +#include "ocmalloc.h" + +//----------------------------------------------------------------------------- +// Macros +//----------------------------------------------------------------------------- +#define TAG PCF("OCCoAPHelper") +#define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG_V(FATAL, TAG, "%s is NULL", #arg); goto exit;} } + +//============================================================================= +// Helper Functions +//============================================================================= + +OCStackResult isVendorSpecific(uint16_t optionID) +{ + if(optionID >= COAP_VENDOR_OPT_START && optionID <= COAP_MAX_OPT) + { + return OC_STACK_OK; + } + return OC_STACK_INVALID_OPTION; +} + +// Convert OCStack code to CoAP code +uint8_t OCToCoAPResponseCode(OCStackResult result) +{ + uint8_t ret; + switch(result) + { + case OC_STACK_OK : + ret = COAP_RESPONSE_200; + break; + + case OC_STACK_RESOURCE_CREATED: + ret = COAP_RESPONSE_201; + break; + + case OC_STACK_RESOURCE_DELETED: + ret = COAP_RESPONSE_202; + break; + + case OC_STACK_INVALID_QUERY : + ret = COAP_RESPONSE_400; + break; + + case OC_STACK_RESOURCE_ERROR: + return COAP_RESPONSE_403; + break; + + case OC_STACK_NO_RESOURCE : + ret = COAP_RESPONSE_404; + break; + + case OC_STACK_INVALID_METHOD : + ret = COAP_RESPONSE_405; + break; + + case OC_STACK_NOTIMPL : + ret = COAP_RESPONSE_501; + break; + + default: + ret = COAP_RESPONSE_500; + } + return ret; +} + +uint8_t OCToCoAPQoS(OCQualityOfService qos, uint8_t * ipAddr) +{ + if(ipAddr[0] == COAP_WK_IPAddr_0 && ipAddr[1] == COAP_WK_IPAddr_1 && + ipAddr[2] == COAP_WK_IPAddr_2 && ipAddr[3] == COAP_WK_IPAddr_3) + { + return COAP_MESSAGE_NON; + } + switch (qos) + { + case OC_HIGH_QOS: + return COAP_MESSAGE_CON; + break; + case OC_MEDIUM_QOS: + case OC_LOW_QOS: + case OC_NA_QOS: + default: + return COAP_MESSAGE_NON; + break; + } +} +// Convert CoAP code to OCStack code +OCStackResult CoAPToOCResponseCode(uint8_t coapCode) +{ + OCStackResult ret; + int decimal; + switch(coapCode) + { + case COAP_RESPONSE_200 : + ret = OC_STACK_OK; + break; + + case COAP_RESPONSE_201 : + ret = OC_STACK_RESOURCE_CREATED; + break; + + case COAP_RESPONSE_202 : + ret = OC_STACK_RESOURCE_DELETED; + break; + + case COAP_RESPONSE_400 : + ret = OC_STACK_INVALID_QUERY; + break; + + case COAP_RESPONSE_403 : + ret = OC_STACK_RESOURCE_ERROR; + break; + + case COAP_RESPONSE_404 : + ret = OC_STACK_NO_RESOURCE; + break; + + case COAP_RESPONSE_405 : + ret = OC_STACK_INVALID_METHOD; + break; + + case COAP_RESPONSE_501 : + ret = OC_STACK_NOTIMPL; + break; + + default: + decimal = ((coapCode >> 5) * 100) + (coapCode & 31); + if (decimal >= 200 && decimal <= 231) + { + ret = OC_STACK_OK; + } + else + { + ret = OC_STACK_ERROR; + } + } + return ret; +} + +// Retrieve Uri and Query from received coap pdu +OCStackResult ParseCoAPPdu(coap_pdu_t * pdu, unsigned char * uriBuf, + unsigned char * queryBuf, uint32_t * observeOption, + uint32_t * maxAgeOption, + uint8_t * numVendorSpecificHeaderOptions, + OCHeaderOption * vendorSpecificHeaderOptions, + coap_block_t * block1, coap_block_t * block2, + uint16_t * size1, uint16_t * size2, + unsigned char * payload) +{ + coap_opt_filter_t filter; + coap_opt_iterator_t opt_iter; + coap_opt_t *option = NULL; + size_t optLen = 0; + unsigned char * optVal = NULL; + size_t uriBufLen = 0; + size_t queryBufLen = 0; + unsigned char * payloadLoc = NULL; + size_t payloadLength = 0; + + coap_option_filter_clear(filter); + if(uriBuf) + { + coap_option_setb(filter, COAP_OPTION_URI_PATH); + } + if(queryBuf) + { + coap_option_setb(filter, COAP_OPTION_URI_QUERY); + } + if(observeOption) + { + coap_option_setb(filter, COAP_OPTION_OBSERVE); + } + if(maxAgeOption) + { + coap_option_setb(filter, COAP_OPTION_MAXAGE); + } + if(block1) + { + coap_option_setb(filter, COAP_OPTION_BLOCK1); + } + if(block2) + { + coap_option_setb(filter, COAP_OPTION_BLOCK2); + } + if(size1) + { + coap_option_setb(filter, COAP_OPTION_SIZE1); + } + if(size2) + { + coap_option_setb(filter, COAP_OPTION_SIZE2); + } + if(vendorSpecificHeaderOptions) + { + coap_option_setbVendor(filter); + } + if(payload) + { + coap_get_data(pdu, &payloadLength, &payloadLoc); + memcpy(payload, payloadLoc, payloadLength); + } + coap_option_iterator_init(pdu, &opt_iter, filter); + + while ((option = coap_option_next(&opt_iter))) + { + optLen = COAP_OPT_LENGTH(option); + optVal = COAP_OPT_VALUE(option); + switch(opt_iter.type) + { + case COAP_OPTION_URI_PATH: + if (uriBufLen + 1 + optLen < MAX_URI_LENGTH) + { + //we still have room in the buffer + uriBuf[uriBufLen++] = '/'; + memcpy(uriBuf + uriBufLen, optVal, optLen); + uriBufLen += optLen; + } + else + { + return OC_STACK_NO_MEMORY; + } + break; + case COAP_OPTION_URI_QUERY: + if (queryBufLen + 1 + optLen < MAX_QUERY_LENGTH) + { + //we still have room in the buffer + memcpy(queryBuf + queryBufLen, optVal, optLen); + queryBufLen += optLen; + queryBuf[queryBufLen++] = '&'; + } + else + { + // TODO: we should check that resources do not have long uri + // at the resource creation + return OC_STACK_NO_MEMORY; + } + break; + case COAP_OPTION_OBSERVE: + memcpy(observeOption, optVal, optLen); + OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^Parsing the observe option %u", + *observeOption); + break; + case COAP_OPTION_MAXAGE: + memcpy(maxAgeOption, optVal, optLen); + OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^Parsing the max age option %u", + *maxAgeOption); + break; + case COAP_OPTION_BLOCK1: + block1->szx = COAP_OPT_BLOCK_SZX(option); + block1->num = coap_opt_block_num(option); + block1->m = 0; + if(COAP_OPT_BLOCK_MORE(option)) + { + block1->m = 1; + } + OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^Parsing block1 %u:%u:%u", + block1->num, block1->m, block1->szx); + break; + case COAP_OPTION_BLOCK2: + block2->szx = COAP_OPT_BLOCK_SZX(option); + block2->num = coap_opt_block_num(option); + block2->m = 0; + if(COAP_OPT_BLOCK_MORE(option)) + { + block2->m = 1; + } + OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^Parsing block2 %u:%u:%u", + block1->num, block1->m, block1->szx); + break; + case COAP_OPTION_SIZE1: + break; + case COAP_OPTION_SIZE2: + break; + default: + if(*numVendorSpecificHeaderOptions >= MAX_HEADER_OPTIONS || + optLen > MAX_HEADER_OPTION_DATA_LENGTH) + { + return OC_STACK_NO_MEMORY; + } + vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].protocolID = OC_COAP_ID; + vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionID = opt_iter.type; + vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionLength = optLen; + memcpy(vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionData, optVal, optLen); + OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^Parsing vendor specific option %u", + vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionID); + OC_LOG_BUFFER(DEBUG, TAG, vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionData, + vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionLength); + (*numVendorSpecificHeaderOptions)++; + } + } + + if(uriBuf) + { + uriBuf[uriBufLen] = '\0'; + } + // delete last '&' in the query + if(queryBuf) + { + queryBuf[queryBufLen?queryBufLen-1:queryBufLen] = '\0'; + } + + OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^The final parsed uri is %s", uriBuf); + OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^The final parsed query is %s", queryBuf); + return OC_STACK_OK; +} + +// Retrieve the token from the PDU +void RetrieveOCCoAPToken(const coap_pdu_t * pdu, OCCoAPToken * rcvdToken) +{ + if (pdu && rcvdToken) + { + rcvdToken->tokenLength = pdu->hdr->token_length; + memcpy(rcvdToken->token, pdu->hdr->token, + rcvdToken->tokenLength); + } +} + +OCStackResult FormOCResponse(OCResponse * * responseLoc, ClientCB * cbNode, + uint8_t TTL, OCClientResponse * clientResponse) +{ + OCResponse * response = (OCResponse *) OCMalloc(sizeof(OCResponse)); + if (!response) + { + return OC_STACK_NO_MEMORY; + } + response->cbNode = cbNode; + response->TTL = TTL; + response->clientResponse = clientResponse; + + *responseLoc = response; + return OC_STACK_OK; +} + +OCStackResult FormOCClientResponse(OCClientResponse * clientResponse, + OCStackResult result, OCDevAddr * remote, uint32_t seqNum, + const unsigned char * resJSONPayload) +{ + clientResponse->sequenceNumber = seqNum; + clientResponse->result = result; + clientResponse->addr = remote; + clientResponse->resJSONPayload = resJSONPayload; + + return OC_STACK_OK; +} + +OCStackResult FormOptionList(coap_list_t * * optListLoc, uint8_t * addMediaType, + uint32_t * addMaxAge, uint32_t * observeOptionPtr, + uint16_t * addPortNumber, uint8_t uriLength, unsigned char * uri, + uint8_t queryLength, unsigned char * query, + OCHeaderOption * vendorSpecificHeaderOptions, + uint8_t numVendorSpecificHeaderOptions) +{ + coap_list_t * optNode = NULL; + int res; + size_t buflen; + unsigned char _buf[MAX_URI_QUERY_BUF_SIZE]; + unsigned char *buf = _buf; + + if(addMediaType) + { + optNode = CreateNewOptionNode(COAP_OPTION_CONTENT_TYPE, + sizeof(*addMediaType), addMediaType); + VERIFY_NON_NULL(optNode); + coap_insert(optListLoc, optNode, OrderOptions); + } + + if(addMaxAge) + { + optNode = CreateNewOptionNode(COAP_OPTION_MAXAGE, + sizeof(*addMaxAge), (uint8_t *)addMaxAge); + VERIFY_NON_NULL(optNode); + coap_insert(optListLoc, optNode, OrderOptions); + } + + if(observeOptionPtr) + { + optNode = CreateNewOptionNode(COAP_OPTION_OBSERVE, + sizeof(*observeOptionPtr), (uint8_t *)observeOptionPtr); + + VERIFY_NON_NULL(optNode); + coap_insert(optListLoc, optNode, OrderOptions); + } + if(addPortNumber && *addPortNumber != COAP_DEFAULT_PORT) + { + optNode = CreateNewOptionNode(COAP_OPTION_URI_PORT, + sizeof(*addPortNumber), (uint8_t *)addPortNumber); + VERIFY_NON_NULL(optNode); + coap_insert(optListLoc, optNode, OrderOptions); + } + + if(uri && uriLength) + { + buf = _buf; + buflen = MAX_URI_QUERY_BUF_SIZE; + res = coap_split_path(uri, uriLength, buf, &buflen); + while (res--) { + optNode = CreateNewOptionNode(COAP_OPTION_URI_PATH, + COAP_OPT_LENGTH(buf), COAP_OPT_VALUE(buf)); + VERIFY_NON_NULL(optNode); + coap_insert(optListLoc, optNode, OrderOptions); + buf += COAP_OPT_SIZE(buf); + } + } + + if(query && queryLength) + { + buf = _buf; + buflen = MAX_URI_QUERY_BUF_SIZE; + res = coap_split_query(query, queryLength, buf, &buflen); + while (res--) { + optNode = CreateNewOptionNode(COAP_OPTION_URI_QUERY, + COAP_OPT_LENGTH(buf), COAP_OPT_VALUE(buf)); + VERIFY_NON_NULL(optNode); + coap_insert(optListLoc, optNode, OrderOptions); + buf += COAP_OPT_SIZE(buf); + } + } + + // make sure that options are valid + if(vendorSpecificHeaderOptions && numVendorSpecificHeaderOptions) + { + uint8_t i = 0; + for( i = 0; i < numVendorSpecificHeaderOptions; i++) + { + if(vendorSpecificHeaderOptions[i].protocolID == OC_COAP_ID) + { + if(isVendorSpecific(vendorSpecificHeaderOptions[i].optionID) + == OC_STACK_OK && + vendorSpecificHeaderOptions[i].optionLength <= + MAX_HEADER_OPTION_DATA_LENGTH) + { + OC_LOG_V(INFO, TAG, " Adding option %d with", + vendorSpecificHeaderOptions[i].optionID); + OC_LOG_BUFFER(INFO, TAG, vendorSpecificHeaderOptions[i].optionData, + vendorSpecificHeaderOptions[i].optionLength); + optNode = CreateNewOptionNode(vendorSpecificHeaderOptions[i].optionID, + vendorSpecificHeaderOptions[i].optionLength, + vendorSpecificHeaderOptions[i].optionData); + VERIFY_NON_NULL(optNode); + coap_insert(optListLoc, optNode, OrderOptions); + } + else + { + coap_delete_list(*optListLoc); + return OC_STACK_INVALID_OPTION; + } + } + } + } + + return OC_STACK_OK; + exit: + coap_delete_list(*optListLoc); + return OC_STACK_NO_MEMORY; +} + +//Send a coap pdu +OCStackResult +SendCoAPPdu(coap_context_t * gCoAPCtx, coap_address_t* dst, coap_pdu_t * pdu, + coap_send_flags_t flag) +{ + coap_tid_t tid = COAP_INVALID_TID; + OCStackResult res = OC_STACK_COMM_ERROR; + uint8_t cache = 0; + + if (!(flag & SEND_DELAYED)) + { + flag = (coap_send_flags_t)( flag | + ((pdu->hdr->type == COAP_MESSAGE_CON) ? SEND_NOW_CON : SEND_NOW)); + } + + tid = coap_send(gCoAPCtx, dst, pdu, flag, &cache); + OC_LOG_V(INFO, TAG, "TID %d", tid); + if(tid != COAP_INVALID_TID) + { + OC_LOG(INFO, TAG, PCF("Sending a pdu with Token:")); + OC_LOG_BUFFER(INFO,TAG, pdu->hdr->token, pdu->hdr->token_length); + res = OC_STACK_OK; + } + + if (( (pdu->hdr->type != COAP_MESSAGE_CON) && (!(flag & SEND_DELAYED)) && (!cache)) + || (tid == COAP_INVALID_TID)) + { + OC_LOG(INFO, TAG, PCF("Deleting PDU")); + coap_delete_pdu(pdu); + } + else + { + OC_LOG(INFO, TAG, PCF("Keeping PDU, we will handle the retry/delay of this pdu")); + } + + return res; +} + +//generate a coap message +coap_pdu_t * +GenerateCoAPPdu(uint8_t msgType, uint8_t code, unsigned short id, + OCCoAPToken * token, unsigned char * payloadJSON, + coap_list_t *options) +{ + coap_pdu_t *pdu; + coap_list_t *opt; + + if(token) + { + pdu = coap_pdu_init(msgType, code, id, COAP_MAX_PDU_SIZE); + VERIFY_NON_NULL(pdu); + pdu->hdr->token_length = token->tokenLength; + if (!coap_add_token(pdu, token->tokenLength, token->token)) + { + OC_LOG(FATAL, TAG, PCF("coap_add_token failed")); + } + } + else + { + pdu = coap_pdu_init(msgType, code, id, sizeof(coap_pdu_t)); + VERIFY_NON_NULL(pdu); + } + + for (opt = options; opt; opt = opt->next) + { + coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option *) opt->data), + COAP_OPTION_LENGTH(*(coap_option *) opt->data), + COAP_OPTION_DATA(*(coap_option *) opt->data)); + } + + if (payloadJSON) + { + coap_add_data(pdu, strlen((const char *) payloadJSON) + 1, + (unsigned char*) payloadJSON); + } + + // display the pdu for debugging purposes + coap_show_pdu(pdu); + + // clean up + coap_delete_list(options); + return pdu; + + exit: + coap_delete_list(options); + return NULL; +} + +//a function to help in ordering coap options +int OrderOptions(void *a, void *b) +{ + if (!a || !b) + { + return a < b ? -1 : 1; + } + + if (COAP_OPTION_KEY(*(coap_option *)a) + < COAP_OPTION_KEY(*(coap_option *)b) ) + { + return -1; + } + + return COAP_OPTION_KEY(*(coap_option *)a) + == COAP_OPTION_KEY(*(coap_option *)b) ; +} + +//a function to create a coap option +coap_list_t * +CreateNewOptionNode(unsigned short key, unsigned int length, unsigned char *data) +{ + coap_option *option = NULL; + coap_list_t *node; + + VERIFY_NON_NULL(data); + option = (coap_option *)coap_malloc(sizeof(coap_option) + length); + VERIFY_NON_NULL(option); + + COAP_OPTION_KEY(*option) = key; + COAP_OPTION_LENGTH(*option) = length; + memcpy(COAP_OPTION_DATA(*option), data, length); + + /* we can pass NULL here as delete function since option is released automatically */ + node = coap_new_listnode(option, NULL); + + if (node) + { + return node; + } + +exit: + OC_LOG(ERROR,TAG, PCF("new_option_node: malloc: was not created")); + coap_free(option); + return NULL; +} + +OCStackResult ReTXCoAPQueue(coap_context_t * ctx, coap_queue_t * queue) +{ + coap_tid_t tid = COAP_INVALID_TID; + OCStackResult result = OC_STACK_ERROR; + tid = coap_retransmit( ctx, queue); + if(tid == COAP_INVALID_TID) + { + OC_LOG_V(DEBUG, TAG, "Retransmission Failed TID %d", + queue->id); + result = OC_STACK_COMM_ERROR; + } + else + { + OC_LOG_V(DEBUG, TAG, "Retransmission TID %d, this is attempt %d", + queue->id, queue->retransmit_cnt); + result = OC_STACK_OK; + } + return result; +} + +OCStackResult HandleFailedCommunication(coap_context_t * ctx, coap_queue_t * queue) +{ + //TODO: this function should change to only use OCStackFeedBack + OCResponse * response = NULL; + ClientCB * cbNode = NULL; + OCClientResponse clientResponse; + OCCoAPToken token; + OCStackResult result = OC_STACK_OK; + + RetrieveOCCoAPToken(queue->pdu, &token); + + cbNode = GetClientCB(&token, NULL, NULL); + if(!cbNode) + { + goto observation; + } + result = FormOCClientResponse(&clientResponse, OC_STACK_COMM_ERROR, + (OCDevAddr *) &(queue->remote), 0, NULL); + if(result != OC_STACK_OK) + { + goto observation; + } + result = FormOCResponse(&response, cbNode, 0, &clientResponse); + if(result != OC_STACK_OK) + { + goto observation; + } + HandleStackResponses(response); + +observation: + result = OCStackFeedBack(&token, OC_OBSERVER_FAILED_COMM); + if(result == OC_STACK_OK) + { + coap_cancel_all_messages(ctx, &queue->remote, token.token, token.tokenLength); + } + OCFree(response); + return result; +} + +// a function to handle the send queue in the passed context +void HandleSendQueue(coap_context_t * ctx) +{ + coap_tick_t now; + coap_queue_t *nextQueue = NULL; + + coap_ticks(&now); + nextQueue = coap_peek_next( ctx ); + while (nextQueue && nextQueue->t <= now - ctx->sendqueue_basetime) + { + nextQueue = coap_pop_next( ctx ); + if((uint8_t)nextQueue->delayedResNeeded) + { + OC_LOG_V(DEBUG, TAG, "Sending Delayed response TID %d", + nextQueue->id); + if(SendCoAPPdu(ctx, &nextQueue->remote, nextQueue->pdu, + (coap_send_flags_t)(nextQueue->secure ? SEND_SECURE_PORT : 0)) + == OC_STACK_COMM_ERROR) + { + OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu")); + HandleFailedCommunication(ctx, nextQueue); + } + nextQueue->pdu = NULL; + coap_delete_node(nextQueue); + } + else + { + OC_LOG_V(DEBUG, TAG, "Retrying a CON pdu TID %d",nextQueue->id); + if(ReTXCoAPQueue(ctx, nextQueue) == OC_STACK_COMM_ERROR) + { + OC_LOG(DEBUG, TAG, PCF("A problem occurred in retransmitting a pdu")); + HandleFailedCommunication(ctx, nextQueue); + coap_delete_node(nextQueue); + } + } + nextQueue = coap_peek_next( ctx ); + } +} diff --git a/resource/csdk/occoap/test/occoaptests.cpp b/resource/csdk/occoap/test/occoaptests.cpp new file mode 100644 index 000000000..5a319e2e3 --- /dev/null +++ b/resource/csdk/occoap/test/occoaptests.cpp @@ -0,0 +1,61 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +//============================================================================= +// Includes +//============================================================================= +/*extern "C" { + #include "occoap.h" + #include "logger.h" +}*/ + +#include "gtest/gtest.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +using namespace std; + +//============================================================================= +// Private Variables +//============================================================================= +static const char TAG[] = "TestHarness"; + +//============================================================================= +// Callback function +//============================================================================= +/*void discoverServicesAsync(const char *Url) { + OC_LOG_V(INFO, TAG, "Entering discoverServicesAsync. URL = %s", Url); +}*/ + +//============================================================================= +// Tests +//============================================================================= +TEST(OCCoapTest, General) { + EXPECT_EQ(0, 0); +} diff --git a/resource/csdk/ocmalloc/include/ocmalloc.h b/resource/csdk/ocmalloc/include/ocmalloc.h new file mode 100644 index 000000000..7019982fd --- /dev/null +++ b/resource/csdk/ocmalloc/include/ocmalloc.h @@ -0,0 +1,94 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OCMALLOC_H_ +#define OCMALLOC_H_ + +// The purpose of this module is to allow custom dynamic memory allocation +// code to easily be added to the TB Stack by redefining the OCMalloc and +// OCFree functions. Examples of when this might be needed are on TB +// platforms that do not support dynamic allocation or if a memory pool +// needs to be added. +// +// Note that these functions are intended to be used ONLY within the TB +// stack and NOT by the application code. The application should be +// responsible for its own dynamic allocation. + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +//----------------------------------------------------------------------------- +// Defines +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// Typedefs +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// Function prototypes +//----------------------------------------------------------------------------- + +/** + * Allocates a block of size bytes, returning a pointer to the beginning of + * the allocated block. + * + * @param size - Size of the memory block in bytes, where size > 0 + * + * @return + * on success, a pointer to the allocated memory block + * on failure, a null pointer is returned + */ +void *OCMalloc(size_t size); + +/** + * Allocates a block of memory for an array of num elements, each of them + * size bytes long and initializes all its bits to zero. + * + * @param num - The number of elements + * @param size - Size of the element type in bytes, where size > 0 + * + * @return + * on success, a pointer to the allocated memory block + * on failure, a null pointer is returned + */ +void *OCCalloc(size_t num, size_t size); + +/** + * Deallocate a block of memory previously allocated by a call to OCMalloc + * + * @param ptr - Pointer to block of memory previously allocated by OCMalloc. + * If ptr is a null pointer, the function does nothing. + */ +void OCFree(void *ptr); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* OCMALLOC_H_ */ diff --git a/resource/csdk/ocmalloc/src/ocmalloc.c b/resource/csdk/ocmalloc/src/ocmalloc.c new file mode 100644 index 000000000..fe62c1554 --- /dev/null +++ b/resource/csdk/ocmalloc/src/ocmalloc.c @@ -0,0 +1,106 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include +#include "ocmalloc.h" + +// Enable extra debug logging for malloc. Comment out to disable +//#define ENABLE_MALLOC_DEBUG (1) + +#ifdef ENABLE_MALLOC_DEBUG + #include "logger.h" + #define TAG PCF("OCMalloc") +#endif + +//----------------------------------------------------------------------------- +// Typedefs +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Private variables +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Macros +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Internal API function +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// Private internal function prototypes +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// Public APIs +//----------------------------------------------------------------------------- + +void *OCMalloc(size_t size) +{ + if (0 == size) + { + return NULL; + } + +#ifdef ENABLE_MALLOC_DEBUG + void *ptr = 0; + + ptr = malloc(size); + OC_LOG_V(INFO, TAG, "malloc: ptr=%p, size=%u", ptr, size); + return ptr; +#else + return malloc(size); +#endif +} + +void *OCCalloc(size_t num, size_t size) +{ + if(0 == size || 0 == num) + { + return NULL; + } + +#ifdef ENABLE_MALLOC_DEBUG + void *ptr = 0; + + ptr = calloc(num, size); + OC_LOG_V(INFO, TAG, "calloc: ptr=%p, num=%u, size=%u", ptr, num, size); + return ptr; +#else + return calloc(num, size); +#endif +} + +void OCFree(void *ptr) +{ +#ifdef ENABLE_MALLOC_DEBUG + OC_LOG_V(INFO, TAG, "free: ptr=%p", ptr); +#endif + + free(ptr); +} + diff --git a/resource/csdk/ocmalloc/test/linux/README b/resource/csdk/ocmalloc/test/linux/README new file mode 100644 index 000000000..72e3c1c41 --- /dev/null +++ b/resource/csdk/ocmalloc/test/linux/README @@ -0,0 +1,35 @@ +------------------------------------------------------------------------------- + NOTICE - Transition to SCONS +------------------------------------------------------------------------------- + +The IoTivity build system is transitioning to SCONS. Although the +makefiles are still available (until v1.0) and some developers are +still using them, they are currently no longer supported. To learn more +about building using SCONS see Readme.scons.txt in the repository root +directory. The build steps used in continuous integration can be found +in auto_build.sh which is also in the the repository root directory. + +------------------------------------------------------------------------------- + +# To build the ocmalloc google unit test for Linux: + +# First +cd /csdk +make deepclean + +make BUILD=release +# or +make BUILD=debug + +# Next +cd /csdk/ocmalloc/test/linux + +make BUILD=release +# or +make BUILD=debug + +# Run the test test + +/csdk/ocmalloc/test/linux/release/unittest +# or +/csdk/ocmalloc/test/linux/debug/unittest diff --git a/resource/csdk/ocmalloc/test/linux/makefile b/resource/csdk/ocmalloc/test/linux/makefile new file mode 100644 index 000000000..31dd9a0f4 --- /dev/null +++ b/resource/csdk/ocmalloc/test/linux/makefile @@ -0,0 +1,107 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +# override with `make BUILD=debug` +# default to release build +BUILD := release +PLATFORM := linux +CC := g++ + +ifeq ($(ROOT_DIR), ) +ROOT_DIR = $(PWD)/../../.. +endif + +# You must create the file "local.properties" on your local machine which contains any local paths, etc +# local.properties should NOT be committed to repo +include $(ROOT_DIR)/local.properties +# GTEST_DIR contains the path to Google Test libs and must be defined in local.properties +# Example: +# GTEST_DIR := /home/johndoe/utils/gtest-1.7.0 + +# NOTE: to run app, make sure that LD_LIBRARY_PATH env variable +# contains $(GTEST_DIR)/lib/.libs + +OUT_DIR := $(PWD)/$(BUILD) +OBJ_DIR := $(OUT_DIR)/obj + + +OUT_DIR := $(PWD) + +OCLOGGER_DIR = $(ROOT_DIR)/logger +OCMALLOC_DIR = $(ROOT_DIR)/ocmalloc +OCRANDOM_DIR = $(ROOT_DIR)/ocrandom +OCSOCKET_DIR = $(ROOT_DIR)/ocsocket +LCOAP_DIR = $(ROOT_DIR)/libcoap-4.1.1 +OCCOAP_DIR = $(ROOT_DIR)/occoap +OCTBSTACK_DIR = $(ROOT_DIR)/stack + +OCLOGGER_INC = $(OCLOGGER_DIR)/include +OCMALLOC_INC = $(OCMALLOC_DIR)/include +OCRANDOM_INC = $(OCRANDOM_DIR)/include +OCSOCKET_INC = $(OCSOCKET_DIR)/include +LCOAP_INC = $(LCOAP_DIR) +OCCOAP_INC = $(OCCOAP_DIR)/include +OCTBSTACK_INC = $(OCTBSTACK_DIR)/include + +INC_DIRS := -I$(OCLOGGER_INC) +INC_DIRS += -I$(OCMALLOC_INC) +INC_DIRS += -I$(OCRANDOM_INC) +INC_DIRS += -I$(OCSOCKET_INC) +INC_DIRS += -I$(LCOAP_INC) +INC_DIRS += -I$(OCCOAP_INC) +INC_DIRS += -I$(OCTBSTACK_INC) +INC_DIRS += -I$(OCTBSTACK_INC)/internal +INC_DIRS += -I$(GTEST_DIR)/include + +CC_FLAGS.debug := -g -O0 -g3 -Wall -ffunction-sections -fdata-sections -fno-exceptions \ + -std=c++0x -pedantic $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD) -DTB_LOG +CC_FLAGS.release := -Os -Wall -fdata-sections -Wl,--gc-sections -Wl,-s -fno-exceptions \ + -std=c++0x $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD) + +LDLIBS += -loctbstack -lpthread +CPPFLAGS += $(CC_FLAGS.$(BUILD)) $(LDLIBS) $(GTEST_DIR)/lib/.libs/libgtest.a \ + $(GTEST_DIR)/lib/.libs/libgtest_main.a + +SOURCES := unittest.cpp + +OBJECTS:= $(patsubst %.c, $(OBJ_DIR)/%.o, $(SOURCES)) + +PROGRAMS := unittest + +all: prep_dirs $(OBJECTS) $(PROGRAMS) + +prep_dirs: + -mkdir -p $(OUT_DIR) + -mkdir -p $(OBJ_DIR) + +$(OBJ_DIR)/%.o: %.cpp + $(CC) -c $(CPPFLAGS) $< -o $@ + +unittest: $(OBJ_DIR)/unittest.o + $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@ + +.PHONY: clean + +clean: legacy_clean + -rm -rf release + -rm -rf debug + +legacy_clean: + rm -f *.o $(PROGRAMS) diff --git a/resource/csdk/ocmalloc/test/linux/unittest.cpp b/resource/csdk/ocmalloc/test/linux/unittest.cpp new file mode 100644 index 000000000..acd957342 --- /dev/null +++ b/resource/csdk/ocmalloc/test/linux/unittest.cpp @@ -0,0 +1,140 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +extern "C" { + #include "ocmalloc.h" +} + +#include "gtest/gtest.h" +#include +#include +#include +#include +#include +#include +#include + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include +#include + +#include +#include +using namespace std; + +//----------------------------------------------------------------------------- +// Private variables +//----------------------------------------------------------------------------- +static uint8_t *pBuffer; + +//----------------------------------------------------------------------------- +// Tests +//----------------------------------------------------------------------------- + +TEST(OCMalloc, MallocPass1) +{ + // Try to allocate a small buffer + pBuffer = (uint8_t *)OCMalloc(1); + EXPECT_TRUE(pBuffer); + OCFree(pBuffer); +} + +TEST(OCMalloc, MallocPass2) +{ + // Try to allocate a small buffer + pBuffer = (uint8_t *)OCMalloc(128); + EXPECT_TRUE(pBuffer); + OCFree(pBuffer); +} + +TEST(OCMalloc, MallocFail1) +{ + // Try to allocate a buffer of size 0 + pBuffer = (uint8_t *)OCMalloc(0); + EXPECT_TRUE(NULL == pBuffer); + OCFree(pBuffer); +} + +TEST(OCMalloc, MallocFail2) +{ + // Try to allocate a ridiculous amount of RAM + pBuffer = (uint8_t *)OCMalloc((size_t)0x7FFFFFFFFFFFFFFF); + EXPECT_TRUE(NULL == pBuffer); + OCFree(pBuffer); +} + +TEST(OCCalloc, CallocPass1) +{ + // Try to allocate a small buffer + pBuffer = (uint8_t *)OCCalloc(1, 1); + EXPECT_TRUE(pBuffer); + OCFree(pBuffer); +} + +TEST(OCCalloc, CallocPass2) +{ + // Try to allocate a small buffer + pBuffer = (uint8_t *)OCCalloc(1, 128); + EXPECT_TRUE(pBuffer); + OCFree(pBuffer); +} + +TEST(OCCalloc, CallocPass3) +{ + // Try to allocate a buffer for an array + pBuffer = (uint8_t *)OCCalloc(5, 128); + EXPECT_TRUE(pBuffer); + OCFree(pBuffer); +} + +TEST(OCCalloc, CallocFail1) +{ + // Try to allocate a buffer of size 0 + pBuffer = (uint8_t *)OCCalloc(1, 0); + EXPECT_TRUE(NULL == pBuffer); + OCFree(pBuffer); +} + +TEST(OCCalloc, CallocFail2) +{ + // Try to allocate a buffer with num of 0 + pBuffer = (uint8_t *)OCCalloc(0, 5); + EXPECT_TRUE(NULL == pBuffer); + OCFree(pBuffer); +} + +TEST(OCCalloc, CallocFail3) +{ + // Try to allocate a buffer with size and num 0 + pBuffer = (uint8_t *)OCCalloc(0, 0); + EXPECT_TRUE(NULL == pBuffer); + OCFree(pBuffer); +} + +TEST(OCCalloc, CallocFail4) +{ + // Try to allocate a ridiculous amount of RAM + pBuffer = (uint8_t *)OCCalloc(1, (size_t)0x7FFFFFFFFFFFFFFF); + EXPECT_TRUE(NULL == pBuffer); + OCFree(pBuffer); +} diff --git a/resource/csdk/ocrandom/include/ocrandom.h b/resource/csdk/ocrandom/include/ocrandom.h new file mode 100644 index 000000000..d516520b4 --- /dev/null +++ b/resource/csdk/ocrandom/include/ocrandom.h @@ -0,0 +1,80 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +#ifndef _RANDOM_H +#define _RANDOM_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__ANDROID__) || defined(__linux__) +#include +#elif defined ARDUINO +// MEGA has 16 input pins whereas Due has only 12 input pins +#define ANALOG_IN (10) +#endif + +/** + * Seed the random number generator. Seeding depends on platform. + * Android and Linux uses current time. Arduino uses Analog reading on pin ANALOG_IN + * @retval 0 for Success, otherwise some error value + */ +int8_t OCSeedRandom(); + +/** + * Generate a uniformly [0,2^32] distributed random number + * @retval On Success, it returns the random value. + */ +uint32_t OCGetRandom(); + +/** + * Generate a uniformly [0,2^8] distributed random number + * @retval On Success, it returns the random value, otherwise -1 for error. + */ +uint8_t OCGetRandomByte(void); + +/** + * Generate a uniformly distributed 8-bit (byte) array random numbers + * @param[out] location + * memory location to start filling with random bytes + * @param[in] len + * length of array to be filled with random bytes + */ +void OCFillRandomMem(uint8_t * location, uint16_t len); + +/* + * Generate a uniformly distributed number on the defined bounded range + * @param[in] firstBound + * the first bound of the range + * @param[in] secondBound + * the second bound of the range + */ +uint32_t OCGetRandomRange(uint32_t firstBound, uint32_t secondBound); + +#ifdef __cplusplus +} +#endif + +#endif //_RANDOM_H diff --git a/resource/csdk/ocrandom/src/ocrandom.c b/resource/csdk/ocrandom/src/ocrandom.c new file mode 100644 index 000000000..8c2d0a4b9 --- /dev/null +++ b/resource/csdk/ocrandom/src/ocrandom.c @@ -0,0 +1,134 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +#if defined(__ANDROID__) || defined(__linux__) +#include "fcntl.h" +#include "unistd.h" +#endif +#include "ocrandom.h" + +#ifdef ARDUINO +#include "Arduino.h" + +uint8_t GetRandomBitRaw() { + return analogRead((uint8_t)ANALOG_IN) & 0x1; +} + +uint8_t GetRandomBitRaw2() { + int a = 0; + for(;;) { + a = GetRandomBitRaw() | (GetRandomBitRaw()<<1); + if (a==1){ + return 0; // 1 to 0 transition: log a zero bit + } + if (a==2){ + return 1;// 0 to 1 transition: log a one bit + } + // For other cases, try again. + } +} + +uint8_t GetRandomBit() { + int a = 0; + for(;;) { + a = GetRandomBitRaw2() | (GetRandomBitRaw2()<<1); + if (a==1){ + return 0; // 1 to 0 transition: log a zero bit + } + if (a==2){ + return 1;// 0 to 1 transition: log a one bit + } + // For other cases, try again. + } +} +#endif + +int8_t OCSeedRandom() { +#if defined(__ANDROID__) || defined(__linux__) + int32_t fd = open("/dev/urandom", O_RDONLY); + if (fd > 0) { + uint32_t randomSeed; + uint32_t totalRead = 0; //how many integers were read + int32_t currentRead = 0; + while (totalRead < sizeof(randomSeed)) { + currentRead = read(fd, (uint8_t*) &randomSeed + totalRead, + sizeof(randomSeed) - totalRead); + if(currentRead > 0){ + totalRead += currentRead; + } + } + close(fd); + srand(randomSeed); + return 0; + } + close(fd); + return -1; +#elif defined ARDUINO + uint32_t result =0; + uint8_t i; + for (i=32; i--;){ + result += result + GetRandomBit(); + } + randomSeed(result); + return 0; +#endif + +} + +void OCFillRandomMem(uint8_t * location, uint16_t len) { + if(!location){ + return; + } + for (; len--;){ + *location++ = OCGetRandomByte(); + } +} + +uint32_t OCGetRandom() { + uint32_t result = 0; + OCFillRandomMem((uint8_t*) &result, 4); + return result; +} + +uint8_t OCGetRandomByte(void) { +#if defined(__ANDROID__) || defined(__linux__) + return rand() & 0x00FF; +#elif defined ARDUINO + return random(256) & 0x00FF; +#endif +} + +uint32_t OCGetRandomRange(uint32_t firstBound, uint32_t secondBound){ + uint32_t base; + uint32_t diff; + uint32_t result; + if(firstBound > secondBound){ + base = secondBound; + diff = firstBound - secondBound; + }else if(firstBound < secondBound){ + base = firstBound; + diff = secondBound - firstBound; + }else{ + return secondBound; + } + result = ((float)OCGetRandom()/((float)(0xFFFFFFFF))*(float)diff) + (float) base; + return result; +} diff --git a/resource/csdk/ocrandom/test/android/makefile b/resource/csdk/ocrandom/test/android/makefile new file mode 100644 index 000000000..6f3f56439 --- /dev/null +++ b/resource/csdk/ocrandom/test/android/makefile @@ -0,0 +1,130 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +# override with `make BUILD=release` +# default to debug build +BUILD := debug + +# You must create the file "local.propertiessudo" on your local machine which contains any local paths, etc +# local_settings.mk should NOT be committed to repo +include ../../local.properties +# GTEST_DIR contains the path to Google Test libs and must be defined in local.properties +# Example: +# GTEST_DIR := /home/johndoe/utils/gtest-1.7.0 + +GTEST_DIR := $(GTEST_DIR_ANDROID) + +# NOTE: to run app, make sure that LD_LIBRARY_PATH env variable +# contains $(GTEST_DIR)/lib/.libs + +CC := $(ANDROID_NDK)/arm-linux-androideabi-gcc +CXX := $(ANDROID_NDK)/arm-linux-androideabi-g++ + +PROG := randomtest + +SRC_DIR := ../../src +TEST_DIR:= ../../test/android +INC_DIR := ../../include + +#CC_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c99 -fpic -D TB_LOG +CC_FLAGS.debug := -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions -D TB_LOG +#CC_FLAGS.release := -O0 -g3 -Wall -c -fmessage-length=0 -std=c99 -fpic +CC_FLAGS := $(CC_FLAGS.$(BUILD)) + +#CXX_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c++0x -fpic -D TB_LOG +CXX_FLAGS.debug := -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions -D TB_LOG +#CXX_FLAGS.release := -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -fpic +CXX_FLAGS := $(CXX_FLAGS.$(BUILD)) + +CFLAGS_ANDROID := -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -DGTEST_HAS_PTHREAD=0 + +INC := -I$(SRC_DIR) +INC += -I$(TEST_DIR) +INC += -I$(INC_DIR) +INC += -I$(GTEST_DIR)/include + + +# using make's computed variables to select object and bin folders +# depending on the build type +OBJ_DIR.debug := ./obj/debug +OBJ_DIR.release := ./obj/release +OBJ_DIR := $(OBJ_DIR.$(BUILD)) + +BIN_DIR.debug := ./bin/debug +BIN_DIR.release := ./bin/release +BIN_DIR := $(BIN_DIR.$(BUILD)) + +C_FILES := $(wildcard $(SRC_DIR)/*.c) +#CPP_FILES := $(wildcard $(SRC_DIR)/*.cpp) +CPP_FILES := $(wildcard $(TEST_DIR)/*.cpp) +OBJ_FILES := $(addprefix $(OBJ_DIR)/,$(notdir $(CPP_FILES:.cpp=.o) $(C_FILES:.c=.o))) +H_FILES := $(wildcard $(TEST_DIR)/*.h) +H_FILES += $(wildcard $(INC_DIR)/*.h) +LD_FLAGS := -L/usr/lib +LD_FLAGS += -L$(GTEST_DIR)/lib/.libs +LDFLAGS_ANDROID := -march=armv7-a -Wl,--fix-cortex-a8 + +#LIBS := -lpthread +#LIBS := -lgtest +#LIBS += -lgtest_main + +LIBS = $(GTEST_DIR)/lib/.libs/libgtest.a $(GTEST_DIR)/lib/.libs/libgtest_main.a +#LIBS = libgtest.a libgtest_main.a + +all: $(PROG) + +$(PROG): $(OBJ_FILES) + mkdir -p $(BIN_DIR) + $(CXX) -o $@ $^ $(LD_FLAGS) $(LDFLAGS_ANDROID) $(LIBS) + mv ./$(PROG) ./$(BIN_DIR) + +$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(INC_DIR)/%.h $(H_FILES) + mkdir -p $(OBJ_DIR) + $(CC) $(CC_FLAGS) $(CFLAGS_ANDROID) $(INC) -c -o $@ $< + +$(OBJ_DIR)/%.o: $(TEST_DIR)/%.cpp $(H_FILES) + mkdir -p $(OBJ_DIR) + $(CXX) $(CXX_FLAGS) $(CFLAGS_ANDROID) $(INC) -c -o $@ $< + +install: all +# adb remount + adb push $(BIN_DIR)/$(PROG) /data/local/tmp + +.PHONY: clean +clean : + rm -rf ./obj/debug/* + rm -rf ./obj/release/* + rm -rf ./lib/debug/* + rm -rf ./lib/release/* + rm -rf ./bin/debug/* + rm -rf ./bin/release/* + rm -rf ./test/tst_*.txt + + +.PHONY: print_vars + +print_vars: + @echo "" + @echo 'BUILD = '$(value BUILD) + @echo 'INC = '$(value INC) + @echo 'CPP_FILES = '$(value CPP_FILES) + @echo 'LIBS = '$(value LIBS) + + diff --git a/resource/csdk/ocrandom/test/android/randomtest.cpp b/resource/csdk/ocrandom/test/android/randomtest.cpp new file mode 100644 index 000000000..6dd8e7f02 --- /dev/null +++ b/resource/csdk/ocrandom/test/android/randomtest.cpp @@ -0,0 +1,65 @@ + +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +extern "C" { + #include "ocrandom.h" +} + +#include "gtest/gtest.h" +#include "math.h" + + +int main(int argc, char* argv[]) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + +TEST(RandomGeneration,OCSeedRandom) { + EXPECT_EQ((uint32_t )0, OCSeedRandom()); +} + +TEST(RandomGeneration,OCGetRandomByte) { + uint8_t value = OCGetRandomByte(); + EXPECT_LE((uint8_t )0, value); + EXPECT_GT(pow(2, 8), value); +} + +TEST(RandomGeneration,OCGetRandom) { + uint32_t value = OCGetRandom(); + EXPECT_LE((uint8_t )0, value); + EXPECT_GT(pow(2, 32), value); +} + +TEST(RandomGeneration,OCFillRandomMem) { + uint16_t ARR_SIZE = 20; + uint8_t array[ARR_SIZE]; + memset(array, 0, ARR_SIZE); + OCFillRandomMem(array + 1, ARR_SIZE - 2); + + for (int i = 1; i < ARR_SIZE - 2; i++) { + uint8_t value = array[i]; + EXPECT_LE((uint8_t )0, value); + EXPECT_GT(pow(2, 8), value); + } + EXPECT_EQ((uint8_t )0, array[0]); + EXPECT_EQ((uint8_t )0, array[ARR_SIZE - 1]); +} + diff --git a/resource/csdk/ocrandom/test/arduino/makefile b/resource/csdk/ocrandom/test/arduino/makefile new file mode 100644 index 000000000..c0713e0ab --- /dev/null +++ b/resource/csdk/ocrandom/test/arduino/makefile @@ -0,0 +1,161 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +# Override with `make BUILD=release` +# default to debug build +BUILD := debug +PLATFORM := arduinomega + +# You must create the file "local.propertiessudo" on your local machine which contains any local paths, etc +# local_settings.mk should NOT be committed to repo +ROOT_DIR = ../../.. +include $(ROOT_DIR)/local.properties + +# Compilers +CC := avr-gcc +CXX := avr-g++ +AR := avr-ar +OBJCopy := avr-objcopy + +# Name of testing application +PROG := randomtest +C_COMPONENTS_DIR := ocrandom + +# Folders that contain C source code +C_SRC_DIR := $(foreach d, $(C_COMPONENTS_DIR),../../../$d/src) + +#Folders that contain C source code related to arduino +C_SRC_DIR_ARDUINO := $(ARDUINO_DIR)/hardware/arduino/cores/arduino + +#Folders that contain CPP source code +CPP_SRC_DIR := ../../test/arduino + +#Folders that contain CPP source code related to arduino +CPP_SRC_DIR_ARDUINO := $(ARDUINO_DIR)/hardware/arduino/cores/arduino + +# Folders that contain Headers +TEMP_INC_DIR := $(foreach d, $(C_COMPONENTS_DIR),../../../$d/include) +TEMP_INC_DIR2 := $(foreach d, $(CXX_COMPONENTS_DIR),../../../$d/include) +INC_DIR := $(TEMP_INC_DIR) $(TEMP_INC_DIR2) +INC_DIR += $(ARDUINO_DIR)/hardware/arduino/cores/arduino +INC_DIR += $(ARDUINO_DIR)/hardware/arduino/variants/mega +INC_CMD = $(foreach d, $(INC_DIR), -I$d) + +# Compiler flags specific to arduino +ARDUINO_FLAGS = -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=156 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR -MMD + +# Compiler flags +CC_FLAGS.debug := -c -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions -std=c99 -DATMEGA2560 -DTB_LOG +CC_FLAGS.release := -c -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions -std=c99 -DATMEGA2560 +CC_FLAGS := $(CC_FLAGS.$(BUILD)) + +CXX_FLAGS.debug := -c -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions -felide-constructors -std=c++0x -DATMEGA2560 -DTB_LOG +CXX_FLAGS.release := -c -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions -felide-constructors -std=c++0x -DATMEGA2560 +CXX_FLAGS := $(CXX_FLAGS.$(BUILD)) + +# using make's computed variables to select object and bin folders +# depending on the build type +OBJ_DIR.debug := ./obj/debug +OBJ_DIR.release := ./obj/release +OBJ_DIR := $(OBJ_DIR.$(BUILD)) + +BIN_DIR.debug := ./bin/debug +BIN_DIR.release := ./bin/release +BIN_DIR := $(BIN_DIR.$(BUILD)) + +C_FILES := $(shell find $(C_SRC_DIR) -maxdepth 1 -name '*.c') +CPP_FILES := $(shell find $(CPP_SRC_DIR) -maxdepth 1 -name '*.cpp') +OBJ_FILES := $(addprefix $(OBJ_DIR)/,$(notdir $(CPP_FILES:.cpp=.o) $(C_FILES:.c=.o))) + +C_FILES_ARDUINO := $(shell find $(C_SRC_DIR_ARDUINO) -maxdepth 1 -name '*.c') +CPP_FILES_ARDUINO := $(shell find $(CPP_SRC_DIR_ARDUINO) -maxdepth 1 -name '*.cpp') +OBJ_FILES_ARDUINO := $(addprefix $(OBJ_DIR)/,$(notdir $(CPP_FILES_ARDUINO:.cpp=.o) $(C_FILES_ARDUINO:.c=.o))) + +all: $(BIN_DIR)/$(PROG).hex + +$(BIN_DIR)/core.a: $(OBJ_FILES_ARDUINO) + mkdir -p $(BIN_DIR) + $(AR) rcs $@ $^ + #mv ./core.a ./$(BIN_DIR) + @echo "" + @echo 'done making core.a' + +$(OBJ_DIR)/%.o: $(CPP_SRC_DIR_ARDUINO)/%.cpp + mkdir -p $(OBJ_DIR) + $(CXX) $(CXX_FLAGS) $(ARDUINO_FLAGS) $(INC_CMD) $< -o $@ + +$(OBJ_DIR)/%.o: $(CPP_SRC_DIR)/%.cpp + mkdir -p $(OBJ_DIR) + $(CXX) $(CXX_FLAGS) $(ARDUINO_FLAGS) $(INC_CMD) $< -o $@ + +$(OBJ_DIR)/%.o: $(C_SRC_DIR_ARDUINO)/%.c + mkdir -p $(OBJ_DIR) + $(CC) $(CC_FLAGS) $(ARDUINO_FLAGS) $(INC_CMD) $< -o $@ + +$(OBJ_DIR)/%.o: $(C_SRC_DIR)/%.c + mkdir -p $(OBJ_DIR) + $(CXX) $(CXX_FLAGS) $(ARDUINO_FLAGS) $(INC_CMD) $< -o $@ + +$(BIN_DIR)/$(PROG).elf: $(OBJ_FILES) $(BIN_DIR)/core.a + #$(CC) -Os -Wl,--gc-sections,--relax $(ARDUINO_FLAGS) $< $(BIN_DIR)/core.a -lm -o $@ + #$(CC) -Os -Wl,--gc-sections,--relax $(ARDUINO_FLAGS) $(OBJ_FILES) $(OBJ_FILES_ARDUINO) -lm -o $@ + $(CC) -Os -Wl,--gc-sections,--relax $(ARDUINO_FLAGS) $(OBJ_FILES) $(BIN_DIR)/core.a -lm -o $@ + @echo "" + @echo 'done making elf' + +$(BIN_DIR)/$(PROG).hex: $(BIN_DIR)/$(PROG).elf + $(OBJCopy) -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 $< $(BIN_DIR)/$(PROG).eep + $(OBJCopy) -O ihex -R .eeprom $< $@ + @echo "" + @echo 'done making hex' + +install: all + #$(ARDUINO_DIR)/hardware/tools/avrdude -C$(ARDUINO_DIR)/hardware/tools/avrdude.conf -v -v -v -v -patmega2560 -cstk500v2 -P/dev/ttyACM0 -b115200 -D -Uflash:w:$(BIN_DIR)/$(PROG).hex:i + avrdude -C$(ARDUINO_DIR)/hardware/tools/avrdude.conf -v -v -v -v -patmega2560 -cstk500v2 -P/dev/ttyACM0 -b115200 -D -Uflash:w:$(BIN_DIR)/$(PROG).hex:i + +.PHONY: clean +clean : + rm -rf ./obj/debug/* + rm -rf ./obj/release/* + rm -rf ./lib/debug/* + rm -rf ./lib/release/* + rm -rf ./bin/debug/* + rm -rf ./bin/release/* + rm -rf ./test/tst_*.txt + rm -fr $(BIN_DIR) + rm -fr $(OBJ_DIR) + + +.PHONY: print_vars +print_vars: + @echo "" + @echo 'BUILD = '$(value BUILD) + @echo 'C_SRC_DIR = '$(value C_SRC_DIR) + @echo 'C_SRC_DIR_ARDUINO = '$(value C_SRC_DIR_ARDUINO) + @echo 'CPP_SRC_DIR = '$(CPP_SRC_DIR) + @echo 'CPP_SRC_DIR_ARDUINO = '$(value CPP_SRC_DIR_ARDUINO) + @echo 'INC_DIR = '$(INC_DIR) + @echo 'H_FILES = '$(H_FILES) + @echo 'C_FILES = '$(C_FILES) + @echo 'CPP_FILES = '$(CPP_FILES) + @echo 'C_FILES_ARDUINO = '$(C_FILES_ARDUINO) + @echo 'CPP_FILES_ARDUINO = '$(CPP_FILES_ARDUINO) + @echo 'OBJ_FILES = '$(OBJ_FILES) + @echo 'OBJ_FILES_ARDUINO = '$(OBJ_FILES_ARDUINO) diff --git a/resource/csdk/ocrandom/test/arduino/randomtest.cpp b/resource/csdk/ocrandom/test/arduino/randomtest.cpp new file mode 100644 index 000000000..904b73cb7 --- /dev/null +++ b/resource/csdk/ocrandom/test/arduino/randomtest.cpp @@ -0,0 +1,81 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "ocrandom.h" +#include "math.h" +#include + +#define ARR_SIZE (20) + +void setup() { + Serial.begin(115200); + Serial.println("Testing Random Number generator for Arduino"); + + Serial.print("Testing OCSeedRandom ... "); + if (OCSeedRandom() == 0) { + Serial.println("[Success]"); + } else { + Serial.println("[Fail]"); + } + + Serial.print("Testing OCGetRandomByte ... "); + uint8_t value8 = OCGetRandomByte(); + if (value8 >= 0 && value8 < pow(2, 8)) { + Serial.println("[Success]"); + } else { + Serial.println("[Fail]"); + } + + Serial.print("Testing OCGetRandom ... "); + uint32_t value32 = OCGetRandom(); + if (value32 >= 0 && value32 < pow(2, 32)) { + Serial.println("[Success]"); + } else { + Serial.println("[Fail]"); + } + + Serial.print("Testing OCFillRandomMem ... "); + uint8_t array[ARR_SIZE]; + memset(array, 0, ARR_SIZE); + OCFillRandomMem(array + 1, ARR_SIZE - 2); + uint8_t overall = 0; + uint8_t value82 = 0; + for (int i = 1; i <= ARR_SIZE - 2; i++) { + value82 = array[i]; + if (value82 >= 0 && value82 < pow(2, 8)) { + overall++; + } + } + if (overall == ARR_SIZE - 2 && array[0] == 0 && array[ARR_SIZE - 1] == 0) { + Serial.println("[Success]"); + } else { + Serial.println("[Fail]"); + Serial.print("overall:");Serial.println(overall); + Serial.print("array[0]:");Serial.println(array[0]); + Serial.print("array[ARR_SIZE - 1]:");Serial.println(array[ARR_SIZE - 1]); + } + Serial.println("========DONE TESTING========="); + +} + +void loop() { + +} + diff --git a/resource/csdk/ocrandom/test/linux/makefile b/resource/csdk/ocrandom/test/linux/makefile new file mode 100644 index 000000000..d5a92ff90 --- /dev/null +++ b/resource/csdk/ocrandom/test/linux/makefile @@ -0,0 +1,125 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +# override with `make BUILD=release` +# default to debug build +BUILD := debug +PLATFORM := linux + +# You must create the file "local.propertiessudo" on your local machine which contains any local paths, etc +# local_settings.mk should NOT be committed to repo +ROOT_DIR = ../../.. +include $(ROOT_DIR)/local.properties +# GTEST_DIR contains the path to Google Test libs and must be defined in local.properties +# Example: +# GTEST_DIR := /home/johndoe/utils/gtest-1.7.0 + +# NOTE: to run app, make sure that LD_LIBRARY_PATH env variable +# contains $(GTEST_DIR)/lib/.libs + +CC := gcc +CXX := g++ + +PROG := randomtest + +SRC_DIR := ../../src +TEST_DIR:= ../../test/linux +INC_DIR := ../../include + +CC_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c99 -fpic -D TB_LOG +CC_FLAGS.release := -O0 -g3 -Wall -c -fmessage-length=0 -std=c99 -fpic +CC_FLAGS := $(CC_FLAGS.$(BUILD)) + +CXX_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c++0x -fpic -D TB_LOG +CXX_FLAGS.release := -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -fpic +CXX_FLAGS := $(CXX_FLAGS.$(BUILD)) + +INC := -I$(SRC_DIR) +INC += -I$(TEST_DIR) +INC += -I$(INC_DIR) +INC += -I$(GTEST_DIR)/include + + +# using make's computed variables to select object and bin folders +# depending on the build type +OBJ_DIR.debug := ./obj/debug +OBJ_DIR.release := ./obj/release +OBJ_DIR := $(OBJ_DIR.$(BUILD)) + +BIN_DIR.debug := ./bin/debug +BIN_DIR.release := ./bin/release +BIN_DIR := $(BIN_DIR.$(BUILD)) + +C_FILES := $(wildcard $(SRC_DIR)/*.c) +#CPP_FILES := $(wildcard $(SRC_DIR)/*.cpp) +CPP_FILES := $(wildcard $(TEST_DIR)/*.cpp) +OBJ_FILES := $(addprefix $(OBJ_DIR)/,$(notdir $(CPP_FILES:.cpp=.o) $(C_FILES:.c=.o))) +H_FILES := $(wildcard $(TEST_DIR)/*.h) +H_FILES += $(wildcard $(INC_DIR)/*.h) +LD_FLAGS := -L/usr/lib +LD_FLAGS += -L$(GTEST_DIR)/lib/.libs + + +LIBS := -lpthread +LIBS += -lgtest +LIBS += -lgtest_main + + +all: $(PROG) + +$(PROG): $(OBJ_FILES) + mkdir -p $(BIN_DIR) + $(CXX) -o $@ $^ $(LD_FLAGS) $(LIBS) +# $(CXX) -o $@ $^ $(GTEST_DIR)/make/gtest_main.a -lpthread + mv ./$(PROG) ./$(BIN_DIR) + +#$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(SRC_DIR)/%.h $(H_FILES) +# $(CC) $(CC_FLAGS) $(INC) -c -o $@ $< + +$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(INC_DIR)/%.h $(H_FILES) + mkdir -p $(OBJ_DIR) + $(CC) $(CC_FLAGS) $(INC) -c -o $@ $< + +$(OBJ_DIR)/%.o: $(TEST_DIR)/%.cpp $(H_FILES) + mkdir -p $(OBJ_DIR) + $(CXX) $(CXX_FLAGS) $(INC) -c -o $@ $< + + +.PHONY: clean +clean : + rm -rf ./obj/debug/* + rm -rf ./obj/release/* + rm -rf ./lib/debug/* + rm -rf ./lib/release/* + rm -rf ./bin/debug/* + rm -rf ./bin/release/* + rm -rf ./test/tst_*.txt + + +.PHONY: print_vars + +print_vars: + @echo "" + @echo 'BUILD = '$(value BUILD) + @echo 'INC = '$(value INC) + @echo 'CPP_FILES = '$(value CPP_FILES) + @echo 'LIBS = '$(value LIBS) + + diff --git a/resource/csdk/ocrandom/test/linux/randomtest.cpp b/resource/csdk/ocrandom/test/linux/randomtest.cpp new file mode 100644 index 000000000..46fde03af --- /dev/null +++ b/resource/csdk/ocrandom/test/linux/randomtest.cpp @@ -0,0 +1,66 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + + +extern "C" { + #include "ocrandom.h" +} + +#include "gtest/gtest.h" +#include "math.h" + +#define ARR_SIZE (20) + +int main(int argc, char* argv[]) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + +TEST(RandomGeneration,OCSeedRandom) { + EXPECT_EQ((uint32_t )0, OCSeedRandom()); +} + +TEST(RandomGeneration,OCGetRandomByte) { + uint8_t value = OCGetRandomByte(); + EXPECT_LE((uint8_t )0, value); + EXPECT_GT(pow(2, 8), value); +} + +TEST(RandomGeneration,OCGetRandom) { + uint32_t value = OCGetRandom(); + EXPECT_LE((uint8_t )0, value); + EXPECT_GT(pow(2, 32), value); +} + +TEST(RandomGeneration,OCFillRandomMem) { + uint8_t array[ARR_SIZE]; + memset(array, 0, ARR_SIZE); + OCFillRandomMem(array + 1, ARR_SIZE - 2); + + for (int i = 1; i <= ARR_SIZE - 2; i++) { + uint8_t value = array[i]; + EXPECT_LE((uint8_t )0, value); + EXPECT_GT(pow(2, 8), value); + } + EXPECT_EQ((uint8_t )0, array[0]); + EXPECT_EQ((uint8_t )0, array[ARR_SIZE - 1]); +} + diff --git a/resource/csdk/ocsocket/README.txt b/resource/csdk/ocsocket/README.txt new file mode 100644 index 000000000..61dc001f9 --- /dev/null +++ b/resource/csdk/ocsocket/README.txt @@ -0,0 +1,28 @@ +------------------------------------------------------------------------------- + NOTICE - Transition to SCONS +------------------------------------------------------------------------------- + +The IoTivity build system is transitioning to SCONS. Although the +makefiles are still available (until v1.0) and some developers are +still using them, they are currently no longer supported. To learn more +about building using SCONS see Readme.scons.txt in the repository root +directory. The build steps used in continuous integration can be found +in auto_build.sh which is also in the the repository root directory. + +------------------------------------------------------------------------------- + +To compile for Linux or Android, include ocsocket.c and ocsocket.h in your project. +Look at the Makefile in ocsocket/test/linux and ocsocket/test/android for compilation dependencies. + +To compile for Arduino, include ocsocket_arduino.cpp and ocsocket.h in your project. +Look at the Makefile in ocsocket/test/arduino for compilation dependencies. +Note: Patch your Arduino Ethernet Shield library for arduino/libraries/Ethernet/utility/socket.cpp +to fix recvfrom issue. + +Place appropriate local.properties file under test directory to provide local path for \ +GTEST libraries/header files to compile tests. + +#Sample local.properties file +GTEST_LINUX_DIR = /home/gtest-1.7.0 +GTEST_ANDROID_DIR = /home/gtest-1.7.0_android/gtest-1.7.0 +ARDUINO_DIR = /usr/share/arduino diff --git a/resource/csdk/ocsocket/include/ocsocket.h b/resource/csdk/ocsocket/include/ocsocket.h new file mode 100644 index 000000000..9bad9eddb --- /dev/null +++ b/resource/csdk/ocsocket/include/ocsocket.h @@ -0,0 +1,321 @@ +//****************************************************************** +/// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef _OCSOCKET_H +#define _OCSOCKET_H + + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/**@mainpage + * + * This module is a part of Open Communication Thin-Block SDK. + */ + + +/**@defgroup socket Socket Interface + * + * This Socket interface needs to be implemented for every platform on + * which CCF TB stack is expected to run. If some functionality is not + * available on a platform, implement the method by returning error + * ERR_NOT_IMPLEMENTED. + */ + +#define ERR_SUCCESS (0) +#define ERR_INVALID_INPUT (-900) +#define ERR_UNKNOWN (-901) +#define ERR_NOT_IMPLEMENTED (-903) + + +/** This would need to be modified for specific platforms and specific + * technologies + */ +#define DEV_ADDR_SIZE_MAX (16) + +/** + *IPv4 or IPv6 addresses + */ +#ifndef AF_INET +#define AF_INET (2) +#endif //AF_INET + +#ifndef AF_INET6 +#define AF_INET6 (10) +#endif //AF_INET6 + + +/** + * Data structure to encapsulate IPv4/IPv6/Contiki/lwIP device addresses + * +*/ +#pragma pack(push, 1) +typedef struct OCDevAddr { + uint32_t size; /**< length of the address stored in addr field. */ + uint8_t addr[DEV_ADDR_SIZE_MAX]; /**< device address. */ +}OCDevAddr; +#pragma pack(pop) + +//-- OCInitNetworkStack ----------------------------------------------------------- +/** @ingroup ocsocket + * + * This method is used to perform any platform specific network + * initialization. Optional to implement. + * + * @retval 0 for Success, otherwise some error value + */ +//------------------------------------------------------------------------ +int32_t OCInitNetworkStack(); + +typedef enum +{ + OC_SOCKET_NOOPTION = 0, + OC_SOCKET_REUSEADDR +} OC_SOCKET_OPTION; + +//-- OCInitUDP ----------------------------------------------------------- +/** @ingroup ocsocket + * + * This method is used to create a new platform specific UDP socket and binds + * it to the address provided. + * + * @param[in] ipAddr + * device address with which the new socket will be bind. + * @param[out] sockfd + * reference to the new socket. + * @param[in] sockoption + * specifies which socket option to be used. + * + * @retval 0 for Success, otherwise some error value + */ +//------------------------------------------------------------------------ +int32_t OCInitUDP(OCDevAddr* ipAddr, int32_t* sockfd, OC_SOCKET_OPTION sockoption); + + + +//-- OCInitUDPMulticast -------------------------------------------------- +/** @ingroup ocsocket + * + * This method is used to create a new platform specific UDP socket for + * multicast and and binds it to the address provided. + * + * @param[in] ipmcastaddr + * multicast address to which IGMP membership be added. + * @param[out] sockfd + * reference to the new socket. + * + * @retval 0 for Success, otherwise some error value + */ +//------------------------------------------------------------------------ +int32_t OCInitUDPMulticast(OCDevAddr* ipmcastaddr, int32_t* sockfd); + + + +//-- OCSendTo ------------------------------------------------------------- +/** @ingroup ocsocket + * + * This method is used to transmit a UDP datagram to another endpoint. + * + * @param[in] sockfd + * socket to be used for sending the datagram. + * @param[in] buf + * datagram buffer. + * @param[in] bufLen + * length of above buffer. + * @param[in] flags + * flags to be used for sending datagram. + * @param[in] addr + * endpoint to which datagram needs to be send. + * + * @retval On Success, it returns the number of bytes send, otherwise + * some negative value. + */ +//------------------------------------------------------------------------ +int32_t OCSendTo(int32_t sockfd, const uint8_t* buf, uint32_t bufLen, uint32_t flags, + OCDevAddr * addr); + + +//-- OCRecvFrom ------------------------------------------------------------ +/** @ingroup ocsocket + * + * This method is used to retrieve a UDP datagram from the socket. + * + * @param[in] sockfd + * socket to be used for retrieving the datagram. + * @param[in] buf + * datagram buffer. + * @param[in] bufLen + * length of above buffer. + * @param[in] flags + * flags to be used for receiving datagram. + * @param[out] addr + * endpoint from which datagram has been received. + * + * @retval On Success, it returns the number of bytes read from the socket, + * otherwise some negative value. + */ +//------------------------------------------------------------------------ +int32_t OCRecvFrom(int32_t sockfd, uint8_t* buf, uint32_t bufLen, uint32_t flags, + OCDevAddr * addr); + +//-- OCClose --------------------------------------------------------------- +/** @ingroup ocsocket + * + * This method is used to close the platform specific socket and release any + * system resources associated with it. + * + * @param[in] sockfd + * socket to be closed. + * + * @retval 0 for Success, otherwise some error value + */ +//------------------------------------------------------------------------ +int32_t OCClose(int32_t sockfd); + + +//Utility methods +//-- OCBuildIPv4Address ------------------------------------------------- +/** @ingroup ocsocket + * + * This method is used to create the IPv4 dev_addr structure. + * + * @param[in] a first byte of IPv4 address. + * @param[in] b second byte of IPv4 address. + * @param[in] c third byte of IPv4 address. + * @param[in] d fourth byte of IPv4 address. + * @param[in] port port number. + * @param[out] ipAddr + * dev_addr to be filled with above data. + * + * @retval 0 for Success, otherwise some error value + */ +//------------------------------------------------------------------------ +int32_t OCBuildIPv4Address(uint8_t a, uint8_t b, uint8_t c, uint8_t d, + uint16_t port, OCDevAddr *ipAddr); + + +//-- OCGetInterfaceAddress ------------------------------------------------------ +/** @ingroup ocsocket + * + * This method is used to retrieved the IPv4/IPv6 address of the local interface. + * If no interface name is provided, this API retrieves the IP address of + * the default interface. + * + * @note currently, only IPv4(AF_INET) is supported for addrType argument. + * + * @param[in] ifName + * interface whose address needs to be retrieved. + * @param[in] ifNameLen + * length of the interface name + * @param[in] addrType + * IPv4 or IPv6 + * @param[out] addrv4 + * IPv4 address in a.b.c.d format + * @param[in] addrLen + * size of the buffer at addrv4. Should be at least 16 bytes for an + * IPv4 address. + * + * @retval 0 for Success, otherwise some error value + */ +//------------------------------------------------------------------------------- +int32_t OCGetInterfaceAddress(uint8_t* ifName, uint32_t ifNameLen, uint16_t addrType, + uint8_t *addrv4, uint32_t addrLen); + + +//-- OCDevAddrToString ---------------------------------------------------- +/** @ingroup ocsocket + * + * This method is used to convert the OCDevAddr to string format + * + * @param[in] addr + * OCDevAddr address. + * @param[out] stringAddress the target string where the address + * is to be stored. Memory for this parameter is + * allocated by the caller. + * + * Note: The length of stringAddress may not exceed DEV_ADDR_SIZE_MAX + * + * @retval 0 for Success, otherwise some error value + */ +//------------------------------------------------------------------------ +int32_t OCDevAddrToString(OCDevAddr *addr, char *stringAddress); + + +//-- OCDevAddrToIPv4Addr ------------------------------------------------- +/** @ingroup ocsocket + * + * This method is used to retrieved the IPv4 address from OCDev address + * data structure. + * + * @param[in] ipAddr + * OCDevAddr address. + * @param[out] a first byte of IPv4 address. + * @param[out] b second byte of IPv4 address. + * @param[out] c third byte of IPv4 address. + * @param[out] d fourth byte of IPv4 address. + * + * @retval 0 for Success, otherwise some error value + */ +//------------------------------------------------------------------------ +int32_t OCDevAddrToIPv4Addr(OCDevAddr *ipAddr, uint8_t *a, uint8_t *b, + uint8_t *c, uint8_t *d ); + + +//-- OCDevAddrToPort ------------------------------------------------- +/** @ingroup ocsocket + * + * This method is used to retrieve the port number from OCDev address + * data structure. + * + * @param[in] ipAddr + * OCDevAddr address. + * @param[out] port + * port number + * + * @retval 0 for Success, otherwise some error value + */ +//------------------------------------------------------------------------ +int32_t OCDevAddrToPort(OCDevAddr *ipAddr, uint16_t *port); + + +//-- OCGetSocketInfo ----------------------------------------------------- +/** @ingroup ocsocket + * + * This method is used to retrieve the port number to which the @p sockfd + * is bound. + * + * @param[in] sockfd + * socket whose port needs to be retrieved + * @param[out] port + * port number + * + * @retval 0 for Success, otherwise some error value + */ +//------------------------------------------------------------------------ +int32_t OCGetSocketInfo(int32_t sockfd, uint16_t *port); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif //_OCSOCKET_H diff --git a/resource/csdk/ocsocket/src/ocsocket.c b/resource/csdk/ocsocket/src/ocsocket.c new file mode 100644 index 000000000..fb4b700a0 --- /dev/null +++ b/resource/csdk/ocsocket/src/ocsocket.c @@ -0,0 +1,433 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __ANDROID__ +#include +#else +#include +#endif + +#include +#include + +/// Module Name +#define MOD_NAME ("ocsocket") + +/// Macro to verify the validity of input argument +#define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, MOD_NAME, #arg " is NULL"); return ERR_INVALID_INPUT;} } + +/// Builds a socket interface address using IP address and port number +int32_t OCBuildIPv4Address(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint16_t port, OCDevAddr *ipAddr) +{ + struct sockaddr_in *sa; + uint32_t ip = a; + + VERIFY_NON_NULL(ipAddr); + memset(ipAddr, 0, sizeof(OCDevAddr)); + + ip <<= 8; + ip |= b; + ip <<= 8; + ip |= c; + ip <<= 8; + ip |= d; + + ipAddr->size = sizeof(struct sockaddr_in); + sa = (struct sockaddr_in*)ipAddr->addr; + sa->sin_family = AF_INET; + sa->sin_addr.s_addr = htonl(ip); + sa->sin_port = htons(port); + + return ERR_SUCCESS; +} + +#ifdef __ANDROID__ +/// Retrieves the IP address assigned to specified wireless interface +int32_t OCGetInterfaceAddress(uint8_t* ifName, uint32_t ifNameLen, uint16_t addrType, + uint8_t *addr, uint32_t addrLen) +{ + int32_t ret = ERR_UNKNOWN; + int32_t sfd = 0xFFFFFFFF; + struct ifreq ifr; + + VERIFY_NON_NULL(addr); + VERIFY_NON_NULL(ifName); + if (ifNameLen > (IFNAMSIZ - 1) ) { + return ERR_INVALID_INPUT; + } + if (addrType != AF_INET) { + return ERR_INVALID_INPUT; + } + + sfd = socket(addrType, SOCK_DGRAM, 0); + if (sfd < 0) { + OC_LOG_V(FATAL, MOD_NAME, "socket API ret val %d", sfd); + goto exit; + } + + ifr.ifr_addr.sa_family = addrType; + + strncpy(ifr.ifr_name, (const char*)ifName, ifNameLen); + + if (ioctl(sfd, SIOCGIFADDR, &ifr) != 0) { + OC_LOG(FATAL, MOD_NAME, "ioctl call failed"); + goto exit; + } + + strncpy((char *)addr, + inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr), + addrLen); + ret = ERR_SUCCESS; + +exit: + if (sfd >= 0) { + close(sfd); + } + return ret; +} + +#else +/// Retrieves the IP address assigned to specified wireless interface +int32_t OCGetInterfaceAddress(uint8_t* ifName, uint32_t ifNameLen, uint16_t addrType, + uint8_t *addr, uint32_t addrLen) +{ + struct ifaddrs *myaddrs = NULL, *ifa = NULL; + int32_t ret = ERR_UNKNOWN; + + VERIFY_NON_NULL(addr); + + if (addrType != AF_INET) { + return ERR_INVALID_INPUT; + } + + if(getifaddrs(&myaddrs) != 0) { + goto exit; + } + + for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == NULL) + continue; + if (!(ifa->ifa_flags & IFF_UP)) + continue; + if (!(ifa->ifa_flags & IFF_RUNNING)) + continue; + + if (ifName && ifa->ifa_name) { + if(strncmp((const char*)ifName, ifa->ifa_name, ifNameLen) != 0) + continue; + } + + switch (ifa->ifa_addr->sa_family) + { + case AF_INET: + { + struct sockaddr_in *s4 = (struct sockaddr_in *)ifa->ifa_addr; + if(inet_ntop(AF_INET, &(s4->sin_addr), (char *)addr, addrLen)) + ret = ERR_SUCCESS; + goto exit; + } + + default: + continue; + } + } + +exit: + if (myaddrs) { + freeifaddrs(myaddrs); + } + return ret; +} +#endif //__ANDROID__ + +/// Creates a BSD socket and binds it specified port for UDP +int32_t OCInitUDP(OCDevAddr* ipAddr, int32_t *sockfd, OC_SOCKET_OPTION sockoption) +{ + int32_t ret = ERR_UNKNOWN; + int32_t sfd = 0xFFFFFFFF; + int set_option_on = 1; + + VERIFY_NON_NULL(ipAddr); + VERIFY_NON_NULL(sockfd); + + OC_LOG_V(DEBUG, MOD_NAME, "%s Begin", __func__ ); + //Create a datagram socket on which to recv/send. + sfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sfd < 0) { + OC_LOG_V(FATAL, MOD_NAME, "socket API ret val %d", sfd); + goto exit; + } + + if(OC_SOCKET_REUSEADDR == sockoption) + { + if ((ret = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (char*) &set_option_on, + sizeof(set_option_on))) < 0) { + OC_LOG_V(FATAL, MOD_NAME, "setsockopt API failed with errno %s", + strerror(errno)); + goto exit; + } + } + + if ((ret = bind(sfd, (struct sockaddr*)ipAddr->addr, ipAddr->size)) < 0) { + OC_LOG_V(FATAL, MOD_NAME, "bind API failed with errno %s", strerror(errno)); + goto exit; + } + + *sockfd = sfd; + ret = ERR_SUCCESS; + +exit: + if ((ret != ERR_SUCCESS) && (sfd >= 0)) { + close(sfd); + } + + OC_LOG_V(DEBUG, MOD_NAME, "%s End", __func__ ); + return ret; +} + + + +/// Creates a BSD socket and binds the specified port for UDP multicast. +int32_t OCInitUDPMulticast(OCDevAddr* ipmcastaddr, int32_t* sockfd) +{ + int32_t ret = ERR_UNKNOWN; + int32_t sfd = 0xFFFFFFFF; + char loopch=1; + int set_option_on = 1; + + VERIFY_NON_NULL(ipmcastaddr); + VERIFY_NON_NULL(sockfd); + + OC_LOG_V(DEBUG, MOD_NAME, "%s Begin", __func__ ); + //Create a datagram socket on which to recv/send. + sfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sfd < 0) { + OC_LOG_V(FATAL, MOD_NAME, "socket API ret val %d", sfd); + goto exit; + + } + + if ((ret = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (char*) &set_option_on, + sizeof(set_option_on))) < 0) { + OC_LOG_V(FATAL, MOD_NAME, "setsockopt API for SO_REUSEADDR failed with errno %s", strerror(errno)); + goto exit; + } + + // bind to multicast port + struct sockaddr_in sa = {0}; + struct sockaddr_in *sin; + + sin = (struct sockaddr_in *)(ipmcastaddr->addr); + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = sin->sin_addr.s_addr; + sa.sin_port = sin->sin_port; + + if ((ret = bind(sfd, (struct sockaddr*)&sa, sizeof(sa))) < 0) { + OC_LOG_V(FATAL, MOD_NAME, "bind API failed with errno %s", strerror(errno)); + goto exit; + } + + // add membership to receiving socket + struct ip_mreq mreq = {{0}}; + mreq.imr_interface.s_addr = htonl(INADDR_ANY); + mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; + if ((ret = setsockopt(sfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq))) < 0) { + OC_LOG_V(FATAL, MOD_NAME, "setsockopt API for IP_ADD_MEMBERSHIP failed with errno %s", strerror(errno)); + goto exit; + } + + //Enable loopback so we can receive our own datagrams. + if ((ret = setsockopt(sfd, IPPROTO_IP, IP_MULTICAST_LOOP, + (char *)&loopch, sizeof(loopch))) < 0) { + OC_LOG_V(FATAL, MOD_NAME, "setsockopt API for IP_MULTICAST_LOOP failed with errno %s", strerror(errno)); + goto exit; + } + + ret = ERR_SUCCESS; + +exit: + if (ret == ERR_SUCCESS) { + *sockfd = sfd; + } else { + close(sfd); + } + + OC_LOG_V(DEBUG, MOD_NAME, "%s End", __func__ ); + return ret; +} + + + +/// Send data to requested end-point using UDP socket +int32_t OCSendTo(int32_t sockfd, const uint8_t* buf, uint32_t bufLen, uint32_t flags, + OCDevAddr * ipAddr) +{ + int32_t ret; + + VERIFY_NON_NULL(buf); + VERIFY_NON_NULL(ipAddr); + + OC_LOG_V(DEBUG, MOD_NAME, "%s Begin", __func__ ); + ret = sendto(sockfd, buf, bufLen, flags, + (struct sockaddr*)ipAddr->addr, ipAddr->size); + + OC_LOG_V(DEBUG, MOD_NAME, "%s End", __func__ ); + return ret; +} + + +/// Retrieve any available data from UDP socket. This is a non-blocking call. +int32_t OCRecvFrom(int32_t sockfd, uint8_t* buf, uint32_t bufLen, uint32_t flags, + OCDevAddr * ipAddr) +{ + int32_t ret = 0; + + VERIFY_NON_NULL(buf); + VERIFY_NON_NULL(ipAddr); + + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 5000; + fd_set reads; + + OC_LOG_V(DEBUG, MOD_NAME, "%s Begin", __func__ ); + + FD_ZERO(&reads); + FD_SET(sockfd, &reads); + ret = select(sockfd + 1, &reads, NULL, NULL, &timeout); + if( ret < 0) { + OC_LOG(FATAL, MOD_NAME, "select API failed"); + return ret; + } + if (!FD_ISSET(sockfd, &reads)) { + OC_LOG(DEBUG, MOD_NAME, "No data to read"); + return ERR_SUCCESS; + } + + // Read available data. + ret = recvfrom(sockfd, buf, bufLen, flags, + (struct sockaddr*)ipAddr->addr, (socklen_t*)&(ipAddr->size)); + if (ret < 1) { + OC_LOG(FATAL, MOD_NAME, "OCRecvFrom ERR"); + } + OC_LOG_V(DEBUG, MOD_NAME, "%s End", __func__ ); + return ret; +} + + +/// Close the socket and release all system resources. +int32_t OCClose(int32_t sockfd) +{ + return (close(sockfd)); +} + +//convert OCDevAddr to String +int32_t OCDevAddrToString(OCDevAddr* addr, char* stringAddress) +{ + uint8_t a; + uint8_t b; + uint8_t c; + uint8_t d; + + if(OCDevAddrToIPv4Addr(addr, &a, &b, &c, &d) == 0) + { + if (!stringAddress) + { + return ERR_INVALID_INPUT; + } + + snprintf(stringAddress, DEV_ADDR_SIZE_MAX, "%u.%u.%u.%u", + a, b, c, d); + return ERR_SUCCESS; + } + else + { + return ERR_INVALID_INPUT; + } +} + +/// Retrieve the IPv4 address embedded inside OCDev address data structure +int32_t OCDevAddrToIPv4Addr(OCDevAddr *ipAddr, uint8_t *a, uint8_t *b, + uint8_t *c, uint8_t *d ) +{ + struct sockaddr_in *sa; + uint32_t ip; + + if ( !ipAddr || !a || !b || !c || !d ) { + OC_LOG(FATAL, MOD_NAME, "Invalid argument"); + return ERR_INVALID_INPUT; + } + + sa = (struct sockaddr_in*)ipAddr->addr; + ip = ntohl(sa->sin_addr.s_addr); + *d = *((uint8_t*)&ip + 0); + *c = *((uint8_t*)&ip + 1); + *b = *((uint8_t*)&ip + 2); + *a = *((uint8_t*)&ip + 3); + + return ERR_SUCCESS; +} + + +/// Retrieve the IPv4 address embedded inside OCDev address data structure +int32_t OCDevAddrToPort(OCDevAddr *ipAddr, uint16_t *port) +{ + struct sockaddr_in *sa; + if ( !ipAddr || !port ) { + OC_LOG(FATAL, MOD_NAME, "Invalid argument"); + return ERR_INVALID_INPUT; + } + + sa = (struct sockaddr_in*)ipAddr->addr; + *port = ntohs(sa->sin_port); + + return ERR_SUCCESS; +} + +/// Retrieve the port to which socket is bound +int32_t OCGetSocketInfo(int32_t sockfd, uint16_t *port) +{ + int32_t ret = ERR_SUCCESS; + + struct sockaddr_in sa; + socklen_t salen = sizeof(sa); + if (getsockname(sockfd, (struct sockaddr*)&sa, &salen) == 0) { + *port = ntohs(sa.sin_port); + } else { + OC_LOG_V(FATAL, MOD_NAME, "getsockname API failed with errno \ + %s", strerror(errno)); + ret = ERR_UNKNOWN; + } + return ret; +} diff --git a/resource/csdk/ocsocket/src/ocsocket_arduino.cpp b/resource/csdk/ocsocket/src/ocsocket_arduino.cpp new file mode 100644 index 000000000..ed51f79d1 --- /dev/null +++ b/resource/csdk/ocsocket/src/ocsocket_arduino.cpp @@ -0,0 +1,268 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include +#include +#include +#include +#include +#include + +/// Ensures the literal string to be stored in Flash memory +#define PCF(str) ((PROGMEM const char *)(F(str))) + +/// Module Name +#define MOD_NAME PCF("ocsocket") + +/// Macro to verify the validity of input argument +#define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG_V(FATAL, MOD_NAME, "%s is NULL", #arg); \ + return ERR_INVALID_INPUT;} } + +/// Length of the IP address decimal notation string +#define IPNAMESIZE (16) + +/// IPv4 address representation for Arduino Ethernet Shield +typedef struct { + uint32_t size; /// size of IP address and port bytes + uint8_t a; + uint8_t b; + uint8_t c; + uint8_t d; + uint16_t port; +} ArduinoAddr; + + +/// Builds a socket interface address using IP address and port number +int32_t OCBuildIPv4Address(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint16_t port, OCDevAddr *ipAddr) +{ + ArduinoAddr* ardAddr = (ArduinoAddr*)ipAddr; + + VERIFY_NON_NULL(ardAddr); + + memset(ardAddr, 0, sizeof(ArduinoAddr)); + + ardAddr->size = sizeof(ArduinoAddr) - sizeof(ardAddr->size); + ardAddr-> a = a; + ardAddr-> b = b; + ardAddr-> c = c; + ardAddr-> d = d; + ardAddr-> port = port; + + return ERR_SUCCESS; +} + + +/// Retrieves the IP address assigned to Arduino Ethernet shield +int32_t OCGetInterfaceAddress(uint8_t* ifName, uint32_t ifNameLen, uint16_t addrType, + uint8_t *addr, uint32_t addrLen) +{ + //TODO : Fix this for scenarios when this API is invoked when device is not connected + uint8_t rawIPAddr[4]; + VERIFY_NON_NULL(addr); + if (addrLen < IPNAMESIZE) { + OC_LOG(FATAL, MOD_NAME, PCF("OCGetInterfaceAddress: addrLen MUST be atleast 16")); + return ERR_INVALID_INPUT; + } + + if (addrType != AF_INET) { + return ERR_INVALID_INPUT; + } + W5100.getIPAddress(rawIPAddr); + snprintf((char *)addr, addrLen, "%d.%d.%d.%d", rawIPAddr[0], rawIPAddr[1], rawIPAddr[2], rawIPAddr[3]); + + OC_LOG_BUFFER(INFO, MOD_NAME, addr, addrLen); + + return ERR_SUCCESS; +} + +/// Retrieves a empty socket and bind it for UDP with the input port +int32_t OCInitUDP(OCDevAddr* ipAddr, int32_t* sockfd, OC_SOCKET_OPTION sockoption) +{ + uint8_t state; + ArduinoAddr* ardAddr = (ArduinoAddr*)ipAddr; + + VERIFY_NON_NULL(ardAddr); + VERIFY_NON_NULL(sockfd); + + OC_LOG(DEBUG, MOD_NAME, PCF("OCInitUDP Begin")); + //Is any socket available to work with ? + *sockfd = -1; + for (int i = 0; i < MAX_SOCK_NUM; i++) { + state = W5100.readSnSR(i); + if (state == SnSR::CLOSED || state == SnSR::FIN_WAIT) { + *sockfd = i; + break; + } + } + + if ( *sockfd == -1) { + return ERR_UNKNOWN; + } + + //Create a datagram socket on which to recv/send. + if (!socket(*sockfd, SnMR::UDP, ardAddr->port, 0)) { + return ERR_UNKNOWN; + } + + OC_LOG(DEBUG, MOD_NAME, PCF("OCInitUDP End")); + return ERR_SUCCESS; +} + + + +/// Retrieves a empty socket and bind it for UDP with the input multicast ip address/port +int32_t OCInitUDPMulticast(OCDevAddr* ipMcastMacAddr, int32_t* sockfd) +{ + uint8_t state; + uint8_t mcastMacAddr[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0x00}; + ArduinoAddr* ardAddr = (ArduinoAddr*)ipMcastMacAddr; + + VERIFY_NON_NULL(ardAddr); + VERIFY_NON_NULL(sockfd); + + OC_LOG(DEBUG, MOD_NAME, PCF("OCInitUDPMulticast Begin")); + //Is any socket available to work with ? + *sockfd = -1; + for (int i = 0; i < MAX_SOCK_NUM; i++) { + state = W5100.readSnSR(i); + if (state == SnSR::CLOSED || state == SnSR::FIN_WAIT) { + *sockfd = i; + break; + } + } + + if ( *sockfd == -1) { + return ERR_UNKNOWN; + } + + //Calculate Multicast MAC address + mcastMacAddr[3] = ardAddr->b & 0x7F; + mcastMacAddr[4] = ardAddr->c; + mcastMacAddr[5] = ardAddr->d; + W5100.writeSnDIPR(*sockfd, (uint8_t*)&(ardAddr->a)); + W5100.writeSnDHAR(*sockfd, mcastMacAddr); + W5100.writeSnDPORT(*sockfd, ardAddr->port); + + //Create a datagram socket on which to recv/send. + if (!socket(*sockfd, SnMR::UDP, ardAddr->port, SnMR::MULTI)) { + return ERR_UNKNOWN; + } + + OC_LOG(DEBUG, MOD_NAME, PCF("OCInitUDPMulticast End")); + return ERR_SUCCESS; +} + + +/// Send data to requested end-point using UDP socket +int32_t OCSendTo(int32_t sockfd, const uint8_t* buf, uint32_t bufLen, uint32_t flags, + OCDevAddr * ipAddr) +{ + int32_t ret; + ArduinoAddr* ardAddr = (ArduinoAddr*)ipAddr; + + VERIFY_NON_NULL(buf); + VERIFY_NON_NULL(ardAddr); + OC_LOG(DEBUG, MOD_NAME, PCF("OCSendTo Begin")); + ret = sendto( sockfd, buf, bufLen, (uint8_t*)&(ardAddr->a), ardAddr->port); + OC_LOG_V(DEBUG, MOD_NAME, "OCSendTo RetVal %d", ret); + return ret; +} + + +/// Retrieve any available data from UDP socket. This is a non-blocking call. +int32_t OCRecvFrom(int32_t sockfd, uint8_t* buf, uint32_t bufLen, uint32_t flags, + OCDevAddr * ipAddr) +{ + /**Bug : When there are multiple UDP packets in Wiznet buffer, W5100.getRXReceivedSize + * will not return correct length of the first packet. + * Fix : Use the patch provided for arduino/libraries/Ethernet/utility/socket.cpp + */ + int32_t ret = 0; + uint16_t recvLen; + ArduinoAddr* ardAddr = (ArduinoAddr*)ipAddr; + + VERIFY_NON_NULL(buf); + VERIFY_NON_NULL(ardAddr); + + OC_LOG(DEBUG, MOD_NAME, PCF("OCRecvFrom Begin")); + recvLen = W5100.getRXReceivedSize(sockfd); + if (recvLen == 0) { + return recvLen; + } + + // Read available data. + ret = recvfrom(sockfd, buf, bufLen, (uint8_t*)&(ardAddr->a), (uint16_t*)&(ardAddr->port)); + ardAddr->size = sizeof(ArduinoAddr) - sizeof(ardAddr->size); + + OC_LOG(DEBUG, MOD_NAME, PCF("OCRecvFrom End")); + return ret; +} + + +/// Close the socket and release all system resources. +int32_t OCClose(int32_t sockfd) +{ + close(sockfd); + return ERR_SUCCESS; +} + + +/// Retrieve the IPv4 address embedded inside OCDev address data structure +int32_t OCDevAddrToIPv4Addr(OCDevAddr *ipAddr, uint8_t *a, uint8_t *b, + uint8_t *c, uint8_t *d ) +{ + ArduinoAddr* ardAddr = (ArduinoAddr*)ipAddr; + + if ( !ardAddr || !a || !b || !c || !d ) { + OC_LOG(FATAL, MOD_NAME, PCF("Invalid argument")); + return ERR_INVALID_INPUT; + } + + *a = ardAddr->a; + *b = ardAddr->b; + *c = ardAddr->c; + *d = ardAddr->d; + + return ERR_SUCCESS; +} + + +/// Retrieve the IPv4 address embedded inside OCDev address data structure +int32_t OCDevAddrToPort(OCDevAddr *ipAddr, uint16_t *port) +{ + ArduinoAddr* ardAddr = (ArduinoAddr*)ipAddr; + + if ( !ardAddr || !port ) { + OC_LOG(FATAL, MOD_NAME, PCF("Invalid argument")); + return ERR_INVALID_INPUT; + } + + *port = ardAddr->port; + + return ERR_SUCCESS; +} + +/// Retrieve the port to which socket is bound +int32_t OCGetSocketInfo(int32_t sockfd, uint16_t *port) +{ + return ERR_NOT_IMPLEMENTED; +} diff --git a/resource/csdk/ocsocket/src/ocsocket_arduino_wifi.cpp b/resource/csdk/ocsocket/src/ocsocket_arduino_wifi.cpp new file mode 100644 index 000000000..37f5fe9a8 --- /dev/null +++ b/resource/csdk/ocsocket/src/ocsocket_arduino_wifi.cpp @@ -0,0 +1,306 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include +#include +#include +#include +#include + +/// Module Name +#define MOD_NAME PCF("ocsocket") + +/// Macro to verify the validity of input argument +#define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG_V(FATAL, MOD_NAME, "%s is NULL", #arg); \ + return ERR_INVALID_INPUT;} } + +/// Length of the IP address decimal notation string +#define IPNAMESIZE (16) + +/// This is the max buffer size between Arduino and WiFi Shield +#define ARDUINO_WIFI_SPI_RECV_BUFFERSIZE (64) + +// Start offsets based on end of received data buffer +#define WIFI_RECBUF_IPADDR_OFFSET (6) +#define WIFI_RECBUF_PORT_OFFSET (2) + +#define WIFI_RECBUF_IPADDR_SIZE (WIFI_RECBUF_IPADDR_OFFSET - WIFI_RECBUF_PORT_OFFSET) +#define WIFI_RECBUF_PORT_SIZE (WIFI_RECBUF_PORT_OFFSET - 0) +#define WIFI_RECBUF_FOOTER_SIZE (WIFI_RECBUF_IPADDR_SIZE + WIFI_RECBUF_PORT_SIZE) + + +/// IPv4 address representation for Arduino Ethernet Shield +typedef struct { + uint32_t size; /// size of IP address and port bytes + uint8_t a; + uint8_t b; + uint8_t c; + uint8_t d; + uint16_t port; +} ArduinoAddr; + + +/// Builds a socket interface address using IP address and port number +int32_t OCBuildIPv4Address(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint16_t port, OCDevAddr *ipAddr) +{ + ArduinoAddr* ardAddr = (ArduinoAddr*)ipAddr; + + VERIFY_NON_NULL(ardAddr); + + memset(ardAddr, 0, sizeof(ArduinoAddr)); + + ardAddr->size = sizeof(ArduinoAddr) - sizeof(ardAddr->size); + ardAddr-> a = a; + ardAddr-> b = b; + ardAddr-> c = c; + ardAddr-> d = d; + ardAddr-> port = port; + + return ERR_SUCCESS; +} + + +/// Retrieves the IP address assigned to Arduino Ethernet shield +int32_t OCGetInterfaceAddress(uint8_t* ifName, uint32_t ifNameLen, uint16_t addrType, + uint8_t *addr, uint32_t addrLen) +{ + WiFiClass WiFi; + + VERIFY_NON_NULL(addr); + if (addrLen < IPNAMESIZE) { + OC_LOG(FATAL, MOD_NAME, PCF("OCGetInterfaceAddress: addrLen MUST be at least 16")); + return ERR_INVALID_INPUT; + } + + if (addrType != AF_INET) { + return ERR_INVALID_INPUT; + } + + IPAddress ip = WiFi.localIP(); + snprintf((char *)addr, addrLen, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); + + OC_LOG_BUFFER(INFO, MOD_NAME, addr, addrLen); + + return ERR_SUCCESS; +} + +/// Retrieves a empty socket and bind it for UDP with the input port +int32_t OCInitUDP(OCDevAddr* ipAddr, int32_t* sockfd, OC_SOCKET_OPTION sockoption) +{ + ArduinoAddr* ardAddr = (ArduinoAddr*)ipAddr; + uint8_t sock; + + VERIFY_NON_NULL(ardAddr); + VERIFY_NON_NULL(sockfd); + + OC_LOG(DEBUG, MOD_NAME, PCF("OCInitUDP Begin")); + //Is any socket available to work with ? + *sockfd = -1; + + sock = WiFiClass::getSocket(); + if (sock != NO_SOCKET_AVAIL) + { + ServerDrv::startServer(ardAddr->port, sock, UDP_MODE); + WiFiClass::_server_port[sock] = ardAddr->port; + *sockfd = (int32_t)sock; + } + + if (*sockfd == -1) + { + return ERR_UNKNOWN; + } + + OC_LOG(DEBUG, MOD_NAME, PCF("OCInitUDP End")); + return ERR_SUCCESS; +} + + + +/// Currently WiFi shield does NOT support multicast. +int32_t OCInitUDPMulticast(OCDevAddr* ipMcastMacAddr, int32_t* sockfd) +{ + return OCInitUDP(ipMcastMacAddr, sockfd, OC_SOCKET_REUSEADDR); +} + + +/// Send data to requested end-point using UDP socket +int32_t OCSendTo(int32_t sockfd, const uint8_t* buf, uint32_t bufLen, uint32_t flags, + OCDevAddr * ipAddr) +{ + int32_t ret = 0; + ArduinoAddr* ardAddr = (ArduinoAddr*)ipAddr; + uint32_t ip; + uint16_t rem, send; + + VERIFY_NON_NULL(buf); + VERIFY_NON_NULL(ardAddr); + OC_LOG(DEBUG, MOD_NAME, PCF("OCSendTo Begin")); + + if (sockfd >= MAX_SOCK_NUM) + { + OC_LOG(ERROR, MOD_NAME, PCF("Invalid sockfd")); + return -1; + } + + memcpy((uint8_t*)&ip, (uint8_t*)&(ardAddr->a), sizeof(ip)); + ServerDrv::startClient(ip, ardAddr->port, (uint8_t)sockfd, UDP_MODE); + + rem = bufLen; + do + { + send = (rem > ARDUINO_WIFI_SPI_RECV_BUFFERSIZE ) ? ARDUINO_WIFI_SPI_RECV_BUFFERSIZE : rem; + if (!ServerDrv::insertDataBuf((uint8_t)sockfd, buf, (uint16_t)send)) + { + OC_LOG(ERROR, MOD_NAME, PCF("insertDataBuf error")); + ret = -1; + break; + } + rem = rem - send; + buf = buf + send; + }while(rem > 0); + + if (ret != -1) + { + if (!ServerDrv::sendUdpData((uint8_t)sockfd)) + { + OC_LOG(ERROR, MOD_NAME, PCF("sendUdpData error")); + ret = -1; + } + else + { + ret = bufLen; + } + } + OC_LOG(DEBUG, MOD_NAME, PCF("OCSendTo End")); + return ret; +} + + +/// Retrieve any available data from UDP socket. This is a non-blocking call. +int32_t OCRecvFrom(int32_t sockfd, uint8_t* buf, uint32_t bufLen, uint32_t flags, + OCDevAddr * ipAddr) +{ + + uint16_t recvLen; + uint16_t size = 0; + ArduinoAddr* ardAddr = (ArduinoAddr*)ipAddr; + + VERIFY_NON_NULL(buf); + VERIFY_NON_NULL(ardAddr); + + OC_LOG(DEBUG, MOD_NAME, PCF("OCRecvFrom Begin")); + if (sockfd >= MAX_SOCK_NUM) + { + OC_LOG(ERROR, MOD_NAME, PCF("Invalid sockfd")); + return -1; + } + + recvLen = (int32_t)ServerDrv::availData((uint8_t)sockfd); + if (recvLen == 0) + { + return recvLen; + } + + // Make sure buf is large enough for received data + if ((uint32_t)recvLen > bufLen) + { + OC_LOG(ERROR, MOD_NAME, PCF("Receive buffer too small")); + return -1; + } + + if (!ServerDrv::getDataBuf((uint8_t)sockfd, buf, &size)) + { + OC_LOG(ERROR, MOD_NAME, PCF("getDataBuf error")); + return -1; + } + + // Read IP Address and Port from end of receive buffer + memcpy(&(ardAddr->a), &buf[size - WIFI_RECBUF_IPADDR_OFFSET], WIFI_RECBUF_IPADDR_SIZE); + // Change the endianness of the port number + *((uint8_t*)&(ardAddr->port)) = buf[size - (WIFI_RECBUF_PORT_OFFSET-1)]; + *((uint8_t*)&(ardAddr->port) + 1) = buf[size - (WIFI_RECBUF_PORT_OFFSET)]; + + size -= WIFI_RECBUF_FOOTER_SIZE; + + ardAddr->size = sizeof(ArduinoAddr) - sizeof(ardAddr->size); + OC_LOG(DEBUG, MOD_NAME, PCF("OCRecvFrom End")); + return (int32_t)size; +} + + +/// Close the socket and release all system resources. +int32_t OCClose(int32_t sockfd) +{ + if (sockfd >= MAX_SOCK_NUM) + { + OC_LOG(ERROR, MOD_NAME, PCF("Invalid sockfd")); + return -1; + } + ServerDrv::stopClient(sockfd); + + WiFiClass::_server_port[sockfd] = 0; + WiFiClass::_state[sockfd] = NA_STATE; + + return ERR_SUCCESS; +} + + +/// Retrieve the IPv4 address embedded inside OCDev address data structure +int32_t OCDevAddrToIPv4Addr(OCDevAddr *ipAddr, uint8_t *a, uint8_t *b, + uint8_t *c, uint8_t *d ) +{ + ArduinoAddr* ardAddr = (ArduinoAddr*)ipAddr; + + if ( !ardAddr || !a || !b || !c || !d ) { + OC_LOG(FATAL, MOD_NAME, PCF("Invalid argument")); + return ERR_INVALID_INPUT; + } + + *a = ardAddr->a; + *b = ardAddr->b; + *c = ardAddr->c; + *d = ardAddr->d; + + return ERR_SUCCESS; +} + + +/// Retrieve the IPv4 address embedded inside OCDev address data structure +int32_t OCDevAddrToPort(OCDevAddr *ipAddr, uint16_t *port) +{ + ArduinoAddr* ardAddr = (ArduinoAddr*)ipAddr; + + if ( !ardAddr || !port ) { + OC_LOG(FATAL, MOD_NAME, PCF("Invalid argument")); + return ERR_INVALID_INPUT; + } + + *port = ardAddr->port; + + return ERR_SUCCESS; +} + +/// Retrieve the port to which socket is bound +int32_t OCGetSocketInfo(int32_t sockfd, uint16_t *port) +{ + return ERR_NOT_IMPLEMENTED; +} diff --git a/resource/csdk/ocsocket/test/android/makefile b/resource/csdk/ocsocket/test/android/makefile new file mode 100644 index 000000000..f68574ddb --- /dev/null +++ b/resource/csdk/ocsocket/test/android/makefile @@ -0,0 +1,70 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +include ../local.properties + +ROOT_DIR = ../../.. +OCSOCK_DIR = $(ROOT_DIR)/ocsocket +LOGGER_DIR = $(ROOT_DIR)/logger +BIN_DIR = $(OCSOCK_DIR)/bin/android/ +OBJ_DIR = $(OCSOCK_DIR)/obj/android/ +INC_DIRS = -I$(OCSOCK_DIR)/include/ -I$(LOGGER_DIR)/include + +CXX=arm-linux-androideabi-g++ +CC=arm-linux-androideabi-gcc +CFLAGS_ANDROID = -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -DGTEST_HAS_PTHREAD=0 +LDFLAGS_ANDROID = -march=armv7-a -Wl,--fix-cortex-a8 -llog + +DEP_LIBS = $(GTEST_ANDROID_DIR)/lib/.libs/libgtest_main.a $(GTEST_ANDROID_DIR)/lib/.libs/libgtest.a + +CFLAGS += -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions -DTB_LOG + +TEST_APP = ocsocket_gtest + +COBJ = ocsocket.o logger.o + +VPATH = $(OCSOCK_DIR)/src:$(LOGGER_DIR)/src + +all: $(TEST_APP) + mkdir -p $(BIN_DIR) + cp $(TEST_APP) $(BIN_DIR) + mkdir -p $(OBJ_DIR) + cp *.o $(OBJ_DIR) + +%.o: %.c + $(CXX) -c $(CFLAGS) $(CFLAGS_ANDROID) $(INC_DIRS) $< -o $@ + +$(TEST_APP).o: $(TEST_APP).cpp + $(CXX) -c $(CFLAGS) $(CFLAGS_ANDROID) $(INC_DIRS) -I$(GTEST_ANDROID_DIR)/include -o $@ $< + +$(TEST_APP): $(TEST_APP).o $(DEP_LIBS) $(COBJ) + $(CXX) -Os -Wl,--gc-sections $(LDFLAGS_ANDROID) $^ -o $@ + +install: all +# adb remount + adb push $(BIN_DIR)$(TEST_APP) /data/local/tmp/ + +.PHONY: clean + +clean: + rm -f *.o $(TEST_APP) recv + rm -fr $(BIN_DIR) + rm -fr $(OBJ_DIR) + diff --git a/resource/csdk/ocsocket/test/android/ocsocket_gtest.cpp b/resource/csdk/ocsocket/test/android/ocsocket_gtest.cpp new file mode 100644 index 000000000..1c90e0b57 --- /dev/null +++ b/resource/csdk/ocsocket/test/android/ocsocket_gtest.cpp @@ -0,0 +1,289 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +#include +#include +#include + +#define MOD_NAME ("ocsocket_test") +#define TEST_PORT_NUM (8888) + +unsigned char buf1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01 +}; +unsigned int buf1_len = sizeof(buf1); + + +unsigned char buf2[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, +}; + +unsigned int buf2_len = sizeof(buf2); + + +TEST(BuildIPv4, Positive) { + OCDevAddr ipaddr; + EXPECT_EQ(ERR_SUCCESS, OCBuildIPv4Address(224,0,0,251,5353, &ipaddr)); +} + + +TEST(BuildIPv4, InvalidInput) { + EXPECT_EQ(ERR_INVALID_INPUT, OCBuildIPv4Address(24,24,24,24,2424, NULL)); + EXPECT_EQ(ERR_INVALID_INPUT, OCBuildIPv4Address(-24,24,-24,24,2424, NULL)); +} + + +TEST(DevAddrToIPv4Addr, Positive) { + OCDevAddr ipaddr; + uint8_t a,b,c,d; + uint16_t port; + OCBuildIPv4Address(1,2,3,4,5353, &ipaddr); + EXPECT_EQ(ERR_SUCCESS, OCDevAddrToIPv4Addr(&ipaddr, &a, &b, &c, &d )); + EXPECT_TRUE((a == 1) && (b == 2) && (c == 3) && (d ==4)); + EXPECT_EQ(ERR_SUCCESS, OCDevAddrToPort(&ipaddr, &port )); + EXPECT_TRUE(port == 5353); +} + + +TEST(DevAddrToIPv4Addr, InvalidInput) { + OCDevAddr ipaddr; + uint8_t a,b,c,d; + uint16_t port; + OCBuildIPv4Address(1,2,3,4,5353, &ipaddr); + EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToIPv4Addr(NULL, &a, &b, &c, &d )); + EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToIPv4Addr(&ipaddr, NULL, &b, &c, &d )); + EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToIPv4Addr(NULL, NULL, &b, &c, &d )); + + EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToPort(NULL, &port )); + EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToPort(&ipaddr, NULL )); + EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToPort(NULL, NULL )); +} + + +TEST(GetInterfaceAddress, Positive) { + uint8_t addr[20]; + uint8_t ifname[] = "wlan0"; + EXPECT_EQ(ERR_SUCCESS, OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, addr, sizeof(addr))); + OC_LOG_V(INFO, MOD_NAME, "IPv4 Address: %s\n", addr); + //On Android, it is MUST to provide interface name + //EXPECT_EQ(0, get_ipv4addr( NULL, 0, addr, sizeof(addr))); +} + +TEST(GetInterfaceAddress, Negative) { + uint8_t addr[20]; + uint8_t ifname[] = "ethxx"; + EXPECT_EQ(ERR_INVALID_INPUT, OCGetInterfaceAddress( NULL, 0, AF_INET, addr, sizeof(addr))); + EXPECT_EQ(ERR_UNKNOWN, OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, addr, sizeof(addr))); + EXPECT_EQ(ERR_INVALID_INPUT, OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, NULL, sizeof(addr))); + EXPECT_EQ(ERR_UNKNOWN, OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, addr, 0)); + EXPECT_EQ(ERR_INVALID_INPUT, OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET6, addr, sizeof(addr))); +} + +TEST(InitUDP, Positive) { + OCDevAddr ipaddr; + int32_t sockfd; + uint8_t addr[20]; + uint8_t ifname[] = "wlan0"; + uint8_t a,b,c,d; + + OCBuildIPv4Address(0,0,0,0, 0, &ipaddr); + EXPECT_EQ(ERR_SUCCESS, OCInitUDP(&ipaddr, &sockfd)); + OCClose(sockfd); + + OCBuildIPv4Address(0,0,0,0, 5678, &ipaddr); + EXPECT_EQ(ERR_SUCCESS, OCInitUDP(&ipaddr, &sockfd)); + OCClose(sockfd); + + OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + sscanf((const char*)addr, "%d.%d.%d.%d", (int*)&a, (int*)&b, (int*)&c, (int*)&d); + OCBuildIPv4Address(a,b,c,d, TEST_PORT_NUM, &ipaddr); + EXPECT_EQ(ERR_SUCCESS, OCInitUDP(&ipaddr, &sockfd)); + OCClose(sockfd); +} + + +TEST(InitUDP, Negative) { + OCDevAddr ipaddr; + int32_t sockfd; + + OCBuildIPv4Address(0,0,0,0, 0, &ipaddr); + EXPECT_EQ(ERR_INVALID_INPUT, OCInitUDP(NULL, &sockfd)); + + EXPECT_EQ(ERR_INVALID_INPUT, OCInitUDP(&ipaddr, NULL)); +} + + + +TEST(InitUDPMulticast, Positive) { + OCDevAddr ipaddr1; + int32_t sfd; + + OCBuildIPv4Address(224, 0, 0, 251, 5353, &ipaddr1); //address to which MEMBERSHIP needs to be added + EXPECT_EQ(ERR_SUCCESS, OCInitUDPMulticast(&ipaddr1, &sfd)); + OCClose(sfd); +} + + +TEST(InitUDPMulticast, Negative) { + OCDevAddr ipaddr1; + int32_t sfd; + + OCBuildIPv4Address(224, 0, 0, 251, 5353, &ipaddr1); //address to which MEMBERSHIP needs to be added + EXPECT_EQ(ERR_INVALID_INPUT, OCInitUDPMulticast(NULL, &sfd)); + EXPECT_EQ(ERR_INVALID_INPUT, OCInitUDPMulticast(&ipaddr1, NULL)); +} + + +TEST(SendToRecvfromUnicast, Positive) { + OCDevAddr ipaddr1, ipaddr2, ipaddr3; + int32_t ssfd, rsfd; + uint8_t addr[20]; + uint8_t ifname[] = "wlan0"; + uint8_t a,b,c,d; + //uint8_t tmp1[512]; + + + OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + sscanf((const char*)addr, "%d.%d.%d.%d", (int*)&a, (int*)&b, (int*)&c, (int*)&d); + + //Create sending socket + OCBuildIPv4Address(a, b, c, d, 0, &ipaddr1); + OCInitUDP(&ipaddr1, &ssfd); + + //Create receiving socket...i.e. bind to the specific port + OCBuildIPv4Address(a,b,c, d+1, TEST_PORT_NUM, &ipaddr2); + OCInitUDP(&ipaddr2, &rsfd); + + //Test 1 -- Send 40 bytes + //Send the packet to ipaddr2(myself:TEST_PORT_NUM) + EXPECT_EQ(buf1_len, OCSendTo(ssfd, buf1, buf1_len, 0, &ipaddr2)); + //Receive the packet + ipaddr3.size = sizeof(ipaddr3.addr); + //EXPECT_EQ(buf1_len, OCRecvFrom(rsfd, tmp1, sizeof(tmp1), 0, &ipaddr3)); + //Compare the received buffer with send buffer + //EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf1, buf1_len)); + + //Test 2 -- Send 1 byte + //Send the packet to ipaddr2(myself:TEST_PORT_NUM) + EXPECT_EQ( 1, OCSendTo(ssfd, buf1, 1, 0, &ipaddr2)); + //Receive the packet + ipaddr3.size = sizeof(ipaddr3.addr); + //EXPECT_EQ( 1, OCRecvFrom(rsfd, tmp1, sizeof(tmp1), 0, &ipaddr3)); + //Compare the received buffer with send buffer + //EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf1, 1)); + + //Test 3 -- Send 320 byte + //Send the packet to ipaddr2(myself:TEST_PORT_NUM) + EXPECT_EQ(buf2_len, OCSendTo(ssfd, buf2, buf2_len, 0, &ipaddr2)); + //Receive the packet + ipaddr3.size = sizeof(ipaddr3.addr); + //EXPECT_EQ(buf2_len, OCRecvFrom(rsfd, tmp1, sizeof(tmp1), 0, &ipaddr3)); + //Compare the received buffer with send buffer + //EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf2, buf2_len)); + + OCClose(ssfd); + OCClose(rsfd); +} + + + +TEST(SendToRecvfromMulticast, Positive) { + OCDevAddr ipaddr1, ipaddr2, ipaddr3, ipaddr4; + int32_t ssfd; + uint8_t tmp1[512]; + + //Create sending socket + OCBuildIPv4Address(0,0,0,0, 5353, &ipaddr1); + OCBuildIPv4Address(224, 0, 0, 251, 5353, &ipaddr2); //address to which MEMBERSHIP needs to be added + OCInitUDPMulticast(&ipaddr2, &ssfd); + + //build the multicast address to which we need to send the datagram + OCBuildIPv4Address(224, 0, 0, 251, 5353, &ipaddr3); + + //Test 1 -- Send 40 bytes + EXPECT_EQ(buf1_len, OCSendTo(ssfd, buf1, buf1_len, 0, &ipaddr3)); + //Receive the packet + ipaddr4.size = sizeof(ipaddr4.addr); + EXPECT_EQ(buf1_len, OCRecvFrom(ssfd, tmp1, sizeof(tmp1), 0, &ipaddr4)); + //Compare the received buffer with send buffer + EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf1, buf1_len)); + + //Test 2 -- Send 1 byte + EXPECT_EQ( 1, OCSendTo(ssfd, buf1, 1, 0, &ipaddr3)); + //Receive the packet + ipaddr4.size = sizeof(ipaddr4.addr); + EXPECT_EQ( 1, OCRecvFrom(ssfd, tmp1, sizeof(tmp1), 0, &ipaddr4)); + //Compare the received buffer with send buffer + EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf1, 1)); + + //Test 3 -- Send 320 byte + EXPECT_EQ(buf2_len, OCSendTo(ssfd, buf2, buf2_len, 0, &ipaddr3)); + //Receive the packet + ipaddr4.size = sizeof(ipaddr4.addr); + EXPECT_EQ(buf2_len, OCRecvFrom(ssfd, tmp1, sizeof(tmp1), 0, &ipaddr3)); + //Compare the received buffer with send buffer + EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf2, buf2_len)); + + OCClose(ssfd); +} + diff --git a/resource/csdk/ocsocket/test/arduino/makefile b/resource/csdk/ocsocket/test/arduino/makefile new file mode 100644 index 000000000..682a5a845 --- /dev/null +++ b/resource/csdk/ocsocket/test/arduino/makefile @@ -0,0 +1,104 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +BUILD := release +PLATFORM := arduinomega +ARDUINO_PORT := /dev/ttyACM0 + +# override with `make PLATFORM=arduinomega ARDUINOWIFI=1` to enable Arduino WiFi shield +ARDUINOWIFI := 0 + +ifeq ($(ARDUINOWIFI),0) + APP_NAME := ocsocket_test + OCSOCKET_CPPOBJ = ocsocket_arduino.o +else + APP_NAME := ocsocket_wifi_test + OCSOCKET_CPPOBJ = ocsocket_arduino_wifi.o +endif + +OBJ_DIR := ./bin + +ROOT_DIR = ../../.. + +include $(ROOT_DIR)/local.properties +include $(ROOT_DIR)/$(PLATFORM).properties + + +#include directories +OCSOCK_DIR = $(ROOT_DIR)/ocsocket +LOGGER_DIR = $(ROOT_DIR)/logger +INC_DIRS = -I$(OCSOCK_DIR)/include/ -I$(LOGGER_DIR)/include + +VPATH := $(SDIR_ARD_PLATFORM):$(LOGGER_DIR)/src:$(OCSOCK_DIR)/src + +CFLAGS := -Os -Wall -c -DTB_LOG + +all: core.a $(APP_NAME).o $(APP_NAME).elf $(APP_NAME).hex + +core.a: $(PLATFORM_OBJS) + $(AR) rcs $@ $^ + $(RANLIB) $@ + +#logger needs to be compiled using C++ compiler +logger.o: logger.c + $(CXX) $(CFLAGS) $(CFLAGS_PLATFORM) $(INC_DIRS) $(INC_DIR_PLATFORM) $< -o $@ + +%.o: %.c + $(CC) $(CFLAGS) $(CFLAGS_PLATFORM) $(INC_DIRS) $(INC_DIR_PLATFORM) $< -o $@ + +%.o: %.cpp + $(CXX) $(CFLAGS) $(CFLAGS_PLATFORM) $(INC_DIRS) $(INC_DIR_PLATFORM) $< -o $@ + +$(APP_NAME).elf: $(APP_NAME).o $(OCSOCKET_CPPOBJ) logger.o core.a + $(CC) -Os -Wl,--gc-sections,--relax $(CFLAGS_PLATFORM) $^ -lm -o $@ + +$(APP_NAME).hex: $(APP_NAME).elf + $(AVR_OBJCOPY) -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 $< $(APP_NAME).eep + $(AVR_OBJCOPY) -O ihex -R .eeprom $< $@ + +install: all + $(AVR_PROGRAMMER) -C$(ARDUINO_DIR)/hardware/tools/avrdude.conf -v -v -v -v -patmega2560 -cstk500v2 -P$(ARDUINO_PORT) -b115200 -D -Uflash:w:$(APP_NAME).hex:i + +.PHONY: clean + +clean: + @rm -f *.o *.d *.elf *.eep *.a *.hex *.bin *.map *- + @rm -rf $(OBJ_DIR) + + + + + + + + + + + + + + + + + + + + + diff --git a/resource/csdk/ocsocket/test/arduino/ocsocket_test.cpp b/resource/csdk/ocsocket/test/arduino/ocsocket_test.cpp new file mode 100644 index 000000000..1271143b4 --- /dev/null +++ b/resource/csdk/ocsocket/test/arduino/ocsocket_test.cpp @@ -0,0 +1,339 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include +#include + +//Mac address of my ethernet shield +static uint8_t ETHERNET_MAC[] = {0x90, 0xA2, 0xDA, 0x0F, 0x2B, 0x72 }; +//IP address of the peer whom I wish to send some data +static uint8_t PEER_IP_ADDR[] = {192, 168, 1, 125}; +static uint8_t MULTICAST_IP_ADDR[] = {224, 0, 1, 187}; + +//Set below to 0 to disable multicast testing +//#define MCAST_TESTING_EN 1 + +#define TEST_NUM_PKTS (20) +#define TEST_PORT_NUM (8888) +#define MAX_BUF_SIZE (256) + +unsigned char TEST_BUF[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, +}; +unsigned int TEST_BUF_LEN = sizeof(TEST_BUF); + +#define PCF(str) ((PROGMEM const char *)(F(str))) + +#define MOD_NAME PCF("ocsocket_test") + +#define VERIFY_SUCCESS(op, res) { if (op == res) {OC_LOG(DEBUG, MOD_NAME, PCF(#op " SUCCEEDED"));} \ + else {OC_LOG(FATAL, MOD_NAME, PCF(#op "!!!! FAILED FAILED FAILED !!!!"));} } + + +//OCGetInterfaceAddress tests +void test10() { + char strAddr[16] = ""; + VERIFY_SUCCESS(OCGetInterfaceAddress(NULL, 0, AF_INET, (uint8_t*)strAddr, 16), ERR_SUCCESS); + OC_LOG(DEBUG, MOD_NAME, PCF("My IP address :")); + OC_LOG_BUFFER(INFO, MOD_NAME, (uint8_t*)strAddr, sizeof(strAddr)); + delay(15000); + VERIFY_SUCCESS(OCGetInterfaceAddress(NULL, 0, AF_INET, NULL, 16), ERR_INVALID_INPUT); + VERIFY_SUCCESS(OCGetInterfaceAddress(NULL, 0, AF_INET, (uint8_t*)strAddr, 10), ERR_INVALID_INPUT); + OC_LOG(DEBUG, MOD_NAME, PCF("test10 - Completed")); +} + +//OCBuildIPv4Address tests +void test20() { + OCDevAddr ipAddr; + VERIFY_SUCCESS(OCBuildIPv4Address( 0, 0, 0, 0, TEST_PORT_NUM, &ipAddr), ERR_SUCCESS); + VERIFY_SUCCESS(OCBuildIPv4Address( 0, 0, 0, 0, TEST_PORT_NUM, NULL), ERR_INVALID_INPUT); + OC_LOG(DEBUG, MOD_NAME, PCF("test20 - Completed")); +} + + +void test30() { + + OCDevAddr ipAddr; + uint8_t a, b, c, d; + uint16_t port; + VERIFY_SUCCESS(OCBuildIPv4Address( 1, 2, 3, 4, TEST_PORT_NUM, &ipAddr), ERR_SUCCESS); + VERIFY_SUCCESS(OCDevAddrToIPv4Addr( &ipAddr, &a, &b, &c, &d), ERR_SUCCESS); + if ((a != 1) || (b != 2) || (c !=3) || (d !=4)) { + OC_LOG(DEBUG, MOD_NAME, PCF("test30 - Failed !!!")); + return; + } + + VERIFY_SUCCESS(OCDevAddrToPort( &ipAddr, &port), ERR_SUCCESS); + if (port != TEST_PORT_NUM) { + OC_LOG(DEBUG, MOD_NAME, PCF("test30 - Failed !!!")); + return; + } + VERIFY_SUCCESS(OCDevAddrToIPv4Addr( NULL, &a, &b, &c, &d), ERR_INVALID_INPUT); + VERIFY_SUCCESS(OCDevAddrToPort( &ipAddr, NULL), ERR_INVALID_INPUT); + OC_LOG(DEBUG, MOD_NAME, PCF("test30 - Completed")); +} + +//OCInitUDP tests +void test40() { + OCDevAddr ipAddr; + int32_t sfd1, sfd2, sfd3, sfd4, sfd5; + + //We should be able to successfully open 4 sockets. + VERIFY_SUCCESS(OCBuildIPv4Address( 0, 0, 0, 0, TEST_PORT_NUM, &ipAddr), ERR_SUCCESS); + VERIFY_SUCCESS(OCInitUDP( &ipAddr, &sfd1), ERR_SUCCESS); + + VERIFY_SUCCESS(OCBuildIPv4Address( 0, 0, 0, 0, TEST_PORT_NUM + 1, &ipAddr), ERR_SUCCESS); + VERIFY_SUCCESS(OCInitUDP( &ipAddr, &sfd2), ERR_SUCCESS); + + VERIFY_SUCCESS(OCBuildIPv4Address( 0, 0, 0, 0, TEST_PORT_NUM + 2, &ipAddr), ERR_SUCCESS); + VERIFY_SUCCESS(OCInitUDP( &ipAddr, &sfd3), ERR_SUCCESS); + + VERIFY_SUCCESS(OCBuildIPv4Address( 0, 0, 0, 0, TEST_PORT_NUM + 3, &ipAddr), ERR_SUCCESS); + VERIFY_SUCCESS(OCInitUDP( &ipAddr, &sfd4), ERR_SUCCESS); + + //5th socket creation call should FAIL + VERIFY_SUCCESS(OCBuildIPv4Address( 0, 0, 0, 0, TEST_PORT_NUM + 4, &ipAddr), ERR_SUCCESS); + VERIFY_SUCCESS(OCInitUDP( &ipAddr, &sfd5), ERR_UNKNOWN); + + VERIFY_SUCCESS(OCClose( sfd4), ERR_SUCCESS); + VERIFY_SUCCESS(OCInitUDP( &ipAddr, &sfd5), ERR_SUCCESS); + + VERIFY_SUCCESS(OCClose( sfd1), ERR_SUCCESS); + VERIFY_SUCCESS(OCClose( sfd2), ERR_SUCCESS); + VERIFY_SUCCESS(OCClose( sfd3), ERR_SUCCESS); + VERIFY_SUCCESS(OCClose( sfd5), ERR_SUCCESS); + OC_LOG(DEBUG, MOD_NAME, PCF("test40 - Completed")); +} + + +//OCInitUDPMulticast tests +void test50() { + OCDevAddr ipAddr; + int32_t sfd1, sfd2; + + VERIFY_SUCCESS(OCBuildIPv4Address( MULTICAST_IP_ADDR[0], MULTICAST_IP_ADDR[1], + MULTICAST_IP_ADDR[2], MULTICAST_IP_ADDR[3], TEST_PORT_NUM, &ipAddr), ERR_SUCCESS); + VERIFY_SUCCESS(OCInitUDPMulticast( &ipAddr, &sfd1), ERR_SUCCESS); + + VERIFY_SUCCESS(OCBuildIPv4Address( 0, 0, 0, 0, TEST_PORT_NUM + 1, &ipAddr), ERR_SUCCESS); + VERIFY_SUCCESS(OCInitUDP( &ipAddr, &sfd2), ERR_SUCCESS); + + VERIFY_SUCCESS(OCClose( sfd1), ERR_SUCCESS); + VERIFY_SUCCESS(OCClose( sfd2), ERR_SUCCESS); + OC_LOG(DEBUG, MOD_NAME, PCF("test50 - Completed")); +} + + +//OCSendTo -- Unicast tests +void test60() { + OCDevAddr ipAddr, peerAddr; + int32_t sfd; + + VERIFY_SUCCESS(OCBuildIPv4Address( 0, 0, 0, 0, TEST_PORT_NUM, &ipAddr), ERR_SUCCESS); + VERIFY_SUCCESS(OCBuildIPv4Address(PEER_IP_ADDR[0], PEER_IP_ADDR[0], + PEER_IP_ADDR[0], PEER_IP_ADDR[0], TEST_PORT_NUM, &peerAddr), ERR_SUCCESS); + + VERIFY_SUCCESS(OCInitUDP( &ipAddr, &sfd), ERR_SUCCESS); + for (int i = 2; i < 300; ) { + VERIFY_SUCCESS(OCSendTo(sfd, TEST_BUF, i, 0, &peerAddr), i); + i = i + 12; + + delay(100); + } + VERIFY_SUCCESS(OCClose( sfd), ERR_SUCCESS); + OC_LOG(DEBUG, MOD_NAME, PCF("test60 - Completed")); +} + + +//OCSendTo -- Multicast tests +void test70() { + OCDevAddr ipAddrMcast; + int32_t sfd; + + VERIFY_SUCCESS(OCBuildIPv4Address( MULTICAST_IP_ADDR[0], MULTICAST_IP_ADDR[1], + MULTICAST_IP_ADDR[2], MULTICAST_IP_ADDR[3], TEST_PORT_NUM, &ipAddrMcast), ERR_SUCCESS); + VERIFY_SUCCESS(OCInitUDPMulticast( &ipAddrMcast, &sfd), ERR_SUCCESS); + for (int i = 2; i < 300; ) { + VERIFY_SUCCESS(OCSendTo(sfd, TEST_BUF, i, 0, &ipAddrMcast), i); + i = i + 12; + + delay(100); + } + VERIFY_SUCCESS(OCClose( sfd), ERR_SUCCESS); + OC_LOG(DEBUG, MOD_NAME, PCF("test70 - Completed")); +} + + + +//End to End - Unicast Send/Recv test +//Start sample app 'sendrecv' on different Linux box. +void test80() { + OCDevAddr ipAddr, peerAddr; + int32_t sfd; + int32_t recvLen; + uint8_t buf[MAX_BUF_SIZE]; + uint8_t pktrecv = 0; + + //Unicast + VERIFY_SUCCESS(OCBuildIPv4Address( 0, 0, 0, 0, TEST_PORT_NUM, &ipAddr), ERR_SUCCESS); + VERIFY_SUCCESS(OCInitUDP( &ipAddr, &sfd), ERR_SUCCESS); + + do { + recvLen = OCRecvFrom(sfd, buf, MAX_BUF_SIZE, 0, &peerAddr); + if (recvLen > 0) { + pktrecv++; + OC_LOG(DEBUG, MOD_NAME, PCF("Rcvd data from :")); + OC_LOG_BUFFER(INFO, MOD_NAME, peerAddr.addr, peerAddr.size); + OC_LOG(DEBUG, MOD_NAME, PCF("Data Length :")); + OC_LOG_BUFFER(INFO, MOD_NAME, (uint8_t*)&recvLen, sizeof(recvLen)); + + VERIFY_SUCCESS(OCSendTo(sfd, buf, recvLen, 0, &peerAddr), recvLen); + } else { + OC_LOG(DEBUG, MOD_NAME, PCF("No data received")); + } + delay(500); //delay secs + } while (pktrecv < TEST_NUM_PKTS); + + VERIFY_SUCCESS(OCClose(sfd), ERR_SUCCESS); + OC_LOG(DEBUG, MOD_NAME, PCF("test80 - Completed")); +} + + +//End to End - Multicast Send/Recv test +//Start sample app 'sendrecv' on different Linux box. +void test90() { + OCDevAddr ipAddrMcast, peerAddr; + int32_t sfd; + int32_t recvLen; + uint8_t buf[MAX_BUF_SIZE]; + uint8_t pktrecv = 0; + + //Multicast + VERIFY_SUCCESS(OCBuildIPv4Address( MULTICAST_IP_ADDR[0], MULTICAST_IP_ADDR[1], + MULTICAST_IP_ADDR[2], MULTICAST_IP_ADDR[3], TEST_PORT_NUM, &ipAddrMcast), ERR_SUCCESS); + VERIFY_SUCCESS(OCInitUDPMulticast( &ipAddrMcast, &sfd), ERR_SUCCESS); + + do { + + recvLen = OCRecvFrom(sfd, buf, MAX_BUF_SIZE, 0, &peerAddr); + if (recvLen > 0) { + pktrecv++; + OC_LOG(DEBUG, MOD_NAME, PCF("Rcvd data from :")); + OC_LOG_BUFFER(INFO, MOD_NAME, peerAddr.addr, peerAddr.size); + OC_LOG(DEBUG, MOD_NAME, PCF("Data Length :")); + OC_LOG_BUFFER(INFO, MOD_NAME, (uint8_t*)&recvLen, sizeof(recvLen)); + + VERIFY_SUCCESS(OCSendTo(sfd, buf, recvLen, 0, &ipAddrMcast), recvLen); + } else { + OC_LOG(DEBUG, MOD_NAME, PCF("No data received")); + } + delay(500); //delay secs + } while (pktrecv < TEST_NUM_PKTS); + + VERIFY_SUCCESS(OCClose(sfd), ERR_SUCCESS); + OC_LOG(DEBUG, MOD_NAME, PCF("test90 - Completed")); +} + + + +//End to End - 'Simultaneous' Unicast-Multicast Send/Recv test +//This tests if Arduino Wiznet shield can open 2 independent sockets listening on same port: +// one for unicast traffic and another for multicast traffic. +//Start sample app 'sendrecv' on different Linux box. +void test100() { + //TBD + //TBD + //TBD +} + + + + + +void setup() { + + Serial.begin(115200); + + Serial.println("Trying to get an IP address using DHCP"); + if (Ethernet.begin(ETHERNET_MAC) == 0) { + Serial.println("Failed to configure Ethernet using DHCP"); + } +} + +void loop() { + test10(); + test20(); + test30(); + test40(); + test50(); + test60(); //SendTo --Unicast + test70(); //SendTo --Multicast + test80(); //End-to-End --Unicast + delay(5000); + test90(); //End-to-End --Multicast + + do { + OC_LOG(DEBUG, MOD_NAME, PCF("All tests Completed")); + delay(10000); + } while (1); +} + + diff --git a/resource/csdk/ocsocket/test/arduino/ocsocket_wifi_test.cpp b/resource/csdk/ocsocket/test/arduino/ocsocket_wifi_test.cpp new file mode 100644 index 000000000..0138afbf8 --- /dev/null +++ b/resource/csdk/ocsocket/test/arduino/ocsocket_wifi_test.cpp @@ -0,0 +1,204 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include +#include +#include + +/// WiFi Shield firmware with Intel patches +static const char INTEL_WIFI_SHIELD_FW_VER[] = "1.2.0"; + +/// IP address of the peer whom I wish to send/recv some data +static uint8_t PEER_IP_ADDR[] = {192, 168, 1, 132}; + +/// Port number of the peer whom I wish to send/recv some data +#define TEST_PORT_NUM (4097) + +/// Max buffer size +#define MAX_BUF_SIZE (1024) + +/// Some test bytes to send to the peer +unsigned char TEST_BUF[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, +}; +unsigned int TEST_BUF_LEN = sizeof(TEST_BUF); + +#define MOD_NAME PCF("ocsocket_test") + +#define VERIFY_SUCCESS(op, res) { if (op == res) {OC_LOG(DEBUG, MOD_NAME, PCF(#op " SUCCEEDED"));} \ + else {OC_LOG(FATAL, MOD_NAME, PCF(#op "!!!! FAILED FAILED FAILED !!!!"));} } + +/// WiFi network info and credentials +char ssid[] = "mDNSAP"; +char pass[] = "letmein9"; +int status = WL_IDLE_STATUS; + +//Start sample app 'sendrecv' on different Linux box. +void SendReceiveTest() +{ + Serial.println("entering SendReceiveTest..."); + OCDevAddr ipAddr, peerAddr, recvAddr; + int32_t sfd; + int32_t recvLen; + uint8_t buf[MAX_BUF_SIZE]; + uint16_t recvPort; + + VERIFY_SUCCESS(OCBuildIPv4Address( 0, 0, 0, 0, TEST_PORT_NUM, &ipAddr), ERR_SUCCESS); + VERIFY_SUCCESS(OCBuildIPv4Address(PEER_IP_ADDR[0], PEER_IP_ADDR[1], + PEER_IP_ADDR[2], PEER_IP_ADDR[3], TEST_PORT_NUM, &peerAddr), ERR_SUCCESS); + VERIFY_SUCCESS(OCInitUDP( &ipAddr, &sfd), ERR_SUCCESS); + OC_LOG(DEBUG, MOD_NAME, PCF("Peer Addr :")); + OC_LOG_BUFFER(INFO, MOD_NAME, peerAddr.addr, peerAddr.size); + for (int i = 0; i < 300; i++) + { + + OC_LOG_V(DEBUG, MOD_NAME, "--------------------- i --------------- %d", i); + VERIFY_SUCCESS(OCSendTo(sfd, TEST_BUF, i + 10, 0, &peerAddr), i+10); + + delay(2000); + recvLen = OCRecvFrom(sfd, buf, MAX_BUF_SIZE, 0, &recvAddr); + if (recvLen > 0) + { + OC_LOG(DEBUG, MOD_NAME, PCF("Rcvd data from :")); + OC_LOG_BUFFER(INFO, MOD_NAME, recvAddr.addr, recvAddr.size); + OCDevAddrToPort(&recvAddr, &recvPort); + OC_LOG_V(DEBUG, MOD_NAME, "Recv Data from Port %hu", recvPort); + OC_LOG(DEBUG, MOD_NAME, PCF("Data Length :")); + OC_LOG_BUFFER(INFO, MOD_NAME, (uint8_t*)&recvLen, sizeof(recvLen)); + OC_LOG(DEBUG, MOD_NAME, PCF("Data :")); + if (recvLen < 255) + { + OC_LOG_BUFFER(INFO, MOD_NAME, buf, recvLen); + } + else + { + int idx = 0; + int rem = recvLen; + do { + if (rem > 255) + { + OC_LOG_BUFFER(INFO, MOD_NAME, buf + idx, 255); + rem = rem - 255; + } + else + { + OC_LOG_BUFFER(INFO, MOD_NAME, buf + idx, rem); + rem = 0; + } + idx = idx + 255; + }while(rem > 0); + } + + } + } + VERIFY_SUCCESS(OCClose( sfd), ERR_SUCCESS); + OC_LOG(DEBUG, MOD_NAME, PCF("WifiTest - Completed")); + +} +void setup() +{ + Serial.begin(115200); + Serial.println("WiFi test starting..."); + + // check for the presence of the shield: + if (WiFi.status() == WL_NO_SHIELD) + { + Serial.println("WiFi shield not present"); + // don't continue: + while(true); + } + + Serial.print("WiFi version: "); + Serial.println(WiFi.firmwareVersion()); + + if (strcmp(WiFi.firmwareVersion(), INTEL_WIFI_SHIELD_FW_VER) != 0) + { + Serial.println("!!!!! Upgrade WiFi Shield Firmware version !!!!!!"); + } + + // attempt to connect to Wifi network: + while ( status != WL_CONNECTED) { + Serial.print("Attempting to connect to SSID: "); + Serial.println(ssid); + status = WiFi.begin(ssid,pass); + + // wait 10 seconds for connection: + delay(10000); + } + Serial.println("Connected to wifi"); + + IPAddress ip = WiFi.localIP(); + Serial.print("IP Address: "); + Serial.println(ip); +} + +void loop() { + Serial.println("entering loop..."); + SendReceiveTest(); + delay(5000); + + do { + OC_LOG(DEBUG, MOD_NAME, PCF("All tests Completed")); + delay(10000); + } while (1); +} + + diff --git a/resource/csdk/ocsocket/test/linux/makefile b/resource/csdk/ocsocket/test/linux/makefile new file mode 100644 index 000000000..adf6abcf7 --- /dev/null +++ b/resource/csdk/ocsocket/test/linux/makefile @@ -0,0 +1,65 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +PLATFORM := linux + +ROOT_DIR = ../../.. +include $(ROOT_DIR)/local.properties + +OCSOCK_DIR = $(ROOT_DIR)/ocsocket +OC_LOG_DIR = $(ROOT_DIR)/../oc_logger +LOGGER_DIR = $(ROOT_DIR)/logger +BIN_DIR = $(OCSOCK_DIR)/bin/linux/ +OBJ_DIR = $(OCSOCK_DIR)/obj/linux/ +INC_DIRS = -I$(OCSOCK_DIR)/include/ -I$(LOGGER_DIR)/include -I$(OC_LOG_DIR)/include + +CXX = g++ +CC = gcc + +CFLAGS += -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions -DTB_LOG +DEP_LIBS = $(GTEST_LINUX_DIR)/lib/.libs/libgtest_main.a $(GTEST_LINUX_DIR)/lib/.libs/libgtest.a +VPATH = $(OCSOCK_DIR)/src:$(LOGGER_DIR)/src + +TEST_APP = ocsocket_gtest +COBJ = logger.o ocsocket.o + +all: $(TEST_APP) + mkdir -p $(BIN_DIR) + cp $(TEST_APP) $(BIN_DIR) + mkdir -p $(OBJ_DIR) + cp *.o $(OBJ_DIR) + +%.o: %.c + $(CC) -c $(CFLAGS) $(INC_DIRS) $< -o $@ + +$(TEST_APP).o: $(TEST_APP).cpp + $(CXX) -c $(CFLAGS) -pthread $(INC_DIRS) -I$(GTEST_LINUX_DIR)/include -o $@ $< + +$(TEST_APP): $(TEST_APP).o $(DEP_LIBS) $(COBJ) + $(CXX) -Os -Wl,--gc-sections $^ -lpthread -o $@ + +.PHONY: clean + +clean: + rm -f *.o $(TEST_APP) + rm -fr $(BIN_DIR) + rm -fr $(OBJ_DIR) + + diff --git a/resource/csdk/ocsocket/test/linux/ocsocket_gtest.cpp b/resource/csdk/ocsocket/test/linux/ocsocket_gtest.cpp new file mode 100644 index 000000000..b6c98729c --- /dev/null +++ b/resource/csdk/ocsocket/test/linux/ocsocket_gtest.cpp @@ -0,0 +1,318 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +#include +#include +#include + +#define MOD_NAME ("ocsocket_test") + +#define TEST_PORT_NUM (8888) + +unsigned char buf1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01 +}; +unsigned int buf1_len = sizeof(buf1); + + +unsigned char buf2[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, + 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, +}; +unsigned int buf2_len = sizeof(buf2); + +TEST(BuildIPv4, Positive) { + OCDevAddr ipaddr; + EXPECT_EQ(ERR_SUCCESS, OCBuildIPv4Address(224,0,0,251,5353, &ipaddr)); +} + + +TEST(BuildIPv4, InvalidInput) { + EXPECT_EQ(ERR_INVALID_INPUT, OCBuildIPv4Address(24,24,24,24,2424, NULL)); + EXPECT_EQ(ERR_INVALID_INPUT, OCBuildIPv4Address(-24,24,-24,24,2424, NULL)); +} + +TEST(DevAddrToIPv4Addr, Positive) { + OCDevAddr ipaddr; + uint8_t a,b,c,d; + uint16_t port; + OCBuildIPv4Address(1,2,3,4,5353, &ipaddr); + EXPECT_EQ(ERR_SUCCESS, OCDevAddrToIPv4Addr(&ipaddr, &a, &b, &c, &d )); + EXPECT_TRUE((a == 1) && (b == 2) && (c == 3) && (d ==4)); + EXPECT_EQ(ERR_SUCCESS, OCDevAddrToPort(&ipaddr, &port )); + EXPECT_TRUE(port == 5353); +} + + +TEST(DevAddrToIPv4Addr, InvalidInput) { + OCDevAddr ipaddr; + uint8_t a,b,c,d; + uint16_t port; + OCBuildIPv4Address(1,2,3,4,5353, &ipaddr); + EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToIPv4Addr(NULL, &a, &b, &c, &d )); + EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToIPv4Addr(&ipaddr, NULL, &b, &c, &d )); + EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToIPv4Addr(NULL, NULL, &b, &c, &d )); + + EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToPort(NULL, &port )); + EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToPort(&ipaddr, NULL )); + EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToPort(NULL, NULL )); +} + + + + +TEST(GetInterfaceAddress, Positive) { + uint8_t addr[20]; + uint8_t ifname[] = "eth0"; + EXPECT_EQ(ERR_SUCCESS, OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, addr, sizeof(addr))); + printf("IPv4 Address: %s\n", addr); + EXPECT_EQ(ERR_SUCCESS, OCGetInterfaceAddress( NULL, 0, AF_INET, addr, sizeof(addr))); + printf("IPv4 Address: %s\n", addr); +} + +TEST(GetInterfaceAddress, Negative) { + uint8_t addr[20]; + uint8_t ifname[] = "ethxx"; + EXPECT_EQ(ERR_UNKNOWN, OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, addr, sizeof(addr))); + EXPECT_EQ(ERR_INVALID_INPUT, OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, NULL, sizeof(addr))); + EXPECT_EQ(ERR_UNKNOWN, OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, addr, 0)); + EXPECT_EQ(ERR_INVALID_INPUT, OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET6, addr, sizeof(addr))); +} + +TEST(InitUDP, Positive) { + OCDevAddr ipaddr; + int32_t sockfd; + uint8_t addr[20]; + uint8_t ifname[] = "eth0"; + uint8_t a,b,c,d; + + OCBuildIPv4Address(0,0,0,0, 0, &ipaddr); + EXPECT_EQ(ERR_SUCCESS, OCInitUDP(&ipaddr, &sockfd)); + OCClose(sockfd); + + OCBuildIPv4Address(0,0,0,0, 5678, &ipaddr); + EXPECT_EQ(ERR_SUCCESS, OCInitUDP(&ipaddr, &sockfd)); + OCClose(sockfd); + + OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + sscanf((const char*)addr, "%d.%d.%d.%d", (int*)&a, (int*)&b, (int*)&c, (int*)&d); + OCBuildIPv4Address(a,b,c,d, TEST_PORT_NUM, &ipaddr); + EXPECT_EQ(ERR_SUCCESS, OCInitUDP(&ipaddr, &sockfd)); + OCClose(sockfd); +} + + +TEST(InitUDP, Negative) { + OCDevAddr ipaddr; + int32_t sockfd; + + OCBuildIPv4Address(0,0,0,0, 0, &ipaddr); + EXPECT_EQ(ERR_INVALID_INPUT, OCInitUDP(NULL, &sockfd)); + + EXPECT_EQ(ERR_INVALID_INPUT, OCInitUDP(&ipaddr, NULL)); +} + + + +TEST(InitUDPMulticast, Positive) { + OCDevAddr ipaddr1; + int32_t sfd; + + OCBuildIPv4Address(224, 0, 0, 251, 5353, &ipaddr1); //address to which MEMBERSHIP needs to be added + EXPECT_EQ(ERR_SUCCESS, OCInitUDPMulticast(&ipaddr1, &sfd)); + OCClose(sfd); +} + + +TEST(InitUDPMulticast, Negative) { + OCDevAddr ipaddr1; + int32_t sfd; + + OCBuildIPv4Address(224, 0, 0, 251, 5353, &ipaddr1); //address to which MEMBERSHIP needs to be added + EXPECT_EQ(ERR_INVALID_INPUT, OCInitUDPMulticast(NULL, &sfd)); + EXPECT_EQ(ERR_INVALID_INPUT, OCInitUDPMulticast(&ipaddr1, NULL)); +} + + +TEST(SendToRecvfromUnicast, Positive) { + OCDevAddr ipaddr1, ipaddr2, ipaddr3; + int32_t ssfd, rsfd; + uint8_t addr[20]; + uint8_t ifname[] = "eth0"; + uint8_t a,b,c,d; + uint8_t tmp1[512]; + + //Create sending socket + OCBuildIPv4Address(0,0,0,0, 0, &ipaddr1); + OCInitUDP(&ipaddr1, &ssfd); + + //Create receiving socket...i.e. bind to the specific port + OCBuildIPv4Address(0,0,0,0, TEST_PORT_NUM, &ipaddr2); + OCInitUDP(&ipaddr2, &rsfd); + + //Since this is a Unit test, we will attempt to send message to ourself at a specific port + OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + sscanf((const char*)addr, "%d.%d.%d.%d", (int*)&a, (int*)&b, (int*)&c, (int*)&d); + OCBuildIPv4Address(a,b,c,d, TEST_PORT_NUM, &ipaddr2); + + //Test 1 -- Send 40 bytes + //Send the packet to ipaddr2(myself:TEST_PORT_NUM) + EXPECT_EQ(buf1_len, OCSendTo(ssfd, buf1, buf1_len, 0, &ipaddr2)); + //Receive the packet + ipaddr3.size = sizeof(ipaddr3.addr); + EXPECT_EQ(buf1_len, OCRecvFrom(rsfd, tmp1, sizeof(tmp1), 0, &ipaddr3)); + //Compare the received buffer with send buffer + EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf1, buf1_len)); + + //Test 2 -- Send 1 byte + //Send the packet to ipaddr2(myself:TEST_PORT_NUM) + EXPECT_EQ( 1, OCSendTo(ssfd, buf1, 1, 0, &ipaddr2)); + //Receive the packet + ipaddr3.size = sizeof(ipaddr3.addr); + EXPECT_EQ( 1, OCRecvFrom(rsfd, tmp1, sizeof(tmp1), 0, &ipaddr3)); + //Compare the received buffer with send buffer + EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf1, 1)); + + //Test 3 -- Send 320 byte + //Send the packet to ipaddr2(myself:TEST_PORT_NUM) + EXPECT_EQ(buf2_len, OCSendTo(ssfd, buf2, buf2_len, 0, &ipaddr2)); + //Receive the packet + ipaddr3.size = sizeof(ipaddr3.addr); + EXPECT_EQ(buf2_len, OCRecvFrom(rsfd, tmp1, sizeof(tmp1), 0, &ipaddr3)); + //Compare the received buffer with send buffer + EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf2, buf2_len)); + + OCClose(ssfd); + OCClose(rsfd); +} + + +TEST(SendToRecvfromMulticast, Positive) { + OCDevAddr ipaddr1, ipaddr2, ipaddr3, ipaddr4; + int32_t ssfd; + uint8_t tmp1[512]; + + //Create sending socket + OCBuildIPv4Address(0,0,0,0, 5353, &ipaddr1); + OCBuildIPv4Address(224, 0, 0, 251, 5353, &ipaddr2); //address to which MEMBERSHIP needs to be added + OCInitUDPMulticast(&ipaddr2, &ssfd); + + //build the multicast address to which we need to send the datagram + OCBuildIPv4Address(224, 0, 0, 251, 5353, &ipaddr3); + + //Test 1 -- Send 40 bytes + EXPECT_EQ(buf1_len, OCSendTo(ssfd, buf1, buf1_len, 0, &ipaddr3)); + //Receive the packet + ipaddr4.size = sizeof(ipaddr4.addr); + EXPECT_EQ(buf1_len, OCRecvFrom(ssfd, tmp1, sizeof(tmp1), 0, &ipaddr4)); + //Compare the received buffer with send buffer + EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf1, buf1_len)); + + //Test 2 -- Send 1 byte + EXPECT_EQ( 1, OCSendTo(ssfd, buf1, 1, 0, &ipaddr3)); + //Receive the packet + ipaddr4.size = sizeof(ipaddr4.addr); + EXPECT_EQ( 1, OCRecvFrom(ssfd, tmp1, sizeof(tmp1), 0, &ipaddr4)); + //Compare the received buffer with send buffer + EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf1, 1)); + + //Test 3 -- Send 320 byte + EXPECT_EQ(buf2_len, OCSendTo(ssfd, buf2, buf2_len, 0, &ipaddr3)); + //Receive the packet + ipaddr4.size = sizeof(ipaddr4.addr); + EXPECT_EQ(buf2_len, OCRecvFrom(ssfd, tmp1, sizeof(tmp1), 0, &ipaddr3)); + //Compare the received buffer with send buffer + EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf2, buf2_len)); + + OCClose(ssfd); +} + +TEST(GetSocketInfo, Positive) { + OCDevAddr ipaddr; + int32_t sockfd; + uint8_t addr[20]; + uint8_t ifname[] = "eth0"; + uint16_t port; + uint8_t a,b,c,d; + + OCBuildIPv4Address(0,0,0,0, 0, &ipaddr); + EXPECT_EQ(ERR_SUCCESS, OCInitUDP(&ipaddr, &sockfd)); + EXPECT_EQ(ERR_SUCCESS, OCGetSocketInfo(sockfd, &port)); + OC_LOG_V(DEBUG, MOD_NAME, "Port %d", port); + OCClose(sockfd); + + OCBuildIPv4Address(0,0,0,0, 5678, &ipaddr); + EXPECT_EQ(ERR_SUCCESS, OCInitUDP(&ipaddr, &sockfd)); + EXPECT_EQ(ERR_SUCCESS, OCGetSocketInfo(sockfd, &port)); + OC_LOG_V(DEBUG, MOD_NAME, "Port %d", port); + EXPECT_TRUE(port == 5678); + OCClose(sockfd); + + OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + sscanf((const char*)addr, "%d.%d.%d.%d", (int*)&a, (int*)&b, (int*)&c, (int*)&d); + OCBuildIPv4Address(a,b,c,d, TEST_PORT_NUM, &ipaddr); + EXPECT_EQ(ERR_SUCCESS, OCInitUDP(&ipaddr, &sockfd)); + EXPECT_EQ(ERR_SUCCESS, OCGetSocketInfo(sockfd, &port)); + OC_LOG_V(DEBUG, MOD_NAME, "Port %d", port); + EXPECT_TRUE(port == TEST_PORT_NUM); + OCClose(sockfd); +} diff --git a/resource/csdk/ocsocket/test/makefile b/resource/csdk/ocsocket/test/makefile new file mode 100644 index 000000000..8d6598e23 --- /dev/null +++ b/resource/csdk/ocsocket/test/makefile @@ -0,0 +1,36 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +all: + $(MAKE) -C android all + $(MAKE) -C linux all + $(MAKE) -C arduino all + +install: all + $(MAKE) -C android install + $(MAKE) -C arduino install + +.PHONY: clean + +clean: + $(MAKE) -C android clean + $(MAKE) -C linux clean + $(MAKE) -C arduino clean + diff --git a/resource/csdk/ocsocket/test/sendrecv.cpp b/resource/csdk/ocsocket/test/sendrecv.cpp new file mode 100644 index 000000000..e657d6bcf --- /dev/null +++ b/resource/csdk/ocsocket/test/sendrecv.cpp @@ -0,0 +1,226 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +//static uint8_t MULTICAST_IP_ADDR[] = {224, 0, 1, 187}; +//static uint32_t TEST_PORT_NUM = 8888; + + +#define MAX_BUF (1024) +uint8_t g_bfr[] = { + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, + }; +uint32_t g_bfrlen = sizeof(g_bfr); + +int multicast_test(int argc, char* argv[]) +{ + int32_t sfd; + char loopch=0; + int set_option_on = 1; + struct sockaddr_in mcastsock = {0}, peer; + uint8_t recvbuf[MAX_BUF]; + uint32_t len, bufLen, fromlen; + + printf("Running multicast tests\n"); + + bufLen = atoi(argv[4]); + if (bufLen > g_bfrlen) { + printf("Warning: Input buffer provided too big. Trimming to supported size\n"); + bufLen = g_bfrlen; + } + + //Create a datagram socket on which to send. + sfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sfd < 0) { + printf("Error in opening datagram socket"); + return -1; + } + + //Initialize the group sockaddr structure with a + mcastsock.sin_family = AF_INET; + mcastsock.sin_addr.s_addr = inet_addr(argv[2]); + mcastsock.sin_port = htons(atoi(argv[3])); + + //Disable loopback so you do not receive your own datagrams. + if (setsockopt(sfd, IPPROTO_IP, IP_MULTICAST_LOOP, + (char *)&loopch, sizeof(loopch)) < 0) { + //printf("setting IP_MULTICAST_LOOP:"); + close(sfd); + return -1; + } + + //Play nice with other processes who may be listening at this + //port/IP address combination + if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (char*) &set_option_on, + sizeof(set_option_on)) < 0) { + //printf("setting SO_REUSEADDR:"); + close(sfd); + return -1; + } + + if (bind(sfd, (sockaddr*)&mcastsock, sizeof(mcastsock)) < 0) { + printf("bind returns error"); + close(sfd); + return -1; + } + + struct ip_mreq mreq = {0}; + mreq.imr_interface.s_addr = htonl(INADDR_ANY); + mreq.imr_multiaddr.s_addr = mcastsock.sin_addr.s_addr; + if ((setsockopt(sfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq))) < 0) { + printf("multicast -- adding membership failed"); + close(sfd); + return -1; + } + + do { + len = sendto(sfd, g_bfr, bufLen, 0, + (struct sockaddr*)&mcastsock, sizeof(mcastsock)); + if (len > 0) { + printf ("Send %d bytes to %s\n", len, inet_ntoa(mcastsock.sin_addr)); + } + + fromlen = sizeof(peer); + len = recvfrom(sfd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*)&peer, &fromlen); + if (len > 0) { + printf("Rcvd %d bytes from %s\n", len, inet_ntoa(peer.sin_addr)); + } + + sleep(1); + } while (true); + + close(sfd); + return 0; +} + + + + +int unicast_test(int argc, char* argv[]) +{ + int32_t sfd; + struct sockaddr_in sa, peer; + uint8_t recvbuf[MAX_BUF]; + uint32_t len, bufLen, fromlen; + + printf("Running unicast tests\n"); + + bufLen = atoi(argv[4]); + if (bufLen > g_bfrlen) { + printf("Warning: Input buffer provided too big. Trimming to supported size\n"); + bufLen = g_bfrlen; + } + + sfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sfd < 0) { + printf("socket API ret val %d\n", sfd); + return -1; + } + + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = INADDR_ANY; + sa.sin_port = htons(atoi(argv[3])); + + if (bind(sfd, (struct sockaddr*)&sa, sizeof(sa)) < 0) { + printf("bin API ret val %d\n", sfd); + close(sfd); + return -1; + } + + peer.sin_family = AF_INET; + inet_aton(argv[2], &peer.sin_addr); + peer.sin_port = htons(atoi(argv[3])); + + do { + len = sendto(sfd, g_bfr, bufLen, 0, + (struct sockaddr*)&peer, sizeof(peer)); + + if (len > 0) { + printf ("Send %d bytes to %s\n", len, inet_ntoa(peer.sin_addr)); + } + + fromlen = sizeof(peer); + len = recvfrom(sfd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*)&peer, &fromlen); + if (len > 0) { + printf("Rcvd %d bytes from %s\n", len, inet_ntoa(peer.sin_addr)); + } + + sleep(1); + } while(true); + + close(sfd); + return 0; +} + + + + +int main(int argc, char * argv[]) +{ + + if (argc < 5) { + printf("Usage: sendrecv \n"); + return -1; + } + + if (argv[1][0] == 'u') { + unicast_test(argc, argv); + } else { + multicast_test(argc, argv); + } + + return 0; +} diff --git a/resource/csdk/ocsocket/test/sendrecv_README.txt b/resource/csdk/ocsocket/test/sendrecv_README.txt new file mode 100644 index 000000000..2c4553058 --- /dev/null +++ b/resource/csdk/ocsocket/test/sendrecv_README.txt @@ -0,0 +1,3 @@ +sendrecv.cpp is a test application for verifying the end to end test for Arduino/Android platforms. +To compile: + g++ -o sendrecv sendrecv.cpp diff --git a/resource/csdk/stack/README b/resource/csdk/stack/README new file mode 100644 index 000000000..965b4766a --- /dev/null +++ b/resource/csdk/stack/README @@ -0,0 +1,45 @@ +Build notes + +//------------------------------------------------- +// NOTICE - Transition to SCONS +//------------------------------------------------- + +The IoTivity build system is transitioning to SCONS. Although the +makefiles are still available (until v1.0) and some developers are +still using them, they are currently no longer supported. To learn more +about building using SCONS see Readme.scons.txt in the repository root +directory. The build steps used in continuous integration can be found +in auto_build.sh which is also in the the repository root directory. + +//------------------------------------------------- +// Linux +//------------------------------------------------- +To build, run +make + +To enable logging, ensure that +-D TB_LOG +is set in the compiler flags + +//------------------------------------------------- +// Android +//------------------------------------------------- +To enable logging for Android, TB_LOG should be defined in the ./jni/Android.mk file as + +LOCAL_CFLAGS := -DTB_LOG + +//------------------------------------------------- +// Arduino +//------------------------------------------------- +To enable the logger for Arduino, TB_LOG should be defined in +Properties|C/C++ Build|Settings|Tool Settings|AVR Compiler|Symbols +and +Properties|C/C++ Build|Settings|Tool Settings|AVR C++ Compiler|Symbols + +Note: when building for Arduino, force the compiler to use avr-g++ to build logger.c. Or rename logger.c to logger.cpp. + +Note: when building for Arduino, several warnings are generated when trying to place strings in +PROGMEM +"warning: only initialized variables can be placed into program memory area" +This appears to be a known gcc bug - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734 + diff --git a/resource/csdk/stack/include/internal/occlientcb.h b/resource/csdk/stack/include/internal/occlientcb.h new file mode 100644 index 000000000..67c58a9e1 --- /dev/null +++ b/resource/csdk/stack/include/internal/occlientcb.h @@ -0,0 +1,195 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// + +#ifndef OC_CLIENT_CB +#define OC_CLIENT_CB + +#include +#include +#include + +typedef struct OCPresence { + // This is the TTL associated with presence + uint32_t TTL; + uint32_t * timeOut; + uint32_t TTLlevel; +}OCPresence; + +typedef struct OCMulticastNode { + unsigned char * uri; + uint32_t nonce; + struct OCMulticastNode * next; +} OCMulticastNode; + +extern OCMulticastNode * mcPresenceNodes; + +typedef struct ClientCB { + // callback method defined in application address space + OCClientResponseHandler callBack; + // callback context data + void * context; + // callback method to delete context data + OCClientContextDeleter deleteCallback; + // when a response is recvd with this token, above callback will be invoked + OCCoAPToken token; + // Invocation handle tied to original call to OCDoResource() + OCDoHandle handle; + // This is used to determine if all responses should be consumed or not. + // (For now, only pertains to OC_REST_OBSERVE_ALL Vs. OC_REST_OBSERVE functionality) + OCMethod method; + // This is the sequence identifier the server applies to the invocation tied to 'handle'. + uint32_t sequenceNumber; + // This is the request uri associated with the call back + unsigned char * requestUri; + // Struct to hold TTL info for presence + #ifdef WITH_PRESENCE + OCPresence * presence; + OCResourceType * filterResourceType; + #endif + // next node in this list + struct ClientCB *next; +} ClientCB; + +extern struct ClientCB *cbList; + +//-- AddClientCB ----------------------------------------------------------- +/** @ingroup ocstack + * + * This method is used to add a client callback method in cbList. + * + * @param[out] clientCB + * The resulting node from making this call. Null if out of memory. + * @param[in] cb + * address to client callback function. + * @param[in] token + * identifier for OTA CoAP comms. + * @param[in] handle + * Masked in the public API as an 'invocation handle' - Used for callback management. + * @param[in] requestUri + * the resource uri of the request. + * @param[in] resourceType + * the resourceType associated with a presence request. + * + * @brief If the handle you're looking for does not exist, the stack will reply with a RST message. + * + * @retval OC_STACK_OK for Success, otherwise some error value + */ +//------------------------------------------------------------------------ +OCStackResult AddClientCB(ClientCB** clientCB, OCCallbackData* cbData, + OCCoAPToken * token, OCDoHandle *handle, OCMethod method, + unsigned char * requestUri, unsigned char * resourceType); + +//-- DeleteClientCB ----------------------------------------------------------- +/** @ingroup ocstack + * + * This method is used to remove a callback node from cbList. + * + * @param[in] cbNode + * address to client callback node. + */ +//------------------------------------------------------------------------ +void DeleteClientCB(ClientCB *cbNode); + + +//-- GetClientCB --------------------------------------------------------- +/** @ingroup ocstack + * + * This method is used to search a cb node in cbList. + * + * @param[in] token + * token to search for. + * @param[in] handle + * handle to search for. + * @param[in] requestUri + * Uri to search for. + * + * @brief You can search by token OR by handle. Not both. + * + * @retval address of the node if found, otherwise NULL + */ +//------------------------------------------------------------------------ +ClientCB* GetClientCB(OCCoAPToken * token, OCDoHandle handle, unsigned char * requestUri); + + +/** + * Inserts a new resource type filter into this clientCB node. + * + * @param cbNode - the node to add the new resourceType filter to + * @param resourceTypeName - the value to create the new resourceType filter from + * + * @return + * OC_STACK_OK on success + * OC_STACK_ERROR with invalid parameters + * OC_STACK_NO_MEMORY when out of memory + */ +OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, const char * resourceTypeName); + +//-- DeleteClientCBList -------------------------------------------------- +/** @ingroup ocstack + * + * This method is used to clear the cbList. + * + */ +//------------------------------------------------------------------------ +void DeleteClientCBList(); + +//-- FindAndDeleteClientCB ----------------------------------------------- +/** @ingroup ocstack + * + * This method is used to verify the presence of a cb node in cbList + * and then delete it. + * + * @param[in] cbNode + * address to client callback node. + */ +//------------------------------------------------------------------------ +void FindAndDeleteClientCB(ClientCB * cbNode); + +/** @ingroup ocstack + * + * This method is used to search a multicast presence node from list. + * + * @param[in] uri + * the uri of the request. + * + * @return OCMulticastNode + * The resulting node from making this call. Null if doesn't exist. + */ +//------------------------------------------------------------------------ +OCMulticastNode* GetMCPresenceNode(unsigned char * uri); + +/** @ingroup ocstack + * + * This method is used to add a multicast presence node to the list. + * + * @param[out] outnode + * The resulting node from making this call. Null if out of memory. + * @param[in] uri + * the uri of the server. + * @param[in] nonce + * current nonce for the server + * + * @return OC_STACK_OK for Success, otherwise some error value + */ +//------------------------------------------------------------------------ +OCStackResult AddMCPresenceNode(OCMulticastNode** outnode, unsigned char* uri, uint32_t nonce); + +#endif //OC_CLIENT_CB diff --git a/resource/csdk/stack/include/internal/occollection.h b/resource/csdk/stack/include/internal/occollection.h new file mode 100644 index 000000000..e421d0678 --- /dev/null +++ b/resource/csdk/stack/include/internal/occollection.h @@ -0,0 +1,32 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OC_COLLECTION_H +#define OC_COLLECTION_H + +#include "ocstack.h" +#include "ocresourcehandler.h" + +uint8_t GetNumOfResourcesInCollection (OCResource *resource); + +OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag, + OCEntityHandlerRequest *entityHandlerRequest); + +#endif //OC_COLLECTION_H diff --git a/resource/csdk/stack/include/internal/ocobserve.h b/resource/csdk/stack/include/internal/ocobserve.h new file mode 100644 index 000000000..ba8730669 --- /dev/null +++ b/resource/csdk/stack/include/internal/ocobserve.h @@ -0,0 +1,86 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OC_OBSERVE_H +#define OC_OBSERVE_H + +/* In CoAP sequence number is a 24 bit field */ +#define MAX_SEQUENCE_NUMBER (0xFFFFFF) + +#define MAX_OBSERVER_FAILED_COMM (2) +#define MAX_OBSERVER_NON_COUNT (3) + +/* This information is stored for each registerd observer */ +typedef struct ResourceObserver { + // Observation Identifier for request + OCObservationId observeId; + // URI of observed resource + unsigned char *resUri; + // Query + unsigned char *query; + // CoAP token for the observe request + OCCoAPToken token; + // Resource handle + OCResource *resource; + // IP address & port of client registered for observe + OCDevAddr *addr; + // Quality of service of the request + OCQualityOfService qos; + // number of times the server failed to reach the observer + uint8_t failedCommCount; + // number of times the server sent NON notifications + uint8_t lowQosCount; + // force the qos value to CON + uint8_t forceHighQos; + // next node in this list + struct ResourceObserver *next; +} ResourceObserver; + +#ifdef WITH_PRESENCE +OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge, + OCResourceType *resourceType, OCQualityOfService qos); +#else +OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge, + OCQualityOfService qos); +#endif +OCStackResult SendListObserverNotification (OCResource * resource, + OCObservationId *obsIdList, uint8_t numberOfIds, + unsigned char *notificationJSONPayload, uint32_t maxAge, + OCQualityOfService qos); + +void DeleteObserverList(); + +OCStackResult GenerateObserverId (OCObservationId *observationId); + +OCStackResult AddObserver (const char *resUri, + const char *query, + OCObservationId obsId, + OCCoAPToken *token, + OCDevAddr *addr, + OCResource *resHandle, + OCQualityOfService qos); + +OCStackResult DeleteObserverUsingToken (OCCoAPToken * token); + +ResourceObserver* GetObserverUsingToken (const OCCoAPToken * token); + +ResourceObserver* GetObserverUsingId (const OCObservationId observeId); + +#endif //OC_OBSERVE_H diff --git a/resource/csdk/stack/include/internal/ocresource.h b/resource/csdk/stack/include/internal/ocresource.h new file mode 100644 index 000000000..bbd652bbb --- /dev/null +++ b/resource/csdk/stack/include/internal/ocresource.h @@ -0,0 +1,158 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OCRESOURCE_H_ +#define OCRESOURCE_H_ + +#define OC_OBSERVER_NOT_INTERESTED (0) +#define OC_OBSERVER_STILL_INTERESTED (1) +#define OC_OBSERVER_FAILED_COMM (2) + +//----------------------------------------------------------------------------- +// Virtual Resource Presence Attributes +//----------------------------------------------------------------------------- +#ifdef WITH_PRESENCE +typedef struct PRESENCERESOURCE{ + OCResourceHandle handle; + uint32_t presenceTTL; +} PresenceResource; +#endif + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +struct rsrc_t; + +//----------------------------------------------------------------------------- +// Typedefs +//----------------------------------------------------------------------------- + +// IF here stands for Interface +typedef enum { + STACK_IF_DEFAULT = 0, + STACK_IF_LL, + STACK_IF_BATCH, + STACK_IF_GROUP, + STACK_IF_INVALID +} OCStackIfTypes; + +// following structure will be created in occollection. +typedef struct occapability { + struct occapability* next; + + char *capability; // It is a name about resource capability. + char *status; // It is mean status of capability. +} OCCapability; + + +// following structure will be created in occollection. +typedef struct ocaction { + struct ocaction *next; + + // Target Uri. + // It will be used to execute the action. + char *resourceUri; + + OCCapability* head; +} OCAction; + +// following structure will be created in occollection. +typedef struct ocactionset { + + struct ocactionset *next; + + char *actionsetName; + + OCAction* head; +} OCActionSet; + + + +typedef struct resourcetype_t { + struct resourcetype_t *next; // linked list; for multiple types on resource + + // Name of the type; this string is ‘.’ (dot) separate list of segments where each segment is a + // namespace and the final segment is the type; type and sub-types can be separate with + // ‘-‘ (dash) usually only two segments would be defined. Either way this string is meant to be + // human friendly and is used opaquely and not parsed by code. This name is used in the “rt=” + // parameter of a resource description when resources are introspected and is also use in the + // /types list of available types. + char *resourcetypename; +} OCResourceType; + +typedef struct attr_t { + struct attr_t *next; // Points to next resource in list + + // The name of the attribute; used to look up the attribute in list; + // for a given attribute SHOULD not be changed once assigned + const char *attrName; + char *attrValue; // value of the attribute as string +} OCAttribute; + +typedef struct resourceinterface_t { + struct resourceinterface_t *next; // linked list; for multiple interfaces on resource + + // Name of the interface; this is ‘.’ (dot) separate list of segments where each segment is a + // namespace and the final segment is the interface; usually only two segments would be + // defined. Either way this string is opaque and not parsed by segment + char *name ; + + // Supported content types to serialize request and response on this interface + // (REMOVE for V1 – only jSON for all but core.ll that uses Link Format) +#if 0 + char *inputContentType ; + char *outputContentType ; +#endif + /*** Future placeholder for access control and policy ***/ +} OCResourceInterface; + +typedef struct rsrc_t { + struct rsrc_t *next; // Points to next resource in list + // Relative path on the device; will be combined with base url to create fully qualified path + char *host; + char *uri; + OCResourceType *rsrcType; // Resource type(s); linked list + OCResourceInterface *rsrcInterface; // Resource interface(s); linked list + OCAttribute *rsrcAttributes; // Resource interface(s); linked list + // Array of pointers to resources; can be used to represent a container of resources + // (i.e. hierarchies of resources) or for reference resources (i.e. for a resource collection) + struct rsrc_t *rsrcResources[MAX_CONTAINED_RESOURCES]; + //struct rsrc_t *rsrcResources; + // Pointer to function that handles the entity bound to the resource. + // This handler has to be explicitly defined by the programmer + OCEntityHandler entityHandler; + // Properties on the resource – defines meta information on the resource + OCResourceProperty resourceProperties ; /* ACTIVE, DISCOVERABLE etc */ + // Pointer to an opaque object where app/user specific data can be placed with the resource; + // this could be information for the entity handler between invocations + void *context; + // NOTE: Methods supported by this resource should be based on the interface targeted + // i.e. look into the interface structure based on the query request Can be removed here; + // place holder for the note above + /* method_t methods; */ + // Sequence number for observable resources. Per the CoAP standard it is a 24 bit value. + uint32_t sequenceNum; + // Pointer of ActionSet which to support group action. + OCActionSet *actionsetHead; +} OCResource; + + + +#endif /* OCRESOURCE_H_ */ diff --git a/resource/csdk/stack/include/internal/ocresourcehandler.h b/resource/csdk/stack/include/internal/ocresourcehandler.h new file mode 100644 index 000000000..f56769cef --- /dev/null +++ b/resource/csdk/stack/include/internal/ocresourcehandler.h @@ -0,0 +1,97 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OC_RESOURCEHANDLER_H +#define OC_RESOURCEHANDLER_H + +#include "ocstack.h" +#include "ocstackinternal.h" +#include "ocserverrequest.h" + +#define OC_RSRVD_OC "oc" +#define OC_RSRVD_PAYLOAD "payload" +#define OC_RSRVD_HREF "href" +#define OC_RSRVD_RESOURCE_TYPE "rt" +#define OC_RSRVD_RESOURCE_TYPE_PRESENCE "core.presence" +#define OC_RSRVD_INTERFACE "if" +#define OC_RSRVD_DEVICE_ID "di" +#define OC_RSRVD_DEVICE_NAME "dn" +#define OC_RSRVD_INTERFACE_DEFAULT "oc.mi.def" +#define OC_RSRVD_INTERFACE_LL "oc.mi.ll" +#define OC_RSRVD_INTERFACE_BATCH "oc.mi.b" +#define OC_RSRVD_INTERFACE_GROUP "oc.mi.c" + + +#define OC_RSRVD_OBSERVABLE "obs" +#define OC_RSRVD_SECURE "sec" +#define OC_RSRVD_HOSTING_PORT "port" + +#define OC_JSON_PREFIX "{\"oc\":[" +#define OC_JSON_PREFIX_LEN (sizeof(OC_JSON_PREFIX) - 1) +#define OC_JSON_SUFFIX "]}" +#define OC_JSON_SUFFIX_LEN (sizeof(OC_JSON_SUFFIX) - 1) +#define OC_JSON_SEPARATOR ',' + +#define OC_RESOURCE_OBSERVABLE 1 +#define OC_RESOURCE_SECURE 1 + +typedef enum { + STACK_RES_DISCOVERY_NOFILTER = 0, + STACK_RES_DISCOVERY_IF_FILTER, + STACK_RES_DISCOVERY_RT_FILTER, + STACK_DEVICE_DISCOVERY_DI_FILTER, + STACK_DEVICE_DISCOVERY_DN_FILTER +} StackQueryTypes; + +typedef enum { + OC_RESOURCE_VIRTUAL = 0, + OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER, + OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER, + OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER, + OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER, + OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER, + OC_RESOURCE_NOT_SPECIFIED +} ResourceHandling; + +OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag, + OCEntityHandlerRequest * request); + +const char * GetVirtualResourceUri( OCVirtualResources resource); +OCResource *FindResourceByUri(const char* resourceUri); +uint8_t IsVirtualResource(const char* resourceUri); + +OCStackResult DetermineResourceHandling (OCServerRequest *request, + ResourceHandling *handling, + OCResource **resource); + +OCStackResult +ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request); + +OCStackResult SaveDeviceInfo(OCDeviceInfo deviceInfo); + +void DeleteDeviceInfo(); + +OCStackResult +BuildVirtualResourceResponse(OCResource *resourcePtr, uint8_t filterOn, + char *filterValue, char * out, uint16_t *remaining); + +OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult); + +#endif //OC_RESOURCEHANDLER_H diff --git a/resource/csdk/stack/include/internal/ocserverrequest.h b/resource/csdk/stack/include/internal/ocserverrequest.h new file mode 100644 index 000000000..e96ed511f --- /dev/null +++ b/resource/csdk/stack/include/internal/ocserverrequest.h @@ -0,0 +1,110 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OC_SERVER_REQUEST_H +#define OC_SERVER_REQUEST_H + +#include "occoap.h" + +/** + * The signature of the internal call back functions to handle responses from entity handler + */ +typedef OCStackResult (* OCEHResponseHandler)(OCEntityHandlerResponse * ehResponse); +OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse); +OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse); + +// following structure will be created in occoap and passed up the stack on the server side +typedef struct OCServerRequest { + // the REST method retrieved from received request PDU + OCMethod method; + // resourceUrl will be filled in occoap using the path options in received request PDU + unsigned char resourceUrl[MAX_URI_LENGTH]; + // resource query send by client + unsigned char query[MAX_QUERY_LENGTH]; + + // qos is indicating if the request is CON or NON + OCQualityOfService qos; + // Observe option field + uint32_t observationOption; + OCStackResult observeResult; + uint8_t numResponses; + OCEHResponseHandler ehResponseHandler; + ////////////////////////////////////////////////////////// + // IP address & port of client registered for observe //These + OCDevAddr requesterAddr; //Members + // CoAP token for the observe request //Might + OCCoAPToken requestToken; //Be + // The ID of CoAP pdu //Kept in + uint16_t coapID; //CoAP + uint8_t delayedResNeeded; + uint8_t secured; + ////////////////////////////////////////////////////////// + // An array of the received vendor specific header options + uint8_t numRcvdVendorSpecificHeaderOptions; + OCHeaderOption rcvdVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS]; + uint8_t requestComplete; + struct OCServerRequest * next; + // Flag indicating slow response + uint8_t slowFlag; + uint8_t notificationFlag; + // reqJSON is retrieved from the payload of the received request PDU + unsigned char reqJSONPayload[1]; +} OCServerRequest; + +// following structure will be created in ocstack to aggregate responses (in future: for block transfer) +typedef struct OCServerResponse { + struct OCServerResponse * next; + // this is the pointer to server payload data to be transferred + unsigned char *payload; + uint16_t remainingPayloadSize; + OCRequestHandle requestHandle; +} OCServerResponse; + +OCServerRequest * GetServerRequestUsingToken (const OCCoAPToken token); + +OCServerRequest * GetServerRequestUsingHandle (const OCServerRequest * handle); + +OCServerResponse * GetServerResponseUsingHandle (const OCServerRequest * handle); + +OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID, + uint8_t delayedResNeeded, uint8_t secured, uint8_t notificationFlag, OCMethod method, + uint8_t numRcvdVendorSpecificHeaderOptions, uint32_t observationOption, + OCQualityOfService qos, unsigned char * query, + OCHeaderOption * rcvdVendorSpecificHeaderOptions, + unsigned char * reqJSONPayload, OCCoAPToken * requestToken, + OCDevAddr * requesterAddr, unsigned char * resourceUrl, uint32_t reqTotalSize); + +OCStackResult AddServerResponse (OCServerResponse ** response, OCRequestHandle requestHandle); + +// Internal function to create OCEntityHandlerRequest at the server from a received coap pdu +OCStackResult FormOCEntityHandlerRequest(OCEntityHandlerRequest * entityHandlerRequest, OCRequestHandle request, + OCMethod method, OCResourceHandle resource, unsigned char * queryBuf, unsigned char * bufReqPayload, + uint8_t numVendorOptions, OCHeaderOption * vendorOptions, OCObserveAction observeAction, + OCObservationId observeID); + +void FindAndDeleteServerRequest(OCServerRequest * serverRequest); + +void DeleteServerRequest(OCServerRequest * serverRequest); + +void FindAndDeleteServerResponse(OCServerResponse * serverResponse); + +void DeleteServerResponse(OCServerResponse * serverResponse); + +#endif //OC_SERVER_REQUEST_H diff --git a/resource/csdk/stack/include/internal/ocstackinternal.h b/resource/csdk/stack/include/internal/ocstackinternal.h new file mode 100644 index 000000000..2a4d8f69f --- /dev/null +++ b/resource/csdk/stack/include/internal/ocstackinternal.h @@ -0,0 +1,169 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// + +//----------------------------------------------------------------------------- +// Internal include file used by lower layers of the OC stack +//----------------------------------------------------------------------------- +#ifndef OCSTACKINTERNAL_H_ +#define OCSTACKINTERNAL_H_ + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include "ocstack.h" +#include "ocstackconfig.h" +#include "occoaptoken.h" +#include "occlientcb.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + + +//----------------------------------------------------------------------------- +// Global variables +//----------------------------------------------------------------------------- +extern OCDeviceEntityHandler defaultDeviceHandler; + +//----------------------------------------------------------------------------- +// Defines +//----------------------------------------------------------------------------- +#define OC_COAP_SCHEME "coap://" +#define OC_OFFSET_SEQUENCE_NUMBER (4) // the first outgoing sequence number will be 5 + +typedef struct { + // Observe option field + uint32_t option; + // IP address & port of client registered for observe + OCDevAddr *subAddr; + // CoAP token for the observe request + OCCoAPToken *token; + // The result of the observe request + OCStackResult result; +} OCObserveReq; + +// following structure will be created in occoap and passed up the stack on the server side +typedef struct { + // Observe option field + uint32_t observationOption; + // the REST method retrieved from received request PDU + OCMethod method; + // resourceUrl will be filled in occoap using the path options in received request PDU + unsigned char resourceUrl[MAX_URI_LENGTH]; + // resource query send by client + unsigned char query[MAX_QUERY_LENGTH]; + // reqJSON is retrieved from the payload of the received request PDU + unsigned char reqJSONPayload[MAX_REQUEST_LENGTH]; + // qos is indicating if the request is CON or NON + OCQualityOfService qos; + // An array of the received vendor specific header options + uint8_t numRcvdVendorSpecificHeaderOptions; + OCHeaderOption rcvdVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS]; + ////////////////////////////////////////////////////////// + // TODO: Consider moving these member to CoAP + // IP address & port of client registered for observe + OCDevAddr requesterAddr; + // CoAP token for the observe request + OCCoAPToken requestToken; + // The ID of CoAP pdu + uint16_t coapID; + uint8_t delayedResNeeded; + uint8_t secured; + ////////////////////////////////////////////////////////// + uint8_t reqMorePacket; + uint32_t reqPacketNum; + uint16_t reqPacketSize; + uint32_t resPacketNum; + uint16_t resPacketSize; + uint32_t reqTotalSize; +} OCServerProtocolRequest; + +typedef struct +{ + // Observe option field + uint32_t observationOption; + // qos is indicating if the request is CON or NON + OCQualityOfService qos; + // Allow the entity handler to pass a result with the response + OCStackResult result; + // IP address & port of client registered for observe + OCDevAddr *requesterAddr; + // CoAP token for the observe request + OCCoAPToken *requestToken; + // The ID of CoAP pdu + uint16_t coapID; + // Flag indicating that response is to be delayed before sending + uint8_t delayedResNeeded; + uint8_t secured; + uint8_t slowFlag; + uint8_t notificationFlag; + // this is the pointer to server payload data to be transferred + unsigned char *payload; + // size of server payload data. Don't rely on null terminated data for size + uint16_t payloadSize; + // An array of the vendor specific header options the entity handler wishes to use in response + uint8_t numSendVendorSpecificHeaderOptions; + OCHeaderOption *sendVendorSpecificHeaderOptions; + // URI of new resource that entity handler might create + unsigned char * resourceUri; +} OCServerProtocolResponse; + +// following structure will be created in occoap and passed up the stack on the client side +typedef struct { + // handle is retrieved by comparing the token-handle pair in the PDU. + ClientCB * cbNode; + // This is how long this response is valid for (in seconds). + uint32_t TTL; + // this structure will be passed to client + OCClientResponse * clientResponse; +} OCResponse; + +//----------------------------------------------------------------------------- +// Internal function prototypes +//----------------------------------------------------------------------------- +OCStackResult OCStackFeedBack(OCCoAPToken * token, uint8_t status); +OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest); +void HandleStackResponses(OCResponse * response); +int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr, uint16_t * port); +#ifdef WITH_PRESENCE +OCStackResult SendPresenceNotification(OCResourceType *resourceType); +#endif + +OCStackResult BindResourceInterfaceToResource(OCResource* resource, + const char *resourceInterfaceName); + +OCStackResult BindResourceTypeToResource(OCResource* resource, + const char *resourceTypeName); +OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName); + +#ifdef WITH_PRESENCE +//TODO: should the following function be public? +OCStackResult OCChangeResourceProperty(OCResourceProperty * inputProperty, + OCResourceProperty resourceProperties, uint8_t enable); +#endif + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* OCSTACKINTERNAL_H_ */ diff --git a/resource/csdk/stack/include/internal/oicgroup.h b/resource/csdk/stack/include/internal/oicgroup.h new file mode 100644 index 000000000..2493fba85 --- /dev/null +++ b/resource/csdk/stack/include/internal/oicgroup.h @@ -0,0 +1,57 @@ +//****************************************************************** +// +// Copyright 2014 Samsung Electronics All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OIC_GROUP_H +#define OIC_GROUP_H + +#include "ocstack.h" +#include "ocstackinternal.h" + +void AddCapability(OCCapability** head, OCCapability* node); + +void AddAction(OCAction** head, OCAction* node); + +void AddActionSet(OCActionSet **head, OCActionSet* node); + +void DeleteCapability(OCCapability *del); + +void DeleteAction(OCAction** action); + +void DeleteActionSet(OCActionSet** actionset); + +OCStackResult DeleteActionSets(OCResource** resource); + +OCStackResult FindAndDeleteActionSet(OCResource **resource, const char * actionsetName); + +OCStackResult GetActionSetFromString(OCResource **resource, unsigned char *request, char** method, + char **actionsetName); + +OCStackResult GetStringFromActionSet(OCActionSet* actionset, char** desc); + +OCStackApplicationResult ActionSetCB(void* context, OCDoHandle handle, + OCClientResponse* clientResponse); + +void ActionSetCD(void *context); + +OCStackResult +BuildCollectionGroupActionJSONResponse(OCMethod method/*OCEntityHandlerFlag flag*/, + OCResource *resource, OCEntityHandlerRequest *ehRequest); + +#endif // OIC_GROUP_H diff --git a/resource/csdk/stack/include/ocsecurity.h b/resource/csdk/stack/include/ocsecurity.h new file mode 100644 index 000000000..0d71086e5 --- /dev/null +++ b/resource/csdk/stack/include/ocsecurity.h @@ -0,0 +1,49 @@ +//****************************************************************** +// +// Copyright 2014 Intel Corporation All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OC_SECURITY_H +#define OC_SECURITY_H + +#include "ocstack.h" +#include "ocsecurityconfig.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Provides the DTLS PSK credetials blob to OC stack. + * + * @param credInfo + * binary blob containing credentials + * @param len + * length of binary blob + * + * @retval OC_STACK_OK for Success, otherwise some error value + */ +OCStackResult OCSetDtlsPskCredentials(const OCDtlsPskCredsBlob *credInfo, + size_t len); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif //OC_SECURITY_H diff --git a/resource/csdk/stack/include/ocsecurityconfig.h b/resource/csdk/stack/include/ocsecurityconfig.h new file mode 100644 index 000000000..eaa06b43e --- /dev/null +++ b/resource/csdk/stack/include/ocsecurityconfig.h @@ -0,0 +1,59 @@ +//****************************************************************** +// +// Copyright 2014 Intel Corporation All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OC_SECURITY_CONFIG_H +#define OC_SECURITY_CONFIG_H + +#include + +#define DTLS_PSK_ID_LEN 16 +#define DTLS_PSK_PSK_LEN 16 + +#define DtlsPskCredsBlobVer_1 1 /**< Credentials stored in plaintext */ +#define DtlsPskCredsBlobVer_CurrentVersion DtlsPskCredsBlobVer_1 + +/** + * Credentials for a device. Includes identity and the associated PSK. + */ +typedef struct +{ + unsigned char id[DTLS_PSK_ID_LEN]; + unsigned char psk[DTLS_PSK_PSK_LEN]; +} OCDtlsPskCreds; + + +/** + * Binary blob containing device identity and the credentials for all devices + * trusted by this device. + */ +typedef struct +{ + uint16_t blobVer; /**< version of the blob */ + uint16_t reserved; /**< reserved for future use */ + unsigned char identity[DTLS_PSK_ID_LEN]; /**< identity of self */ + uint32_t num; /**< number of credentials in this blob */ + OCDtlsPskCreds creds[1]; /**< list of credentials. Size of this + array is determined by 'num' variable. */ +} OCDtlsPskCredsBlob; + + +#endif //OC_SECURITY_CONFIG_H + + diff --git a/resource/csdk/stack/include/ocstack.h b/resource/csdk/stack/include/ocstack.h new file mode 100644 index 000000000..8be0d123e --- /dev/null +++ b/resource/csdk/stack/include/ocstack.h @@ -0,0 +1,853 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OCSTACK_H_ +#define OCSTACK_H_ + +#include "ocsocket.h" +#include "ocstackconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus +#define WITH_PRESENCE +//----------------------------------------------------------------------------- +// Defines +//----------------------------------------------------------------------------- + +//TODO: May want to refactor this in upcoming sprints. +//Don't want to expose to application layer that lower level stack is using CoAP. +#define OC_WELL_KNOWN_QUERY "coap://224.0.1.187:5683/oc/core" +#define OC_EXPLICIT_DEVICE_DISCOVERY_URI "coap://224.0.1.187:5683/oc/core?rt=core.led" +#define OC_MULTICAST_PREFIX "coap://224.0.1.187:5683" +#define OC_MULTICAST_IP "coap://224.0.1.187" + +#define USE_RANDOM_PORT (0) +#ifdef WITH_PRESENCE +#define OC_DEFAULT_PRESENCE_TTL (60) +#define OC_PRESENCE_URI "/oc/presence" +extern uint8_t PresenceTimeOutSize; // length of PresenceTimeOut - 1 +extern uint32_t PresenceTimeOut[]; +#endif +//----------------------------------------------------------------------------- +// Typedefs +//----------------------------------------------------------------------------- + +/** + * OC Virtual resources supported by every OC device + */ +typedef enum { + OC_WELL_KNOWN_URI= 0, // "/oc/core" + OC_DEVICE_URI, // "/oc/core/d" + OC_RESOURCE_TYPES_URI, // "/oc/core/d/type" + #ifdef WITH_PRESENCE + OC_PRESENCE, // "/oc/presence" + #endif + OC_MAX_VIRTUAL_RESOURCES // Max items in the list +} OCVirtualResources; + +/** + * Standard RESTful HTTP Methods + */ +typedef enum { + OC_REST_NOMETHOD = 0, + OC_REST_GET = (1 << 0), // Read + OC_REST_PUT = (1 << 1), // Write + OC_REST_POST = (1 << 2), // Update + OC_REST_DELETE = (1 << 3), // Delete + // Register observe request for most up date notifications ONLY. + OC_REST_OBSERVE = (1 << 4), + // Register observe request for all notifications, including stale notifications. + OC_REST_OBSERVE_ALL = (1 << 5), + // Deregister observation, intended for internal use + OC_REST_CANCEL_OBSERVE = (1 << 6), + #ifdef WITH_PRESENCE + // Subscribe for all presence notifications of a particular resource. + OC_REST_PRESENCE = (1 << 7) + #endif +} OCMethod; + +/** + * Host Mode of Operation + */ +typedef enum { + OC_CLIENT = 0, + OC_SERVER, + OC_CLIENT_SERVER +} OCMode; + +extern OCMode myStackMode; +/** + * Quality of Service + */ +typedef enum { + OC_LOW_QOS = 0, + OC_MEDIUM_QOS, + OC_HIGH_QOS, + OC_NA_QOS // No Quality is defined, let the stack decide +} OCQualityOfService; + +/** + * Resource Properties + * + * OC_ACTIVE - When this bit is set, the resource is initialized, otherwise the resource + * is 'inactive'. 'inactive' signifies that the resource has been marked for + * deletion or is already deleted. + * OC_DISCOVERABLE - When this bit is set, the resource is allowed to be discovered by clients. + * OC_OBSERVABLE - When this bit is set, the resource is allowed to be observed by clients. + * OC_SLOW - When this bit is set, the resource has been marked as 'slow'. 'slow' signifies + * that responses from this resource can expect delays in processing its + * requests from clients. + * OC_SECURE - When this bit is set, the resource is a secure resource. + */ +typedef enum { + OC_ACTIVE = (1 << 0), + OC_DISCOVERABLE = (1 << 1), + OC_OBSERVABLE = (1 << 2), + OC_SLOW = (1 << 3), + OC_SECURE = (1 << 4) +} OCResourceProperty; + +/** + * Transport Protocol IDs + */ +typedef enum { + OC_INVALID_ID = (1 << 0), + OC_COAP_ID = (1 << 1) +} OCTransportProtocolID; + +/** + * Declares Stack Results & Errors + */ +typedef enum { + /* Success status code - START HERE */ + OC_STACK_OK = 0, + OC_STACK_RESOURCE_CREATED, + OC_STACK_RESOURCE_DELETED, + OC_STACK_CONTINUE, + /* Success status code - END HERE */ + /* Error status code - START HERE */ + OC_STACK_INVALID_URI, + OC_STACK_INVALID_QUERY, + OC_STACK_INVALID_IP, + OC_STACK_INVALID_PORT, + OC_STACK_INVALID_CALLBACK, + OC_STACK_INVALID_METHOD, + OC_STACK_INVALID_PARAM, + OC_STACK_INVALID_OBSERVE_PARAM, + OC_STACK_NO_MEMORY, + OC_STACK_COMM_ERROR, + OC_STACK_NOTIMPL, + OC_STACK_NO_RESOURCE, /* resource not found */ + OC_STACK_RESOURCE_ERROR, /* ex: not supported method or interface */ + OC_STACK_SLOW_RESOURCE, + OC_STACK_NO_OBSERVERS, /* resource has no registered observers */ + OC_STACK_OBSERVER_NOT_FOUND, + #ifdef WITH_PRESENCE + OC_STACK_PRESENCE_STOPPED, + OC_STACK_PRESENCE_TIMEOUT, + OC_STACK_PRESENCE_DO_NOT_HANDLE, + #endif + OC_STACK_VIRTUAL_DO_NOT_HANDLE, + OC_STACK_INVALID_OPTION, + OC_STACK_MALFORMED_RESPONSE, /* the remote reply contained malformed data */ + OC_STACK_PERSISTENT_BUFFER_REQUIRED, + OC_STACK_INVALID_REQUEST_HANDLE, + OC_STACK_INVALID_DEVICE_INFO, + OC_STACK_ERROR + /* Error status code - END HERE */ +} OCStackResult; + +/** + * Handle to an @ref OCDoResource invocation. + */ +typedef void * OCDoHandle; + +/** + * Handle to an OCResource object owned by the OCStack. + */ +typedef void * OCResourceHandle; + +typedef void * OCRequestHandle; +typedef void * OCResponseHandle; + +/** + * Unique identifier for each observation request. Used when observations are + * registered or deregistering. Used by entity handler to signal specific + * observers to be notified of resource changes. + * There can be maximum of 256 observations per server. + */ +typedef uint8_t OCObservationId; + +/** + * Action associated with observation + */ +typedef enum { + OC_OBSERVE_REGISTER = 0, + OC_OBSERVE_DEREGISTER = 1, + OC_OBSERVE_NO_OPTION = 2 +} OCObserveAction; + +typedef struct { + // Action associated with observation request + OCObserveAction action; + // Identifier for observation being registered/deregistered + OCObservationId obsId; +} OCObservationInfo; + +/** + * Possible returned values from entity handler + */ +typedef enum { + OC_EH_OK = 0, + OC_EH_ERROR, + OC_EH_RESOURCE_CREATED, + OC_EH_RESOURCE_DELETED, + OC_EH_SLOW, + OC_EH_FORBIDDEN +} OCEntityHandlerResult; + +// following structure will be used to define the vendor specific header options to be included +// in communication packets + +typedef struct OCHeaderOption { + // The protocol ID this option applies to + OCTransportProtocolID protocolID; + // The header option ID which will be added to communication packets + uint16_t optionID; + // its length 191 + uint16_t optionLength; + // pointer to its data + uint8_t optionData[MAX_HEADER_OPTION_DATA_LENGTH]; +} OCHeaderOption; + +/** + * Incoming requests handled by the server. Requests are passed in as a parameter to the @ref OCEntityHandler callback API. + * @brief The @ref OCEntityHandler callback API must be implemented in the application in order to receive these requests. + */ +typedef struct { + // Associated resource + OCResourceHandle resource; + OCRequestHandle requestHandle; + // the REST method retrieved from received request PDU + OCMethod method; + // resource query send by client + unsigned char * query; + // Information associated with observation - valid only when OCEntityHandler + // flag includes OC_OBSERVE_FLAG + OCObservationInfo obsInfo; + // An array of the received vendor specific header options + uint8_t numRcvdVendorSpecificHeaderOptions; + OCHeaderOption * rcvdVendorSpecificHeaderOptions; + // reqJSON is retrieved from the payload of the received request PDU + unsigned char * reqJSONPayload; +}OCEntityHandlerRequest; + +/** + * Response from queries to remote servers. Queries are made by calling the @ref OCDoResource API. + */ +typedef struct { + // Address of remote server + OCDevAddr * addr; + // the is the result of our stack, OCStackResult should contain coap/other error codes; + OCStackResult result; + // If associated with observe, this will represent the sequence of notifications from server. + uint32_t sequenceNumber; + // resJSONPayload is retrieved from the payload of the received request PDU + unsigned const char * resJSONPayload; + // An array of the received vendor specific header options + uint8_t numRcvdVendorSpecificHeaderOptions; + OCHeaderOption rcvdVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS]; +}OCClientResponse; + +/** + * Following structure describes the device properties. All non-Null properties will be included + * in a device discovery request. + */ +typedef struct +{ + char *deviceName; + char *hostName; + char *deviceUUID; + char *contentType; + char *version; + char *manufacturerName; + char *manufacturerUrl; + char *modelNumber; + char *dateOfManufacture; + char *platformVersion; + char *firmwareVersion; + char *supportUrl; +} OCDeviceInfo; + +typedef struct +{ + // Request handle is passed to server via the entity handler for each incoming request. + // Stack assigns when request is received, server sets to indicate what request response is for + OCRequestHandle requestHandle; + // New handle for tracking block (or slow) response. Stack assigns, server uses for subsequent calls + OCResponseHandle *responseHandle; + // Resource handle + OCResourceHandle resourceHandle; + // Allow the entity handler to pass a result with the response + OCEntityHandlerResult ehResult; + // this is the pointer to server payload data to be transferred + unsigned char *payload; + // size of server payload data. I don't think we should rely on null terminated data for size + uint16_t payloadSize; + // An array of the vendor specific header options the entity handler wishes to use in response + uint8_t numSendVendorSpecificHeaderOptions; + OCHeaderOption sendVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS]; + // URI of new resource that entity handler might create + unsigned char resourceUri[MAX_URI_LENGTH]; + // Server sets to true for persistent response buffer, false for non-persistent response buffer + uint8_t persistentBufferFlag; +} OCEntityHandlerResponse; + +typedef enum { + OC_INIT_FLAG = (1 << 0), + OC_REQUEST_FLAG = (1 << 1), + OC_OBSERVE_FLAG = (1 << 2) +} OCEntityHandlerFlag; //entity_handler_flag_t ; + +// possible returned values from client application +typedef enum { + OC_STACK_DELETE_TRANSACTION = 0, + OC_STACK_KEEP_TRANSACTION +} OCStackApplicationResult; + +//----------------------------------------------------------------------------- +// Callback function definitions +//----------------------------------------------------------------------------- + +/** + * Client applications implement this callback to consume responses received from Servers. + */ +typedef OCStackApplicationResult (* OCClientResponseHandler)(void *context, OCDoHandle handle, + OCClientResponse * clientResponse); + +/** + * Client applications using a context pointer implement this callback to delete the + * context upon removal of the callback/context pointer from the internal callback-list + */ +typedef void (* OCClientContextDeleter)(void *context); + +/* + * This info is passed from application to OC Stack when initiating a request to Server + */ +typedef struct { + void *context; + OCClientResponseHandler cb; + OCClientContextDeleter cd; +} OCCallbackData; + +/** + * Application server implementations must implement this callback to consume requests OTA. + * Entity handler callback needs to fill the resPayload of the entityHandlerRequest. + */ +typedef OCEntityHandlerResult (*OCEntityHandler) +(OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest); + +/** + * Device Entity handler need to use this call back instead of OCEntityHandler + */ +typedef OCEntityHandlerResult (*OCDeviceEntityHandler) +(OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest, char* uri); + +//----------------------------------------------------------------------------- +// Function prototypes +//----------------------------------------------------------------------------- + +/** + * Initialize the OC Stack. Must be called prior to starting the stack. + * + * @param ipAddr + * IP Address of host device + * @param port + * Port of host device + * @param mode + * Host device is client, server, or client-server + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack init error + */ +OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode); + +/** + * Stop the OC stack. Use for a controlled shutdown. + * + * Note: OCStop() performs operations similar to OCStopPresence(), as well as OCDeleteResource() on + * all resources this server is hosting. OCDeleteResource() performs operations similar to + * OCNotifyAllObservers() to notify all client observers that the respective resource is being + * deleted. + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack not initialized + */ +OCStackResult OCStop(); + +/** + * Called in main loop of OC client or server. Allows low-level processing of + * stack services. + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ +OCStackResult OCProcess(); + +/** + * Discover or Perform requests on a specified resource (specified by that Resource's respective + * URI). + * + * @param handle - @ref OCDoHandle to refer to the request sent out on behalf of + * calling this API. + * @param method - @ref OCMethod to perform on the resource + * @param requiredUri - URI of the resource to interact with + * @param referenceUri - URI of the reference resource + * @param request - JSON encoded request + * @param qos - quality of service. Note that if this API is called on a uri with + * the well-known multicast IP address, the qos will be forced to + * OC_LOW_QOS + * since it is impractical to send other QOS levels on such addresses. + * @param clientApplicationCB- asynchronous callback function that is invoked + * by the stack when discovery or resource interaction is complete + * @param options - The address of an array containing the vendor specific + * header options to be sent with the request + * @param numOptions - Number of header options to be included + * + * Note: Presence subscription amendments (ie. adding additional resource type filters by calling + * this API again) require the use of the same base URI as the original request to successfully + * amend the presence filters. + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_INVALID_CALLBACK - invalid callback function pointer + * OC_STACK_INVALID_METHOD - invalid resource method + * OC_STACK_INVALID_URI - invalid required or reference URI + * OC_STACK_INVALID_QUERY - number of resource types specified for filtering presence + * notifications exceeds @ref MAX_PRESENCE_FILTERS. + */ +OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri, const char *referenceUri, + const char *request, OCQualityOfService qos, OCCallbackData *cbData, OCHeaderOption * options, + uint8_t numOptions); + +/** + * Cancel a request associated with a specific @ref OCDoResource invocation. + * + * @param handle - Used to identify a specific OCDoResource invocation. + * @param qos - used to specify Quality of Service (read below for more info) + * @param options- used to specify vendor specific header options when sending + * explicit observe cancellation + * @param numOptions- Number of header options to be included + * + * @return + * OC_STACK_OK - No errors; Success + * OC_STACK_INVALID_PARAM - The handle provided is invalid. + */ +OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options, + uint8_t numOptions); + +#ifdef WITH_PRESENCE +/** + * When operating in @ref OCServer or @ref OCClientServer mode, this API will start sending out + * presence notifications to clients via multicast. Once this API has been called with a success, + * clients may query for this server's presence and this server's stack will respond via multicast. + * + * Server can call this function when it comes online for the first time, or when it comes back + * online from offline mode, or when it re enters network. + * + * @param ttl - Time To Live in seconds + * Note: If ttl is '0', then the default stack value will be used (60 Seconds). + * + * @return + * OC_STACK_OK - No errors; Success + */ +OCStackResult OCStartPresence(const uint32_t ttl); + +/** + * When operating in @ref OCServer or @ref OCClientServer mode, this API will stop sending out + * presence notifications to clients via multicast. Once this API has been called with a success, + * this server's stack will not respond to clients querying for this server's presence. + * + * Server can call this function when it is terminating, going offline, or when going + * away from network. + * + * @return + * OC_STACK_OK - No errors; Success + */ + +OCStackResult OCStopPresence(); +#endif + + +/** + * Set default device entity handler + * + * @param entityHandler - entity handler function that is called by ocstack to handle requests for + * any undefined resources or default actions. + * if NULL is passed it removes the device default entity handler. + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ +OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandler); + +/** + * Set device information. + * + * @param deviceInfo - Structure passed by the server application containing + * the device information. + * + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_INVALID_PARAM - invalid paramerter + * OC_STACK_ERROR - stack process error + */ +OCStackResult OCSetDeviceInfo(OCDeviceInfo deviceInfo); + +/** + * Create a resource. + * + * @param handle - pointer to handle to newly created resource. Set by ocstack. Used to refer to resource + * @param resourceTypeName - name of resource type. Example: "core.led" + * @param resourceInterfaceName - name of resource interface. Example: "core.rw" + * @param uri - URI of the resource. Example: "/a/led" + * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc + * NULL for default entity handler + * @param resourceProperties - properties supported by resource. Example: OC_DISCOVERABLE|OC_OBSERVABLE + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ +OCStackResult OCCreateResource(OCResourceHandle *handle, + const char *resourceTypeName, + const char *resourceInterfaceName, + const char *uri, + OCEntityHandler entityHandler, + uint8_t resourceProperties); + +/** + * Create a resource. with host ip address for remote resource + * + * @param handle - pointer to handle to newly created resource. Set by ocstack. + * Used to refer to resource + * @param resourceTypeName - name of resource type. Example: "core.led" + * @param resourceInterfaceName - name of resource interface. Example: "core.rw" + * @param host - HOST address of the remote resource. Example: "coap://xxx.xxx.xxx.xxx:xxxxx" + * @param uri - URI of the resource. Example: "/a/led" + * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc + * NULL for default entity handler + * @param resourceProperties - properties supported by resource. + * Example: OC_DISCOVERABLE|OC_OBSERVABLE + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ +OCStackResult OCCreateResourceWithHost(OCResourceHandle *handle, + const char *resourceTypeName, + const char *resourceInterfaceName, + const char *host, + const char *uri, + OCEntityHandler entityHandler, + uint8_t resourceProperties); + +/** + * Add a resource to a collection resource. + * + * @param collectionHandle - handle to the collection resource + * @param resourceHandle - handle to resource to be added to the collection resource + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + * OC_STACK_INVALID_PARAM - invalid collectionhandle + */ +OCStackResult OCBindResource(OCResourceHandle collectionHandle, OCResourceHandle resourceHandle); + +/** + * Remove a resource from a collection resource. + * + * @param collectionHandle - handle to the collection resource + * @param resourceHandle - handle to resource to be removed from the collection resource + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + * OC_STACK_INVALID_PARAM - invalid collectionhandle + */ +OCStackResult OCUnBindResource(OCResourceHandle collectionHandle, OCResourceHandle resourceHandle); + +/** + * Bind a resourcetype to a resource. + * + * @param handle - handle to the resource + * @param resourceTypeName - name of resource type. Example: "core.led" + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ +OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle, + const char *resourceTypeName); +/** + * Bind a resource interface to a resource. + * + * @param handle - handle to the resource + * @param resourceInterfaceName - name of resource interface. Example: "core.rw" + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ +OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle, + const char *resourceInterfaceName); + +/** + * Bind an entity handler to the resource. + * + * @param handle - handle to the resource that the contained resource is to be bound + * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ +OCStackResult OCBindResourceHandler(OCResourceHandle handle, OCEntityHandler entityHandler); + +/** + * Get the number of resources that have been created in the stack. + * + * @param numResources - pointer to count variable + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + + */ +OCStackResult OCGetNumberOfResources(uint8_t *numResources); + +/** + * Get a resource handle by index. + * + * @param index - index of resource, 0 to Count - 1 + * + * @return + * Resource handle - if found + * NULL - if not found + */ +OCResourceHandle OCGetResourceHandle(uint8_t index); + +/** + * Delete resource specified by handle. Deletes resource and all resourcetype and resourceinterface + * linked lists. + * + * Note: OCDeleteResource() performs operations similar to OCNotifyAllObservers() to notify all + * client observers that "this" resource is being deleted. + * + * @param handle - handle of resource to be deleted + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ +OCStackResult OCDeleteResource(OCResourceHandle handle); + +/** + * Get the URI of the resource specified by handle. + * + * @param handle - handle of resource + * @return + * URI string - if resource found + * NULL - resource not found + */ +const char *OCGetResourceUri(OCResourceHandle handle); + +/** + * Get the properties of the resource specified by handle. + * NOTE: that after a resource is created, the OC_ACTIVE property is set + * for the resource by the stack. + * + * @param handle - handle of resource + * @return + * property bitmap - if resource found + * NULL - resource not found + */ +uint8_t OCGetResourceProperties(OCResourceHandle handle); + +/** + * Get the number of resource types of the resource. + * + * @param handle - handle of resource + * @param numResourceTypes - pointer to count variable + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ +OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle, uint8_t *numResourceTypes); + +/** + * Get name of resource type of the resource. + * + * @param handle - handle of resource + * @param index - index of resource, 0 to Count - 1 + * + * @return + * resource type name - if resource found + * NULL - resource not found + */ +const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index); + +/** + * Get the number of resource interfaces of the resource. + * + * @param handle - handle of resource + * @param numResources - pointer to count variable + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + + */ +OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle, uint8_t *numResourceInterfaces); + +/** + * Get name of resource interface of the resource. + * + * @param handle - handle of resource + * @param index - index of resource, 0 to Count - 1 + * + * @return + * resource interface name - if resource found + * NULL - resource not found + */ +const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index); + +/** + * Get methods of resource interface of the resource. + * + * @param handle - handle of resource + * @param index - index of resource, 0 to Count - 1 + * + * @return + * allowed methods - if resource found + * NULL - resource not found + */ +uint8_t OCGetResourceInterfaceAllowedMethods(OCResourceHandle handle, uint8_t index); + +/** + * Get resource handle from the collection resource by index. + * + * @param collectionHandle - handle of collection resource + * @param index - index of contained resource, 0 to Count - 1 + * + * @return + * handle to contained resource - if resource found + * NULL - resource not found + */ +OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle, uint8_t index); + +/** + * Get the entity handler for a resource. + * + * @param handle - handle of resource + * + * @return + * entity handler - if resource found + * NULL - resource not found + */ +OCEntityHandler OCGetResourceHandler(OCResourceHandle handle); + +/** + * Notify all registered observers that the resource representation has + * changed. If observation includes a query the client is notified only + * if the query is valid after the resource representation has changed. + * + * @param handle - handle of resource + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_NO_RESOURCE - invalid resource handle + * OC_STACK_NO_OBSERVERS - no more observers intrested in resource + */ +OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos); + +/** + * Notify specific observers with updated value of representation. + * Before this API is invoked by entity handler it has finished processing + * queries for the associated observers. + * + * @param handle - handle of resource + * @param obsIdList - list of observation ids that need to be notified + * @param numberOfIds - number of observation ids included in obsIdList + * @param notificationJSONPayload - JSON encoded payload to send in notification + * @param qos - desired quality of service of the observation notifications + * NOTE: The memory for obsIdList and notificationJSONPayload is managed by the + * entity invoking the API. The maximum size of the notification is 1015 bytes + * for non-Arduino platforms. For Arduino the maximum size is 247 bytes. + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_NO_RESOURCE - invalid resource handle + */ +OCStackResult +OCNotifyListOfObservers (OCResourceHandle handle, + OCObservationId *obsIdList, + uint8_t numberOfIds, + unsigned char *notificationJSONPayload, + OCQualityOfService qos); + + +/** + * Send a response to a request. + * The response can be a normal, slow, or block (i.e. a response that + * is too large to be sent in a single PDU and must span multiple transmissions) + * + * @param response - pointer to structure that contains response parameters + * + * @return + * OC_STACK_OK - no errors + */ +OCStackResult OCDoResponse(OCEntityHandlerResponse *response); + +/** + * Cancel a response. Applies to a block response + * + * @param responseHandle - response handle set by stack in OCServerResponse after + * OCDoResponse is called + * + * @return + * OC_STACK_OK - No errors; Success + * OC_STACK_INVALID_PARAM - The handle provided is invalid. + */ +OCStackResult OCCancelResponse(OCResponseHandle responseHandle); + + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* OCSTACK_H_ */ diff --git a/resource/csdk/stack/include/ocstackconfig.h b/resource/csdk/stack/include/ocstackconfig.h new file mode 100644 index 000000000..9e14bd3d0 --- /dev/null +++ b/resource/csdk/stack/include/ocstackconfig.h @@ -0,0 +1,86 @@ +//****************************************************************** +// +// Copyright 2014 Intel Corporation All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OCSTACK_CONFIG_H_ +#define OCSTACK_CONFIG_H_ + +// This file contains all the variables which can be configured/modified as +// per platform or specific product usage scenarios. + + +/** + * Maximum length of the response supported by Server for any REST request. + */ +#ifdef WITH_ARDUINO +#define MAX_RESPONSE_LENGTH (256) +#else +#define MAX_RESPONSE_LENGTH (1024) +#endif + +/** + * Maximum length of the request supported by Client/Server for any REST request. + */ +#ifdef WITH_ARDUINO +#define MAX_REQUEST_LENGTH (256) +#else +#define MAX_REQUEST_LENGTH (1024) +#endif + +/** + * Maximum length of the URI supported by client/server while processing + * REST requests/responses. + */ +#define MAX_URI_LENGTH (64) + +/** + * Maximum length of the query supported by client/server while processing + * REST requests/responses. + */ +#define MAX_QUERY_LENGTH (64) + +/** + * Maximum length of the Manufacturer name supported by the server + * for manufacturer name + */ +#define MAX_MANUFACTURER_NAME_LENGTH (16) + +/** + * Maximum length of the URL to the Manufacturer details supported by + * the server. + */ +#define MAX_MANUFACTURER_URL_LENGTH (32) + +/** + * Maximum number of resources which can be contained inside collection + * resource. + */ +#define MAX_CONTAINED_RESOURCES (5) + +/** + * Maximum number of vendor specific header options an application can set or receive in pdu + */ +#define MAX_HEADER_OPTIONS (2) + +/** + * Maximum Length of the vendor specific header option + */ +#define MAX_HEADER_OPTION_DATA_LENGTH (16) + +#endif //OCSTACK_CONFIG_H_ diff --git a/resource/csdk/stack/samples/arduino/SimpleClientServer/README b/resource/csdk/stack/samples/arduino/SimpleClientServer/README new file mode 100644 index 000000000..78f204efa --- /dev/null +++ b/resource/csdk/stack/samples/arduino/SimpleClientServer/README @@ -0,0 +1,46 @@ +------------------------------------------------------------------------------- + NOTICE - Transition to SCONS +------------------------------------------------------------------------------- + +The IoTivity build system is transitioning to SCONS. Although the +makefiles are still available (until v1.0) and some developers are +still using them, they are currently no longer supported. To learn more +about building using SCONS see Readme.scons.txt in the repository root +directory. The build steps used in continuous integration can be found +in auto_build.sh which is also in the the repository root directory. + +------------------------------------------------------------------------------- +**Arduino** -- Must be built with the same BUILD mode declared as octbstack.a. +------------------------------------------------------------------------------- +When an Arduino SimpleClientServer application is running, it outputs logs to +serial port. This requires the current user to be a part of the "dialout" user +group permissions on Ubuntu. If your Arduino device is NOT installed at +location "ttyACM0", you must define ARDUINO_PORT to the location it is +installed at. This location will be referred to as . + +You can only install one application at a time. Your choices are "oclient" or +"ocserver." Your selection will be referred to as . + +This makefile relies on "local.properties" at the directory level of the +makefile that generates octbstack.a. Please refer to the README at that level +to determine what definitions are needed for your environment. + +To make occlient or ocserver in release mode: + + make + +To make & install occlient or ocserver in release mode, with specified: + + make install APP_INSTALL= ARDUINO_PORT= + +To make & install occlient or ocserver in debug mode: + + make install APP_INSTALL= ARDUINO_PORT= BUILD=debug + +------------------------------------------------------------------------------- +**Clean-Up** +------------------------------------------------------------------------------- +To clean occlient & ocserver sample apps and objects: + + sudo make clean + diff --git a/resource/csdk/stack/samples/arduino/SimpleClientServer/makefile b/resource/csdk/stack/samples/arduino/SimpleClientServer/makefile new file mode 100644 index 000000000..09a61a495 --- /dev/null +++ b/resource/csdk/stack/samples/arduino/SimpleClientServer/makefile @@ -0,0 +1,38 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +BUILD := release +ARDUINO_PORT := /dev/ttyACM0 +APP_INSTALL := ocserver +PLATFORM := arduinomega +ARDUINOWIFI := 0 + +ocserver: + $(MAKE) -c ./$@ "BUILD=$(BUILD)" "install" "PLATFORM=$(PLATFORM)" "ARDUINO_PORT=$(ARDUINO_PORT)" "BUILD=$(BUILD)" "ARDUINOWIFI=$(ARDUINOWIFI)" + +occlient: + $(MAKE) -c ./$@ "BUILD=$(BUILD)" + +install: + $(MAKE) -C ./$(APP_INSTALL) "install" "PLATFORM=$(PLATFORM)" "ARDUINO_PORT=$(ARDUINO_PORT)" "BUILD=$(BUILD)" "ARDUINOWIFI=$(ARDUINOWIFI)" + +clean: + $(MAKE) -C ./occlient "clean" + $(MAKE) -C ./ocserver "clean" diff --git a/resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/README b/resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/README new file mode 100644 index 000000000..dc0e35b75 --- /dev/null +++ b/resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/README @@ -0,0 +1,51 @@ +------------------------------------------------------------------------------- + NOTICE - Transition to SCONS +------------------------------------------------------------------------------- + +The IoTivity build system is transitioning to SCONS. Although the +makefiles are still available (until v1.0) and some developers are +still using them, they are currently no longer supported. To learn more +about building using SCONS see Readme.scons.txt in the repository root +directory. The build steps used in continuous integration can be found +in auto_build.sh which is also in the the repository root directory. + +------------------------------------------------------------------------------- +**Arduino** -- Must be built with the same BUILD mode declared as octbstack.a. +------------------------------------------------------------------------------- +When an Arduino SimpleClientServer application is running, it outputs logs to +serial port. This requires the current user to be a part of the "dialout" user +group permissions on Ubuntu. If your Arduino device is NOT installed at +location "ttyACM0", you must define ARDUINO_PORT to the location it is +installed at. This location will be referred to as . + +This makefile relies on "local.properties" at the directory level of the +makefile that generates octbstack.a. Please refer to the README at that level +to determine what definitions are needed for your environment. + +To make ocserver in release mode: + + make (arduinomega) + make -f makefiledue (arduinodue) + +To make & install ocserver in release mode, with NOT specified: + + make install (arduinomega) + make -f makefiledue install (arduinodue) + +To make & install ocserver in release mode, with specified: + + make install ARDUINO_PORT= + +To make & install ocserver in debug mode, with specified: + + make install ARDUINO_PORT= BUILD=debug + +To make ocserver_wifi with Arduino WiFi Shield support: + + make ARDUINOWIFI=1 (arduinomega) +------------------------------------------------------------------------------- +**Clean-Up** +------------------------------------------------------------------------------- +To clean ocserver sample app and objects: + + make clean diff --git a/resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/SConscript b/resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/SConscript new file mode 100644 index 000000000..f5a4222a5 --- /dev/null +++ b/resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/SConscript @@ -0,0 +1,23 @@ +Import('env') + +arduino_simplecs_env = env.Clone() +###################################################################### +# Build flags +###################################################################### +arduino_simplecs_env.PrependUnique(CPPPATH = [ + '../../../../../ocsocket/include', + '../../../../../logger/include', + '../../../../../stack/include', + '../../../../../../oc_logger/include' + ]) + +arduino_simplecs_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')]) +arduino_simplecs_env.PrependUnique(LIBS = ['octbstack', 'coap']) + +arduino_simplecs = arduino_simplecs_env.Program('SimpleClientServer', 'ocserver.cpp') +env.CreateBin('SimpleClientServer') + +i_arduino_simplecs = arduino_simplecs_env.Install(env.get('BUILD_DIR'), arduino_simplecs) + +Alias('arduino_simplecs', i_arduino_simplecs) +env.AppendTarget('arduino_simplecs') \ No newline at end of file diff --git a/resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/makefile b/resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/makefile new file mode 100644 index 000000000..3b0110986 --- /dev/null +++ b/resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/makefile @@ -0,0 +1,122 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# + +BUILD := release +PLATFORM := arduinomega +ARDUINO_PORT := ttyACM0 + +# override with `make PLATFORM=arduinomega ARDUINOWIFI=1` to enable Arduino WiFi shield +ARDUINOWIFI := 0 + +APP_NAME := ocserver + +ROOT_DIR = ../../../../.. +LOGGER_DIR = $(ROOT_DIR)/logger +OC_LOG_DIR = $(ROOT_DIR)/../oc_logger +TBSTACK_DIR = $(ROOT_DIR)/stack +TBSOCKET_DIR = $(ROOT_DIR)/ocsocket + +include $(ROOT_DIR)/local.properties +include $(ROOT_DIR)/$(PLATFORM).properties + +VPATH := $(SDIR_ARD_PLATFORM) + +#include directories +OCSOCK_DIR = $(ROOT_DIR)/ocsocket +LOGGER_DIR = $(ROOT_DIR)/logger +STACK_DIR = $(ROOT_DIR)/stack +INC_DIRS = -I$(OCSOCK_DIR)/include/ -I$(OC_LOG_DIR)/include -I$(LOGGER_DIR)/include -I$(STACK_DIR)/include + +CC_FLAGS.debug := -O1 -g3 -Wall -c -fmessage-length=0 -pedantic -fpic +CC_FLAGS.release := -Os -Wall -c -fmessage-length=0 -fpic + +CFLAGS := $(CC_FLAGS.$(BUILD)) -DTB_LOG + +ifeq ($(ARDUINOWIFI),1) + CFLAGS += -DARDUINOWIFI + ARDUINO_SHIELD_TYPE := "/wifi_shield" + TRANSPORT_OBJS = $(WIFI_COBJ) +else + ARDUINO_SHIELD_TYPE := "/ethernet_shield" + TRANSPORT_OBJS = $(ETH_CPPOBJ) $(ETH_UTIL_CPPOBJ) +endif + +OUT_DIR := $(PLATFORM)$(ARDUINO_SHIELD_TYPE)/$(BUILD) + +OBJ_DIR := $(OUT_DIR)/bin + +all: prep_dirs core.a $(APP_NAME).o $(APP_NAME).elf $(APP_NAME).hex + +core.a: $(PLATFORM_OBJS) + @cd $(OBJ_DIR) && $(AR) -x ../../../../$(ROOT_DIR)/$(PLATFORM)$(ARDUINO_SHIELD_TYPE)/$(BUILD)/liboctbstack.a + $(AR) rcs $(OBJ_DIR)/$@ $(foreach obj, $^, $(OBJ_DIR)/$(obj)) $(OBJ_DIR)/*.o + @cd $(OBJ_DIR) && $(RANLIB) $@ + +prep_dirs: + -mkdir $(PLATFORM) + -mkdir $(PLATFORM)/$(ARDUINO_SHIELD_TYPE) + -mkdir $(OUT_DIR) + -mkdir $(OBJ_DIR) + +%.o: %.c + $(CC) $(CFLAGS) $(CFLAGS_PLATFORM) $(INC_DIRS) $(INC_DIR_PLATFORM) $< -o $(OBJ_DIR)/$@ + +%.o: %.cpp + $(CXX) $(CFLAGS) $(CFLAGS_PLATFORM) $(INC_DIRS) $(INC_DIR_PLATFORM) $< -o $(OBJ_DIR)/$@ + +$(APP_NAME).elf: $(APP_NAME).o core.a +ifeq ($(PLATFORM),arduinomega) + $(CC) -Os -Wl,--gc-sections,--relax $(CFLAGS_PLATFORM) $(foreach obj, $^, $(OBJ_DIR)/$(obj)) -lm -o $(OBJ_DIR)/$@ +else ifeq ($(PLATFORM),arduinodue) + $(CXX) -Os -Wl,--gc-sections -mcpu=cortex-m3 -T/$(SDIR_ARD_CORE_3)/linker_scripts/gcc/flash.ld -Wl,-Map,$(APP_NAME).map -o $(OBJ_DIR)/$@ -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group $(foreach obj, $(APP_NAME).o $(SYSCALLS_SAM3_OBJ) $(SPI_OBJ) $(TRANSPORT_OBJS) $(VARIANT_OBJ) core.a, $(OBJ_DIR)/$(obj)) $(SDIR_ARD_CORE_3)/libsam_sam3x8e_gcc_rel.a -Wl,--end-group +else + $(error Wrong value for PLATFORM !!) +endif + +$(APP_NAME).hex: $(APP_NAME).elf +ifeq ($(PLATFORM),arduinomega) + $(AVR_OBJCOPY) -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 $(OBJ_DIR)/$< $(OBJ_DIR)/$(APP_NAME).eep + $(AVR_OBJCOPY) -O ihex -R .eeprom $(OBJ_DIR)/$< $(OUT_DIR)/$@ +else ifeq ($(PLATFORM),arduinodue) + $(ARDUINO_TOOLS_DIR)/arm-none-eabi-objcopy -O binary $(OBJ_DIR)/$< $(OUT_DIR)/$@ +else + $(error Wrong value for PLATFORM !!) +endif + +install: all +ifeq ($(PLATFORM),arduinomega) + $(AVR_PROGRAMMER) -C$(ARDUINO_DIR)/hardware/tools/avrdude.conf -v -v -v -v -patmega2560 -cstk500v2 -P/dev/$(ARDUINO_PORT) -b115200 -D -Uflash:w:$(OUT_DIR)/$(APP_NAME).hex:i +else ifeq ($(PLATFORM),arduinodue) + stty -F /dev/$(ARDUINO_PORT) speed 1200 cs8 -cstopb -parenb + $(ARDUINO_DIR)/hardware/tools/bossac -i -d --port=$(ARDUINO_PORT) -U false -e -w -v -b $(OUT_DIR)/$(APP_NAME).hex -R +else + $(error Wrong value for PLATFORM !!) +endif + +.PHONY: clean + +clean: legacy_clean + rm -rf arduinomega + rm -rf arduinodue + +legacy_clean: + @rm -rf bin + @rm -f *.o *.d *.elf *.eep *.a *.hex *.bin *.map *- diff --git a/resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/ocserver.cpp b/resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/ocserver.cpp new file mode 100644 index 000000000..e5cd93ff2 --- /dev/null +++ b/resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/ocserver.cpp @@ -0,0 +1,345 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// Do not remove the include below +#include "Arduino.h" + +#include "logger.h" +#include "ocstack.h" +#include + +#ifdef ARDUINOWIFI +// Arduino WiFi Shield +#include +#include +#include +#else +// Arduino Ethernet Shield +#include +#include +#include +#include +#include +#include +#include +#endif + +const char *getResult(OCStackResult result); + +PROGMEM const char TAG[] = "ArduinoServer"; + +int gLightUnderObservation = 0; +void createLightResource(); + +/* Structure to represent a Light resource */ +typedef struct LIGHTRESOURCE{ + OCResourceHandle handle; + bool state; + int power; +} LightResource; + +static LightResource Light; + +static char responsePayloadGet[] = "{\"href\":\"/a/light\",\"rep\":{\"state\":\"on\",\"power\":10}}"; +static char responsePayloadPut[] = "{\"href\":\"/a/light\",\"rep\":{\"state\":\"off\",\"power\":0}}"; + +/// This is the port which Arduino Server will use for all unicast communication with it's peers +static uint16_t OC_WELL_KNOWN_PORT = 5683; + +#ifdef ARDUINOWIFI +// Arduino WiFi Shield +// Note : Arduino WiFi Shield currently does NOT support multicast and therefore +// this server will NOT be listening on 224.0.1.187 multicast address. + +/// WiFi Shield firmware with Intel patches +static const char INTEL_WIFI_SHIELD_FW_VER[] = "1.2.0"; + +/// WiFi network info and credentials +char ssid[] = "mDNSAP"; +char pass[] = "letmein9"; + +int ConnectToNetwork() +{ + char *fwVersion; + int status = WL_IDLE_STATUS; + // check for the presence of the shield: + if (WiFi.status() == WL_NO_SHIELD) + { + OC_LOG(ERROR, TAG, PCF("WiFi shield not present")); + return -1; + } + + // Verify that WiFi Shield is running the firmware with all UDP fixes + fwVersion = WiFi.firmwareVersion(); + OC_LOG_V(INFO, TAG, "WiFi Shield Firmware version %s", fwVersion); + if ( strncmp(fwVersion, INTEL_WIFI_SHIELD_FW_VER, sizeof(INTEL_WIFI_SHIELD_FW_VER)) !=0 ) + { + OC_LOG(DEBUG, TAG, PCF("!!!!! Upgrade WiFi Shield Firmware version !!!!!!")); + return -1; + } + + // attempt to connect to Wifi network: + while (status != WL_CONNECTED) + { + OC_LOG_V(INFO, TAG, "Attempting to connect to SSID: %s", ssid); + status = WiFi.begin(ssid,pass); + + // wait 10 seconds for connection: + delay(10000); + } + OC_LOG(DEBUG, TAG, PCF("Connected to wifi")); + + IPAddress ip = WiFi.localIP(); + OC_LOG_V(INFO, TAG, "IP Address: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); + return 0; +} +#else +// Arduino Ethernet Shield +int ConnectToNetwork() +{ + // Note: ****Update the MAC address here with your shield's MAC address**** + uint8_t ETHERNET_MAC[] = {0x90, 0xA2, 0xDA, 0x0E, 0xC4, 0x05}; + uint8_t error = Ethernet.begin(ETHERNET_MAC); + if (error == 0) + { + OC_LOG_V(ERROR, TAG, "error is: %d", error); + return -1; + } + + IPAddress ip = Ethernet.localIP(); + OC_LOG_V(INFO, TAG, "IP Address: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); + return 0; +} +#endif //ARDUINOWIFI + +// On Arduino Atmel boards with Harvard memory architecture, the stack grows +// downwards from the top and the heap grows upwards. This method will print +// the distance(in terms of bytes) between those two. +// See here for more details : +// http://www.atmel.com/webdoc/AVRLibcReferenceManual/malloc_1malloc_intro.html +void PrintArduinoMemoryStats() +{ + #ifdef ARDUINO_AVR_MEGA2560 + //This var is declared in avr-libc/stdlib/malloc.c + //It keeps the largest address not allocated for heap + extern char *__brkval; + //address of tmp gives us the current stack boundry + int tmp; + OC_LOG_V(INFO, TAG, "Stack: %u Heap: %u", (unsigned int)&tmp, (unsigned int)__brkval); + OC_LOG_V(INFO, TAG, "Unallocated Memory between heap and stack: %u", + ((unsigned int)&tmp - (unsigned int)__brkval)); + #endif +} + +// This is the entity handler for the registered resource. +// This is invoked by OCStack whenever it recevies a request for this resource. +OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest ) +{ + OCEntityHandlerResult ehRet = OC_EH_OK; + OCEntityHandlerResponse response = {0}; + char payload[MAX_RESPONSE_LENGTH] = {0}; + + if(entityHandlerRequest && (flag & OC_REQUEST_FLAG)) + { + OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG")); + + if(OC_REST_GET == entityHandlerRequest->method) + { + size_t responsePayloadGetLength = strlen(responsePayloadGet); + if (responsePayloadGetLength < (sizeof(payload) - 1)) + { + strncpy(payload, responsePayloadGet, responsePayloadGetLength); + } + else + { + ehRet = OC_EH_ERROR; + } + } + else if(OC_REST_PUT == entityHandlerRequest->method) + { + //Do something with the 'put' payload + size_t responsePayloadPutLength = strlen(responsePayloadPut); + if (responsePayloadPutLength < (sizeof(payload) - 1)) + { + strncpy((char *)payload, responsePayloadPut, responsePayloadPutLength); + } + else + { + ehRet = OC_EH_ERROR; + } + } + + if (ehRet == OC_EH_OK) + { + // Format the response. Note this requires some info about the request + response.requestHandle = entityHandlerRequest->requestHandle; + response.resourceHandle = entityHandlerRequest->resource; + response.ehResult = ehRet; + response.payload = (unsigned char *)payload; + response.payloadSize = strlen(payload); + response.numSendVendorSpecificHeaderOptions = 0; + memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions); + memset(response.resourceUri, 0, sizeof response.resourceUri); + // Indicate that response is NOT in a persistent buffer + response.persistentBufferFlag = 0; + + // Send the response + if (OCDoResponse(&response) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "Error sending response"); + ehRet = OC_EH_ERROR; + } + } + } + if (entityHandlerRequest && (flag & OC_OBSERVE_FLAG)) + { + if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action) + { + OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_REGISTER from client")); + gLightUnderObservation = 1; + } + else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action) + { + OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_DEREGISTER from client")); + } + } + + return ehRet; +} + +// This method is used to display 'Observe' functionality of OC Stack. +static uint8_t modCounter = 0; +void *ChangeLightRepresentation (void *param) +{ + (void)param; + OCStackResult result = OC_STACK_ERROR; + modCounter += 1; + if(modCounter % 10 == 0) // Matching the timing that the Linux Sample Server App uses for the same functionality. + { + Light.power += 5; + if (gLightUnderObservation) + { + OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", Light.power); + result = OCNotifyAllObservers (Light.handle, OC_NA_QOS); + if (OC_STACK_NO_OBSERVERS == result) + { + gLightUnderObservation = 0; + } + } + } + return NULL; +} + +//The setup function is called once at startup of the sketch +void setup() +{ + // Add your initialization code here + // Note : This will initialize Serial port on Arduino at 115200 bauds + OC_LOG_INIT(); + OC_LOG(DEBUG, TAG, PCF("OCServer is starting...")); + uint16_t port = OC_WELL_KNOWN_PORT; + + // Connect to Ethernet or WiFi network + if (ConnectToNetwork() != 0) + { + OC_LOG(ERROR, TAG, PCF("Unable to connect to network")); + return; + } + + // Initialize the OC Stack in Server mode + if (OCInit(NULL, port, OC_SERVER) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, PCF("OCStack init error")); + return; + } + + // Declare and create the example resource: Light + createLightResource(); +} + +// The loop function is called in an endless loop +void loop() +{ + // This artificial delay is kept here to avoid endless spinning + // of Arduino microcontroller. Modify it as per specfic application needs. + delay(2000); + + // This call displays the amount of free SRAM available on Arduino + PrintArduinoMemoryStats(); + + // Give CPU cycles to OCStack to perform send/recv and other OCStack stuff + if (OCProcess() != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, PCF("OCStack process error")); + return; + } + ChangeLightRepresentation(NULL); +} + +void createLightResource() +{ + Light.state = false; + OCStackResult res = OCCreateResource(&Light.handle, + "core.light", + "oc.mi.def", + "/a/light", + OCEntityHandlerCb, + OC_DISCOVERABLE|OC_OBSERVABLE); + OC_LOG_V(INFO, TAG, "Created Light resource with result: %s", getResult(res)); +} + +const char *getResult(OCStackResult result) { + switch (result) { + case OC_STACK_OK: + return "OC_STACK_OK"; + case OC_STACK_INVALID_URI: + return "OC_STACK_INVALID_URI"; + case OC_STACK_INVALID_QUERY: + return "OC_STACK_INVALID_QUERY"; + case OC_STACK_INVALID_IP: + return "OC_STACK_INVALID_IP"; + case OC_STACK_INVALID_PORT: + return "OC_STACK_INVALID_PORT"; + case OC_STACK_INVALID_CALLBACK: + return "OC_STACK_INVALID_CALLBACK"; + case OC_STACK_INVALID_METHOD: + return "OC_STACK_INVALID_METHOD"; + case OC_STACK_NO_MEMORY: + return "OC_STACK_NO_MEMORY"; + case OC_STACK_COMM_ERROR: + return "OC_STACK_COMM_ERROR"; + case OC_STACK_INVALID_PARAM: + return "OC_STACK_INVALID_PARAM"; + case OC_STACK_NOTIMPL: + return "OC_STACK_NOTIMPL"; + case OC_STACK_NO_RESOURCE: + return "OC_STACK_NO_RESOURCE"; + case OC_STACK_RESOURCE_ERROR: + return "OC_STACK_RESOURCE_ERROR"; + case OC_STACK_SLOW_RESOURCE: + return "OC_STACK_SLOW_RESOURCE"; + case OC_STACK_NO_OBSERVERS: + return "OC_STACK_NO_OBSERVERS"; + case OC_STACK_ERROR: + return "OC_STACK_ERROR"; + default: + return "UNKNOWN"; + } +} diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/common.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/common.cpp new file mode 100644 index 000000000..3f2b586fa --- /dev/null +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/common.cpp @@ -0,0 +1,74 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include + +const char *getResult(OCStackResult result) { + switch (result) { + case OC_STACK_OK: + return "OC_STACK_OK"; + case OC_STACK_RESOURCE_CREATED: + return "OC_STACK_RESOURCE_CREATED"; + case OC_STACK_RESOURCE_DELETED: + return "OC_STACK_RESOURCE_DELETED"; + case OC_STACK_INVALID_URI: + return "OC_STACK_INVALID_URI"; + case OC_STACK_INVALID_QUERY: + return "OC_STACK_INVALID_QUERY"; + case OC_STACK_INVALID_IP: + return "OC_STACK_INVALID_IP"; + case OC_STACK_INVALID_PORT: + return "OC_STACK_INVALID_PORT"; + case OC_STACK_INVALID_CALLBACK: + return "OC_STACK_INVALID_CALLBACK"; + case OC_STACK_INVALID_METHOD: + return "OC_STACK_INVALID_METHOD"; + case OC_STACK_NO_MEMORY: + return "OC_STACK_NO_MEMORY"; + case OC_STACK_COMM_ERROR: + return "OC_STACK_COMM_ERROR"; + case OC_STACK_INVALID_PARAM: + return "OC_STACK_INVALID_PARAM"; + case OC_STACK_NOTIMPL: + return "OC_STACK_NOTIMPL"; + case OC_STACK_NO_RESOURCE: + return "OC_STACK_NO_RESOURCE"; + case OC_STACK_RESOURCE_ERROR: + return "OC_STACK_RESOURCE_ERROR"; + case OC_STACK_SLOW_RESOURCE: + return "OC_STACK_SLOW_RESOURCE"; + case OC_STACK_NO_OBSERVERS: + return "OC_STACK_NO_OBSERVERS"; + #ifdef WITH_PRESENCE + case OC_STACK_VIRTUAL_DO_NOT_HANDLE: + return "OC_STACK_VIRTUAL_DO_NOT_HANDLE"; + case OC_STACK_PRESENCE_STOPPED: + return "OC_STACK_PRESENCE_STOPPED"; + case OC_STACK_PRESENCE_TIMEOUT: + return "OC_STACK_PRESENCE_TIMEOUT"; + #endif + case OC_STACK_ERROR: + return "OC_STACK_ERROR"; + default: + return "UNKNOWN"; + } +} diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/makefile b/resource/csdk/stack/samples/linux/SimpleClientServer/makefile new file mode 100644 index 000000000..07164adc8 --- /dev/null +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/makefile @@ -0,0 +1,137 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +# override with `make BUILD=debug` +# default to release build +BUILD := release +PLATFORM := linux +CC := g++ +OUT_DIR := $(BUILD) +OBJ_DIR := $(OUT_DIR)/obj + +ifeq ($(ROOT_DIR), ) +ROOT_DIR = ../../../.. +endif + +OUT_DIR = . + +OCLOGGER_DIR = $(ROOT_DIR)/logger +OC_LOG_DIR = $(ROOT_DIR)/../oc_logger +OCRANDOM_DIR = $(ROOT_DIR)/ocrandom +OCSOCKET_DIR = $(ROOT_DIR)/ocsocket +LCOAP_DIR = $(ROOT_DIR)/libcoap-4.1.1 +OCCOAP_DIR = $(ROOT_DIR)/occoap +OCMALLOC_DIR = $(ROOT_DIR)/ocmalloc +OCTBSTACK_DIR = $(ROOT_DIR)/stack +EXTLIBS_DIR = $(ROOT_DIR)/../../extlibs +CJSON_DIR = $(EXTLIBS_DIR)/cjson + +CJSON_SRC = $(CJSON_DIR) + +OCLOGGER_INC = $(OCLOGGER_DIR)/include +OC_LOG_INC = $(OC_LOG_DIR)/include +OCRANDOM_INC = $(OCRANDOM_DIR)/include +OCSOCKET_INC = $(OCSOCKET_DIR)/include +LCOAP_INC = $(LCOAP_DIR) +OCCOAP_INC = $(OCCOAP_DIR)/include +OCMALLOC_INC = $(OCMALLOC_DIR)/include +OCTBSTACK_INC = $(OCTBSTACK_DIR)/include +CJSON_INC = $(CJSON_DIR) + +INC_DIRS := -I$(OCLOGGER_INC) +INC_DIRS += -I$(OC_LOG_INC) +INC_DIRS += -I$(OCRANDOM_INC) +INC_DIRS += -I$(OCSOCKET_INC) +INC_DIRS += -I$(LCOAP_INC) +INC_DIRS += -I$(OCCOAP_INC) +INC_DIRS += -I$(OCMALLOC_INC) +INC_DIRS += -I$(OCTBSTACK_INC) +INC_DIRS += -I$(CJSON_INC) + +CC_FLAGS.debug := -O0 -g3 -Wall -ffunction-sections -fdata-sections -fno-exceptions \ + -std=c++0x -pedantic $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD) -DTB_LOG +CC_FLAGS.release := -Os -Wall -fdata-sections -Wl,--gc-sections -Wl,-s -fno-exceptions \ + -std=c++0x $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD) -DTB_LOG + +LDLIBS += -loctbstack -lpthread +CPPFLAGS += $(CC_FLAGS.$(BUILD)) $(LDLIBS) + +CJSON_SOURCES := $(CJSON_SRC)/cJSON.c + +SOURCES := $(CJSON_SOURCES) +SOURCES += occlient.cpp ocserver.cpp occlientcoll.cpp ocservercoll.cpp common.cpp ocserverbasicops.cpp occlientbasicops.cpp ocserverslow.cpp occlientslow.cpp + +OBJECTS:= $(patsubst %.cpp, $(OBJ_DIR)/%.o, $(SOURCES)) + +PROGRAMS += ocserver +PROGRAMS += occlient +PROGRAMS += ocserverbasicops +PROGRAMS += ocserverslow +PROGRAMS += ocservercoll +PROGRAMS += occlientcoll +PROGRAMS += occlientbasicops +PROGRAMS += occlientslow + +all: c_sdk prep_dirs $(OBJECTS) $(PROGRAMS) + +prep_dirs: + -mkdir -p $(OUT_DIR) + -mkdir -p $(OBJ_DIR) + +c_sdk: + cd $(ROOT_DIR) && $(MAKE) BUILD=$(BUILD) PLATFORM=$(PLATFORM) + +$(OBJ_DIR)/%.o: %.cpp + $(CC) -c $(CPPFLAGS) $< -o $@ + +ocserver: $(OBJ_DIR)/ocserver.o $(OBJ_DIR)/common.o + $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@ + +ocserverslow: $(OBJ_DIR)/ocserverslow.o $(OBJ_DIR)/common.o + $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@ + +ocserverbasicops: $(OBJ_DIR)/ocserverbasicops.o $(OBJ_DIR)/common.o + $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@ + +ocservercoll: $(OBJ_DIR)/ocservercoll.o $(OBJ_DIR)/common.o + $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@ + +occlient: $(OBJ_DIR)/occlient.o $(OBJ_DIR)/common.o + $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@ + +occlientbasicops: $(OBJ_DIR)/occlientbasicops.o $(OBJ_DIR)/common.o + $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@ + +occlientslow: $(OBJ_DIR)/occlientslow.o $(OBJ_DIR)/common.o + $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@ + +occlientcoll: $(OBJ_DIR)/occlientcoll.o $(OBJ_DIR)/common.o + $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@ + +.PHONY: clean + +clean: legacy_clean + -rm -rf release + -rm -rf debug + cd $(ROOT_DIR) && $(MAKE) clean + cd $(ROOT_DIR) && $(MAKE) deepclean + +legacy_clean: + rm -f *.o $(PROGRAMS) diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp new file mode 100644 index 000000000..9965a22cf --- /dev/null +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp @@ -0,0 +1,706 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include +#include +#include +#include +#include +#include "ocstack.h" +#include "logger.h" +#include "occlient.h" + +static int UNICAST_DISCOVERY = 0; +static int TEST_CASE = 0; +static const char * TEST_APP_UNICAST_DISCOVERY_QUERY = "coap://0.0.0.0:5683/oc/core"; +static const char * TEST_APP_UNICAST_DEVICE_DISCOVERY_QUERY = "coap://0.0.0.0:5683/oc/core/d"; +static const char * TEST_APP_MULTICAST_DEVICE_DISCOVERY_QUERY = "coap://224.0.1.187:5683/oc/core/d"; +static std::string putPayload = "{\"state\":\"on\",\"power\":5}"; +static std::string coapServerIP = "255.255.255.255"; +static std::string coapServerPort = "5683"; +static std::string coapServerResource = "/a/light"; + +// The handle for the observe registration +OCDoHandle gObserveDoHandle; +#ifdef WITH_PRESENCE +// The handle for observe registration +OCDoHandle gPresenceHandle; +#endif +// After this crosses a threshold client deregisters for further notifications +int gNumObserveNotifies = 0; + +#ifdef WITH_PRESENCE +int gNumPresenceNotifies = 0; +#endif + +int gQuitFlag = 0; +/* SIGINT handler: set gQuitFlag to 1 for graceful termination */ +void handleSigInt(int signum) { + if (signum == SIGINT) { + gQuitFlag = 1; + } +} + +static void PrintUsage() +{ + OC_LOG(INFO, TAG, "Usage : occlient -u <0|1> -t <1|2|3|4|5|6|7>"); + OC_LOG(INFO, TAG, "-u <0|1> : Perform multicast/unicast discovery of resources"); + OC_LOG(INFO, TAG, "-t 1 : Discover Resources"); + OC_LOG(INFO, TAG, "-t 2 : Discover Resources and Initiate Nonconfirmable Get Request"); + OC_LOG(INFO, TAG, "-t 3 : Discover Resources and Initiate Nonconfirmable Put Requests"); + OC_LOG(INFO, TAG, "-t 4 : Discover Resources and Initiate Nonconfirmable Post Requests"); + OC_LOG(INFO, TAG, "-t 5 : Discover Resources and Initiate Nonconfirmable Delete Requests"); + OC_LOG(INFO, TAG, "-t 6 : Discover Resources and Initiate Nonconfirmable Observe Requests"); + OC_LOG(INFO, TAG, "-t 7 : Discover Resources and Initiate Nonconfirmable Get Request for a resource which is unavailable"); + + OC_LOG(INFO, TAG, "-t 8 : Discover Resources and Initiate Confirmable Get Request"); + OC_LOG(INFO, TAG, "-t 9 : Discover Resources and Initiate Confirmable Post Request"); + OC_LOG(INFO, TAG, "-t 10 : Discover Resources and Initiate Confirmable Delete Requests"); + OC_LOG(INFO, TAG, "-t 11 : Discover Resources and Initiate Confirmable Observe Requests"); + + #ifdef WITH_PRESENCE + OC_LOG(INFO, TAG, "-t 12 : Discover Resources and Initiate Nonconfirmable presence"); + OC_LOG(INFO, TAG, "-t 13 : Discover Resources and Initiate Nonconfirmable presence with "\ + "filter"); + OC_LOG(INFO, TAG, "-t 14 : Discover Resources and Initiate Nonconfirmable presence with "\ + "2 filters"); + #endif + + OC_LOG(INFO, TAG, "-t 15 : Discover Resources and Initiate Nonconfirmable Observe Requests "\ + "then cancel immediately"); + OC_LOG(INFO, TAG, "-t 16 : Discover Resources and Initiate Nonconfirmable Get Request and "\ + "add vendor specific header options"); + OC_LOG(INFO, TAG, "-t 17 : Discover Devices"); +} + +OCStackResult InvokeOCDoResource(std::ostringstream &query, + OCMethod method, OCQualityOfService qos, + OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions) +{ + OCStackResult ret; + OCCallbackData cbData; + OCDoHandle handle; + + cbData.cb = cb; + cbData.context = (void*)DEFAULT_CONTEXT_VALUE; + cbData.cd = NULL; + + ret = OCDoResource(&handle, method, query.str().c_str(), 0, + (method == OC_REST_PUT) ? putPayload.c_str() : NULL, + qos, &cbData, options, numOptions); + + if (ret != OC_STACK_OK) + { + OC_LOG_V(ERROR, TAG, "OCDoResource returns error %d with method %d", ret, method); + } + else if (method == OC_REST_OBSERVE || method == OC_REST_OBSERVE_ALL) + { + gObserveDoHandle = handle; + } + #ifdef WITH_PRESENCE + else if (method == OC_REST_PRESENCE) + { + gPresenceHandle = handle; + } + #endif + + return ret; +} + +OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) { + if(ctx == (void*)DEFAULT_CONTEXT_VALUE) + { + OC_LOG(INFO, TAG, "Callback Context for PUT recvd successfully"); + } + + if(clientResponse) + { + OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result)); + OC_LOG_V(INFO, TAG, "JSON = %s =============> Put Response", clientResponse->resJSONPayload); + } + return OC_STACK_DELETE_TRANSACTION; +} + +OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse) +{ + if(ctx == (void*)DEFAULT_CONTEXT_VALUE) + { + OC_LOG(INFO, TAG, "Callback Context for POST recvd successfully"); + } + + if(clientResponse) + { + OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result)); + OC_LOG_V(INFO, TAG, "JSON = %s =============> Post Response", clientResponse->resJSONPayload); + } + return OC_STACK_DELETE_TRANSACTION; +} + +OCStackApplicationResult deleteReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse) +{ + if(ctx == (void*)DEFAULT_CONTEXT_VALUE) + { + OC_LOG(INFO, TAG, "Callback Context for DELETE recvd successfully"); + } + + if(clientResponse) + { + OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result)); + OC_LOG_V(INFO, TAG, "JSON = %s =============> Delete Response", clientResponse->resJSONPayload); + } + return OC_STACK_DELETE_TRANSACTION; +} + +OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) +{ + if(clientResponse == NULL) + { + OC_LOG(INFO, TAG, "The clientResponse is NULL"); + return OC_STACK_DELETE_TRANSACTION; + } + if(ctx == (void*)DEFAULT_CONTEXT_VALUE) + { + OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully"); + } + + OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result)); + OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber); + OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response", clientResponse->resJSONPayload); + + if(clientResponse->rcvdVendorSpecificHeaderOptions && + clientResponse->numRcvdVendorSpecificHeaderOptions) + { + OC_LOG (INFO, TAG, "Received vendor specific options"); + uint8_t i = 0; + OCHeaderOption * rcvdOptions = clientResponse->rcvdVendorSpecificHeaderOptions; + for( i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++) + { + if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID) + { + OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with", + ((OCHeaderOption)rcvdOptions[i]).optionID ); + OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData, + ((OCHeaderOption)rcvdOptions[i]).optionLength); + } + } + } + return OC_STACK_DELETE_TRANSACTION; +} + +OCStackApplicationResult obsReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) { + if(ctx == (void*)DEFAULT_CONTEXT_VALUE) + { + OC_LOG(INFO, TAG, "Callback Context for OBS query recvd successfully"); + } + + if(clientResponse) + { + OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result)); + OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber); + OC_LOG_V(INFO, TAG, "Callback Context for OBSERVE notification recvd successfully %d", gNumObserveNotifies); + OC_LOG_V(INFO, TAG, "JSON = %s =============> Obs Response", clientResponse->resJSONPayload); + gNumObserveNotifies++; + if (gNumObserveNotifies == 3) //large number to test observing in DELETE case. + { + if(TEST_CASE == TEST_OBS_REQ_NON || TEST_CASE == TEST_OBS_REQ_CON){ + if (OCCancel (gObserveDoHandle, OC_LOW_QOS, NULL, 0) != OC_STACK_OK){ + OC_LOG(ERROR, TAG, "Observe cancel error"); + } + return OC_STACK_DELETE_TRANSACTION; + }else if(TEST_CASE == TEST_OBS_REQ_NON_CANCEL_IMM){ + if (OCCancel (gObserveDoHandle, OC_HIGH_QOS, NULL, 0) != OC_STACK_OK){ + OC_LOG(ERROR, TAG, "Observe cancel error"); + } + } + } + if(clientResponse->sequenceNumber == OC_OBSERVE_REGISTER){ + OC_LOG(INFO, TAG, "This also serves as a registration confirmation"); + }else if(clientResponse->sequenceNumber == OC_OBSERVE_DEREGISTER){ + OC_LOG(INFO, TAG, "This also serves as a deregistration confirmation"); + return OC_STACK_DELETE_TRANSACTION; + }else if(clientResponse->sequenceNumber == OC_OBSERVE_NO_OPTION){ + OC_LOG(INFO, TAG, "This also tells you that registration/deregistration failed"); + return OC_STACK_DELETE_TRANSACTION; + } + } + return OC_STACK_KEEP_TRANSACTION; +} +#ifdef WITH_PRESENCE +OCStackApplicationResult presenceCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) { + if(ctx == (void*)DEFAULT_CONTEXT_VALUE) + { + OC_LOG(INFO, TAG, "Callback Context for Presence recvd successfully"); + } + + if(clientResponse) + { + OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result)); + OC_LOG_V(INFO, TAG, "NONCE NUMBER: %u", clientResponse->sequenceNumber); + OC_LOG_V(INFO, TAG, "Callback Context for Presence notification recvd successfully %d", gNumPresenceNotifies); + OC_LOG_V(INFO, TAG, "JSON = %s =============> Presence Response", clientResponse->resJSONPayload); + gNumPresenceNotifies++; + if (gNumPresenceNotifies == 20) + { + if (OCCancel (gPresenceHandle, OC_LOW_QOS, NULL, 0) != OC_STACK_OK){ + OC_LOG(ERROR, TAG, "Presence cancel error"); + } + return OC_STACK_DELETE_TRANSACTION; + } + } + return OC_STACK_KEEP_TRANSACTION; +} +#endif + +// This is a function called back when a device is discovered +OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle, + OCClientResponse * clientResponse) { + uint8_t remoteIpAddr[4]; + uint16_t remotePortNu; + + if (ctx == (void*) DEFAULT_CONTEXT_VALUE) + { + OC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully"); + } + + if (clientResponse) + { + OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result)); + + OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddr, + remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3); + OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNu); + + OC_LOG_V(INFO, TAG, + "Device =============> Discovered %s @ %d.%d.%d.%d:%d", + clientResponse->resJSONPayload, remoteIpAddr[0], remoteIpAddr[1], + remoteIpAddr[2], remoteIpAddr[3], remotePortNu); + + parseClientResponse(clientResponse); + + switch(TEST_CASE) + { + case TEST_GET_REQ_NON: + InitGetRequest(OC_LOW_QOS, 0); + break; + case TEST_PUT_REQ_NON: + InitPutRequest(); + break; + case TEST_POST_REQ_NON: + InitPostRequest(OC_LOW_QOS); + break; + case TEST_DELETE_REQ_NON: + InitDeleteRequest(OC_LOW_QOS); + break; + case TEST_OBS_REQ_NON: + case TEST_OBS_REQ_NON_CANCEL_IMM: + InitObserveRequest(OC_LOW_QOS); + break; + case TEST_GET_UNAVAILABLE_RES_REQ_NON: + InitGetRequestToUnavailableResource(); + break; + case TEST_GET_REQ_CON: + InitGetRequest(OC_HIGH_QOS, 0); + break; + case TEST_POST_REQ_CON: + InitPostRequest(OC_HIGH_QOS); + break; + case TEST_DELETE_REQ_CON: + InitDeleteRequest(OC_HIGH_QOS); + break; + case TEST_OBS_REQ_CON: + InitObserveRequest(OC_HIGH_QOS); + break; + #ifdef WITH_PRESENCE + case TEST_OBS_PRESENCE: + case TEST_OBS_PRESENCE_WITH_FILTER: + case TEST_OBS_PRESENCE_WITH_FILTERS: + InitPresence(); + break; + #endif + case TEST_GET_REQ_NON_WITH_VENDOR_HEADER_OPTIONS: + InitGetRequest(OC_LOW_QOS, 1); + break; + case TEST_DISCOVER_DEV_REQ: + InitDeviceDiscovery(); + break; + default: + PrintUsage(); + break; + } + } + + return (UNICAST_DISCOVERY) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ; + +} + +OCStackApplicationResult DeviceDiscoveryReqCB (void* ctx, OCDoHandle handle, + OCClientResponse * clientResponse) +{ + if (ctx == (void*) DEFAULT_CONTEXT_VALUE) + { + OC_LOG(INFO, TAG, "Callback Context for Device DISCOVER query recvd successfully"); + } + + if(clientResponse) + { + //OC_LOG truncates the response as it is too long. + fprintf(stderr, "Discovery response: \n %s\n", clientResponse->resJSONPayload); + fflush(stderr); + } + + return (UNICAST_DISCOVERY) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION; +} + +#ifdef WITH_PRESENCE +int InitPresence() +{ + OCStackResult result = OC_STACK_OK; + OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); + std::ostringstream query; + std::ostringstream querySuffix; + query << "coap://" << coapServerIP << ":" << coapServerPort << OC_PRESENCE_URI; + if(TEST_CASE == TEST_OBS_PRESENCE) + { + result = InvokeOCDoResource(query, OC_REST_PRESENCE, OC_LOW_QOS, + presenceCB, NULL, 0); + } + if(TEST_CASE == TEST_OBS_PRESENCE_WITH_FILTER || TEST_CASE == TEST_OBS_PRESENCE_WITH_FILTERS) + { + querySuffix.str(""); + querySuffix << query.str() << "?rt=core.light"; + result = InvokeOCDoResource(querySuffix, OC_REST_PRESENCE, OC_LOW_QOS, + presenceCB, NULL, 0); + } + if(TEST_CASE == TEST_OBS_PRESENCE_WITH_FILTERS) + { + if(result == OC_STACK_OK) + { + querySuffix.str(""); + querySuffix << query.str() << "?rt=core.fan"; + result = InvokeOCDoResource(querySuffix, OC_REST_PRESENCE, OC_LOW_QOS, + presenceCB, NULL, 0); + } + } + return result; +} +#endif +int InitGetRequestToUnavailableResource() +{ + OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); + std::ostringstream query; + query << "coap://" << coapServerIP << ":" << coapServerPort << "/SomeUnknownResource"; + return (InvokeOCDoResource(query, OC_REST_GET, OC_LOW_QOS, getReqCB, NULL, 0)); +} + +int InitObserveRequest(OCQualityOfService qos) +{ + OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); + std::ostringstream query; + query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource; + return (InvokeOCDoResource(query, OC_REST_OBSERVE, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS, obsReqCB, NULL, 0)); +} + +int InitPutRequest() +{ + OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); + std::ostringstream query; + query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource; + return (InvokeOCDoResource(query, OC_REST_PUT, OC_LOW_QOS, putReqCB, NULL, 0)); +} + +int InitPostRequest(OCQualityOfService qos) +{ + OCStackResult result; + OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); + std::ostringstream query; + query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource; + + // First POST operation (to create an Light instance) + result = InvokeOCDoResource(query, OC_REST_POST, + ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), + postReqCB, NULL, 0); + if (OC_STACK_OK != result) + { + // Error can happen if for example, network connectivity is down + OC_LOG(INFO, TAG, "First POST call did not succeed"); + } + + // Second POST operation (to create an Light instance) + result = InvokeOCDoResource(query, OC_REST_POST, + ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), + postReqCB, NULL, 0); + if (OC_STACK_OK != result) + { + OC_LOG(INFO, TAG, "Second POST call did not succeed"); + } + + // This POST operation will update the original resourced /a/light + return (InvokeOCDoResource(query, OC_REST_POST, + ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), + postReqCB, NULL, 0)); +} + +void* RequestDeleteDeathResourceTask(void* myqos) +{ + sleep (30); //long enough to give the server time to finish deleting the resource. + std::ostringstream query; + query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource; + + OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); + + // Second DELETE operation to delete the resource that might have been removed already. + OCQualityOfService qos; + if (myqos == NULL) + qos = OC_LOW_QOS; + else + qos = OC_HIGH_QOS; + + OCStackResult result = InvokeOCDoResource(query, OC_REST_DELETE, + qos, + deleteReqCB, NULL, 0); + + if (OC_STACK_OK != result) + { + OC_LOG(INFO, TAG, "Second DELETE call did not succeed"); + } + + return NULL; +} + +int InitDeleteRequest(OCQualityOfService qos) +{ + OCStackResult result; + std::ostringstream query; + query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource; + + OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); + + // First DELETE operation + result = InvokeOCDoResource(query, OC_REST_DELETE, + qos, + deleteReqCB, NULL, 0); + if (OC_STACK_OK != result) + { + // Error can happen if for example, network connectivity is down + OC_LOG(INFO, TAG, "First DELETE call did not succeed"); + } + else + { + //Create a thread to delete this resource again + pthread_t threadId; + pthread_create (&threadId, NULL, RequestDeleteDeathResourceTask, (void*)qos); + } + + OC_LOG_V(INFO, TAG, "\n\nExit %s", __func__); + return result; +} + +int InitGetRequest(OCQualityOfService qos, uint8_t withVendorSpecificHeaderOptions) +{ + OCHeaderOption options[MAX_HEADER_OPTIONS]; + + OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); + std::ostringstream query; + query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource; + + if(withVendorSpecificHeaderOptions) + { + uint8_t option0[] = {1,2,3,4,5,6,7,8,9,10}; + uint8_t option1[] = {11,12,13,14,15,16,17,18,19,20}; + memset(options, 0, sizeof(OCHeaderOption) * MAX_HEADER_OPTIONS); + options[0].protocolID = OC_COAP_ID; + options[0].optionID = 2048; + memcpy(options[0].optionData, option0, sizeof(option0)); + options[0].optionLength = 10; + options[1].protocolID = OC_COAP_ID; + options[1].optionID = 3000; + memcpy(options[1].optionData, option1, sizeof(option1)); + options[1].optionLength = 10; + } + if(withVendorSpecificHeaderOptions) + { + return (InvokeOCDoResource(query, OC_REST_GET, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS, getReqCB, options, 2)); + } + else + { + return (InvokeOCDoResource(query, OC_REST_GET, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS, getReqCB, NULL, 0)); + } +} + +int InitDeviceDiscovery() +{ + OCStackResult ret; + OCCallbackData cbData; + OCDoHandle handle; + char szQueryUri[64] = { 0 }; + + cbData.cb = DeviceDiscoveryReqCB; + cbData.context = (void*)DEFAULT_CONTEXT_VALUE; + cbData.cd = NULL; + + if(UNICAST_DISCOVERY) + { + strncpy(szQueryUri, TEST_APP_UNICAST_DEVICE_DISCOVERY_QUERY, + (strlen(TEST_APP_UNICAST_DEVICE_DISCOVERY_QUERY) + 1)); + } + else + { + strncpy(szQueryUri, TEST_APP_MULTICAST_DEVICE_DISCOVERY_QUERY, + (strlen(TEST_APP_MULTICAST_DEVICE_DISCOVERY_QUERY) + 1)); + } + + ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0); + + if (ret != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack device error"); + } + + return ret; +} + +int InitDiscovery() +{ + OCStackResult ret; + OCCallbackData cbData; + OCDoHandle handle; + /* Start a discovery query*/ + char szQueryUri[64] = { 0 }; + if (UNICAST_DISCOVERY) + { + strcpy(szQueryUri, TEST_APP_UNICAST_DISCOVERY_QUERY); + } + else + { + strcpy(szQueryUri, OC_WELL_KNOWN_QUERY); + } + cbData.cb = discoveryReqCB; + cbData.context = (void*)DEFAULT_CONTEXT_VALUE; + cbData.cd = NULL; + ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0); + if (ret != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack resource error"); + } + return ret; +} + +int main(int argc, char* argv[]) { + uint8_t addr[20] = {0}; + uint8_t* paddr = NULL; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + int opt; + + while ((opt = getopt(argc, argv, "u:t:")) != -1) + { + switch(opt) + { + case 'u': + UNICAST_DISCOVERY = atoi(optarg); + break; + case 't': + TEST_CASE = atoi(optarg); + break; + default: + PrintUsage(); + return -1; + } + } + + if ((UNICAST_DISCOVERY != 0 && UNICAST_DISCOVERY != 1) || + (TEST_CASE < TEST_DISCOVER_REQ || TEST_CASE >= MAX_TESTS) ) + { + PrintUsage(); + return -1; + } + + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, + sizeof(addr)) == ERR_SUCCESS) + { + OC_LOG_V(INFO, TAG, "Starting occlient on address %s",addr); + paddr = addr; + } + + /* Initialize OCStack*/ + if (OCInit((char *) paddr, port, OC_CLIENT) != OC_STACK_OK) { + OC_LOG(ERROR, TAG, "OCStack init error"); + return 0; + } + + InitDiscovery(); + + // Break from loop with Ctrl+C + OC_LOG(INFO, TAG, "Entering occlient main loop..."); + signal(SIGINT, handleSigInt); + while (!gQuitFlag) { + + if (OCProcess() != OC_STACK_OK) { + OC_LOG(ERROR, TAG, "OCStack process error"); + return 0; + } + + sleep(2); + } + OC_LOG(INFO, TAG, "Exiting occlient main loop..."); + + if (OCStop() != OC_STACK_OK) { + OC_LOG(ERROR, TAG, "OCStack stop error"); + } + + return 0; +} + +std::string getIPAddrTBServer(OCClientResponse * clientResponse) { + if(!clientResponse) return ""; + if(!clientResponse->addr) return ""; + uint8_t a, b, c, d = 0; + if(0 != OCDevAddrToIPv4Addr(clientResponse->addr, &a, &b, &c, &d) ) return ""; + + char ipaddr[16] = {'\0'}; + snprintf(ipaddr, sizeof(ipaddr), "%d.%d.%d.%d", a,b,c,d); // ostringstream not working correctly here, hence snprintf + return std::string (ipaddr); +} + +std::string getPortTBServer(OCClientResponse * clientResponse){ + if(!clientResponse) return ""; + if(!clientResponse->addr) return ""; + uint16_t p = 0; + if(0 != OCDevAddrToPort(clientResponse->addr, &p) ) return ""; + std::ostringstream ss; + ss << p; + return ss.str(); +} + +std::string getQueryStrForGetPut(OCClientResponse * clientResponse){ + + return "/a/light"; +} + +void parseClientResponse(OCClientResponse * clientResponse){ + coapServerIP = getIPAddrTBServer(clientResponse); + coapServerPort = getPortTBServer(clientResponse); + coapServerResource = getQueryStrForGetPut(clientResponse); +} diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.h b/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.h new file mode 100644 index 000000000..96444cad4 --- /dev/null +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.h @@ -0,0 +1,139 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OCCLIENT_H_ +#define OCCLIENT_H_ + +#include "ocstack.h" + + +//----------------------------------------------------------------------------- +// Defines +//----------------------------------------------------------------------------- +#define TAG "occlient" +#define DEFAULT_CONTEXT_VALUE 0x99 +#ifndef MAX_LENGTH_IPv4_ADDR +#define MAX_LENGTH_IPv4_ADDR 16 +#endif + +//----------------------------------------------------------------------------- +// Typedefs +//----------------------------------------------------------------------------- + +/** + * List of methods that can be inititated from the client + */ +typedef enum { + TEST_DISCOVER_REQ = 1, + TEST_GET_REQ_NON, + TEST_PUT_REQ_NON, + TEST_POST_REQ_NON, + TEST_DELETE_REQ_NON, + TEST_OBS_REQ_NON, + TEST_GET_UNAVAILABLE_RES_REQ_NON, + TEST_GET_REQ_CON, + TEST_POST_REQ_CON, + TEST_DELETE_REQ_CON, + TEST_OBS_REQ_CON, +#ifdef WITH_PRESENCE + TEST_OBS_PRESENCE, + TEST_OBS_PRESENCE_WITH_FILTER, + TEST_OBS_PRESENCE_WITH_FILTERS, +#endif + TEST_OBS_REQ_NON_CANCEL_IMM, + TEST_GET_REQ_NON_WITH_VENDOR_HEADER_OPTIONS, + TEST_DISCOVER_DEV_REQ, + MAX_TESTS +} CLIENT_TEST; + +#ifdef WITH_PRESENCE +int InitPresence(); +#endif + +//---------------------------------------------------------------------------- +// Function prototype +//---------------------------------------------------------------------------- + +/* call getResult in common.cpp to get the result in string format. */ +const char *getResult(OCStackResult result); + +/* Get the IP address of the server */ +std::string getIPAddrTBServer(OCClientResponse * clientResponse); + +/* Get the port number the server is listening on */ +std::string getPortTBServer(OCClientResponse * clientResponse); + +/* Returns the query string for GET and PUT operations */ +std::string getQueryStrForGetPut(OCClientResponse * clientResponse); + +/* Following are initialization functions for GET, Observe, PUT + * POST, Delete & Discovery operations + */ +int InitGetRequestToUnavailableResource(); +int InitObserveRequest(OCQualityOfService qos); +int InitPutRequest(); +int InitGetRequest(OCQualityOfService qos, uint8_t withVendorSpecificHeaderOptions); +int InitPostRequest(OCQualityOfService qos); +int InitDeleteRequest(OCQualityOfService qos); +int InitGetRequest(OCQualityOfService qos); +int InitDeviceDiscovery(); +int InitDiscovery(); + +/* Function to retrieve ip address, port no. of the server + * and query for the operations to be performed. + */ +void parseClientResponse(OCClientResponse * clientResponse); + +/* Call delete operation on already deleted resource */ +void* RequestDeleteDeathResourceTask(void* myqos); + +/* This method calls OCDoResource() which in turn makes calls + * to the lower layers + */ +OCStackResult InvokeOCDoResource(std::ostringstream &query, + OCMethod method, OCQualityOfService qos, + OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions); + +//----------------------------------------------------------------------------- +// Callback functions +//----------------------------------------------------------------------------- + +/* Following are callback functions for the GET, Observe, PUT + * POST, Delete, Presence & Discovery operations + */ +OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse); + +OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse); + +OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse); + +OCStackApplicationResult obsReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse); + +OCStackApplicationResult presenceCB(void* ctx, + OCDoHandle handle, OCClientResponse * clientResponse); + +OCStackApplicationResult deleteReqCB(void *ctx, + OCDoHandle handle, OCClientResponse *clientResponse); + +OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle, + OCClientResponse * clientResponse); + + +#endif diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.cpp new file mode 100644 index 000000000..a5269353d --- /dev/null +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.cpp @@ -0,0 +1,386 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include +#include +#include +#include +#include +#include "ocstack.h" +#include "logger.h" +#include "occlientbasicops.h" + +static int UNICAST_DISCOVERY = 0; +static int TEST_CASE = 0; +static const char * TEST_APP_UNICAST_DISCOVERY_QUERY = "coap://0.0.0.0:5683/oc/core"; +static std::string putPayload = "{\"state\":\"off\",\"power\":10}"; +static std::string coapServerIP = "255.255.255.255"; +static std::string coapServerPort = "5683"; +static std::string coapServerResource = "/a/led"; + +int gQuitFlag = 0; + +/* SIGINT handler: set gQuitFlag to 1 for graceful termination */ +void handleSigInt(int signum) +{ + if (signum == SIGINT) + { + gQuitFlag = 1; + } +} + +static void PrintUsage() +{ + OC_LOG(INFO, TAG, "Usage : occlient -u <0|1> -t <1|2|3>"); + OC_LOG(INFO, TAG, "-u <0|1> : Perform multicast/unicast discovery of resources"); + OC_LOG(INFO, TAG, "-t 1 : Discover Resources"); + OC_LOG(INFO, TAG, "-t 2 : Discover Resources and" + " Initiate Nonconfirmable Get/Put/Post Requests"); + OC_LOG(INFO, TAG, "-t 3 : Discover Resources and Initiate Confirmable Get/Put/Post Requests"); +} + +OCStackResult InvokeOCDoResource(std::ostringstream &query, + OCMethod method, OCQualityOfService qos, + OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions) +{ + OCStackResult ret; + OCCallbackData cbData; + OCDoHandle handle; + + cbData.cb = cb; + cbData.context = (void*)DEFAULT_CONTEXT_VALUE; + cbData.cd = NULL; + + ret = OCDoResource(&handle, method, query.str().c_str(), 0, + (method == OC_REST_PUT || method == OC_REST_POST) ? putPayload.c_str() : NULL, + qos, &cbData, options, numOptions); + + if (ret != OC_STACK_OK) + { + OC_LOG_V(ERROR, TAG, "OCDoResource returns error %d with method %d", ret, method); + } + + return ret; +} + +OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) +{ + if(ctx == (void*)DEFAULT_CONTEXT_VALUE) + { + OC_LOG(INFO, TAG, "Callback Context for PUT recvd successfully"); + } + + if(clientResponse) + { + OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result)); + OC_LOG_V(INFO, TAG, "JSON = %s =============> Put Response", clientResponse->resJSONPayload); + } + return OC_STACK_DELETE_TRANSACTION; +} + +OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse) +{ + if(ctx == (void*)DEFAULT_CONTEXT_VALUE) + { + OC_LOG(INFO, TAG, "Callback Context for POST recvd successfully"); + } + + if(clientResponse) + { + OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result)); + OC_LOG_V(INFO, TAG, "JSON = %s =============> Post Response", + clientResponse->resJSONPayload); + } + return OC_STACK_DELETE_TRANSACTION; +} + +OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) +{ + if(clientResponse == NULL) + { + OC_LOG(INFO, TAG, "The clientResponse is NULL"); + return OC_STACK_DELETE_TRANSACTION; + } + if(ctx == (void*)DEFAULT_CONTEXT_VALUE) + { + OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully"); + } + + OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result)); + OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber); + OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response", + clientResponse->resJSONPayload); + + if(clientResponse->rcvdVendorSpecificHeaderOptions && + clientResponse->numRcvdVendorSpecificHeaderOptions) + { + OC_LOG (INFO, TAG, "Received vendor specific options"); + uint8_t i = 0; + OCHeaderOption * rcvdOptions = clientResponse->rcvdVendorSpecificHeaderOptions; + for( i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++) + { + if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID) + { + OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with", + ((OCHeaderOption)rcvdOptions[i]).optionID ); + OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData, + ((OCHeaderOption)rcvdOptions[i]).optionLength); + } + } + } + return OC_STACK_DELETE_TRANSACTION; +} + +// This is a function called back when a device is discovered +OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle, + OCClientResponse * clientResponse) +{ + uint8_t remoteIpAddr[4]; + uint16_t remotePortNu; + + if (ctx == (void*) DEFAULT_CONTEXT_VALUE) + { + OC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully"); + } + + if (clientResponse) + { + OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result)); + + OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddr, + remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3); + OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNu); + + OC_LOG_V(INFO, TAG, + "Device =============> Discovered %s @ %d.%d.%d.%d:%d", + clientResponse->resJSONPayload, remoteIpAddr[0], remoteIpAddr[1], + remoteIpAddr[2], remoteIpAddr[3], remotePortNu); + + parseClientResponse(clientResponse); + + switch(TEST_CASE) + { + case TEST_NON_CON_OP: + InitGetRequest(OC_LOW_QOS); + InitPutRequest(); + InitPostRequest(OC_LOW_QOS); + break; + case TEST_CON_OP: + InitGetRequest(OC_HIGH_QOS); + InitPutRequest(); + InitPostRequest(OC_HIGH_QOS); + break; + default: + PrintUsage(); + break; + } + } + + return (UNICAST_DISCOVERY) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ; + +} + +int InitPutRequest() +{ + OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); + std::ostringstream query; + query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource; + return (InvokeOCDoResource(query, OC_REST_PUT, OC_LOW_QOS, putReqCB, NULL, 0)); +} + +int InitPostRequest(OCQualityOfService qos) +{ + OCStackResult result; + OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); + std::ostringstream query; + query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource; + + // First POST operation (to create an LED instance) + result = InvokeOCDoResource(query, OC_REST_POST, + ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), + postReqCB, NULL, 0); + if (OC_STACK_OK != result) + { + // Error can happen if for example, network connectivity is down + OC_LOG(INFO, TAG, "First POST call did not succeed"); + } + + // Second POST operation (to create an LED instance) + result = InvokeOCDoResource(query, OC_REST_POST, + ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), + postReqCB, NULL, 0); + if (OC_STACK_OK != result) + { + OC_LOG(INFO, TAG, "Second POST call did not succeed"); + } + + // This POST operation will update the original resourced /a/led + return (InvokeOCDoResource(query, OC_REST_POST, + ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), + postReqCB, NULL, 0)); +} + +int InitGetRequest(OCQualityOfService qos) +{ + OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); + std::ostringstream query; + query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource; + + return (InvokeOCDoResource(query, OC_REST_GET, (qos == OC_HIGH_QOS)? + OC_HIGH_QOS:OC_LOW_QOS, getReqCB, NULL, 0)); +} + +int InitDiscovery() +{ + OCStackResult ret; + OCCallbackData cbData; + OCDoHandle handle; + /* Start a discovery query*/ + char szQueryUri[64] = { 0 }; + if (UNICAST_DISCOVERY) + { + strcpy(szQueryUri, TEST_APP_UNICAST_DISCOVERY_QUERY); + } + else + { + strcpy(szQueryUri, OC_WELL_KNOWN_QUERY); + } + cbData.cb = discoveryReqCB; + cbData.context = (void*)DEFAULT_CONTEXT_VALUE; + cbData.cd = NULL; + ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0); + if (ret != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack resource error"); + } + return ret; +} + +int main(int argc, char* argv[]) +{ + uint8_t addr[20] = {0}; + uint8_t* paddr = NULL; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + int opt; + + while ((opt = getopt(argc, argv, "u:t:")) != -1) + { + switch(opt) + { + case 'u': + UNICAST_DISCOVERY = atoi(optarg); + break; + case 't': + TEST_CASE = atoi(optarg); + break; + default: + PrintUsage(); + return -1; + } + } + + if ((UNICAST_DISCOVERY != 0 && UNICAST_DISCOVERY != 1) || + (TEST_CASE < TEST_DISCOVER_REQ || TEST_CASE >= MAX_TESTS) ) + { + PrintUsage(); + return -1; + } + + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, + sizeof(addr)) == ERR_SUCCESS) + { + OC_LOG_V(INFO, TAG, "Starting occlient on address %s",addr); + paddr = addr; + } + + /* Initialize OCStack*/ + if (OCInit((char *) paddr, port, OC_CLIENT) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack init error"); + return 0; + } + + InitDiscovery(); + + // Break from loop with Ctrl+C + OC_LOG(INFO, TAG, "Entering occlient main loop..."); + signal(SIGINT, handleSigInt); + while (!gQuitFlag) + { + if (OCProcess() != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack process error"); + return 0; + } + + sleep(2); + } + OC_LOG(INFO, TAG, "Exiting occlient main loop..."); + + if (OCStop() != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack stop error"); + } + + return 0; +} + +std::string getIPAddrTBServer(OCClientResponse * clientResponse) +{ + if(!clientResponse) return ""; + if(!clientResponse->addr) return ""; + uint8_t a, b, c, d = 0; + if(0 != OCDevAddrToIPv4Addr(clientResponse->addr, &a, &b, &c, &d) ) return ""; + + char ipaddr[16] = {'\0'}; + // ostringstream not working correctly here, hence snprintf + snprintf(ipaddr, sizeof(ipaddr), "%d.%d.%d.%d", a,b,c,d); + return std::string (ipaddr); +} + + +std::string getPortTBServer(OCClientResponse * clientResponse) +{ + if(!clientResponse) return ""; + if(!clientResponse->addr) return ""; + uint16_t p = 0; + if(0 != OCDevAddrToPort(clientResponse->addr, &p) ) return ""; + std::ostringstream ss; + ss << p; + return ss.str(); +} + +std::string getQueryStrForGetPut(OCClientResponse * clientResponse) +{ + return "/a/led"; +} + +void parseClientResponse(OCClientResponse * clientResponse) +{ + coapServerIP = getIPAddrTBServer(clientResponse); + coapServerPort = getPortTBServer(clientResponse); + coapServerResource = getQueryStrForGetPut(clientResponse); +} diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.h b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.h new file mode 100644 index 000000000..6752bed75 --- /dev/null +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.h @@ -0,0 +1,102 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OCCLIENT_BASICOPS_H_ +#define OCCLIENT_BASICOPS_H_ + +#include "ocstack.h" + +//----------------------------------------------------------------------------- +// Defines +//----------------------------------------------------------------------------- +#define TAG "occlientbasicops" +#define DEFAULT_CONTEXT_VALUE 0x99 +#ifndef MAX_LENGTH_IPv4_ADDR +#define MAX_LENGTH_IPv4_ADDR 16 +#endif + +//----------------------------------------------------------------------------- +// Typedefs +//----------------------------------------------------------------------------- + +/** + * List of methods that can be inititated from the client + */ +typedef enum { + TEST_DISCOVER_REQ = 1, + TEST_NON_CON_OP, + TEST_CON_OP, + MAX_TESTS +} CLIENT_TEST; + +//----------------------------------------------------------------------------- +// Function prototype +//----------------------------------------------------------------------------- + +/* call getResult in common.cpp to get the result in string format. */ +const char *getResult(OCStackResult result); + +/* Get the IP address of the server */ +std::string getIPAddrTBServer(OCClientResponse * clientResponse); + +/* Get the port number the server is listening on */ +std::string getPortTBServer(OCClientResponse * clientResponse); + +/* Returns the query string for GET and PUT operations */ +std::string getQueryStrForGetPut(OCClientResponse * clientResponse); + +/* Following are initialization functions for GET, PUT + * POST & Discovery operations + */ +int InitPutRequest(); +int InitGetRequest(OCQualityOfService qos); +int InitPostRequest(OCQualityOfService qos); +int InitDiscovery(); + +/* Function to retrieve ip address, port no. of the server + * and query for the operations to be performed. + */ +void parseClientResponse(OCClientResponse * clientResponse); + +/* This method calls OCDoResource() which in turn makes calls + * to the lower layers + */ +OCStackResult InvokeOCDoResource(std::ostringstream &query, + OCMethod method, OCQualityOfService qos, + OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions); + +//----------------------------------------------------------------------------- +// Callback functions +//----------------------------------------------------------------------------- + +/* Following are callback functions for the GET, PUT + * POST & Discovery operations + */ + +OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse); + +OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse); + +OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse); + +OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle, + OCClientResponse * clientResponse); + +#endif diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/occlientcoll.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientcoll.cpp new file mode 100644 index 000000000..e8db15a7d --- /dev/null +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientcoll.cpp @@ -0,0 +1,417 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include +#include +#include +#include +#include +#include +#include "logger.h" +const char *getResult(OCStackResult result); +std::string getIPAddrTBServer(OCClientResponse * clientResponse); +std::string getPortTBServer(OCClientResponse * clientResponse); +std::string getQueryStrForGetPut(unsigned const char * responsePayload); + +#define TAG PCF("occlient") +#define DEFAULT_CONTEXT_VALUE 0x99 +#ifndef MAX_LENGTH_IPv4_ADDR +#define MAX_LENGTH_IPv4_ADDR 16 +#endif + +typedef enum { + TEST_INVALID = 0, + TEST_GET_DEFAULT, + TEST_GET_BATCH, + TEST_GET_LINK_LIST, + TEST_PUT_DEFAULT, + TEST_PUT_BATCH, + TEST_PUT_LINK_LIST, + TEST_UNKNOWN_RESOURCE_GET_DEFAULT, + TEST_UNKNOWN_RESOURCE_GET_BATCH, + TEST_UNKNOWN_RESOURCE_GET_LINK_LIST, + MAX_TESTS +} CLIENT_TEST; + +unsigned static int TEST = TEST_INVALID; + +typedef struct +{ + unsigned char text[30]; + CLIENT_TEST test; +} testToTextMap; + +testToTextMap queryInterface[] = { + {"invalid", TEST_INVALID}, + {"?if=oc.mi.def", TEST_GET_DEFAULT}, + {"?if=oc.mi.b", TEST_GET_BATCH}, + {"?if=oc.mi.ll", TEST_GET_LINK_LIST}, + {"?if=oc.mi.def", TEST_UNKNOWN_RESOURCE_GET_DEFAULT}, + {"?if=oc.mi.b", TEST_UNKNOWN_RESOURCE_GET_BATCH}, + {"?if=oc.mi.ll", TEST_UNKNOWN_RESOURCE_GET_LINK_LIST}, + {"?if=oc.mi.def", TEST_PUT_DEFAULT}, + {"?if=oc.mi.b", TEST_PUT_BATCH}, + {"?if=oc.mi.ll", TEST_PUT_LINK_LIST}, +}; + +static std::string putPayload = "{\"state\":\"off\",\"power\":\"0\"}"; + +// The handle for the observe registration +OCDoHandle gObserveDoHandle; +// After this crosses a threshold client deregisters for further observations +int gNumObserveNotifies = 1; + +int gQuitFlag = 0; +/* SIGINT handler: set gQuitFlag to 1 for graceful termination */ +void handleSigInt(int signum) { + if (signum == SIGINT) { + gQuitFlag = 1; + } +} + +// Forward Declaration +OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse); +int InitGetRequestToUnavailableResource(OCClientResponse * clientResponse); +int InitObserveRequest(OCClientResponse * clientResponse); +int InitPutRequest(OCClientResponse * clientResponse); +int InitGetRequest(OCClientResponse * clientResponse); +int InitDiscovery(); + +void PrintUsage() +{ + OC_LOG(INFO, TAG, "Usage : occlientcoll -t "); + OC_LOG(INFO, TAG, "Test Case 1 : Discover Resources && Initiate GET Request on an"\ + "available resource using default interface."); + OC_LOG(INFO, TAG, "Test Case 2 : Discover Resources && Initiate GET Request on an"\ + "available resource using batch interface."); + OC_LOG(INFO, TAG, "Test Case 3 : Discover Resources && Initiate GET Request on an"\ + "available resource using link list interface."); + OC_LOG(INFO, TAG, "Test Case 4 : Discover Resources && Initiate GET & PUT Request on an"\ + "available resource using default interface."); + OC_LOG(INFO, TAG, "Test Case 5 : Discover Resources && Initiate GET & PUT Request on an"\ + "available resource using batch interface."); + OC_LOG(INFO, TAG, "Test Case 6 : Discover Resources && Initiate GET & PUT Request on an"\ + "available resource using link list interface."); + OC_LOG(INFO, TAG, "Test Case 7 : Discover Resources && Initiate GET Request on an"\ + "unavailable resource using default interface."); + OC_LOG(INFO, TAG, "Test Case 8 : Discover Resources && Initiate GET Request on an"\ + "unavailable resource using batch interface."); + OC_LOG(INFO, TAG, "Test Case 9 : Discover Resources && Initiate GET Request on an"\ + "unavailable resource using link list interface."); +} + +OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) { + if(clientResponse == NULL) + { + OC_LOG(INFO, TAG, "The clientResponse is NULL"); + return OC_STACK_DELETE_TRANSACTION; + } + if(ctx == (void*)DEFAULT_CONTEXT_VALUE) { + OC_LOG_V(INFO, TAG, "Callback Context for PUT query recvd successfully"); + OC_LOG_V(INFO, TAG, "JSON = %s =============> Discovered", clientResponse->resJSONPayload); + } + + return OC_STACK_KEEP_TRANSACTION; +} + +OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) { + OC_LOG_V(INFO, TAG, "StackResult: %s", + getResult(clientResponse->result)); + if(ctx == (void*)DEFAULT_CONTEXT_VALUE) { + OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber); + if(clientResponse->sequenceNumber == 0) { + OC_LOG_V(INFO, TAG, "Callback Context for GET query recvd successfully"); + OC_LOG_V(INFO, TAG, "Fnd' Rsrc': %s", clientResponse->resJSONPayload); + } + else { + OC_LOG_V(INFO, TAG, "Callback Context for Get recvd successfully %d", gNumObserveNotifies); + OC_LOG_V(INFO, TAG, "Fnd' Rsrc': %s", clientResponse->resJSONPayload); + gNumObserveNotifies++; + if (gNumObserveNotifies == 3) + { + if (OCCancel (gObserveDoHandle, OC_LOW_QOS, NULL, 0) != OC_STACK_OK){ + OC_LOG(ERROR, TAG, "Observe cancel error"); + } + } + } + } + if(TEST == TEST_PUT_DEFAULT || TEST == TEST_PUT_BATCH || TEST == TEST_PUT_LINK_LIST) + { + InitPutRequest(clientResponse); + } + return OC_STACK_KEEP_TRANSACTION; +} + + +// This is a function called back when a device is discovered +OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle, + OCClientResponse * clientResponse) { + uint8_t remoteIpAddr[4]; + uint16_t remotePortNu; + + OC_LOG(INFO, TAG, + "Entering discoveryReqCB (Application Layer CB)"); + OC_LOG_V(INFO, TAG, "StackResult: %s", + getResult(clientResponse->result)); + + if (ctx == (void*) DEFAULT_CONTEXT_VALUE) { + OC_LOG_V(INFO, TAG, "Callback Context recvd successfully"); + } + + OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddr, + remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3); + OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNu); + + OC_LOG_V(INFO, TAG, + "Device =============> Discovered %s @ %d.%d.%d.%d:%d", + clientResponse->resJSONPayload, remoteIpAddr[0], remoteIpAddr[1], + remoteIpAddr[2], remoteIpAddr[3], remotePortNu); + + if(TEST == TEST_UNKNOWN_RESOURCE_GET_DEFAULT || TEST == TEST_UNKNOWN_RESOURCE_GET_BATCH ||\ + TEST == TEST_UNKNOWN_RESOURCE_GET_LINK_LIST) + { + InitGetRequestToUnavailableResource(clientResponse); + } + else + { + InitGetRequest(clientResponse); + } + return OC_STACK_KEEP_TRANSACTION; +} + + +int InitGetRequestToUnavailableResource(OCClientResponse * clientResponse) +{ + OCStackResult ret; + OCCallbackData cbData; + OCDoHandle handle; + std::ostringstream getQuery; + getQuery << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << "/SomeUnknownResource"; + cbData.cb = getReqCB; + cbData.context = (void*)DEFAULT_CONTEXT_VALUE; + cbData.cd = NULL; + + ret = OCDoResource(&handle, OC_REST_GET, getQuery.str().c_str(), 0, 0, OC_LOW_QOS, + &cbData, NULL, 0); + if (ret != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack resource error"); + } + return ret; +} + + +int InitObserveRequest(OCClientResponse * clientResponse) +{ + OCStackResult ret; + OCCallbackData cbData; + OCDoHandle handle; + std::ostringstream obsReg; + obsReg << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << getQueryStrForGetPut(clientResponse->resJSONPayload); + cbData.cb = getReqCB; + cbData.context = (void*)DEFAULT_CONTEXT_VALUE; + cbData.cd = NULL; + OC_LOG_V(INFO, TAG, "OBSERVE payload from client = %s ", putPayload.c_str()); + + ret = OCDoResource(&handle, OC_REST_OBSERVE, obsReg.str().c_str(), 0, 0, OC_LOW_QOS, + &cbData, NULL, 0); + if (ret != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack resource error"); + } + else + { + gObserveDoHandle = handle; + } + return ret; +} + + +int InitPutRequest(OCClientResponse * clientResponse) +{ + OCStackResult ret; + OCCallbackData cbData; + OCDoHandle handle; + //* Make a PUT query*/ + std::ostringstream getQuery; + getQuery << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << + "/a/room" << queryInterface[TEST].text; + cbData.cb = putReqCB; + cbData.context = (void*)DEFAULT_CONTEXT_VALUE; + cbData.cd = NULL; + OC_LOG_V(INFO, TAG, "PUT payload from client = %s ", putPayload.c_str()); + + ret = OCDoResource(&handle, OC_REST_PUT, getQuery.str().c_str(), 0, putPayload.c_str(), + OC_LOW_QOS, &cbData, NULL, 0); + if (ret != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack resource error"); + } + return ret; +} + + +int InitGetRequest(OCClientResponse * clientResponse) +{ + OCStackResult ret; + OCCallbackData cbData; + OCDoHandle handle; + + uint8_t remoteIpAddr[4]; + uint16_t remotePortNu; + + OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddr, + remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3); + OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNu); + + //* Make a GET query*/ + std::ostringstream getQuery; + getQuery << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << + "/a/room" << queryInterface[TEST].text; + + std::cout << "Get Query: " << getQuery.str() << std::endl; + + cbData.cb = getReqCB; + cbData.context = (void*)DEFAULT_CONTEXT_VALUE; + cbData.cd = NULL; + ret = OCDoResource(&handle, OC_REST_GET, getQuery.str().c_str(), 0, 0, OC_LOW_QOS, + &cbData, NULL, 0); + if (ret != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack resource error"); + } + return ret; +} + +int InitDiscovery() +{ + OCStackResult ret; + OCCallbackData cbData; + OCDoHandle handle; + /* Start a discovery query*/ + char szQueryUri[64] = { 0 }; + + strcpy(szQueryUri, OC_WELL_KNOWN_QUERY); + + cbData.cb = discoveryReqCB; + cbData.context = (void*)DEFAULT_CONTEXT_VALUE; + cbData.cd = NULL; + ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, + &cbData, NULL, 0); + if (ret != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack resource error"); + } + return ret; +} + +int main(int argc, char* argv[]) { + uint8_t addr[20] = {0}; + uint8_t* paddr = NULL; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + int opt; + + while ((opt = getopt(argc, argv, "t:")) != -1) + { + switch(opt) + { + case 't': + TEST = atoi(optarg); + break; + default: + PrintUsage(); + return -1; + } + } + if(TEST <= TEST_INVALID || TEST >= MAX_TESTS){ + PrintUsage(); + return -1; + } + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, + sizeof(addr)) == ERR_SUCCESS) + { + OC_LOG_V(INFO, TAG, "Starting occlient on address %s",addr); + paddr = addr; + } + + /* Initialize OCStack*/ + if (OCInit((char *) paddr, port, OC_CLIENT) != OC_STACK_OK) { + OC_LOG(ERROR, TAG, "OCStack init error"); + return 0; + } + + InitDiscovery(); + + // Break from loop with Ctrl+C + OC_LOG(INFO, TAG, "Entering occlient main loop..."); + signal(SIGINT, handleSigInt); + while (!gQuitFlag) { + + if (OCProcess() != OC_STACK_OK) { + OC_LOG(ERROR, TAG, "OCStack process error"); + return 0; + } + + sleep(2); + } + OC_LOG(INFO, TAG, "Exiting occlient main loop..."); + + if (OCStop() != OC_STACK_OK) { + OC_LOG(ERROR, TAG, "OCStack stop error"); + } + + return 0; +} + +std::string getIPAddrTBServer(OCClientResponse * clientResponse) { + if(!clientResponse) return ""; + if(!clientResponse->addr) return ""; + uint8_t a, b, c, d = 0; + if(0 != OCDevAddrToIPv4Addr(clientResponse->addr, &a, &b, &c, &d) ) return ""; + + char ipaddr[16] = {'\0'}; + snprintf(ipaddr, sizeof(ipaddr), "%d.%d.%d.%d", a,b,c,d); // ostringstream not working correctly here, hence snprintf + //printf("IP address string of the TB server = %s\n", *out_ipaddr); + return std::string (ipaddr); +} + + +std::string getPortTBServer(OCClientResponse * clientResponse){ + if(!clientResponse) return ""; + if(!clientResponse->addr) return ""; + uint16_t p = 0; + if(0 != OCDevAddrToPort(clientResponse->addr, &p) ) return ""; + std::ostringstream ss; + ss << p; + return ss.str(); +} + +std::string getQueryStrForGetPut(unsigned const char * responsePayload){ + + std::string jsonPayload(reinterpret_cast(const_cast(responsePayload))); + + return "/a/room"; +} diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.cpp new file mode 100644 index 000000000..689b01581 --- /dev/null +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.cpp @@ -0,0 +1,310 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include +#include +#include +#include +#include +#include "ocstack.h" +#include "logger.h" +#include "occlientslow.h" + +static int UNICAST_DISCOVERY = 0; +static int TEST_CASE = 0; +static const char * TEST_APP_UNICAST_DISCOVERY_QUERY = "coap://0.0.0.0:5683/oc/core"; +static std::string putPayload = "{\"state\":\"off\",\"power\":10}"; +static std::string coapServerIP = "255.255.255.255"; +static std::string coapServerPort = "5683"; +static std::string coapServerResource = "/a/led"; + +int gQuitFlag = 0; + +/* SIGINT handler: set gQuitFlag to 1 for graceful termination */ +void handleSigInt(int signum) +{ + if (signum == SIGINT) + { + gQuitFlag = 1; + } +} + +static void PrintUsage() +{ + OC_LOG(INFO, TAG, "Usage : occlient -u <0|1> -t <1|2|3>"); + OC_LOG(INFO, TAG, "-u <0|1> : Perform multicast/unicast discovery of resources"); + OC_LOG(INFO, TAG, "-t 1 : Discover Resources"); + OC_LOG(INFO, TAG, "-t 2 : Discover Resources and Initiate Nonconfirmable Get Request"); + OC_LOG(INFO, TAG, "-t 3 : Discover Resources and Initiate Confirmable Get Request"); +} + +OCStackResult InvokeOCDoResource(std::ostringstream &query, + OCMethod method, OCQualityOfService qos, + OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions) +{ + OCStackResult ret; + OCCallbackData cbData; + OCDoHandle handle; + + cbData.cb = cb; + cbData.context = (void*)DEFAULT_CONTEXT_VALUE; + cbData.cd = NULL; + + ret = OCDoResource(&handle, method, query.str().c_str(), 0, + NULL, + qos, &cbData, options, numOptions); + + if (ret != OC_STACK_OK) + { + OC_LOG_V(ERROR, TAG, "OCDoResource returns error %d with method %d", ret, method); + } + + return ret; +} + +OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) +{ + if(clientResponse == NULL) + { + OC_LOG(INFO, TAG, "The clientResponse is NULL"); + return OC_STACK_DELETE_TRANSACTION; + } + if(ctx == (void*)DEFAULT_CONTEXT_VALUE) + { + OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully"); + } + + OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result)); + OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber); + OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response", + clientResponse->resJSONPayload); + + if(clientResponse->rcvdVendorSpecificHeaderOptions && + clientResponse->numRcvdVendorSpecificHeaderOptions) + { + OC_LOG (INFO, TAG, "Received vendor specific options"); + uint8_t i = 0; + OCHeaderOption * rcvdOptions = clientResponse->rcvdVendorSpecificHeaderOptions; + for( i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++) + { + if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID) + { + OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with", + ((OCHeaderOption)rcvdOptions[i]).optionID ); + OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData, + ((OCHeaderOption)rcvdOptions[i]).optionLength); + } + } + } + return OC_STACK_DELETE_TRANSACTION; +} + +// This is a function called back when a device is discovered +OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle, + OCClientResponse * clientResponse) +{ + uint8_t remoteIpAddr[4]; + uint16_t remotePortNu; + + if (ctx == (void*) DEFAULT_CONTEXT_VALUE) + { + OC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully"); + } + + if (clientResponse) + { + OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result)); + + OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddr, + remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3); + OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNu); + + OC_LOG_V(INFO, TAG, + "Device =============> Discovered %s @ %d.%d.%d.%d:%d", + clientResponse->resJSONPayload, remoteIpAddr[0], remoteIpAddr[1], + remoteIpAddr[2], remoteIpAddr[3], remotePortNu); + + parseClientResponse(clientResponse); + + switch(TEST_CASE) + { + case TEST_NON_CON_OP: + InitGetRequest(OC_LOW_QOS); + break; + case TEST_CON_OP: + InitGetRequest(OC_HIGH_QOS); + break; + default: + PrintUsage(); + break; + } + } + + return (UNICAST_DISCOVERY) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ; + +} + +int InitGetRequest(OCQualityOfService qos) +{ + OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); + std::ostringstream query; + query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource; + + return (InvokeOCDoResource(query, OC_REST_GET, (qos == OC_HIGH_QOS)? + OC_HIGH_QOS:OC_LOW_QOS, getReqCB, NULL, 0)); +} + +int InitDiscovery() +{ + OCStackResult ret; + OCCallbackData cbData; + OCDoHandle handle; + /* Start a discovery query*/ + char szQueryUri[64] = { 0 }; + if (UNICAST_DISCOVERY) + { + strcpy(szQueryUri, TEST_APP_UNICAST_DISCOVERY_QUERY); + } + else + { + strcpy(szQueryUri, OC_WELL_KNOWN_QUERY); + } + cbData.cb = discoveryReqCB; + cbData.context = (void*)DEFAULT_CONTEXT_VALUE; + cbData.cd = NULL; + ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0); + if (ret != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack resource error"); + } + return ret; +} + +int main(int argc, char* argv[]) +{ + uint8_t addr[20] = {0}; + uint8_t* paddr = NULL; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + int opt; + + while ((opt = getopt(argc, argv, "u:t:")) != -1) + { + switch(opt) + { + case 'u': + UNICAST_DISCOVERY = atoi(optarg); + break; + case 't': + TEST_CASE = atoi(optarg); + break; + default: + PrintUsage(); + return -1; + } + } + + if ((UNICAST_DISCOVERY != 0 && UNICAST_DISCOVERY != 1) || + (TEST_CASE < TEST_DISCOVER_REQ || TEST_CASE >= MAX_TESTS) ) + { + PrintUsage(); + return -1; + } + + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, + sizeof(addr)) == ERR_SUCCESS) + { + OC_LOG_V(INFO, TAG, "Starting occlient on address %s",addr); + paddr = addr; + } + + /* Initialize OCStack*/ + if (OCInit((char *) paddr, port, OC_CLIENT) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack init error"); + return 0; + } + + InitDiscovery(); + + // Break from loop with Ctrl+C + OC_LOG(INFO, TAG, "Entering occlient main loop..."); + signal(SIGINT, handleSigInt); + while (!gQuitFlag) + { + if (OCProcess() != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack process error"); + return 0; + } + + sleep(2); + } + OC_LOG(INFO, TAG, "Exiting occlient main loop..."); + + if (OCStop() != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack stop error"); + } + + return 0; +} + +std::string getIPAddrTBServer(OCClientResponse * clientResponse) +{ + if(!clientResponse) return ""; + if(!clientResponse->addr) return ""; + uint8_t a, b, c, d = 0; + if(0 != OCDevAddrToIPv4Addr(clientResponse->addr, &a, &b, &c, &d) ) return ""; + + char ipaddr[16] = {'\0'}; + // ostringstream not working correctly here, hence snprintf + snprintf(ipaddr, sizeof(ipaddr), "%d.%d.%d.%d", a,b,c,d); + return std::string (ipaddr); +} + + +std::string getPortTBServer(OCClientResponse * clientResponse) +{ + if(!clientResponse) return ""; + if(!clientResponse->addr) return ""; + uint16_t p = 0; + if(0 != OCDevAddrToPort(clientResponse->addr, &p) ) return ""; + std::ostringstream ss; + ss << p; + return ss.str(); +} + +std::string getQueryStrForGetPut(OCClientResponse * clientResponse) +{ + return "/a/led"; +} + +void parseClientResponse(OCClientResponse * clientResponse) +{ + coapServerIP = getIPAddrTBServer(clientResponse); + coapServerPort = getPortTBServer(clientResponse); + coapServerResource = getQueryStrForGetPut(clientResponse); +} diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.h b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.h new file mode 100644 index 000000000..60713d7d8 --- /dev/null +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.h @@ -0,0 +1,95 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OCCLIENT_BASICOPS_H_ +#define OCCLIENT_BASICOPS_H_ + +#include "ocstack.h" + +//----------------------------------------------------------------------------- +// Defines +//----------------------------------------------------------------------------- +#define TAG "occlientslow" +#define DEFAULT_CONTEXT_VALUE 0x99 +#ifndef MAX_LENGTH_IPv4_ADDR +#define MAX_LENGTH_IPv4_ADDR 16 +#endif + +//----------------------------------------------------------------------------- +// Typedefs +//----------------------------------------------------------------------------- + +/** + * List of methods that can be inititated from the client + */ +typedef enum { + TEST_DISCOVER_REQ = 1, + TEST_NON_CON_OP, + TEST_CON_OP, + MAX_TESTS +} CLIENT_TEST; + +//----------------------------------------------------------------------------- +// Function prototype +//----------------------------------------------------------------------------- + +/* call getResult in common.cpp to get the result in string format. */ +const char *getResult(OCStackResult result); + +/* Get the IP address of the server */ +std::string getIPAddrTBServer(OCClientResponse * clientResponse); + +/* Get the port number the server is listening on */ +std::string getPortTBServer(OCClientResponse * clientResponse); + +/* Returns the query string for GET and PUT operations */ +std::string getQueryStrForGetPut(OCClientResponse * clientResponse); + +/* Following are initialization functions for GET, PUT + * POST & Discovery operations + */ +int InitGetRequest(OCQualityOfService qos); +int InitDiscovery(); + +/* Function to retrieve ip address, port no. of the server + * and query for the operations to be performed. + */ +void parseClientResponse(OCClientResponse * clientResponse); + +/* This function calls OCDoResource() which in turn makes calls + * to the lower layers + */ +OCStackResult InvokeOCDoResource(std::ostringstream &query, + OCMethod method, OCQualityOfService qos, + OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions); + +//----------------------------------------------------------------------------- +// Callback functions +//----------------------------------------------------------------------------- + +/* Following are callback functions for the GET and Discovery operations + */ + +OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse); + +OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle, + OCClientResponse * clientResponse); + +#endif diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp new file mode 100644 index 000000000..6131cd033 --- /dev/null +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp @@ -0,0 +1,1021 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ocstack.h" +#include "logger.h" +#include "cJSON.h" +#include "ocserver.h" + +//string length of "/a/light/" + std::numeric_limits::digits10 + '\0'" +// 9 + 9 + 1 = 19 +const int URI_MAXSIZE = 19; + +static int gObserveNotifyType = 3; + +int gQuitFlag = 0; +int gLightUnderObservation = 0; + +static LightResource Light; +// This variable determines instance number of the Light resource. +// Used by POST method to create a new instance of Light resource. +static int gCurrLightInstance = 0; + +static LightResource gLightInstance[SAMPLE_MAX_NUM_POST_INSTANCE]; + +Observers interestedObservers[SAMPLE_MAX_NUM_OBSERVATIONS]; + +#ifdef WITH_PRESENCE +static int stopPresenceCount = 10; +#define numPresenceResources (2) +#endif + +//TODO: Follow the pattern used in constructJsonResponse() when the payload is decided. +const char responsePayloadDeleteOk[] = "{App determines payload: Delete Resource operation succeeded.}"; +const char responsePayloadDeleteNotOK[] = "{App determines payload: Delete Resource operation failed.}"; +const char responsePayloadResourceDoesNotExist[] = "{App determines payload: The resource does not exist.}"; +const char responsePayloadDeleteResourceNotSupported[] = + "{App determines payload: The request is received for a non-support resource.}"; + + +char *gResourceUri= (char *)"/a/light"; +const char *contentType = "myContentType"; +const char *dateOfManufacture = "myDateOfManufacture"; +const char *deviceName = "myDeviceName"; +const char *deviceUUID = "myDeviceUUID"; +const char *firmwareVersion = "myFirmwareVersion"; +const char *hostName = "myHostName"; +const char *manufacturerName = "myManufacturerNa"; +const char *manufacturerUrl = "myManufacturerUrl"; +const char *modelNumber = "myModelNumber"; +const char *platformVersion = "myPlatformVersion"; +const char *supportUrl = "mySupportUrl"; +const char *version = "myVersion"; + +OCDeviceInfo deviceInfo; + +static uint16_t OC_WELL_KNOWN_PORT = 5683; + +//This function takes the request as an input and returns the response +//in JSON format. +char* constructJsonResponse (OCEntityHandlerRequest *ehRequest) +{ + cJSON *json = cJSON_CreateObject(); + cJSON *format; + char *jsonResponse; + LightResource *currLightResource = &Light; + + if (ehRequest->resource == gLightInstance[0].handle) + { + currLightResource = &gLightInstance[0]; + gResourceUri = (char *) "a/light/0"; + } + else if (ehRequest->resource == gLightInstance[1].handle) + { + currLightResource = &gLightInstance[1]; + gResourceUri = (char *) "a/light/1"; + } + + if(OC_REST_PUT == ehRequest->method) + { + cJSON *putJson = cJSON_Parse((char *)ehRequest->reqJSONPayload); + currLightResource->state = ( !strcmp(cJSON_GetObjectItem(putJson,"state")->valuestring, + "on") ? true:false); + currLightResource->power = cJSON_GetObjectItem(putJson,"power")->valuedouble; + cJSON_Delete(putJson); + } + + cJSON_AddStringToObject(json,"href",gResourceUri); + cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject()); + cJSON_AddStringToObject(format, "state", (char *) (currLightResource->state ? "on":"off")); + cJSON_AddNumberToObject(format, "power", currLightResource->power); + + jsonResponse = cJSON_Print(json); + cJSON_Delete(json); + + return jsonResponse; +} + +OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize) +{ + OCEntityHandlerResult ehResult; + char *getResp = constructJsonResponse(ehRequest); + + if (maxPayloadSize > strlen ((char *)getResp)) + { + strncpy(payload, getResp, strlen((char *)getResp)); + ehResult = OC_EH_OK; + } + else + { + OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small", + maxPayloadSize); + ehResult = OC_EH_ERROR; + } + + free(getResp); + + return ehResult; +} + +OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize) +{ + OCEntityHandlerResult ehResult; + char *putResp = constructJsonResponse(ehRequest); + + if (maxPayloadSize > strlen ((char *)putResp)) + { + strncpy(payload, putResp, strlen((char *)putResp)); + ehResult = OC_EH_OK; + } + else + { + OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small", + maxPayloadSize); + ehResult = OC_EH_ERROR; + } + + free(putResp); + + return ehResult; +} + +OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, OCEntityHandlerResponse *response, char *payload, uint16_t maxPayloadSize) +{ + OCEntityHandlerResult ehResult = OC_EH_OK; + char *respPLPost_light = NULL; + cJSON *json; + cJSON *format; + + /* + * The entity handler determines how to process a POST request. + * Per the REST paradigm, POST can also be used to update representation of existing + * resource or create a new resource. + * In the sample below, if the POST is for /a/light then a new instance of the Light + * resource is created with default representation (if representation is included in + * POST payload it can be used as initial values) as long as the instance is + * lesser than max new instance count. Once max instance count is reached, POST on + * /a/light updated the representation of /a/light (just like PUT) + */ + + if (ehRequest->resource == Light.handle) + { + if (gCurrLightInstance < SAMPLE_MAX_NUM_POST_INSTANCE) + { + // Create new Light instance + char newLightUri[URI_MAXSIZE]; + snprintf(newLightUri, URI_MAXSIZE, "/a/light/%d", gCurrLightInstance); + + json = cJSON_CreateObject(); + cJSON_AddStringToObject(json,"href",gResourceUri); + cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject()); + cJSON_AddStringToObject(format, "createduri", (char *) newLightUri); + + if (0 == createLightResource (newLightUri, &gLightInstance[gCurrLightInstance])) + { + OC_LOG (INFO, TAG, "Created new Light instance\n"); + gLightInstance[gCurrLightInstance].state = 0; + gLightInstance[gCurrLightInstance].power = 0; + gCurrLightInstance++; + respPLPost_light = cJSON_Print(json); + strncpy ((char *)response->resourceUri, newLightUri, MAX_URI_LENGTH); + ehResult = OC_EH_RESOURCE_CREATED; + } + + cJSON_Delete(json); + } + else + { + // Update repesentation of /a/light + Light.state = true; + Light.power = 11; + respPLPost_light = constructJsonResponse(ehRequest); + } + } + else + { + for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++) + { + if (ehRequest->resource == gLightInstance[i].handle) + { + gLightInstance[i].state = true; + gLightInstance[i].power = 22; + if (i == 0) + { + respPLPost_light = constructJsonResponse(ehRequest); + break; + } + else if (i == 1) + { + respPLPost_light = constructJsonResponse(ehRequest); + } + } + } + } + + if ((respPLPost_light != NULL) && (maxPayloadSize > strlen ((char *)respPLPost_light))) + { + strncpy(payload, respPLPost_light, strlen((char *)respPLPost_light)); + } + else + { + OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small", + maxPayloadSize); + ehResult = OC_EH_ERROR; + } + + free(respPLPost_light); + return ehResult; +} + +OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize) +{ + if(ehRequest == NULL) + { + OC_LOG(INFO, TAG, "The ehRequest is NULL"); + return OC_EH_ERROR; + } + OCEntityHandlerResult ehResult = OC_EH_OK; + + OC_LOG_V(INFO, TAG, "\n\nExecuting %s for resource %d ", __func__, ehRequest->resource); + + /* + * In the sample below, the application will: + * 1a. pass the delete request to the c stack + * 1b. internally, the c stack figures out what needs to be done and does it accordingly + * (e.g. send observers notification, remove observers...) + * 1c. the c stack returns with the result whether the request is fullfilled. + * 2. optionally, app removes observers out of its array 'interestedObservers' + */ + + const char* deleteResponse = NULL; + + if ((ehRequest != NULL) && (ehRequest->resource == Light.handle)) + { + //Step 1: Ask stack to do the work. + OCStackResult result = OCDeleteResource(ehRequest->resource); + + if (result == OC_STACK_OK) + { + OC_LOG (INFO, TAG, "\n\nDelete Resource operation succeeded."); + ehResult = OC_EH_OK; + deleteResponse = responsePayloadDeleteOk; + + //Step 2: clear observers who wanted to observe this resource at the app level. + for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++) + { + if (interestedObservers[i].resourceHandle == ehRequest->resource) + { + interestedObservers[i].valid = false; + interestedObservers[i].observationId = 0; + interestedObservers[i].resourceHandle = NULL; + } + } + } + else if (result == OC_STACK_NO_RESOURCE) + { + OC_LOG(INFO, TAG, "\n\nThe resource doesn't exist or it might have been deleted."); + deleteResponse = responsePayloadResourceDoesNotExist; + ehResult = OC_EH_RESOURCE_DELETED; + } + else + { + OC_LOG(INFO, TAG, "\n\nEncountered error from OCDeleteResource()."); + deleteResponse = responsePayloadDeleteNotOK; + ehResult = OC_EH_ERROR; + } + } + else if (ehRequest->resource != Light.handle) + { + //Let's this app not supporting DELETE on some resources so + //consider the DELETE request is received for a non-support resource. + OC_LOG_V(INFO, TAG, "\n\nThe request is received for a non-support resource."); + deleteResponse = responsePayloadDeleteResourceNotSupported; + ehResult = OC_EH_FORBIDDEN; + } + + if (maxPayloadSize > strlen ((char *)deleteResponse)) + { + strncpy(payload, deleteResponse, strlen((char *)deleteResponse)); + } + else + { + OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small", + maxPayloadSize); + ehResult = OC_EH_ERROR; + } + + return ehResult; +} + +OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize) +{ + OC_LOG_V(INFO, TAG, "\n\nExecuting %s ", __func__); + + const char* response = NULL; + response = responsePayloadResourceDoesNotExist; + + if ( (ehRequest != NULL) && + (maxPayloadSize > strlen ((char *)response)) ) + { + strncpy((char *)payload, response, strlen((char *)response)); + } + else + { + OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small", + maxPayloadSize); + } + + return OC_EH_RESOURCE_DELETED; +} + +void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest) +{ + OC_LOG_V (INFO, TAG, "Received observation registration request with observation Id %d", + ehRequest->obsInfo.obsId); + for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++) + { + if (interestedObservers[i].valid == false) + { + interestedObservers[i].observationId = ehRequest->obsInfo.obsId; + interestedObservers[i].valid = true; + gLightUnderObservation = 1; + break; + } + } +} + +void ProcessObserveDeregister (OCEntityHandlerRequest *ehRequest) +{ + bool clientStillObserving = false; + + OC_LOG_V (INFO, TAG, "Received observation deregistration request for observation Id %d", + ehRequest->obsInfo.obsId); + for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++) + { + if (interestedObservers[i].observationId == ehRequest->obsInfo.obsId) + { + interestedObservers[i].valid = false; + } + if (interestedObservers[i].valid == true) + { + // Even if there is one single client observing we continue notifying entity handler + clientStillObserving = true; + } + } + if (clientStillObserving == false) + gLightUnderObservation = 0; +} + +OCEntityHandlerResult +OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag, + OCEntityHandlerRequest *entityHandlerRequest, char* uri) +{ + OC_LOG_V (INFO, TAG, "Inside device default entity handler - flags: 0x%x, uri: %s", flag, uri); + + OCEntityHandlerResult ehResult = OC_EH_OK; + OCEntityHandlerResponse response; + char payload[MAX_RESPONSE_LENGTH] = {0}; + + // Validate pointer + if (!entityHandlerRequest) + { + OC_LOG (ERROR, TAG, "Invalid request pointer"); + return OC_EH_ERROR; + } + + // Initialize certain response fields + response.numSendVendorSpecificHeaderOptions = 0; + memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions); + memset(response.resourceUri, 0, sizeof response.resourceUri); + + if (flag & OC_INIT_FLAG) + { + OC_LOG (INFO, TAG, "Flag includes OC_INIT_FLAG"); + } + if (flag & OC_REQUEST_FLAG) + { + OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG"); + if (entityHandlerRequest->resource == NULL) { + OC_LOG (INFO, TAG, "Received request from client to a non-existing resource"); + ehResult = ProcessNonExistingResourceRequest(entityHandlerRequest, payload, sizeof(payload) - 1); + } + else if (OC_REST_GET == entityHandlerRequest->method) + { + OC_LOG (INFO, TAG, "Received OC_REST_GET from client"); + ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1); + } + else if (OC_REST_PUT == entityHandlerRequest->method) + { + OC_LOG (INFO, TAG, "Received OC_REST_PUT from client"); + ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1); + } + else if (OC_REST_DELETE == entityHandlerRequest->method) + { + OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client"); + ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1); + } + else + { + OC_LOG_V (INFO, TAG, "Received unsupported method %d from client", + entityHandlerRequest->method); + ehResult = OC_EH_ERROR; + } + + // If the result isn't an error or forbidden, send response + if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN))) + { + // Format the response. Note this requires some info about the request + response.requestHandle = entityHandlerRequest->requestHandle; + response.resourceHandle = entityHandlerRequest->resource; + response.ehResult = ehResult; + response.payload = (unsigned char *)payload; + response.payloadSize = strlen(payload); + // Indicate that response is NOT in a persistent buffer + response.persistentBufferFlag = 0; + + // Send the response + if (OCDoResponse(&response) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "Error sending response"); + ehResult = OC_EH_ERROR; + } + } + } + if (flag & OC_OBSERVE_FLAG) + { + OC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG"); + if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action) + { + OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client"); + } + else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action) + { + OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client"); + } + } + + return ehResult; +} + +OCEntityHandlerResult +OCNOPEntityHandlerCb (OCEntityHandlerFlag flag, + OCEntityHandlerRequest *entityHandlerRequest) +{ + // This is callback is associated with the 2 presence notification + // resources. They are non-operational. + return OC_EH_OK; +} + +OCEntityHandlerResult +OCEntityHandlerCb (OCEntityHandlerFlag flag, + OCEntityHandlerRequest *entityHandlerRequest) +{ + OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag); + + OCEntityHandlerResult ehResult = OC_EH_OK; + OCEntityHandlerResponse response; + char payload[MAX_RESPONSE_LENGTH] = {0}; + + // Validate pointer + if (!entityHandlerRequest) + { + OC_LOG (ERROR, TAG, "Invalid request pointer"); + return OC_EH_ERROR; + } + + // Initialize certain response fields + response.numSendVendorSpecificHeaderOptions = 0; + memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions); + memset(response.resourceUri, 0, sizeof response.resourceUri); + + if (flag & OC_INIT_FLAG) + { + OC_LOG (INFO, TAG, "Flag includes OC_INIT_FLAG"); + } + if (flag & OC_REQUEST_FLAG) + { + OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG"); + if (OC_REST_GET == entityHandlerRequest->method) + { + OC_LOG (INFO, TAG, "Received OC_REST_GET from client"); + ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1); + } + else if (OC_REST_PUT == entityHandlerRequest->method) + { + OC_LOG (INFO, TAG, "Received OC_REST_PUT from client"); + ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1); + } + else if (OC_REST_POST == entityHandlerRequest->method) + { + OC_LOG (INFO, TAG, "Received OC_REST_POST from client"); + ehResult = ProcessPostRequest (entityHandlerRequest, &response, payload, sizeof(payload) - 1); + } + else if (OC_REST_DELETE == entityHandlerRequest->method) + { + OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client"); + ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1); + } + else + { + OC_LOG_V (INFO, TAG, "Received unsupported method %d from client", + entityHandlerRequest->method); + } + + // If the result isn't an error or forbidden, send response + if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN))) + { + // Format the response. Note this requires some info about the request + response.requestHandle = entityHandlerRequest->requestHandle; + response.resourceHandle = entityHandlerRequest->resource; + response.ehResult = ehResult; + response.payload = (unsigned char *)payload; + response.payloadSize = strlen(payload); + // Indicate that response is NOT in a persistent buffer + response.persistentBufferFlag = 0; + + // Handle vendor specific options + if(entityHandlerRequest->rcvdVendorSpecificHeaderOptions && + entityHandlerRequest->numRcvdVendorSpecificHeaderOptions) + { + OC_LOG (INFO, TAG, "Received vendor specific options"); + uint8_t i = 0; + OCHeaderOption * rcvdOptions = entityHandlerRequest->rcvdVendorSpecificHeaderOptions; + for( i = 0; i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions; i++) + { + if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID) + { + OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with", + ((OCHeaderOption)rcvdOptions[i]).optionID ); + OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData, + ((OCHeaderOption)rcvdOptions[i]).optionLength); + } + } + OCHeaderOption * sendOptions = response.sendVendorSpecificHeaderOptions; + uint8_t option2[] = {21,22,23,24,25,26,27,28,29,30}; + uint8_t option3[] = {31,32,33,34,35,36,37,38,39,40}; + sendOptions[0].protocolID = OC_COAP_ID; + sendOptions[0].optionID = 2248; + memcpy(sendOptions[0].optionData, option2, sizeof(option2)); + sendOptions[0].optionLength = 10; + sendOptions[1].protocolID = OC_COAP_ID; + sendOptions[1].optionID = 2600; + memcpy(sendOptions[1].optionData, option3, sizeof(option3)); + sendOptions[1].optionLength = 10; + response.numSendVendorSpecificHeaderOptions = 2; + } + + // Send the response + if (OCDoResponse(&response) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "Error sending response"); + ehResult = OC_EH_ERROR; + } + } + } + if (flag & OC_OBSERVE_FLAG) + { + OC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG"); + + if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action) + { + OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client"); + ProcessObserveRegister (entityHandlerRequest); + } + else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action) + { + OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client"); + ProcessObserveDeregister (entityHandlerRequest); + } + } + + return ehResult; +} + +/* SIGINT handler: set gQuitFlag to 1 for graceful termination */ +void handleSigInt(int signum) { + if (signum == SIGINT) { + gQuitFlag = 1; + } +} + +void *ChangeLightRepresentation (void *param) +{ + (void)param; + OCStackResult result = OC_STACK_ERROR; + + uint8_t j = 0; + uint8_t numNotifies = (SAMPLE_MAX_NUM_OBSERVATIONS)/2; + OCObservationId obsNotify[numNotifies]; + + while (!gQuitFlag) + { + sleep(10); + Light.power += 5; + if (gLightUnderObservation) + { + OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", Light.power); + if (gObserveNotifyType == 1) + { + // Notify list of observers. Alternate observers on the list will be notified. + j = 0; + for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; (i=i+2)) + { + if (interestedObservers[i].valid == true) + { + obsNotify[j] = interestedObservers[i].observationId; + j++; + } + } + + cJSON *json = cJSON_CreateObject(); + cJSON *format; + cJSON_AddStringToObject(json,"href",gResourceUri); + cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject()); + cJSON_AddStringToObject(format, "state", (char *) (Light.state ? "on":"off")); + cJSON_AddNumberToObject(format, "power", Light.power); + char * obsResp = cJSON_Print(json); + cJSON_Delete(json); + result = OCNotifyListOfObservers (Light.handle, obsNotify, j, + (unsigned char *)obsResp, OC_NA_QOS); + free(obsResp); + } + else if (gObserveNotifyType == 0) + { + // Notifying all observers + result = OCNotifyAllObservers (Light.handle, OC_NA_QOS); + if (OC_STACK_NO_OBSERVERS == result) + { + OC_LOG (INFO, TAG, + "=======> No more observers exist, stop sending observations"); + gLightUnderObservation = 0; + } + } + else + { + OC_LOG (ERROR, TAG, "Incorrect notification type selected"); + } + } +#ifdef WITH_PRESENCE + if(stopPresenceCount > 0) + { + OC_LOG_V(INFO, TAG, "================ presence count %d", stopPresenceCount); + } + if(!stopPresenceCount--) + { + OC_LOG(INFO, TAG, "================ stopping presence"); + OCStopPresence(); + } +#endif + } + return NULL; +} + +void *presenceNotificationGenerator(void *param) +{ + sleep(5); + (void)param; + OCDoHandle presenceNotificationHandles[numPresenceResources]; + OCStackResult res = OC_STACK_OK; + + std::array presenceNotificationResources { { + std::string("core.fan"), + std::string("core.led") } }; + std::array presenceNotificationUris { { + std::string("/a/fan"), + std::string("/a/led") } }; + + for(int i=0; i"); + OC_LOG(INFO, TAG, "-o 0 : Notify all observers"); + OC_LOG(INFO, TAG, "-o 1 : Notify list of observers"); +} + +int main(int argc, char* argv[]) +{ + uint8_t addr[20] = {0}; + uint8_t* paddr = NULL; + uint16_t port = OC_WELL_KNOWN_PORT; + uint8_t ifname[] = "eth0"; + pthread_t threadId; + pthread_t threadId_presence; + int opt; + + while ((opt = getopt(argc, argv, "o:")) != -1) + { + switch(opt) + { + case 'o': + gObserveNotifyType = atoi(optarg); + break; + default: + PrintUsage(); + return -1; + } + } + + if ((gObserveNotifyType != 0) && (gObserveNotifyType != 1)) + { + PrintUsage(); + return -1; + } + + OC_LOG(DEBUG, TAG, "OCServer is starting..."); + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, + sizeof(addr)) == ERR_SUCCESS) + { + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + paddr = addr; + } + + if (OCInit((char *) paddr, port, OC_SERVER) != OC_STACK_OK) { + OC_LOG(ERROR, TAG, "OCStack init error"); + return 0; + } +#ifdef WITH_PRESENCE + if (OCStartPresence(0) != OC_STACK_OK) { + OC_LOG(ERROR, TAG, "OCStack presence/discovery error"); + return 0; + } +#endif + + OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandlerCb); + + OCStackResult deviceResult = SetDeviceInfo(contentType, dateOfManufacture, deviceName, + deviceUUID, firmwareVersion, hostName, manufacturerName, + manufacturerUrl, modelNumber, platformVersion, supportUrl, version); + + if (deviceResult != OC_STACK_OK) + { + OC_LOG(INFO, TAG, "Device Registration failed!"); + exit (EXIT_FAILURE); + } + + deviceResult = OCSetDeviceInfo(deviceInfo); + + if (deviceResult != OC_STACK_OK) + { + OC_LOG(INFO, TAG, "Device Registration failed!"); + exit (EXIT_FAILURE); + } + + /* + * Declare and create the example resource: Light + */ + createLightResource(gResourceUri, &Light); + + // Initialize observations data structure for the resource + for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++) + { + interestedObservers[i].valid = false; + } + + /* + * Create a thread for changing the representation of the Light + */ + pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL); + + /* + * Create a thread for generating changes that cause presence notifications + * to be sent to clients + */ + pthread_create(&threadId_presence, NULL, presenceNotificationGenerator, (void *)NULL); + + // Break from loop with Ctrl-C + OC_LOG(INFO, TAG, "Entering ocserver main loop..."); + DeleteDeviceInfo(); + signal(SIGINT, handleSigInt); + while (!gQuitFlag) { + if (OCProcess() != OC_STACK_OK) { + OC_LOG(ERROR, TAG, "OCStack process error"); + return 0; + } + + sleep(2); + } + + /* + * Cancel the Light thread and wait for it to terminate + */ + pthread_cancel(threadId); + pthread_join(threadId, NULL); + pthread_cancel(threadId_presence); + pthread_join(threadId_presence, NULL); + + OC_LOG(INFO, TAG, "Exiting ocserver main loop..."); + + if (OCStop() != OC_STACK_OK) { + OC_LOG(ERROR, TAG, "OCStack process error"); + } + + return 0; +} + +int createLightResource (char *uri, LightResource *lightResource) +{ + if (!uri) + { + OC_LOG(ERROR, TAG, "Resource URI cannot be NULL"); + return -1; + } + + lightResource->state = false; + lightResource->power= 0; + OCStackResult res = OCCreateResource(&(lightResource->handle), + "core.light", + "oc.mi.def", + uri, + OCEntityHandlerCb, + OC_DISCOVERABLE|OC_OBSERVABLE); + OC_LOG_V(INFO, TAG, "Created Light resource with result: %s", getResult(res)); + + return 0; +} + +void DeleteDeviceInfo() +{ + free(deviceInfo.contentType); + free(deviceInfo.dateOfManufacture); + free(deviceInfo.deviceName); + free(deviceInfo.deviceUUID); + free(deviceInfo.firmwareVersion); + free(deviceInfo.hostName); + free(deviceInfo.manufacturerName); + free(deviceInfo.manufacturerUrl); + free(deviceInfo.modelNumber); + free(deviceInfo.platformVersion); + free(deviceInfo.supportUrl); + free(deviceInfo.version); +} + +bool DuplicateString(char** targetString, const char* sourceString) +{ + if(!sourceString) + { + return false; + } + else + { + *targetString = (char *) malloc(strlen(sourceString) + 1); + + if(targetString) + { + strncpy(*targetString, sourceString, (strlen(sourceString) + 1)); + return true; + } + } + return false; +} + +OCStackResult SetDeviceInfo(const char *contentType, const char *dateOfManufacture, + const char *deviceName, const char *deviceUUID, const char *firmwareVersion, + const char *hostName, const char *manufacturerName, const char *manufacturerUrl, + const char *modelNumber, const char *platformVersion, const char *supportUrl, + const char *version) +{ + + bool success = true; + + if(manufacturerName != NULL && (strlen(manufacturerName) > MAX_MANUFACTURER_NAME_LENGTH)) + { + return OC_STACK_INVALID_PARAM; + } + + if(manufacturerUrl != NULL && (strlen(manufacturerUrl) > MAX_MANUFACTURER_URL_LENGTH)) + { + return OC_STACK_INVALID_PARAM; + } + + if(!DuplicateString(&deviceInfo.contentType, contentType)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.dateOfManufacture, dateOfManufacture)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.deviceName, deviceName)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.deviceUUID, deviceUUID)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.firmwareVersion, firmwareVersion)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.hostName, hostName)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.manufacturerName, manufacturerName)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.manufacturerUrl, manufacturerUrl)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.modelNumber, modelNumber)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.platformVersion, platformVersion)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.supportUrl, supportUrl)) + { + success = false; + } + + if(!DuplicateString(&deviceInfo.version, version)) + { + success = false; + } + + if(success) + { + return OC_STACK_OK; + } + + DeleteDeviceInfo(); + return OC_STACK_ERROR; +} diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.h b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.h new file mode 100644 index 000000000..81a9507fa --- /dev/null +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.h @@ -0,0 +1,117 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OCSERVER_H_ +#define OCSERVER_H_ + +#include "ocstack.h" + +//----------------------------------------------------------------------------- +// Defines +//----------------------------------------------------------------------------- +#define TAG "ocserver" +#define SAMPLE_MAX_NUM_OBSERVATIONS 8 +#define SAMPLE_MAX_NUM_POST_INSTANCE 2 + +//----------------------------------------------------------------------------- +// Typedefs +//----------------------------------------------------------------------------- + +/* Structure to represent a Light resource */ +typedef struct LIGHTRESOURCE{ + OCResourceHandle handle; + bool state; + int power; +} LightResource; + +/* Structure to represent the observers */ +typedef struct { + OCObservationId observationId; + bool valid; + OCResourceHandle resourceHandle; +} Observers; + +//----------------------------------------------------------------------------- +// Function prototype +//----------------------------------------------------------------------------- + +/* call getResult in common.cpp to get the result in string format. */ +const char *getResult(OCStackResult result); + +/* Function that creates a new Light resource by calling the + * OCCreateResource() method. + */ +int createLightResource (char *uri, LightResource *lightResource); + +/* This method converts the payload to JSON format */ +char* constructJsonResponse (OCEntityHandlerRequest *ehRequest); + +/* This method changes the Light power using an independent thread + * and notifies the observers of new state of the resource. + */ +void *ChangeLightRepresentation (void *param); + +/* Following methods process the PUT, GET, POST, Delete, + * & Observe requests */ +OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest, + char *payload, + uint16_t maxPayloadSize); +OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest, + char *payload, + uint16_t maxPayloadSize); +OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, + OCEntityHandlerResponse *response, + char *payload, + uint16_t maxPayloadSize); +OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest, + char *payload, + uint16_t maxPayloadSize); + +OCEntityHandlerResult ProcessNonExistingResourceRequest (OCEntityHandlerRequest *ehRequest, + char *payload, + uint16_t maxPayloadSize); + +void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest); +void ProcessObserveDeregister (OCEntityHandlerRequest *ehRequest); + +void DeleteDeviceInfo(); + +OCStackResult SetDeviceInfo(const char *contentType, const char *dateOfManufacture, + const char *deviceName, const char *deviceUUID, const char *firmwareVersion, + const char *hostName, const char *manufacturerName, const char *manufacturerUrl, + const char *modelNumber, const char *platformVersion, const char *supportUrl, + const char *version); + + +//----------------------------------------------------------------------------- +// Callback functions +//----------------------------------------------------------------------------- + +/* Entity Handler callback functions */ +OCEntityHandlerResult +OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag, + OCEntityHandlerRequest *entityHandlerRequest, char* uri); + +OCEntityHandlerResult +OCEntityHandlerCb (OCEntityHandlerFlag flag, + OCEntityHandlerRequest *entityHandlerRequest); + + +#endif diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserverbasicops.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserverbasicops.cpp new file mode 100644 index 000000000..bcd741cb3 --- /dev/null +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserverbasicops.cpp @@ -0,0 +1,363 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include +#include +#include +#include +#include "ocstack.h" +#include "logger.h" +#include "cJSON.h" +#include "ocserverbasicops.h" + +//string length of "/a/led/" + std::numeric_limits::digits10 + '\0'" +// 7 + 9 + 1 = 17 +const int URI_MAXSIZE = 17; + +volatile sig_atomic_t gQuitFlag = 0; + +static LEDResource LED; +// This variable determines instance number of the LED resource. +// Used by POST method to create a new instance of LED resource. +static int gCurrLedInstance = 0; +#define SAMPLE_MAX_NUM_POST_INSTANCE 2 +static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE]; + +char *gResourceUri= (char *)"/a/led"; + +static uint16_t OC_WELL_KNOWN_PORT = 5683; + +//This function takes the request as an input and returns the response +//in JSON format. +char* constructJsonResponse (OCEntityHandlerRequest *ehRequest) +{ + cJSON *json = cJSON_CreateObject(); + cJSON *format; + char *jsonResponse; + LEDResource *currLEDResource = &LED; + + if (ehRequest->resource == gLedInstance[0].handle) + { + currLEDResource = &gLedInstance[0]; + gResourceUri = (char *) "a/led/0"; + } + else if (ehRequest->resource == gLedInstance[1].handle) + { + currLEDResource = &gLedInstance[1]; + gResourceUri = (char *) "a/led/1"; + } + + if(OC_REST_PUT == ehRequest->method) + { + cJSON *putJson = cJSON_Parse((char *)ehRequest->reqJSONPayload); + currLEDResource->state = ( !strcmp(cJSON_GetObjectItem(putJson,"state")->valuestring , + "on") ? true:false); + currLEDResource->power = cJSON_GetObjectItem(putJson,"power")->valuedouble; + cJSON_Delete(putJson); + } + + cJSON_AddStringToObject(json,"href",gResourceUri); + cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject()); + cJSON_AddStringToObject(format, "state", (char *) (currLEDResource->state ? "on":"off")); + cJSON_AddNumberToObject(format, "power", currLEDResource->power); + + jsonResponse = cJSON_Print(json); + cJSON_Delete(json); + return jsonResponse; +} + +OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize) +{ + OCEntityHandlerResult ehResult; + char *getResp = constructJsonResponse(ehRequest); + + if (maxPayloadSize > strlen ((char *)getResp)) + { + strncpy(payload, getResp, strlen((char *)getResp)); + ehResult = OC_EH_OK; + } + else + { + OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small", + maxPayloadSize); + ehResult = OC_EH_ERROR; + } + + free(getResp); + + return ehResult; +} + +OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize) +{ + OCEntityHandlerResult ehResult; + char *putResp = constructJsonResponse(ehRequest); + + if (maxPayloadSize > strlen ((char *)putResp)) + { + strncpy(payload, putResp, strlen((char *)putResp)); + ehResult = OC_EH_OK; + } + else + { + OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small", + maxPayloadSize); + ehResult = OC_EH_ERROR; + } + + free(putResp); + + return ehResult; +} + +OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize) +{ + char *respPLPost_led = NULL; + cJSON *json; + cJSON *format; + OCEntityHandlerResult ehResult; + + /* + * The entity handler determines how to process a POST request. + * Per the REST paradigm, POST can also be used to update representation of existing + * resource or create a new resource. + * In the sample below, if the POST is for /a/led then a new instance of the LED + * resource is created with default representation (if representation is included in + * POST payload it can be used as initial values) as long as the instance is + * lesser than max new instance count. Once max instance count is reached, POST on + * /a/led updated the representation of /a/led (just like PUT) + */ + + if (ehRequest->resource == LED.handle) + { + if (gCurrLedInstance < SAMPLE_MAX_NUM_POST_INSTANCE) + { + // Create new LED instance + char newLedUri[URI_MAXSIZE ]; + snprintf(newLedUri, URI_MAXSIZE, "/a/led/%d", gCurrLedInstance); + + json = cJSON_CreateObject(); + + cJSON_AddStringToObject(json,"href",gResourceUri); + cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject()); + cJSON_AddStringToObject(format, "createduri", (char *) newLedUri); + + if (0 == createLEDResource (newLedUri, &gLedInstance[gCurrLedInstance], false, 0)) + { + OC_LOG (INFO, TAG, "Created new LED instance"); + gLedInstance[gCurrLedInstance].state = 0; + gLedInstance[gCurrLedInstance].power = 0; + gCurrLedInstance++; + respPLPost_led = cJSON_Print(json); + } + + cJSON_Delete(json); + } + else + { + respPLPost_led = constructJsonResponse(ehRequest); + } + } + else + { + for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++) + { + if (ehRequest->resource == gLedInstance[i].handle) + { + if (i == 0) + { + respPLPost_led = constructJsonResponse(ehRequest); + break; + } + else if (i == 1) + { + respPLPost_led = constructJsonResponse(ehRequest); + } + } + } + } + + if ((respPLPost_led != NULL) && (maxPayloadSize > strlen ((char *)respPLPost_led))) + { + strncpy(payload, respPLPost_led, strlen((char *)respPLPost_led)); + ehResult = OC_EH_OK; + } + else + { + OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small", + maxPayloadSize); + ehResult = OC_EH_ERROR; + } + + free(respPLPost_led); + + return ehResult; +} + +OCEntityHandlerResult +OCEntityHandlerCb (OCEntityHandlerFlag flag, + OCEntityHandlerRequest *entityHandlerRequest) +{ + OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag); + + OCEntityHandlerResult ehResult = OC_EH_ERROR; + OCEntityHandlerResponse response; + char payload[MAX_RESPONSE_LENGTH] = {0}; + + if (flag & OC_INIT_FLAG) + { + OC_LOG (INFO, TAG, "Flag includes OC_INIT_FLAG"); + ehResult = OC_EH_OK; + } + if (flag & OC_REQUEST_FLAG) + { + OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG"); + if (entityHandlerRequest) + { + if (OC_REST_GET == entityHandlerRequest->method) + { + OC_LOG (INFO, TAG, "Received OC_REST_GET from client"); + ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1); + } + else if (OC_REST_PUT == entityHandlerRequest->method) + { + OC_LOG (INFO, TAG, "Received OC_REST_PUT from client"); + ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1); + } + else if (OC_REST_POST == entityHandlerRequest->method) + { + OC_LOG (INFO, TAG, "Received OC_REST_POST from client"); + ehResult = ProcessPostRequest (entityHandlerRequest, payload, sizeof(payload) - 1); + } + else + { + OC_LOG_V (INFO, TAG, "Received unsupported method %d from client", + entityHandlerRequest->method); + } + + if (ehResult == OC_EH_OK) + { + // Format the response. Note this requires some info about the request + response.requestHandle = entityHandlerRequest->requestHandle; + response.resourceHandle = entityHandlerRequest->resource; + response.ehResult = ehResult; + response.payload = (unsigned char *)payload; + response.payloadSize = strlen(payload); + response.numSendVendorSpecificHeaderOptions = 0; + memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions); + memset(response.resourceUri, 0, sizeof(response.resourceUri)); + // Indicate that response is NOT in a persistent buffer + response.persistentBufferFlag = 0; + + // Send the response + if (OCDoResponse(&response) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "Error sending response"); + ehResult = OC_EH_ERROR; + } + } + } + } + return ehResult; +} + +/* SIGINT handler: set gQuitFlag to 1 for graceful termination */ +void handleSigInt(int signum) +{ + if (signum == SIGINT) + { + gQuitFlag = 1; + } +} + +int main(int argc, char* argv[]) +{ + uint8_t addr[20] = {0}; + uint8_t* paddr = NULL; + uint16_t port = OC_WELL_KNOWN_PORT; + uint8_t ifname[] = "eth0"; + + OC_LOG(DEBUG, TAG, "OCServer is starting..."); + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, + sizeof(addr)) == ERR_SUCCESS) + { + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + paddr = addr; + } + + if (OCInit((char *) paddr, port, OC_SERVER) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack init error"); + return 0; + } + + /* + * Declare and create the example resource: LED + */ + createLEDResource(gResourceUri, &LED, false, 0); + + // Break from loop with Ctrl-C + OC_LOG(INFO, TAG, "Entering ocserver main loop..."); + signal(SIGINT, handleSigInt); + while (!gQuitFlag) + { + if (OCProcess() != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack process error"); + return 0; + } + + sleep(2); + } + + OC_LOG(INFO, TAG, "Exiting ocserver main loop..."); + + if (OCStop() != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack process error"); + } + + return 0; +} + +int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower) +{ + if (!uri) + { + OC_LOG(ERROR, TAG, "Resource URI cannot be NULL"); + return -1; + } + + ledResource->state = resourceState; + ledResource->power= resourcePower; + OCStackResult res = OCCreateResource(&(ledResource->handle), + "core.led", + "oc.mi.def", + uri, + OCEntityHandlerCb, + OC_DISCOVERABLE|OC_OBSERVABLE); + OC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res)); + + return 0; +} diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserverbasicops.h b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserverbasicops.h new file mode 100644 index 000000000..74f862e81 --- /dev/null +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserverbasicops.h @@ -0,0 +1,80 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OCSERVER_BASICOPS_H_ +#define OCSERVER_BASICOPS_H_ + +#include "ocstack.h" + +//----------------------------------------------------------------------------- +// Defines +//----------------------------------------------------------------------------- +#define TAG "ocserverbasicops" + +//----------------------------------------------------------------------------- +// Typedefs +//----------------------------------------------------------------------------- + +/* Structure to represent a LED resource */ +typedef struct LEDRESOURCE{ + OCResourceHandle handle; + bool state; + int power; +} LEDResource; + +//----------------------------------------------------------------------------- +// Function prototype +//----------------------------------------------------------------------------- + +/* Function that creates a new LED resource by calling the + * OCCreateResource() method. + */ +int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower); + +/* This method converts the payload to JSON format */ +char* constructJsonResponse (OCEntityHandlerRequest *ehRequest); + +/* Following methods process the PUT, GET, POST + * requests + */ +OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest, + char *payload, + uint16_t maxPayloadSize); +OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest, + char *payload, + uint16_t maxPayloadSize); +OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, + char *payload, + uint16_t maxPayloadSize); + +/* call getResult in common.cpp to get the result in string format. */ +const char *getResult(OCStackResult result); + +//----------------------------------------------------------------------------- +// Callback functions +//----------------------------------------------------------------------------- + +/* Entity Handler callback functions */ + +OCEntityHandlerResult +OCEntityHandlerCb (OCEntityHandlerFlag flag, + OCEntityHandlerRequest *entityHandlerRequest); + +#endif diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/ocservercoll.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/ocservercoll.cpp new file mode 100644 index 000000000..75124bb1e --- /dev/null +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/ocservercoll.cpp @@ -0,0 +1,573 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const char *getResult(OCStackResult result); + +#define TAG PCF("ocservercontainer") + +volatile sig_atomic_t gQuitFlag = 0; +int gLightUnderObservation = 0; +void createResources(); +typedef struct LIGHTRESOURCE{ + OCResourceHandle handle; + bool state; + int power; +} LightResource; + +static LightResource light; + +// TODO : hard coded for now, change after Sprint10 +const char rspGetRoomDefault[] = "{\"href\":\"/a/room\",\"rep\":{\"name\":\"John's Room\"}}"; +const char rspGetRoomCollection[] = "{\"href\":\"/a/room\"}"; +// TODO : Needs to be changed to retrieve current status of room and return that in response +const char rspPutRoomDefault[] = "{\"href\":\"/a/room\",\"rep\":{\"name\":\"John's Room\"}}"; +const char rspPutRoomCollection[] = "{\"href\":\"/a/room\"}"; +const char rspFailureRoom[] = "{\"href\":\"/a/room\",\"rep\":{\"error\":\"ROOM_OP_FAIL\"}}"; + +// TODO : hard coded for now, change after Sprint4 +const char rspGetLightDefault[] = "{\"href\":\"/a/light\",\"rep\":{\"state\":\"false\",\"color\":\"0\"}}"; +const char rspGetLightCollection[] = "{\"href\":\"/a/light\"}"; +// TODO : Needs to be changed to retrieve current status of light and return that in response +const char rspPutLightDefault[] = "{\"href\":\"/a/light\",\"rep\":{\"state\":\"true\",\"color\":\"0\"}}"; +const char rspPutLightCollection[] = "{\"href\":\"/a/light\"}"; +const char rspFailureLight[] = "{\"href\":\"/a/light\",\"rep\":{\"error\":\"LIGHT_OP_FAIL\"}}"; + + +// TODO : hard coded for now, change after Sprint4 +const char rspGetFanDefault[] = "{\"href\":\"/a/fan\",\"rep\":{\"state\":\"true\",\"speed\":10}}"; +const char rspGetFanCollection[] = "{\"href\":\"/a/fan\"}"; +// TODO : Needs to be changed to retrieve current status of fan and return that in response +const char rspPutFanDefault[] = "{\"href\":\"/a/fan\",\"rep\":{\"state\":\"false\",\"speed\":0}}"; +const char rspPutFanCollection[] = "{\"href\":\"/a/fan\"}"; +const char rspFailureFan[] = "{\"href\":\"/a/fan\",\"rep\":{\"error\":\"FAN_OP_FAIL\"}}"; + +typedef enum { + TEST_INVALID = 0, + TEST_DEFAULT_COLL_EH, + TEST_APP_COLL_EH, + MAX_TESTS +} SERVER_TEST; + +void PrintUsage() +{ + OC_LOG(INFO, TAG, "Usage : ocservercoll -t "); + OC_LOG(INFO, TAG, "Test Case 1 : Create room resource with default collection entity handler."); + OC_LOG(INFO, TAG, "Test Case 2 : Create room resource with application collection entity handler."); +} + +unsigned static int TEST = TEST_INVALID; + +static OCEntityHandlerResult +HandleCallback(OCEntityHandlerRequest * ehRequest, + const char* opStr, + const char* errStr, + char *payload, + uint16_t maxPayloadSize) +{ + OCEntityHandlerResult ret = OC_EH_OK; + + // Append opStr or errStr, after making sure there is + // enough room in the payload + if (strlen(opStr) < (maxPayloadSize - strlen(payload))) + { + strncat((char*)payload, opStr, strlen(opStr)); + } + else if (strlen(errStr) < (maxPayloadSize - strlen(payload))) + { + strncat((char*)payload, errStr, strlen(errStr)); + ret = OC_EH_ERROR; + } + else + { + ret = OC_EH_ERROR; + } + + return ret; +} + +static void +PrintReceivedMsgInfo(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest) +{ + const char* typeOfMessage; + + switch (flag) { + case OC_INIT_FLAG: + typeOfMessage = "OC_INIT_FLAG"; + break; + case OC_REQUEST_FLAG: + typeOfMessage = "OC_REQUEST_FLAG"; + break; + case OC_OBSERVE_FLAG: + typeOfMessage = "OC_OBSERVE_FLAG"; + break; + default: + typeOfMessage = "UNKNOWN"; + } + + OC_LOG_V(INFO, TAG, "Receiving message type: %s, method %s", + typeOfMessage, + (ehRequest->method == OC_REST_GET) ? "OC_REST_GET" : "OC_REST_PUT" ); +} + +OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag, + OCEntityHandlerRequest * ehRequest) +{ + OCEntityHandlerResult ret = OC_EH_OK; + OCEntityHandlerResponse response; + char payload[MAX_RESPONSE_LENGTH] = {0}; + + OC_LOG_V(INFO, TAG, "Callback for Room"); + PrintReceivedMsgInfo(flag, ehRequest ); + + if(ehRequest && flag == OC_REQUEST_FLAG ) + { + std::string query = (const char*)ehRequest->query; + + if(OC_REST_GET == ehRequest->method) + { + if(query.find("oc.mi.def") != std::string::npos) + { + ret = HandleCallback(ehRequest, rspGetRoomDefault, rspFailureRoom, payload, sizeof(payload)); + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload)); + ret = HandleCallback(ehRequest, rspGetLightCollection, rspFailureLight, payload, sizeof(payload)); + } + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload)); + ret = HandleCallback(ehRequest, rspGetFanCollection, rspFailureFan, payload, sizeof(payload)); + } + } + else if(query.find("oc.mi.ll") != std::string::npos) + { + ret = HandleCallback(ehRequest, rspGetRoomCollection, rspFailureRoom, payload, sizeof(payload)); + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload)); + ret = HandleCallback(ehRequest, rspGetLightCollection, rspFailureLight, payload, sizeof(payload)); + } + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload)); + ret = HandleCallback(ehRequest, rspGetFanCollection, rspFailureFan, payload, sizeof(payload)); + } + } + else if(query.find("oc.mi.b") != std::string::npos) + { + ret = HandleCallback(ehRequest, rspGetRoomCollection, rspFailureRoom, payload, sizeof(payload)); + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload)); + ret = HandleCallback(ehRequest, rspGetLightDefault, rspFailureLight, payload, sizeof(payload)); + } + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload)); + ret = HandleCallback(ehRequest, rspGetFanDefault, rspFailureFan, payload, sizeof(payload)); + } + } + if (ret == OC_EH_OK) + { + // Format the response. Note this requires some info about the request + response.requestHandle = ehRequest->requestHandle; + response.resourceHandle = ehRequest->resource; + response.ehResult = ret; + response.payload = (unsigned char *)payload; + response.payloadSize = strlen(payload); + response.numSendVendorSpecificHeaderOptions = 0; + memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions); + memset(response.resourceUri, 0, sizeof response.resourceUri); + // Indicate that response is NOT in a persistent buffer + response.persistentBufferFlag = 0; + // Send the response + if (OCDoResponse(&response) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "Error sending response"); + ret = OC_EH_ERROR; + } + } + } + else if(OC_REST_PUT == ehRequest->method) + { + if(query.find("oc.mi.def") != std::string::npos) + { + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, rspPutRoomDefault, rspFailureRoom, payload, sizeof(payload)); + } + } + if(query.find("oc.mi.ll") != std::string::npos) + { + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, rspPutRoomCollection, rspFailureRoom, payload, sizeof(payload)); + } + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload)); + ret = HandleCallback(ehRequest, rspPutLightCollection, rspFailureLight, payload, sizeof(payload)); + } + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload)); + ret = HandleCallback(ehRequest, rspPutFanCollection, rspFailureFan, payload, sizeof(payload)); + } + } + if(query.find("oc.mi.b") != std::string::npos) + { + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, rspPutRoomCollection, rspFailureRoom, payload, sizeof(payload)); + } + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload)); + ret = HandleCallback(ehRequest, rspPutLightDefault, rspFailureLight, payload, sizeof(payload)); + } + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload)); + ret = HandleCallback(ehRequest, rspPutFanDefault, rspFailureFan, payload, sizeof(payload)); + } + } + if (ret == OC_EH_OK) + { + // Format the response. Note this requires some info about the request + response.requestHandle = ehRequest->requestHandle; + response.resourceHandle = ehRequest->resource; + response.ehResult = ret; + response.payload = (unsigned char *)payload; + response.payloadSize = strlen(payload); + response.numSendVendorSpecificHeaderOptions = 0; + memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions); + memset(response.resourceUri, 0, sizeof response.resourceUri); + // Indicate that response is NOT in a persistent buffer + response.persistentBufferFlag = 0; + // Send the response + if (OCDoResponse(&response) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "Error sending response"); + ret = OC_EH_ERROR; + } + } + } + else + { + OC_LOG_V (INFO, TAG, "Received unsupported method %d from client", + ehRequest->method); + ret = OC_EH_ERROR; + } + } + else if (ehRequest && flag == OC_OBSERVE_FLAG) + { + gLightUnderObservation = 1; + } + return ret; +} + +OCEntityHandlerResult OCEntityHandlerLightCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest) +{ + OCEntityHandlerResult ret = OC_EH_OK; + OCEntityHandlerResponse response; + char payload[MAX_RESPONSE_LENGTH] = {0}; + + OC_LOG_V(INFO, TAG, "Callback for Light"); + PrintReceivedMsgInfo(flag, ehRequest ); + + if(ehRequest && flag == OC_REQUEST_FLAG) + { + if(OC_REST_GET == ehRequest->method) + { + ret = HandleCallback(ehRequest, rspGetLightDefault, rspFailureLight, payload, sizeof(payload)); + } + else if(OC_REST_PUT == ehRequest->method) + { + ret = HandleCallback(ehRequest, rspPutLightDefault, rspFailureLight, payload, sizeof(payload)); + } + else + { + OC_LOG_V (INFO, TAG, "Received unsupported method %d from client", + ehRequest->method); + ret = OC_EH_ERROR; + } + + if (ret == OC_EH_OK) + { + // Format the response. Note this requires some info about the request + response.requestHandle = ehRequest->requestHandle; + response.resourceHandle = ehRequest->resource; + response.ehResult = ret; + response.payload = (unsigned char *)payload; + response.payloadSize = strlen(payload); + response.numSendVendorSpecificHeaderOptions = 0; + memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions); + memset(response.resourceUri, 0, sizeof response.resourceUri); + // Indicate that response is NOT in a persistent buffer + response.persistentBufferFlag = 0; + + // Send the response + if (OCDoResponse(&response) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "Error sending response"); + ret = OC_EH_ERROR; + } + } + } + else if (ehRequest && flag == OC_OBSERVE_FLAG) + { + gLightUnderObservation = 1; + } + + return ret; +} + +OCEntityHandlerResult OCEntityHandlerFanCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest) +{ + OCEntityHandlerResult ret = OC_EH_OK; + OCEntityHandlerResponse response; + char payload[MAX_RESPONSE_LENGTH] = {0}; + + OC_LOG_V(INFO, TAG, "Callback for Fan"); + PrintReceivedMsgInfo(flag, ehRequest ); + + if(ehRequest && flag == OC_REQUEST_FLAG) + { + if(OC_REST_GET == ehRequest->method) + { + ret = HandleCallback(ehRequest, rspGetFanDefault, rspFailureFan, payload, sizeof(payload)); + } + else if(OC_REST_PUT == ehRequest->method) + { + ret = HandleCallback(ehRequest, rspPutFanDefault, rspFailureFan, payload, sizeof(payload)); + } + else + { + OC_LOG_V (INFO, TAG, "Received unsupported method %d from client", + ehRequest->method); + ret = OC_EH_ERROR; + } + + if (ret == OC_EH_OK) + { + // Format the response. Note this requires some info about the request + response.requestHandle = ehRequest->requestHandle; + response.resourceHandle = ehRequest->resource; + response.ehResult = ret; + response.payload = (unsigned char *)payload; + response.payloadSize = strlen(payload); + response.numSendVendorSpecificHeaderOptions = 0; + memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions); + memset(response.resourceUri, 0, sizeof response.resourceUri); + // Indicate that response is NOT in a persistent buffer + response.persistentBufferFlag = 0; + + // Send the response + if (OCDoResponse(&response) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "Error sending response"); + ret = OC_EH_ERROR; + } + } + + } + else if (ehRequest && flag == OC_OBSERVE_FLAG) + { + gLightUnderObservation = 1; + } + + return ret; +} + +/* SIGINT handler: set gQuitFlag to 1 for graceful termination */ +void handleSigInt(int signum) +{ + if (signum == SIGINT) + { + gQuitFlag = 1; + } +} + +void *ChangeLightRepresentation (void *param) +{ + (void)param; + OCStackResult result = OC_STACK_ERROR; + + while (!gQuitFlag) + { + sleep(10); + light.power += 5; + if (gLightUnderObservation) + { + OC_LOG_V(INFO, TAG, + " =====> Notifying stack of new power level %d\n", light.power); + result = OCNotifyAllObservers (light.handle, OC_NA_QOS); + if (OC_STACK_NO_OBSERVERS == result) + { + gLightUnderObservation = 0; + } + } + } + return NULL; +} + +int main(int argc, char* argv[]) +{ + uint8_t addr[20] = {0}; + uint8_t* paddr = NULL; + uint16_t port = 0; + uint8_t ifname[] = "eth0"; + pthread_t threadId; + int opt; + + while ((opt = getopt(argc, argv, "t:")) != -1) + { + switch(opt) + { + case 't': + TEST = atoi(optarg); + break; + default: + PrintUsage(); + return -1; + } + } + if(TEST <= TEST_INVALID || TEST >= MAX_TESTS){ + PrintUsage(); + return -1; + } + + OC_LOG(DEBUG, TAG, "OCServer is starting..."); + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + if (OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, + sizeof(addr)) == ERR_SUCCESS) + { + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + paddr = addr; + } + + if (OCInit((char *) paddr, port, OC_SERVER) != OC_STACK_OK) { + OC_LOG(ERROR, TAG, "OCStack init error"); + return 0; + } + + /* + * Declare and create the example resource: light + */ + createResources(); + + /* + * Create a thread for changing the representation of the light + */ + pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL); + + // Break from loop with Ctrl-C + OC_LOG(INFO, TAG, "Entering ocserver main loop..."); + signal(SIGINT, handleSigInt); + while (!gQuitFlag) + { + if (OCProcess() != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack process error"); + return 0; + } + sleep(2); + } + + /* + * Cancel the light thread and wait for it to terminate + */ + pthread_cancel(threadId); + pthread_join(threadId, NULL); + + OC_LOG(INFO, TAG, "Exiting ocserver main loop..."); + + if (OCStop() != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack process error"); + } + + return 0; +} +void createResources() +{ + light.state = false; + + OCResourceHandle fan; + OCStackResult res = OCCreateResource(&fan, + "core.fan", + "oc.mi.def", + "/a/fan", + OCEntityHandlerFanCb, + OC_DISCOVERABLE|OC_OBSERVABLE); + OC_LOG_V(INFO, TAG, "Created fan resource with result: %s", getResult(res)); + + OCResourceHandle light; + res = OCCreateResource(&light, + "core.light", + "oc.mi.def", + "/a/light", + OCEntityHandlerLightCb, + OC_DISCOVERABLE|OC_OBSERVABLE); + OC_LOG_V(INFO, TAG, "Created light resource with result: %s", getResult(res)); + + OCResourceHandle room; + + if(TEST == TEST_APP_COLL_EH) + { + res = OCCreateResource(&room, + "core.room", + "oc.mi.b", + "/a/room", + OCEntityHandlerRoomCb, + OC_DISCOVERABLE); + } + else + { + res = OCCreateResource(&room, + "core.room", + "oc.mi.b", + "/a/room", + NULL, + OC_DISCOVERABLE); + } + + OC_LOG_V(INFO, TAG, "Created room resource with result: %s", getResult(res)); + OCBindResourceInterfaceToResource(room, "oc.mi.ll"); + OCBindResourceInterfaceToResource(room, "oc.mi.def"); + + res = OCBindResource(room, light); + OC_LOG_V(INFO, TAG, "OC Bind Contained Resource to resource: %s", getResult(res)); + + res = OCBindResource(room, fan); + OC_LOG_V(INFO, TAG, "OC Bind Contained Resource to resource: %s", getResult(res)); +} diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserverslow.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserverslow.cpp new file mode 100644 index 000000000..e1184e1d4 --- /dev/null +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserverslow.cpp @@ -0,0 +1,362 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ocstack.h" +#include "ocmalloc.h" +#include "logger.h" +#include "cJSON.h" +#include "ocserverslow.h" + +volatile sig_atomic_t gQuitFlag = 0; + +static std::list gRequestList; +static constexpr unsigned int SLOW_RESPONSE_DELAY_SEC = 5; + +static LEDResource LED; +// This variable determines instance number of the LED resource. +// Used by POST method to create a new instance of LED resource. +static unsigned int gCurrLedInstance = 0; +static constexpr unsigned int SAMPLE_MAX_NUM_POST_INSTANCE = 2; +static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE]; + +//char *gResourceUri= const_cast("/a/led"); +char *gResourceUri= (char *)"/a/led"; + +static constexpr uint16_t OC_WELL_KNOWN_PORT = 5683; + +//This function takes the request as an input and returns the response +//in JSON format. +char* constructJsonResponse (OCEntityHandlerRequest *ehRequest) +{ + cJSON *json = cJSON_CreateObject(); + cJSON *format; + char *jsonResponse; + LEDResource *currLEDResource = &LED; + + OC_LOG(INFO, TAG, "Entering constructJsonResponse"); + + if (ehRequest->resource == gLedInstance[0].handle) + { + OC_LOG(INFO, TAG, "handle 0"); + currLEDResource = &gLedInstance[0]; + gResourceUri = const_cast("a/led/0"); + } + else if (ehRequest->resource == gLedInstance[1].handle) + { + OC_LOG(INFO, TAG, "handle 1"); + currLEDResource = &gLedInstance[1]; + gResourceUri = const_cast("a/led/1"); + } + + if(OC_REST_PUT == ehRequest->method) + { + cJSON *putJson = cJSON_Parse((char *)ehRequest->reqJSONPayload); + currLEDResource->state = ( !strcmp(cJSON_GetObjectItem(putJson,"state")->valuestring , + "on") ? true:false); + currLEDResource->power = cJSON_GetObjectItem(putJson,"power")->valuedouble; + cJSON_Delete(putJson); + } + + cJSON_AddStringToObject(json,"href",gResourceUri); + cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject()); + cJSON_AddStringToObject(format, "state", (char *) (currLEDResource->state ? "on":"off")); + cJSON_AddNumberToObject(format, "power", currLEDResource->power); + + OC_LOG(INFO, TAG, "Before constructJsonResponse print"); + jsonResponse = cJSON_Print(json); + OC_LOG(INFO, TAG, "Before constructJsonResponse delete"); + cJSON_Delete(json); + + OC_LOG(INFO, TAG, "Before constructJsonResponse return"); + return jsonResponse; +} + +void ProcessGetRequest (OCEntityHandlerRequest *ehRequest) +{ + OC_LOG(INFO, TAG, "Entering ProcessGetRequest"); + char *getResp = constructJsonResponse(ehRequest); + OC_LOG(INFO, TAG, "After constructJsonResponse"); + OCEntityHandlerResponse response; + + // Format the response. Note this requires some info about the request + response.requestHandle = ehRequest->requestHandle; + response.resourceHandle = ehRequest->resource; + response.ehResult = OC_EH_OK; + response.payload = (unsigned char *)getResp; + response.payloadSize = strlen(getResp) + 1; + response.numSendVendorSpecificHeaderOptions = 0; + memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions); + memset(response.resourceUri, 0, sizeof(response.resourceUri)); + // Indicate that response is NOT in a persistent buffer + response.persistentBufferFlag = 0; + + // Send the response + if (OCDoResponse(&response) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "Error sending response"); + } + + free(getResp); +} + +OCEntityHandlerRequest *CopyRequest(OCEntityHandlerRequest *entityHandlerRequest) +{ + OC_LOG(INFO, TAG, "Copying received request for slow response"); + OCEntityHandlerRequest *request = (OCEntityHandlerRequest *)OCMalloc(sizeof(OCEntityHandlerRequest)); + if (request) + { + // Do shallow copy + memcpy(request, entityHandlerRequest, sizeof(OCEntityHandlerRequest)); + // Do deep copy of query + request->query = (unsigned char * )OCMalloc(strlen((const char *)entityHandlerRequest->query) + 1); + if (request->query) + { + strcpy((char *)request->query, (const char *)entityHandlerRequest->query); + + // Copy the request payload + request->reqJSONPayload = (unsigned char * )OCMalloc(strlen((const char *)entityHandlerRequest->reqJSONPayload) + 1); + if (request->reqJSONPayload) + { + strcpy((char *)request->reqJSONPayload, (const char *)entityHandlerRequest->reqJSONPayload); + + // Ignore vendor specific header options for example + request->numRcvdVendorSpecificHeaderOptions = 0; + request->rcvdVendorSpecificHeaderOptions = NULL; + } + else + { + OCFree(request->query); + OCFree(request); + request = NULL; + } + } + else + { + OCFree(request); + request = NULL; + } + } + + if (request) + { + OC_LOG(INFO, TAG, "Copied client request"); + } + else + { + OC_LOG(ERROR, TAG, "Error copying client request"); + } + return request; +} + +OCEntityHandlerResult +OCEntityHandlerCb (OCEntityHandlerFlag flag, + OCEntityHandlerRequest *entityHandlerRequest) +{ + OCEntityHandlerResult result = OC_EH_ERROR; + OCEntityHandlerRequest *request = NULL; + + OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag); + if (flag & OC_INIT_FLAG) + { + OC_LOG(INFO, TAG, "Flag includes OC_INIT_FLAG"); + result = OC_EH_OK; + } + if (flag & OC_REQUEST_FLAG) + { + OC_LOG(INFO, TAG, "Flag includes OC_REQUEST_FLAG"); + if (entityHandlerRequest) + { + OC_LOG_V (INFO, TAG, "request query %s from client", + entityHandlerRequest->query); + OC_LOG_V (INFO, TAG, "request payload %s from client", + entityHandlerRequest->reqJSONPayload); + // Make deep copy of received request and queue it for slow processing + request = CopyRequest(entityHandlerRequest); + if (request) + { + + OC_LOG(INFO, TAG, "Scheduling slow response for received request"); + gRequestList.push_back(request); + // Indicate to the stack that this is a slow response + result = OC_EH_SLOW; + // Start the slow response alarm + alarm(SLOW_RESPONSE_DELAY_SEC); + } + else + { + OC_LOG(ERROR, TAG, "Error queuing request for slow response"); + // Indicate to the stack that this is a slow response + result = OC_EH_ERROR; + } + } + else + { + OC_LOG(ERROR, TAG, "Invalid request"); + result = OC_EH_ERROR; + } + } + return result; +} + +/* SIGINT handler: set gQuitFlag to 1 for graceful termination */ +void handleSigInt(int signum) +{ + if (signum == SIGINT) + { + gQuitFlag = 1; + } +} + +// SIGINT alarm handler: alarm set by entity handler. Does +// slow response when fired +void AlarmHandler(int sig) +{ + if (sig == SIGALRM) + { + OC_LOG (INFO, TAG, "Server starting slow response"); + if (gRequestList.empty()) + { + OC_LOG (INFO, TAG, "No requests to service"); + return; + } + + // Get the request from the list + OCEntityHandlerRequest *entityHandlerRequest = gRequestList.front(); + gRequestList.pop_front(); + if (entityHandlerRequest->method == OC_REST_GET) + { + OC_LOG (INFO, TAG, "Received OC_REST_GET from client"); + ProcessGetRequest (entityHandlerRequest); + } + else + { + OC_LOG_V (INFO, TAG, "Received unsupported method %d from client", + entityHandlerRequest->method); + } + // Free the request + OCFree(entityHandlerRequest->query); + OCFree(entityHandlerRequest->reqJSONPayload); + OCFree(entityHandlerRequest); + + // If there are more requests in list, re-arm the alarm signal + if (gRequestList.empty()) + { + alarm(SLOW_RESPONSE_DELAY_SEC); + } + } +} + +int main(int argc, char* argv[]) +{ + uint8_t addr[20] = {0}; + uint8_t* paddr = NULL; + uint16_t port = OC_WELL_KNOWN_PORT; + uint8_t ifname[] = "eth0"; + + + OC_LOG(DEBUG, TAG, "OCServer is starting..."); + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, + sizeof(addr)) == ERR_SUCCESS) + { + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + paddr = addr; + } + + if (OCInit((char *) paddr, port, OC_SERVER) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack init error"); + return 0; + } + + /* + * Declare and create the example resource: LED + */ + createLEDResource(gResourceUri, &LED, false, 0); + + // Initialize slow response alarm + signal(SIGALRM, AlarmHandler); + + // Break from loop with Ctrl-C + OC_LOG(INFO, TAG, "Entering ocserver main loop..."); + signal(SIGINT, handleSigInt); + + while (!gQuitFlag) + { + if (OCProcess() != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack process error"); + return 0; + } + + sleep(2); + } + + OC_LOG(INFO, TAG, "Exiting ocserver main loop..."); + + // Free requests + if (!gRequestList.empty()) + { + for (auto iter = gRequestList.begin(); iter != gRequestList.end(); ++iter) + { + OCFree((*iter)->query); + OCFree((*iter)->reqJSONPayload); + OCFree(*iter); + } + gRequestList.clear(); + } + + if (OCStop() != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack process error"); + } + + return 0; +} + +int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower) +{ + if (!uri) + { + OC_LOG(ERROR, TAG, "Resource URI cannot be NULL"); + return -1; + } + + ledResource->state = resourceState; + ledResource->power= resourcePower; + OCStackResult res = OCCreateResource(&(ledResource->handle), + "core.led", + "oc.mi.def", + uri, + OCEntityHandlerCb, + OC_DISCOVERABLE|OC_OBSERVABLE); + OC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res)); + + return 0; +} diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserverslow.h b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserverslow.h new file mode 100644 index 000000000..bf37c3440 --- /dev/null +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserverslow.h @@ -0,0 +1,71 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OCSERVER_SLOW_H_ +#define OCSERVER_SLOW_H_ + +#include "ocstack.h" + +//----------------------------------------------------------------------------- +// Defines +//----------------------------------------------------------------------------- +#define TAG "ocserverslow" + +//----------------------------------------------------------------------------- +// Typedefs +//----------------------------------------------------------------------------- + +/* Structure to represent a LED resource */ +typedef struct LEDRESOURCE{ + OCResourceHandle handle; + bool state; + int power; +} LEDResource; + +//----------------------------------------------------------------------------- +// Function prototypes +//----------------------------------------------------------------------------- + +/* Function that creates a new LED resource by calling the + * OCCreateResource() method. + */ +int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower); + +/* This method converts the payload to JSON format */ +char* constructJsonResponse (OCEntityHandlerRequest *ehRequest); + +/* Following method process the GET request + */ +void ProcessGetRequest (OCEntityHandlerRequest *ehRequest); + +/* call getResult in common.cpp to get the result in string format. */ +const char *getResult(OCStackResult result); + +//----------------------------------------------------------------------------- +// Callback functions +//----------------------------------------------------------------------------- + +/* Entity Handler callback functions */ + +OCEntityHandlerResult +OCEntityHandlerCb (OCEntityHandlerFlag flag, + OCEntityHandlerRequest *entityHandlerRequest); + +#endif diff --git a/resource/csdk/stack/samples/linux/secure/common.cpp b/resource/csdk/stack/samples/linux/secure/common.cpp new file mode 100644 index 000000000..55fb32a35 --- /dev/null +++ b/resource/csdk/stack/samples/linux/secure/common.cpp @@ -0,0 +1,117 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include +#include +#include +#include +#include + +#define TAG "sample-common" + +OCStackResult SetCredentials(const char* filename) { + + FILE *fp = NULL; + uint8_t *data = NULL; + struct stat st; + OCStackResult ret = OC_STACK_ERROR; + + fp = fopen(filename, "rb"); + if (fp) + { + if (stat(filename, &st) == 0) + { + data = (uint8_t*)malloc(st.st_size); + if (data) + { + if (fread(data, 1, st.st_size, fp) == (size_t)st.st_size) + { + // Provide credentials to OC Stack + ret = OCSetDtlsPskCredentials((OCDtlsPskCredsBlob *)data, + st.st_size); + } + else + { + OC_LOG_V(FATAL, TAG, "Error in reading file %s", filename); + } + } + } + fclose(fp); + } + else + { + OC_LOG_V(FATAL, TAG, "Unable to open %s file", filename); + } + + free(data); + + return ret; +} + +const char *getResult(OCStackResult result) { + switch (result) { + case OC_STACK_OK: + return "OC_STACK_OK"; + case OC_STACK_RESOURCE_CREATED: + return "OC_STACK_RESOURCE_CREATED"; + case OC_STACK_RESOURCE_DELETED: + return "OC_STACK_RESOURCE_DELETED"; + case OC_STACK_INVALID_URI: + return "OC_STACK_INVALID_URI"; + case OC_STACK_INVALID_QUERY: + return "OC_STACK_INVALID_QUERY"; + case OC_STACK_INVALID_IP: + return "OC_STACK_INVALID_IP"; + case OC_STACK_INVALID_PORT: + return "OC_STACK_INVALID_PORT"; + case OC_STACK_INVALID_CALLBACK: + return "OC_STACK_INVALID_CALLBACK"; + case OC_STACK_INVALID_METHOD: + return "OC_STACK_INVALID_METHOD"; + case OC_STACK_NO_MEMORY: + return "OC_STACK_NO_MEMORY"; + case OC_STACK_COMM_ERROR: + return "OC_STACK_COMM_ERROR"; + case OC_STACK_INVALID_PARAM: + return "OC_STACK_INVALID_PARAM"; + case OC_STACK_NOTIMPL: + return "OC_STACK_NOTIMPL"; + case OC_STACK_NO_RESOURCE: + return "OC_STACK_NO_RESOURCE"; + case OC_STACK_RESOURCE_ERROR: + return "OC_STACK_RESOURCE_ERROR"; + case OC_STACK_SLOW_RESOURCE: + return "OC_STACK_SLOW_RESOURCE"; + case OC_STACK_NO_OBSERVERS: + return "OC_STACK_NO_OBSERVERS"; + #ifdef WITH_PRESENCE + case OC_STACK_VIRTUAL_DO_NOT_HANDLE: + return "OC_STACK_VIRTUAL_DO_NOT_HANDLE"; + case OC_STACK_PRESENCE_STOPPED: + return "OC_STACK_PRESENCE_STOPPED"; + #endif + case OC_STACK_ERROR: + return "OC_STACK_ERROR"; + default: + return "UNKNOWN"; + } +} diff --git a/resource/csdk/stack/samples/linux/secure/common.h b/resource/csdk/stack/samples/linux/secure/common.h new file mode 100644 index 000000000..408ba5912 --- /dev/null +++ b/resource/csdk/stack/samples/linux/secure/common.h @@ -0,0 +1,31 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OCSAMPLE_COMMON_H_ +#define OCSAMPLE_COMMON_H_ + +/* Get the result in string format. */ +const char *getResult(OCStackResult result); + +/* Read the credentials from persistent storage and provide to OC stack. */ +OCStackResult SetCredentials(const char* filename); + +#endif //OCSAMPLE_COMMON_H_ + diff --git a/resource/csdk/stack/samples/linux/secure/gen_sec_bin.cpp b/resource/csdk/stack/samples/linux/secure/gen_sec_bin.cpp new file mode 100644 index 000000000..2a259aca1 --- /dev/null +++ b/resource/csdk/stack/samples/linux/secure/gen_sec_bin.cpp @@ -0,0 +1,123 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "ocsecurityconfig.h" +#include "logger.h" +#include +#include +#include +#include + +#define TAG "gen_sec_bin" + +void printStruct(const char * device, OCDtlsPskCredsBlob* s) +{ + OC_LOG(INFO, TAG, device); + OC_LOG_V(INFO, TAG, "Version - %d", s->blobVer); + OC_LOG(INFO, TAG, "My Identity :"); + OC_LOG_BUFFER(INFO, TAG, s->identity, DTLS_PSK_ID_LEN); + + OC_LOG_V(INFO, TAG, "Number of trusted Peers - %d", s->num); + OC_LOG(INFO, TAG, "Peer Identity :"); + OC_LOG_BUFFER(INFO, TAG, s->creds[0].id, DTLS_PSK_ID_LEN); + OC_LOG(INFO, TAG, "Peer Psk :"); + OC_LOG_BUFFER(INFO, TAG, s->creds[0].psk, DTLS_PSK_PSK_LEN); +} + + +int main() +{ + OCDtlsPskCredsBlob * s = NULL; + OCDtlsPskCredsBlob * c = NULL; + FILE* fps, *fpc; + + int i; + + srand(time(NULL)); + + s = (OCDtlsPskCredsBlob*) malloc(sizeof(OCDtlsPskCredsBlob)); + c = (OCDtlsPskCredsBlob*) malloc(sizeof(OCDtlsPskCredsBlob)); + + memset(s, 0, sizeof(OCDtlsPskCredsBlob)); + memset(c, 0, sizeof(OCDtlsPskCredsBlob)); + + s->blobVer = DtlsPskCredsBlobVer_CurrentVersion; + c->blobVer = DtlsPskCredsBlobVer_CurrentVersion; + + s->num = c->num = 1; + + for(i = 0; i < DTLS_PSK_ID_LEN; i++) + { + c->creds[0].id[i] = s->identity[i] = rand() % (2^8); + + s->creds[0].id[i] = c->identity[i] = rand() % (2^8); + + c->creds[0].psk[i] = s->creds[0].psk[i] = rand() % (2^8); + } + + // Print Credentials + printStruct("Server", s); + printStruct("Client", c); + + // Write to files + if ((fps = (FILE*) fopen("server_cred.bin", "wb")) != NULL) + { + fwrite(s, sizeof(OCDtlsPskCredsBlob), 1, fps); + fclose(fps); + } + + + if ((fpc = (FILE*) fopen("client_cred.bin", "wb")) != NULL) + { + fwrite(c, sizeof(OCDtlsPskCredsBlob), 1, fpc); + fclose(fpc); + } + + memset(s, 0, sizeof(OCDtlsPskCredsBlob)); + memset(c, 0, sizeof(OCDtlsPskCredsBlob)); + // Read from files; print and verify manually + if ((fps = (FILE*) fopen("server_cred.bin", "rb")) != NULL) + { + if (sizeof(OCDtlsPskCredsBlob) != fread(s, 1, sizeof(OCDtlsPskCredsBlob), fps)) + { + OC_LOG(INFO, TAG, PCF("Reading from the file failed.")); + } + fclose(fps); + } + + + if ((fpc = (FILE*) fopen("client_cred.bin", "rb")) != NULL) + { + if (sizeof(OCDtlsPskCredsBlob) != fread(c, 1, sizeof(OCDtlsPskCredsBlob), fpc)) + { + OC_LOG(INFO, TAG, PCF("Reading from the file failed.")); + } + fclose(fpc); + } + + printf("\n\n"); + OC_LOG(INFO, TAG, PCF("Reading from file and printing again to verify manually")); + printStruct("Server", s); + printStruct("Client", c); + + free(s); + free(c); +} + diff --git a/resource/csdk/stack/samples/linux/secure/makefile b/resource/csdk/stack/samples/linux/secure/makefile new file mode 100644 index 000000000..c77d733ab --- /dev/null +++ b/resource/csdk/stack/samples/linux/secure/makefile @@ -0,0 +1,114 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +# override with `make BUILD=debug` +# default to release build +BUILD := release +PLATFORM := linux +CC := g++ +OUT_DIR := $(BUILD) +OBJ_DIR := $(OUT_DIR)/obj + +ifeq ($(ROOT_DIR), ) +ROOT_DIR = ../../../.. +endif + +OUT_DIR = . + +OCLOGGER_DIR = $(ROOT_DIR)/logger +OC_LOG_DIR = $(ROOT_DIR)/../oc_logger +OCRANDOM_DIR = $(ROOT_DIR)/ocrandom +OCSOCKET_DIR = $(ROOT_DIR)/ocsocket +LCOAP_DIR = $(ROOT_DIR)/libcoap-4.1.1 +OCCOAP_DIR = $(ROOT_DIR)/occoap +OCTBSTACK_DIR = $(ROOT_DIR)/stack +EXTLIBS_DIR = $(ROOT_DIR)/../../extlibs +CJSON_DIR = $(EXTLIBS_DIR)/cjson + +CJSON_SRC = $(CJSON_DIR) + +OCLOGGER_INC = $(OCLOGGER_DIR)/include +OC_LOG_INC = $(OC_LOG_DIR)/include +OCRANDOM_INC = $(OCRANDOM_DIR)/include +OCSOCKET_INC = $(OCSOCKET_DIR)/include +LCOAP_INC = $(LCOAP_DIR) +OCCOAP_INC = $(OCCOAP_DIR)/include +OCTBSTACK_INC = $(OCTBSTACK_DIR)/include +CJSON_INC = $(CJSON_DIR) + +INC_DIRS := -I$(OCLOGGER_INC) +INC_DIRS += -I$(OC_LOG_INC) +INC_DIRS += -I$(OCRANDOM_INC) +INC_DIRS += -I$(OCSOCKET_INC) +INC_DIRS += -I$(LCOAP_INC) +INC_DIRS += -I$(OCCOAP_INC) +INC_DIRS += -I$(OCTBSTACK_INC) +INC_DIRS += -I$(CJSON_INC) + +CC_FLAGS.debug := -O0 -g3 -Wall -ffunction-sections -fdata-sections -fno-exceptions \ + -std=c++0x -pedantic $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD) -DTB_LOG +CC_FLAGS.release := -Os -Wall -fdata-sections -Wl,--gc-sections -Wl,-s -fno-exceptions \ + -std=c++0x $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD) -DTB_LOG + +LDLIBS += -loctbstack -lpthread +CPPFLAGS += $(CC_FLAGS.$(BUILD)) $(LDLIBS) + +CJSON_SOURCES := $(CJSON_SRC)/cJSON.c + +SOURCES := $(CJSON_SOURCES) +SOURCES += common.cpp ocserverbasicops.cpp occlientbasicops.cpp gen_sec_bin.cpp + +OBJECTS:= $(patsubst %.cpp, $(OBJ_DIR)/%.o, $(SOURCES)) + +PROGRAMS += ocserverbasicops +PROGRAMS += occlientbasicops +PROGRAMS += gen_sec_bin + +all: c_sdk prep_dirs $(OBJECTS) $(PROGRAMS) + +prep_dirs: + -mkdir -p $(OUT_DIR) + -mkdir -p $(OBJ_DIR) + +c_sdk: + cd $(ROOT_DIR) && $(MAKE) BUILD=$(BUILD) PLATFORM=$(PLATFORM) + +$(OBJ_DIR)/%.o: %.cpp + $(CC) -c $(CPPFLAGS) $< -o $@ + +ocserverbasicops: $(OBJ_DIR)/ocserverbasicops.o $(OBJ_DIR)/common.o + $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@ + +occlientbasicops: $(OBJ_DIR)/occlientbasicops.o $(OBJ_DIR)/common.o + $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@ + +gen_sec_bin: $(OBJ_DIR)/gen_sec_bin.o + $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@ + +.PHONY: clean + +clean: legacy_clean + -rm -rf release + -rm -rf debug + cd $(ROOT_DIR) && $(MAKE) clean + cd $(ROOT_DIR) && $(MAKE) deepclean + +legacy_clean: + rm -f *.o $(PROGRAMS) diff --git a/resource/csdk/stack/samples/linux/secure/occlientbasicops.cpp b/resource/csdk/stack/samples/linux/secure/occlientbasicops.cpp new file mode 100644 index 000000000..e4125d2b2 --- /dev/null +++ b/resource/csdk/stack/samples/linux/secure/occlientbasicops.cpp @@ -0,0 +1,442 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include +#include +#include +#include +#include +#include "ocstack.h" +#include "logger.h" +#include "occlientbasicops.h" +#include "cJSON.h" +#include "common.h" + +#define TAG "occlientbasicops" +static int UNICAST_DISCOVERY = 0; +static int TEST_CASE = 0; +static const char * TEST_APP_UNICAST_DISCOVERY_QUERY = "coap://0.0.0.0:5683/oc/core"; +static std::string putPayload = "{\"state\":\"off\",\"power\":10}"; +static std::string coapServerIP; +static std::string coapServerPort; +static std::string coapServerResource; +static int coapSecureResource; + +//File containing Client's Identity and the PSK credentials +//of other devices which the client trusts +//This can be generated using 'gen_sec_bin' application +static char CRED_FILE[] = "client_cred.bin"; + + +int gQuitFlag = 0; + +/* SIGINT handler: set gQuitFlag to 1 for graceful termination */ +void handleSigInt(int signum) +{ + if (signum == SIGINT) + { + gQuitFlag = 1; + } +} + +static void PrintUsage() +{ + OC_LOG(INFO, TAG, "Usage : occlient -u <0|1> -t <1|2|3>"); + OC_LOG(INFO, TAG, "-u <0|1> : Perform multicast/unicast discovery of resources"); + OC_LOG(INFO, TAG, "-t 1 : Discover Resources"); + OC_LOG(INFO, TAG, "-t 2 : Discover Resources and" + " Initiate Nonconfirmable Get/Put/Post Requests"); + OC_LOG(INFO, TAG, "-t 3 : Discover Resources and Initiate Confirmable Get/Put/Post Requests"); +} + +OCStackResult InvokeOCDoResource(std::ostringstream &query, + OCMethod method, OCQualityOfService qos, + OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions) +{ + OCStackResult ret; + OCCallbackData cbData; + OCDoHandle handle; + + cbData.cb = cb; + cbData.context = NULL; + cbData.cd = NULL; + + ret = OCDoResource(&handle, method, query.str().c_str(), 0, + (method == OC_REST_PUT || method == OC_REST_POST) ? putPayload.c_str() : NULL, + qos, &cbData, options, numOptions); + + if (ret != OC_STACK_OK) + { + OC_LOG_V(ERROR, TAG, "OCDoResource returns error %d with method %d", ret, method); + } + + return ret; +} + +OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) +{ + OC_LOG(INFO, TAG, "Callback Context for PUT recvd successfully"); + + if(clientResponse) + { + OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result)); + OC_LOG_V(INFO, TAG, "JSON = %s =============> Put Response", clientResponse->resJSONPayload); + } + return OC_STACK_DELETE_TRANSACTION; +} + +OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse) +{ + OC_LOG(INFO, TAG, "Callback Context for POST recvd successfully"); + + if(clientResponse) + { + OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result)); + OC_LOG_V(INFO, TAG, "JSON = %s =============> Post Response", + clientResponse->resJSONPayload); + } + return OC_STACK_DELETE_TRANSACTION; +} + +OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) +{ + OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully"); + + if(clientResponse) + { + OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result)); + OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber); + OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response", + clientResponse->resJSONPayload); + } + return OC_STACK_DELETE_TRANSACTION; +} + +// This is a function called back when a device is discovered +OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle, + OCClientResponse * clientResponse) +{ + uint8_t remoteIpAddr[4]; + uint16_t remotePortNu; + + OC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully"); + + if (clientResponse) + { + OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result)); + + OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddr, + remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3); + OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNu); + + OC_LOG_V(INFO, TAG, + "Device =============> Discovered %s @ %d.%d.%d.%d:%d", + clientResponse->resJSONPayload, remoteIpAddr[0], remoteIpAddr[1], + remoteIpAddr[2], remoteIpAddr[3], remotePortNu); + + if (parseClientResponse(clientResponse) != -1) + { + switch(TEST_CASE) + { + case TEST_NON_CON_OP: + InitGetRequest(OC_LOW_QOS); + InitPutRequest(); + //InitPostRequest(OC_LOW_QOS); + break; + case TEST_CON_OP: + InitGetRequest(OC_HIGH_QOS); + InitPutRequest(); + //InitPostRequest(OC_HIGH_QOS); + break; + } + } + } + + return (UNICAST_DISCOVERY) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ; + +} + +int InitPutRequest() +{ + OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); + std::ostringstream query; + query << (coapSecureResource ? "coaps://" : "coap://") << coapServerIP + << ":" << coapServerPort << coapServerResource; + return (InvokeOCDoResource(query, OC_REST_PUT, OC_LOW_QOS, putReqCB, NULL, 0)); +} + +int InitPostRequest(OCQualityOfService qos) +{ + OCStackResult result; + OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); + std::ostringstream query; + query << (coapSecureResource ? "coaps://" : "coap://") << coapServerIP + << ":" << coapServerPort << coapServerResource; + + // First POST operation (to create an LED instance) + result = InvokeOCDoResource(query, OC_REST_POST, + ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), + postReqCB, NULL, 0); + if (OC_STACK_OK != result) + { + // Error can happen if for example, network connectivity is down + OC_LOG(INFO, TAG, "First POST call did not succeed"); + } + + // Second POST operation (to create an LED instance) + result = InvokeOCDoResource(query, OC_REST_POST, + ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), + postReqCB, NULL, 0); + if (OC_STACK_OK != result) + { + OC_LOG(INFO, TAG, "Second POST call did not succeed"); + } + + // This POST operation will update the original resourced /a/led + return (InvokeOCDoResource(query, OC_REST_POST, + ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), + postReqCB, NULL, 0)); +} + +int InitGetRequest(OCQualityOfService qos) +{ + OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); + std::ostringstream query; + query << (coapSecureResource ? "coaps://" : "coap://") << coapServerIP + << ":" << coapServerPort << coapServerResource; + + return (InvokeOCDoResource(query, OC_REST_GET, (qos == OC_HIGH_QOS)? + OC_HIGH_QOS:OC_LOW_QOS, getReqCB, NULL, 0)); +} + +int InitDiscovery() +{ + OCStackResult ret; + OCCallbackData cbData; + OCDoHandle handle; + /* Start a discovery query*/ + char szQueryUri[64] = { 0 }; + if (UNICAST_DISCOVERY) + { + strcpy(szQueryUri, TEST_APP_UNICAST_DISCOVERY_QUERY); + } + else + { + strcpy(szQueryUri, OC_WELL_KNOWN_QUERY); + } + cbData.cb = discoveryReqCB; + cbData.context = NULL; + cbData.cd = NULL; + ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0); + if (ret != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack resource error"); + } + return ret; +} + +int main(int argc, char* argv[]) +{ + uint8_t addr[20] = {0}; + uint8_t* paddr = NULL; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + int opt; + struct timespec timeout; + + while ((opt = getopt(argc, argv, "u:t:")) != -1) + { + switch(opt) + { + case 'u': + UNICAST_DISCOVERY = atoi(optarg); + break; + case 't': + TEST_CASE = atoi(optarg); + break; + default: + PrintUsage(); + return -1; + } + } + + if ((UNICAST_DISCOVERY != 0 && UNICAST_DISCOVERY != 1) || + (TEST_CASE < TEST_DISCOVER_REQ || TEST_CASE >= MAX_TESTS) ) + { + PrintUsage(); + return -1; + } + + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, + sizeof(addr)) == ERR_SUCCESS) + { + OC_LOG_V(INFO, TAG, "Starting occlient on address %s",addr); + paddr = addr; + } + + /* Initialize OCStack*/ + if (OCInit((char *) paddr, port, OC_CLIENT) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack init error"); + return 0; + } + + /* + * Read DTLS PSK credentials from persistent storage and + * set in the OC stack. + */ + if (SetCredentials(CRED_FILE) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "SetCredentials failed"); + return 0; + } + + InitDiscovery(); + + timeout.tv_sec = 0; + timeout.tv_nsec = 100000000L; + + // Break from loop with Ctrl+C + OC_LOG(INFO, TAG, "Entering occlient main loop..."); + signal(SIGINT, handleSigInt); + while (!gQuitFlag) + { + if (OCProcess() != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack process error"); + return 0; + } + + nanosleep(&timeout, NULL); + } + OC_LOG(INFO, TAG, "Exiting occlient main loop..."); + + if (OCStop() != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack stop error"); + } + + return 0; +} + +std::string getIPAddrTBServer(OCClientResponse * clientResponse) +{ + if(!clientResponse) return ""; + if(!clientResponse->addr) return ""; + uint8_t a, b, c, d = 0; + if(0 != OCDevAddrToIPv4Addr(clientResponse->addr, &a, &b, &c, &d) ) return ""; + + char ipaddr[16] = {'\0'}; + // ostringstream not working correctly here, hence snprintf + snprintf(ipaddr, sizeof(ipaddr), "%d.%d.%d.%d", a,b,c,d); + return std::string (ipaddr); +} + + +std::string getPortTBServer(OCClientResponse * clientResponse) +{ + if(!clientResponse) return ""; + if(!clientResponse->addr) return ""; + uint16_t p = 0; + if(0 != OCDevAddrToPort(clientResponse->addr, &p) ) return ""; + std::ostringstream ss; + ss << p; + return ss.str(); +} + +int parseClientResponse(OCClientResponse * clientResponse) +{ + int port = -1; + cJSON * root = NULL; + cJSON * oc = NULL; + + // Initialize all global variables + coapServerResource.clear(); + coapServerPort.clear(); + coapServerIP.clear(); + coapSecureResource = 0; + + root = cJSON_Parse((char *)(clientResponse->resJSONPayload)); + if (!root) + { + return -1; + } + + oc = cJSON_GetObjectItem(root,"oc"); + if (!oc) + { + return -1; + } + + if (oc->type == cJSON_Array) + { + if (cJSON_GetArraySize(oc) > 0) + { + cJSON * resource = cJSON_GetArrayItem(oc, 0); + if (cJSON_GetObjectItem(resource, "href")) + { + coapServerResource.assign(cJSON_GetObjectItem(resource, "href")->valuestring); + } + else + { + coapServerResource = ""; + } + OC_LOG_V(INFO, TAG, "Uri -- %s", coapServerResource.c_str()); + + cJSON * prop = cJSON_GetObjectItem(resource,"prop"); + if (prop) + { + // If this is a secure resource, the info about the port at which the + // resource is hosted on server is embedded inside discovery JSON response + if (cJSON_GetObjectItem(prop, "sec")) + { + if ((cJSON_GetObjectItem(prop, "sec")->valueint) == 1) + { + coapSecureResource = 1; + } + } + OC_LOG_V(INFO, TAG, "Secure -- %s", coapSecureResource == 1 ? "YES" : "NO"); + if (cJSON_GetObjectItem(prop, "port")) + { + port = cJSON_GetObjectItem(prop, "port")->valueint; + OC_LOG_V(INFO, TAG, "Hosting Server Port (embedded inside JSON) -- %u", port); + + std::ostringstream ss; + ss << port; + coapServerPort = ss.str(); + } + } + } + } + cJSON_Delete(root); + + coapServerIP = getIPAddrTBServer(clientResponse); + if (port == -1) + { + coapServerPort = getPortTBServer(clientResponse); + OC_LOG_V(INFO, TAG, "Hosting Server Port -- %s", coapServerPort.c_str()); + } + return 0; +} diff --git a/resource/csdk/stack/samples/linux/secure/occlientbasicops.h b/resource/csdk/stack/samples/linux/secure/occlientbasicops.h new file mode 100644 index 000000000..689d7e63a --- /dev/null +++ b/resource/csdk/stack/samples/linux/secure/occlientbasicops.h @@ -0,0 +1,91 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OCCLIENT_BASICOPS_H_ +#define OCCLIENT_BASICOPS_H_ + +#include "ocstack.h" + +//----------------------------------------------------------------------------- +// Typedefs +//----------------------------------------------------------------------------- + +/** + * List of methods that can be inititated from the client + */ +typedef enum { + TEST_DISCOVER_REQ = 1, + TEST_NON_CON_OP, + TEST_CON_OP, + MAX_TESTS +} CLIENT_TEST; + +//----------------------------------------------------------------------------- +// Function prototype +//----------------------------------------------------------------------------- + +/* Get the IP address of the server */ +std::string getIPAddrTBServer(OCClientResponse * clientResponse); + +/* Get the port number the server is listening on */ +std::string getPortTBServer(OCClientResponse * clientResponse); + +/* Returns the query string for GET and PUT operations */ +std::string getQueryStrForGetPut(OCClientResponse * clientResponse); + +/* Following are initialization functions for GET, PUT + * POST & Discovery operations + */ +int InitPutRequest(); +int InitGetRequest(OCQualityOfService qos); +int InitPostRequest(OCQualityOfService qos); +int InitDiscovery(); + +/* Function to retrieve ip address, port no. of the server + * and query for the operations to be performed. + */ +int parseClientResponse(OCClientResponse * clientResponse); + +/* This method calls OCDoResource() which in turn makes calls + * to the lower layers + */ +OCStackResult InvokeOCDoResource(std::ostringstream &query, + OCMethod method, OCQualityOfService qos, + OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions); + +//----------------------------------------------------------------------------- +// Callback functions +//----------------------------------------------------------------------------- + +/* Following are callback functions for the GET, PUT + * POST & Discovery operations + */ + +OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse); + +OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse); + +OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse); + +OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle, + OCClientResponse * clientResponse); + +#endif + diff --git a/resource/csdk/stack/samples/linux/secure/ocserverbasicops.cpp b/resource/csdk/stack/samples/linux/secure/ocserverbasicops.cpp new file mode 100644 index 000000000..b6d579cda --- /dev/null +++ b/resource/csdk/stack/samples/linux/secure/ocserverbasicops.cpp @@ -0,0 +1,381 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include +#include +#include +#include +#include "ocstack.h" +#include "logger.h" +#include "cJSON.h" +#include "ocserverbasicops.h" +#include "common.h" + +int gQuitFlag = 0; + +static LEDResource LED; +// This variable determines instance number of the LED resource. +// Used by POST method to create a new instance of LED resource. +static int gCurrLedInstance = 0; +#define SAMPLE_MAX_NUM_POST_INSTANCE 2 +static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE]; + +char *gResourceUri= (char *)"/a/led"; + +static uint16_t OC_WELL_KNOWN_PORT = 5683; + +//File containing Server's Identity and the PSK credentials +//of other devices which the server trusts +//This can be generated using 'gen_sec_bin' application +static char CRED_FILE[] = "server_cred.bin"; + +//This function takes the request as an input and returns the response +//in JSON format. +char* constructJsonResponse (OCEntityHandlerRequest *ehRequest) +{ + cJSON *json = cJSON_CreateObject(); + cJSON *format; + char *jsonResponse; + LEDResource *currLEDResource = &LED; + + if (ehRequest->resource == gLedInstance[0].handle) + { + currLEDResource = &gLedInstance[0]; + gResourceUri = (char *) "a/led/0"; + } + else if (ehRequest->resource == gLedInstance[1].handle) + { + currLEDResource = &gLedInstance[1]; + gResourceUri = (char *) "a/led/1"; + } + + if(OC_REST_PUT == ehRequest->method) + { + cJSON *putJson = cJSON_Parse((char *)ehRequest->reqJSONPayload); + currLEDResource->state = ( !strcmp(cJSON_GetObjectItem(putJson,"state")->valuestring , + "on") ? true:false); + currLEDResource->power = cJSON_GetObjectItem(putJson,"power")->valuedouble; + cJSON_Delete(putJson); + } + + cJSON_AddStringToObject(json,"href",gResourceUri); + cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject()); + cJSON_AddStringToObject(format, "state", (char *) (currLEDResource->state ? "on":"off")); + cJSON_AddNumberToObject(format, "power", currLEDResource->power); + + jsonResponse = cJSON_Print(json); + cJSON_Delete(json); + return jsonResponse; +} + +OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest, + char *payload, size_t maxPayloadSize) +{ + OCEntityHandlerResult ehResult; + + char *getResp = constructJsonResponse(ehRequest); + if (maxPayloadSize > strlen (getResp)) + { + strcpy(payload, getResp); + ehResult = OC_EH_OK; + } + else + { + OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small", + maxPayloadSize); + ehResult = OC_EH_ERROR; + } + + free(getResp); + + return ehResult; +} + +OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest, + char *payload, size_t maxPayloadSize) +{ + OCEntityHandlerResult ehResult; + + char *putResp = constructJsonResponse(ehRequest); + if (maxPayloadSize > strlen (putResp)) + { + strcpy(payload, putResp); + ehResult = OC_EH_OK; + } + else + { + OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small", + maxPayloadSize); + ehResult = OC_EH_ERROR; + } + + free(putResp); + + return ehResult; +} + +OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, + char *payload, size_t maxPayloadSize) +{ + char *respPLPost_led = NULL; + cJSON *json; + cJSON *format; + OCEntityHandlerResult ehResult; + + /* + * The entity handler determines how to process a POST request. + * Per the REST paradigm, POST can also be used to update representation of existing + * resource or create a new resource. + * In the sample below, if the POST is for /a/led then a new instance of the LED + * resource is created with default representation (if representation is included in + * POST payload it can be used as initial values) as long as the instance is + * lesser than max new instance count. Once max instance count is reached, POST on + * /a/led updated the representation of /a/led (just like PUT) + */ + + if (ehRequest->resource == LED.handle) + { + if (gCurrLedInstance < SAMPLE_MAX_NUM_POST_INSTANCE) + { + // Create new LED instance + char newLedUri[15] = "/a/led/"; + int newLedUriLength = strlen(newLedUri); + snprintf (newLedUri + newLedUriLength, sizeof(newLedUri)-newLedUriLength, "%d", gCurrLedInstance); + + json = cJSON_CreateObject(); + + cJSON_AddStringToObject(json,"href",gResourceUri); + cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject()); + cJSON_AddStringToObject(format, "createduri", (char *) newLedUri); + + if (0 == createLEDResource (newLedUri, &gLedInstance[gCurrLedInstance], false, 0)) + { + OC_LOG (INFO, TAG, "Created new LED instance"); + gLedInstance[gCurrLedInstance].state = 0; + gLedInstance[gCurrLedInstance].power = 0; + gCurrLedInstance++; + respPLPost_led = cJSON_Print(json); + } + + cJSON_Delete(json); + } + else + { + respPLPost_led = constructJsonResponse(ehRequest); + } + } + else + { + for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++) + { + if (ehRequest->resource == gLedInstance[i].handle) + { + if (i == 0) + { + respPLPost_led = constructJsonResponse(ehRequest); + break; + } + else if (i == 1) + { + respPLPost_led = constructJsonResponse(ehRequest); + } + } + } + } + + if ((respPLPost_led != NULL) && (maxPayloadSize > strlen (respPLPost_led))) + { + strcpy(payload, respPLPost_led); + ehResult = OC_EH_OK; + } + else + { + OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small", + maxPayloadSize); + ehResult = OC_EH_ERROR; + } + + free(respPLPost_led); + + return ehResult; +} + +OCEntityHandlerResult +OCEntityHandlerCb (OCEntityHandlerFlag flag, + OCEntityHandlerRequest *entityHandlerRequest) +{ + OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag); + + OCEntityHandlerResult ehResult = OC_EH_ERROR; + OCEntityHandlerResponse response; + char payload[MAX_RESPONSE_LENGTH]; + + if (flag & OC_INIT_FLAG) + { + OC_LOG (INFO, TAG, "Flag includes OC_INIT_FLAG"); + ehResult = OC_EH_OK; + } + if (flag & OC_REQUEST_FLAG) + { + OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG"); + if (entityHandlerRequest) + { + if (OC_REST_GET == entityHandlerRequest->method) + { + OC_LOG (INFO, TAG, "Received OC_REST_GET from client"); + ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload)); + } + else if (OC_REST_PUT == entityHandlerRequest->method) + { + OC_LOG (INFO, TAG, "Received OC_REST_PUT from client"); + ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload)); + } + else if (OC_REST_POST == entityHandlerRequest->method) + { + OC_LOG (INFO, TAG, "Received OC_REST_POST from client"); + ehResult = ProcessPostRequest (entityHandlerRequest, payload, sizeof(payload)); + } + else + { + OC_LOG_V (INFO, TAG, "Received unsupported method %d from client", + entityHandlerRequest->method); + } + + if (ehResult == OC_EH_OK) + { + // Format the response. Note this requires some info about the request + response.requestHandle = entityHandlerRequest->requestHandle; + response.resourceHandle = entityHandlerRequest->resource; + response.ehResult = ehResult; + response.payload = (unsigned char *)payload; + response.payloadSize = strlen(payload); + response.numSendVendorSpecificHeaderOptions = 0; + memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions); + memset(response.resourceUri, 0, sizeof(response.resourceUri)); + // Indicate that response is NOT in a persistent buffer + response.persistentBufferFlag = 0; + + // Send the response + if (OCDoResponse(&response) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "Error sending response"); + ehResult = OC_EH_ERROR; + } + } + } + } + return ehResult; +} + +/* SIGINT handler: set gQuitFlag to 1 for graceful termination */ +void handleSigInt(int signum) +{ + if (signum == SIGINT) + { + gQuitFlag = 1; + } +} + +int main(int argc, char* argv[]) +{ + uint8_t addr[20] = {0}; + uint8_t* paddr = NULL; + uint16_t port = OC_WELL_KNOWN_PORT; + uint8_t ifname[] = "eth0"; + struct timespec timeout; + + OC_LOG(DEBUG, TAG, "OCServer is starting..."); + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, + sizeof(addr)) == ERR_SUCCESS) + { + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + paddr = addr; + } + + if (OCInit((char *) paddr, port, OC_SERVER) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack init error"); + return 0; + } + + /* + * Read DTLS PSK credentials from persistent storage and + * set in the OC stack. + */ + if (SetCredentials(CRED_FILE) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "SetCredentials failed"); + return 0; + } + /* + * Declare and create the example resource: LED + */ + createLEDResource(gResourceUri, &LED, false, 0); + + timeout.tv_sec = 0; + timeout.tv_nsec = 100000000L; + + // Break from loop with Ctrl-C + OC_LOG(INFO, TAG, "Entering ocserver main loop..."); + signal(SIGINT, handleSigInt); + while (!gQuitFlag) + { + if (OCProcess() != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack process error"); + return 0; + } + nanosleep(&timeout, NULL); + } + + OC_LOG(INFO, TAG, "Exiting ocserver main loop..."); + + if (OCStop() != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack process error"); + } + + return 0; +} + +int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower) +{ + if (!uri) + { + OC_LOG(ERROR, TAG, "Resource URI cannot be NULL"); + return -1; + } + + ledResource->state = resourceState; + ledResource->power= resourcePower; + OCStackResult res = OCCreateResource(&(ledResource->handle), + "core.led", + "oc.mi.def", + uri, + OCEntityHandlerCb, + OC_DISCOVERABLE|OC_OBSERVABLE | OC_SECURE); + OC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res)); + + return 0; +} diff --git a/resource/csdk/stack/samples/linux/secure/ocserverbasicops.h b/resource/csdk/stack/samples/linux/secure/ocserverbasicops.h new file mode 100644 index 000000000..4e1f7ebef --- /dev/null +++ b/resource/csdk/stack/samples/linux/secure/ocserverbasicops.h @@ -0,0 +1,77 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OCSERVER_BASICOPS_H_ +#define OCSERVER_BASICOPS_H_ + +#include "ocstack.h" + +//----------------------------------------------------------------------------- +// Defines +//----------------------------------------------------------------------------- +#define TAG "ocserverbasicops" + +//----------------------------------------------------------------------------- +// Typedefs +//----------------------------------------------------------------------------- + +/* Structure to represent a LED resource */ +typedef struct LEDRESOURCE{ + OCResourceHandle handle; + bool state; + int power; +} LEDResource; + +//----------------------------------------------------------------------------- +// Function prototype +//----------------------------------------------------------------------------- + +/* Function that creates a new LED resource by calling the + * OCCreateResource() method. + */ +int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower); + +/* This method converts the payload to JSON format */ +char* constructJsonResponse (OCEntityHandlerRequest *ehRequest); + +/* Following methods process the PUT, GET, POST + * requests + */ +OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest, + char *payload, + size_t maxPayloadSize); +OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest, + char *payload, + size_t maxPayloadSize); +OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, + char *payload, + size_t maxPayloadSize); + +//----------------------------------------------------------------------------- +// Callback functions +//----------------------------------------------------------------------------- + +/* Entity Handler callback functions */ + +OCEntityHandlerResult +OCEntityHandlerCb (OCEntityHandlerFlag flag, + OCEntityHandlerRequest *entityHandlerRequest); + +#endif diff --git a/resource/csdk/stack/src/occlientcb.c b/resource/csdk/stack/src/occlientcb.c new file mode 100644 index 000000000..9e0b2323a --- /dev/null +++ b/resource/csdk/stack/src/occlientcb.c @@ -0,0 +1,237 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +#include "occlientcb.h" +#include "occoap.h" +#include "utlist.h" +#include "logger.h" +#include "ocmalloc.h" +#include + +/// Module Name +#define TAG PCF("occlientcb") + +struct ClientCB *cbList = NULL; +OCMulticastNode * mcPresenceNodes = NULL; + +OCStackResult AddClientCB(ClientCB** clientCB, OCCallbackData* cbData, + OCCoAPToken * token, OCDoHandle *handle, OCMethod method, + unsigned char * requestUri, unsigned char * resourceTypeName) { + + ClientCB *cbNode = NULL; + + #ifdef WITH_PRESENCE + if(method == OC_REST_PRESENCE) + { // Retrieve the presence callback structure for this specific requestUri. + cbNode = GetClientCB(NULL, NULL, requestUri); + } + #endif // WITH_PRESENCE + + if(!cbNode)// If it does not already exist, create new node. + { + cbNode = (ClientCB*) OCMalloc(sizeof(ClientCB)); + if(!cbNode) + { + *clientCB = NULL; + goto exit; + } + else + { + cbNode->callBack = cbData->cb; + cbNode->context = cbData->context; + cbNode->deleteCallback = cbData->cd; + memcpy(&(cbNode->token), token, sizeof(OCCoAPToken)); + cbNode->handle = *handle; + cbNode->method = method; + cbNode->sequenceNumber = 0; + #ifdef WITH_PRESENCE + cbNode->presence = NULL; + cbNode->filterResourceType = NULL; + #endif // WITH_PRESENCE + cbNode->requestUri = requestUri; + LL_APPEND(cbList, cbNode); + *clientCB = cbNode; + } + } + else + { + // Ensure that the handle the SDK hands back up to the application layer for the + // OCDoResource call matches the found ClientCB Node. + *clientCB = cbNode; + OCFree(requestUri); + OCFree(*handle); + *handle = cbNode->handle; + } + + #ifdef WITH_PRESENCE + if(method == OC_REST_PRESENCE && resourceTypeName) + { // Amend the found or created node by adding a new resourceType to it. + return InsertResourceTypeFilter(cbNode, (const char *)resourceTypeName); + } + #endif + + return OC_STACK_OK; + + exit: + return OC_STACK_NO_MEMORY; +} + +void DeleteClientCB(ClientCB * cbNode) { + if(cbNode) { + LL_DELETE(cbList, cbNode); + OC_LOG(INFO, TAG, PCF("deleting tokens")); + OC_LOG_BUFFER(INFO, TAG, cbNode->token.token, cbNode->token.tokenLength); + OCFree(cbNode->handle); + OCFree(cbNode->requestUri); + if(cbNode->deleteCallback) + { + cbNode->deleteCallback(cbNode->context); + } + + #ifdef WITH_PRESENCE + if(cbNode->presence) { + OCFree(cbNode->presence->timeOut); + OCFree(cbNode->presence); + } + if(cbNode->method == OC_REST_PRESENCE) + { + OCResourceType * pointer = cbNode->filterResourceType; + OCResourceType * next = NULL; + while(pointer) + { + next = pointer->next; + OCFree(pointer->resourcetypename); + OCFree(pointer); + pointer = next; + } + } + #endif // WITH_PRESENCE + OCFree(cbNode); + cbNode = NULL; + } +} + +ClientCB* GetClientCB(OCCoAPToken * token, OCDoHandle handle, unsigned char * requestUri) { + ClientCB* out = NULL; + if(token) { + LL_FOREACH(cbList, out) { + OC_LOG(INFO, TAG, PCF("comparing tokens")); + OC_LOG_BUFFER(INFO, TAG, token->token, token->tokenLength); + OC_LOG_BUFFER(INFO, TAG, out->token.token, out->token.tokenLength); + if((out->token.tokenLength == token->tokenLength) && + (memcmp(out->token.token, token->token, token->tokenLength) == 0) ) { + return out; + } + } + } + else if(handle) { + LL_FOREACH(cbList, out) { + if(out->handle == handle) { + return out; + } + } + } + else if(requestUri) { + LL_FOREACH(cbList, out) { + if(out->requestUri && strcmp((char *)out->requestUri, (char *)requestUri) == 0) { + return out; + } + } + } + OC_LOG(INFO, TAG, PCF("Callback Not found !!")); + return NULL; +} + +OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, const char * resourceTypeName) +{ + OCResourceType * newResourceType = NULL; + if(cbNode && resourceTypeName) + { + // Form a new resourceType member. + newResourceType = (OCResourceType *) OCMalloc(sizeof(OCResourceType)); + if(!newResourceType) + { + return OC_STACK_NO_MEMORY; + } + + newResourceType->next = NULL; + newResourceType->resourcetypename = (char *) resourceTypeName; + + LL_APPEND(cbNode->filterResourceType, newResourceType); + return OC_STACK_OK; + } + return OC_STACK_ERROR; +} + +void DeleteClientCBList() { + ClientCB* out; + ClientCB* tmp; + LL_FOREACH_SAFE(cbList, out, tmp) { + DeleteClientCB(out); + } + cbList = NULL; +} + +void FindAndDeleteClientCB(ClientCB * cbNode) { + ClientCB* tmp; + if(cbNode) + { + LL_FOREACH(cbList, tmp) + { + if (cbNode == tmp) + { + DeleteClientCB(tmp); + break; + } + } + } +} + +OCStackResult AddMCPresenceNode(OCMulticastNode** outnode, unsigned char* uri, uint32_t nonce) +{ + OCMulticastNode *node; + + node = (OCMulticastNode*) OCMalloc(sizeof(OCMulticastNode)); + + if (node) { + node->nonce = nonce; + node->uri = uri; + LL_APPEND(mcPresenceNodes, node); + *outnode = node; + return OC_STACK_OK; + } + *outnode = NULL; + return OC_STACK_NO_MEMORY; +} + +OCMulticastNode* GetMCPresenceNode(unsigned char * uri) { + OCMulticastNode* out = NULL; + + if(uri) { + LL_FOREACH(mcPresenceNodes, out) { + if(out->uri && strcmp((char *)out->uri, (char *)uri) == 0) { + return out; + } + } + } + OC_LOG(INFO, TAG, PCF("MulticastNode Not found !!")); + return NULL; +} diff --git a/resource/csdk/stack/src/occollection.c b/resource/csdk/stack/src/occollection.c new file mode 100644 index 000000000..5d486bf08 --- /dev/null +++ b/resource/csdk/stack/src/occollection.c @@ -0,0 +1,471 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#define _POSIX_C_SOURCE 200112L +#include +#include "ocstack.h" +#include "ocstackinternal.h" +#include "ocresourcehandler.h" +#include "logger.h" +#include "debug.h" +#include "cJSON.h" +/// Module Name +#include + +#define WITH_GROUPACTION 1 + +#include "oicgroup.h" + +#define TAG PCF("occollection") + +#define NUM_PARAM_IN_QUERY 2 + +static OCStackResult CheckRTParamSupport(const OCResource* resource, const char* rtPtr) +{ + OCResourceType* rTPointer = resource->rsrcType; + while (rTPointer) + { + if( strcmp (rTPointer->resourcetypename, rtPtr) == 0) + return OC_STACK_OK; + + rTPointer = rTPointer->next; + } + return OC_STACK_ERROR; +} + +static OCStackResult CheckIFParamSupport(const OCResource* resource, const char* ifPtr) +{ + OCResourceInterface* iFPointer = resource->rsrcInterface; + while (iFPointer) + { + if( strcmp (iFPointer->name, ifPtr) == 0) + return OC_STACK_OK; + + iFPointer = iFPointer->next; + } + return OC_STACK_ERROR; +} + +static OCStackResult +ValidateQuery (const unsigned char *query, OCResourceHandle resource, + OCStackIfTypes *ifParam, char **rtParam) +{ + uint8_t numFields = 0, numParam; + + //TODO: Query and URL validation is being done for virtual resource case + // using ValidateUrlQuery function. We should be able to merge it with this + // function. + OC_LOG(INFO, TAG, PCF("Entering ValidateQuery")); + + if (!query) + return OC_STACK_ERROR; + + if (!(*query)) + { + // Query string is empty + OC_LOG_V(INFO, TAG, PCF("Empty query string, use default IF and RT")); + *ifParam = STACK_IF_DEFAULT; + *rtParam = (char *) OCGetResourceTypeName (resource, 0); + return OC_STACK_OK; + } + + // Break the query string to validate it and determine IF and RT parameters + // Validate there are atmost 2 parameters in string and that one is 'if' and other 'rt' + char *endStr, *ifPtr = NULL, *rtPtr = NULL; + char *token = strtok_r ((char *)query, "&", &endStr); + + // External loop breaks query string into fields using the & separator + while (token != NULL) + { + numFields++; + char *endToken; + char *innerToken = strtok_r (token, "=", &endToken); + numParam = 0; + + // Internal loop parses the field to extract values (parameters) assigned to each field + while (innerToken != NULL) + { + numParam++; + if (strcmp (innerToken, OC_RSRVD_INTERFACE) == 0) + { + // Determine the value of IF parameter + innerToken = strtok_r (NULL, "=", &endToken); + ifPtr = innerToken; + } else if (strcmp (innerToken, OC_RSRVD_RESOURCE_TYPE) == 0) { + // Determine the value of RT parameter + innerToken = strtok_r (NULL, "=", &endToken); + rtPtr = innerToken; + } else { + innerToken = strtok_r (NULL, "=", &endToken); + } + } + if (numParam != 2) + { + // Query parameter should be of the form if=. String should not have & or = + return OC_STACK_INVALID_QUERY; + } + token = strtok_r (NULL, "&", &endStr); + } + if (numFields > NUM_PARAM_IN_QUERY) + { + // M1 release supports one IF value, one RT value and no other params + return OC_STACK_INVALID_QUERY; + } + + if (ifPtr) + { + if(CheckIFParamSupport((OCResource *)resource, ifPtr) != OC_STACK_OK) + { + return OC_STACK_INVALID_QUERY; + } + if (strcmp (ifPtr, OC_RSRVD_INTERFACE_DEFAULT) == 0) + { + *ifParam = STACK_IF_DEFAULT; + } + else if (strcmp (ifPtr, OC_RSRVD_INTERFACE_LL) == 0) + { + *ifParam = STACK_IF_LL; + } + else if (strcmp (ifPtr, OC_RSRVD_INTERFACE_BATCH) == 0) + { + *ifParam = STACK_IF_BATCH; + } + else if(strcmp (ifPtr, OC_RSRVD_INTERFACE_GROUP) == 0) + { + *ifParam = STACK_IF_GROUP; + } + else + { + return OC_STACK_ERROR; + } + } + else + { + // IF not specified in query, use default IF + *ifParam = STACK_IF_DEFAULT; + } + + if (rtPtr) + { + if (CheckRTParamSupport((OCResource *)resource, rtPtr) == OC_STACK_OK) + { + *rtParam = rtPtr; + } + else + { + return OC_STACK_INVALID_QUERY; + } + } + else + { + // RT not specified in query. Use the first resource type for the resource as default. + *rtParam = (char *) OCGetResourceTypeName (resource, 0); + } + OC_LOG_V(INFO, TAG, "Query params: IF = %d, RT = %s", *ifParam, *rtParam); + + return OC_STACK_OK; +} + + +static OCStackResult BuildRootResourceJSON(OCResource *resource, + unsigned char * bufferPtr, uint16_t *remaining) +{ + OCStackResult ret = OC_STACK_ERROR; + cJSON *resObj; + char *jsonStr; + uint16_t jsonLen; + + OC_LOG(INFO, TAG, PCF("Entering BuildRootResourceJSON")); + resObj = cJSON_CreateObject(); + + if (resource) + { + cJSON_AddItemToObject (resObj, OC_RSRVD_HREF, cJSON_CreateString(resource->uri)); + } + jsonStr = cJSON_PrintUnformatted (resObj); + jsonLen = strlen(jsonStr); + if (jsonLen < *remaining) + { + strcpy((char*) bufferPtr, jsonStr); + *remaining -= jsonLen; + bufferPtr += jsonLen; + ret = OC_STACK_OK; + } + + cJSON_Delete (resObj); + free (jsonStr); + + return ret; +} + + +static OCStackResult +HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest, + uint8_t filterOn, char *filterValue) +{ + OCStackResult ret = OC_STACK_ERROR; + unsigned char jsonbuffer[MAX_RESPONSE_LENGTH] = {0}; + size_t jsonbufferLength = 0; + uint16_t remaining = 0; + unsigned char * ptr = NULL; + OCResource * collResource = (OCResource *) ehRequest->resource; + + ptr = jsonbuffer; + remaining = MAX_RESPONSE_LENGTH; + + ret = BuildRootResourceJSON(collResource, ptr, &remaining); + ptr += strlen((char*)ptr); + + if (ret == OC_STACK_OK && remaining >= (sizeof(OC_JSON_SEPARATOR) + 1)) + { + *ptr = OC_JSON_SEPARATOR; + ptr++; + remaining--; + } + else + { + ret = OC_STACK_ERROR; + } + *(ptr + 1) = '\0'; + + if (ret == OC_STACK_OK) + { + for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++) + { + OCResource* temp = collResource->rsrcResources[i]; + if (temp) + { + ret = BuildVirtualResourceResponse(temp, filterOn, filterValue, (char*)ptr, &remaining); + if (ret != OC_STACK_OK) + { + break; + } + ptr += strlen((char*)ptr); + if (collResource->rsrcResources[i+1] && remaining > sizeof(OC_JSON_SEPARATOR)) + { + *ptr = OC_JSON_SEPARATOR; + ptr++; + remaining--; + } + *(ptr + 1) = '\0'; + } + else + { + break; + } + } + } + + jsonbufferLength = strlen((const char *)jsonbuffer); + if(ret == OC_STACK_OK && jsonbufferLength) + { + OCEntityHandlerResponse response = {0}; + response.ehResult = OC_EH_OK; + response.payload = jsonbuffer; + response.payloadSize = jsonbufferLength + 1; + response.persistentBufferFlag = 0; + response.requestHandle = (OCRequestHandle) ehRequest->requestHandle; + response.resourceHandle = (OCResourceHandle) collResource; + ret = OCDoResponse(&response); + } + return ret; +} + +static OCStackResult +HandleBatchInterface(OCEntityHandlerRequest *ehRequest) +{ + OCStackResult stackRet = OC_STACK_ERROR; + OCEntityHandlerResult ehResult = OC_EH_ERROR; + unsigned char jsonbuffer[MAX_RESPONSE_LENGTH] = {0}; + size_t jsonbufferLength = 0; + uint16_t remaining = 0; + unsigned char * ptr = NULL; + OCResource * collResource = (OCResource *) ehRequest->resource; + + ptr = jsonbuffer; + remaining = MAX_RESPONSE_LENGTH; + + stackRet = BuildRootResourceJSON(collResource, ptr, &remaining); + ptr += strlen((char*)ptr); + *(ptr + 1) = '\0'; + + jsonbufferLength = strlen((const char *)jsonbuffer); + if(jsonbufferLength) + { + OCEntityHandlerResponse response = {0}; + response.ehResult = OC_EH_OK; + response.payload = jsonbuffer; + response.payloadSize = jsonbufferLength + 1; + response.persistentBufferFlag = 0; + response.requestHandle = (OCRequestHandle) ehRequest->requestHandle; + response.resourceHandle = (OCResourceHandle) collResource; + stackRet = OCDoResponse(&response); + } + + if (stackRet == OC_STACK_OK) + { + for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++) + { + OCResource* temp = collResource->rsrcResources[i]; + if (temp) + { + // Note that all entity handlers called through a collection + // will get the same pointer to ehRequest, the only difference + // is ehRequest->resource + ehRequest->resource = (OCResourceHandle) temp; + + ehResult = temp->entityHandler(OC_REQUEST_FLAG, ehRequest); + + // The default collection handler is returning as OK + if(stackRet != OC_STACK_SLOW_RESOURCE) + { + stackRet = OC_STACK_OK; + } + // if a single resource is slow, then entire response will be treated + // as slow response + if(ehResult == OC_EH_SLOW) + { + OC_LOG(INFO, TAG, PCF("This is a slow resource")); + ((OCServerRequest *)ehRequest->requestHandle)->slowFlag = 1; + stackRet = EntityHandlerCodeToOCStackCode(ehResult); + } + } + else + { + break; + } + } + ehRequest->resource = (OCResourceHandle) collResource; + } + return stackRet; +} + +uint8_t GetNumOfResourcesInCollection (OCResource *resource) +{ + uint8_t num = 0; + for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++) + { + if (resource->rsrcResources[i]) + { + num++; + } + } + return num; +} + + +OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag, + OCEntityHandlerRequest *ehRequest) +{ + OCStackResult result = OC_STACK_ERROR; + OCStackIfTypes ifQueryParam = STACK_IF_INVALID; + char *rtQueryParam = NULL; + + OC_LOG_V(INFO, TAG, "DefaultCollectionEntityHandler with query %s", ehRequest->query); + + if (flag != OC_REQUEST_FLAG) + return OC_STACK_ERROR; + + result = ValidateQuery ((const unsigned char *)ehRequest->query, + ehRequest->resource, &ifQueryParam, &rtQueryParam); + + if (result != OC_STACK_OK) + return result; + + + if(!((ehRequest->method == OC_REST_GET) || + (ehRequest->method == OC_REST_PUT) || + (ehRequest->method == OC_REST_POST))) + return OC_STACK_ERROR; + + if (ehRequest->method == OC_REST_GET) + { + switch (ifQueryParam) + { + case STACK_IF_DEFAULT: + // Get attributes of collection resource and properties of contined resource + // M1 release does not support attributes for collection resource, so the GET + // operation is same as the GET on LL interface. + OC_LOG(INFO, TAG, PCF("STACK_IF_DEFAULT")); + return HandleLinkedListInterface(ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL); + + case STACK_IF_LL: + OC_LOG(INFO, TAG, PCF("STACK_IF_LL")); + return HandleLinkedListInterface(ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL); + + case STACK_IF_BATCH: + OC_LOG(INFO, TAG, PCF("STACK_IF_BATCH")); + ((OCServerRequest *)ehRequest->requestHandle)->ehResponseHandler = HandleAggregateResponse; + ((OCServerRequest *)ehRequest->requestHandle)->numResponses = + GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1; + return HandleBatchInterface(ehRequest); + case STACK_IF_GROUP: + return BuildCollectionGroupActionJSONResponse(OC_REST_GET/*flag*/, + (OCResource *) ehRequest->resource, ehRequest); + default: + return OC_STACK_ERROR; + } + } else if (ehRequest->method == OC_REST_PUT) { + switch (ifQueryParam) + { + case STACK_IF_DEFAULT: + // M1 release does not support PUT on default interface + return OC_STACK_ERROR; + + case STACK_IF_LL: + // LL interface only supports GET + return OC_STACK_ERROR; + + case STACK_IF_BATCH: + ((OCServerRequest *)ehRequest->requestHandle)->ehResponseHandler = HandleAggregateResponse; + ((OCServerRequest *)ehRequest->requestHandle)->numResponses = + GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1; + return HandleBatchInterface(ehRequest); + + case STACK_IF_GROUP: + { + OC_LOG_V(INFO, TAG, "IF_COLLECTION PUT with request ::\n%s\n ", + ehRequest->reqJSONPayload); + return BuildCollectionGroupActionJSONResponse(OC_REST_PUT/*flag*/, + (OCResource *) ehRequest->resource, ehRequest); + } + default: + return OC_STACK_ERROR; + } + } + else if (ehRequest->method == OC_REST_POST) + { + + switch (ifQueryParam) + { + case STACK_IF_GROUP: + { + OC_LOG_V(INFO, TAG, "IF_COLLECTION POST with request :: \n%s\n ", + ehRequest->reqJSONPayload); + return BuildCollectionGroupActionJSONResponse(OC_REST_POST/*flag*/, + (OCResource *) ehRequest->resource, ehRequest); + } + default: + return OC_STACK_ERROR; + } + } + return result; +} + diff --git a/resource/csdk/stack/src/ocobserve.c b/resource/csdk/stack/src/ocobserve.c new file mode 100644 index 000000000..c1e8a1b1f --- /dev/null +++ b/resource/csdk/stack/src/ocobserve.c @@ -0,0 +1,397 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include "ocstack.h" +#include "ocstackconfig.h" +#include "ocstackinternal.h" +#include "ocobserve.h" +#include "ocresourcehandler.h" +#include "occoap.h" +#include "utlist.h" +#include "debug.h" +#include "ocrandom.h" +#include "ocmalloc.h" +#include "ocserverrequest.h" + +// Module Name +#define MOD_NAME PCF("ocobserve") + +#define TAG PCF("OCStackObserve") + +#define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} } + +static struct ResourceObserver * serverObsList = NULL; + +// send notifications based on the qos of the request +// The qos passed as a parameter overrides what the client requested +// If we want the client preference taking high priority make: +// qos = resourceObserver->qos; +OCQualityOfService DetermineObserverQoS(OCMethod method, ResourceObserver * resourceObserver, + OCQualityOfService appQoS) +{ + OCQualityOfService decidedQoS = appQoS; + if(appQoS == OC_NA_QOS) + { + decidedQoS = resourceObserver->qos; + } + + if(appQoS != OC_HIGH_QOS) + { + OC_LOG_V(INFO, TAG, "Current NON count for this observer is %d", + resourceObserver->lowQosCount); + #ifdef WITH_PRESENCE + if((resourceObserver->forceHighQos \ + || resourceObserver->lowQosCount >= MAX_OBSERVER_NON_COUNT) \ + && method != OC_REST_PRESENCE) + #else + if(resourceObserver->forceHighQos \ + || resourceObserver->lowQosCount >= MAX_OBSERVER_NON_COUNT) + #endif + { + resourceObserver->lowQosCount = 0; + // at some point we have to to send CON to check on the + // availability of observer + OC_LOG(INFO, TAG, PCF("This time we are sending the notification as High qos")); + decidedQoS = OC_HIGH_QOS; + } + else + { + (resourceObserver->lowQosCount)++; + } + } + return decidedQoS; +} + +#ifdef WITH_PRESENCE +OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge, + OCResourceType *resourceType, OCQualityOfService qos) +#else +OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge, + OCQualityOfService qos) +#endif +{ + OC_LOG(INFO, TAG, PCF("Entering SendObserverNotification")); + OCStackResult result = OC_STACK_ERROR; + ResourceObserver * resourceObserver = serverObsList; + uint8_t numObs = 0; + OCServerRequest * request = NULL; + OCEntityHandlerRequest ehRequest = {0}; + OCEntityHandlerResult ehResult = OC_EH_ERROR; + + // Find clients that are observing this resource + while (resourceObserver) + { + if (resourceObserver->resource == resPtr) + { + numObs++; + #ifdef WITH_PRESENCE + if(method != OC_REST_PRESENCE) + { + #endif + qos = DetermineObserverQoS(method, resourceObserver, qos); + result = AddServerRequest(&request, 0, 0, 0, 1, OC_REST_GET, + 0, resPtr->sequenceNum, qos, resourceObserver->query, + NULL, NULL, + &resourceObserver->token, resourceObserver->addr, + resourceObserver->resUri, 0); + request->observeResult = OC_STACK_OK; + if(request && result == OC_STACK_OK) + { + result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request, + request->method, (OCResourceHandle) resPtr, request->query, + request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions, + request->rcvdVendorSpecificHeaderOptions, OC_OBSERVE_NO_OPTION, 0); + if(result == OC_STACK_OK) + { + ehResult = resPtr->entityHandler(OC_REQUEST_FLAG, &ehRequest); + if(ehResult == OC_EH_ERROR) + { + FindAndDeleteServerRequest(request); + } + } + } + #ifdef WITH_PRESENCE + } + else + { + OCEntityHandlerResponse ehResponse = {0}; + unsigned char presenceResBuf[MAX_RESPONSE_LENGTH] = {0}; + //This is effectively the implementation for the presence entity handler. + OC_LOG(DEBUG, TAG, PCF("This notification is for Presence")); + result = AddServerRequest(&request, 0, 0, 0, 1, OC_REST_GET, + 0, OC_OBSERVE_NO_OPTION, OC_LOW_QOS, + NULL, NULL, NULL, &resourceObserver->token, + resourceObserver->addr, resourceObserver->resUri, 0); + if(result == OC_STACK_OK) + { + // we create the payload here + if(resourceType && resourceType->resourcetypename) + { + snprintf((char *)presenceResBuf, sizeof(presenceResBuf), "%u:%u:%s", + resPtr->sequenceNum, maxAge, resourceType->resourcetypename); + } + else + { + snprintf((char *)presenceResBuf, sizeof(presenceResBuf), "%u:%u", + resPtr->sequenceNum, maxAge); + } + ehResponse.ehResult = OC_EH_OK; + ehResponse.payload = presenceResBuf; + ehResponse.payloadSize = strlen((const char *)presenceResBuf) + 1; + ehResponse.persistentBufferFlag = 0; + ehResponse.requestHandle = (OCRequestHandle) request; + ehResponse.resourceHandle = (OCResourceHandle) resPtr; + strcpy((char *)ehResponse.resourceUri, (const char *)resourceObserver->resUri); + result = OCDoResponse(&ehResponse); + } + } + #endif + } + resourceObserver = resourceObserver->next; + } + if (numObs == 0) + { + OC_LOG(INFO, TAG, PCF("Resource has no observers")); + result = OC_STACK_NO_OBSERVERS; + } + return result; +} + +OCStackResult SendListObserverNotification (OCResource * resource, + OCObservationId *obsIdList, uint8_t numberOfIds, + unsigned char *notificationJSONPayload, uint32_t maxAge, + OCQualityOfService qos) +{ + uint8_t numIds = numberOfIds; + ResourceObserver *observation = NULL; + uint8_t numSentNotification = 0; + OCServerRequest * request = NULL; + OCStackResult result = OC_STACK_ERROR; + OCEntityHandlerResponse ehResponse = {0}; + + OC_LOG(INFO, TAG, PCF("Entering SendListObserverNotification")); + while(numIds) + { + OC_LOG_V(INFO, TAG, "Need to notify observation id %d", *obsIdList); + observation = NULL; + observation = GetObserverUsingId (*obsIdList); + if(observation) + { + // Found observation - verify if it matches the resource handle + if (observation->resource == resource) + { + qos = DetermineObserverQoS(OC_REST_GET, observation, qos); + + result = AddServerRequest(&request, 0, 0, 0, 1, OC_REST_GET, + 0, resource->sequenceNum, qos, observation->query, + NULL, NULL, &observation->token, + observation->addr, observation->resUri, 0); + request->observeResult = OC_STACK_OK; + if(request && result == OC_STACK_OK) + { + memset(&ehResponse, 0, sizeof(OCEntityHandlerResponse)); + ehResponse.ehResult = OC_EH_OK; + ehResponse.payload = (unsigned char *) OCMalloc(MAX_RESPONSE_LENGTH); + if(!ehResponse.payload) + { + FindAndDeleteServerRequest(request); + continue; + } + strcpy((char *)ehResponse.payload, (const char *)notificationJSONPayload); + ehResponse.payloadSize = strlen((const char *)ehResponse.payload) + 1; + ehResponse.persistentBufferFlag = 0; + ehResponse.requestHandle = (OCRequestHandle) request; + ehResponse.resourceHandle = (OCResourceHandle) resource; + result = OCDoResponse(&ehResponse); + if(result == OC_STACK_OK) + { + OCFree(ehResponse.payload); + FindAndDeleteServerRequest(request); + } + } + else + { + FindAndDeleteServerRequest(request); + } + + numSentNotification++; + } + } + obsIdList++; + numIds--; + } + if(numSentNotification == numberOfIds) + { + return OC_STACK_OK; + } + else if(numSentNotification == 0) + { + return OC_STACK_NO_OBSERVERS; + } + else + { + //TODO: we need to signal that not every one in the + // list got an update, should we also indicate who did not receive on? + return OC_STACK_OK; + } +} + +OCStackResult GenerateObserverId (OCObservationId *observationId) +{ + ResourceObserver *resObs = NULL; + + OC_LOG(INFO, TAG, PCF("Entering GenerateObserverId")); + VERIFY_NON_NULL (observationId); + + do + { + *observationId = OCGetRandomByte(); + // Check if observation Id already exists + resObs = GetObserverUsingId (*observationId); + } while (NULL != resObs); + + OC_LOG_V(INFO, TAG, "Observation ID is %u", *observationId); + + return OC_STACK_OK; +exit: + return OC_STACK_ERROR; +} + +OCStackResult AddObserver (const char *resUri, + const char *query, + OCObservationId obsId, + OCCoAPToken *token, + OCDevAddr *addr, + OCResource *resHandle, + OCQualityOfService qos) +{ + ResourceObserver *obsNode = NULL; + + obsNode = (ResourceObserver *) OCCalloc(1, sizeof(ResourceObserver)); + if (obsNode) + { + obsNode->observeId = obsId; + + obsNode->resUri = (unsigned char *)OCMalloc(strlen(resUri)+1); + VERIFY_NON_NULL (obsNode->resUri); + memcpy (obsNode->resUri, resUri, strlen(resUri)+1); + + obsNode->qos = qos; + if(query) + { + obsNode->query = (unsigned char *)OCMalloc(strlen(query)+1); + VERIFY_NON_NULL (obsNode->query); + memcpy (obsNode->query, query, strlen(query)+1); + } + + obsNode->token.tokenLength = token->tokenLength; + memcpy (obsNode->token.token, token->token, token->tokenLength); + + obsNode->addr = (OCDevAddr *)OCMalloc(sizeof(OCDevAddr)); + VERIFY_NON_NULL (obsNode->addr); + memcpy (obsNode->addr, addr, sizeof(OCDevAddr)); + + obsNode->resource = resHandle; + + LL_APPEND (serverObsList, obsNode); + return OC_STACK_OK; + } + +exit: + if (obsNode) + { + OCFree(obsNode->resUri); + OCFree(obsNode->query); + OCFree(obsNode->addr); + OCFree(obsNode); + } + return OC_STACK_NO_MEMORY; +} + +ResourceObserver* GetObserverUsingId (const OCObservationId observeId) +{ + ResourceObserver *out = NULL; + + if (observeId) + { + LL_FOREACH (serverObsList, out) + { + if (out->observeId == observeId) + { + return out; + } + } + } + OC_LOG(INFO, TAG, PCF("Observer node not found!!")); + return NULL; +} + +ResourceObserver* GetObserverUsingToken (const OCCoAPToken * token) +{ + ResourceObserver *out = NULL; + + if(token) + { + LL_FOREACH (serverObsList, out) + { + OC_LOG(INFO, TAG,PCF("comparing tokens")); + OC_LOG_BUFFER(INFO, TAG, token->token, token->tokenLength); + OC_LOG_BUFFER(INFO, TAG, out->token.token, out->token.tokenLength); + if((out->token.tokenLength == token->tokenLength) && + (memcmp(out->token.token, token->token, token->tokenLength) == 0)) + { + return out; + } + } + } + OC_LOG(INFO, TAG, PCF("Observer node not found!!")); + return NULL; +} + +OCStackResult DeleteObserverUsingToken (OCCoAPToken * token) +{ + ResourceObserver *obsNode = NULL; + + obsNode = GetObserverUsingToken (token); + if (obsNode) + { + OC_LOG_V(INFO, TAG, PCF("deleting tokens")); + OC_LOG_BUFFER(INFO, TAG, obsNode->token.token, obsNode->token.tokenLength); + LL_DELETE (serverObsList, obsNode); + OCFree(obsNode->resUri); + OCFree(obsNode->query); + OCFree(obsNode->addr); + OCFree(obsNode); + } + // it is ok if we did not find the observer... + return OC_STACK_OK; +} + +void DeleteObserverList() +{ + ResourceObserver *out = NULL; + ResourceObserver *tmp = NULL; + LL_FOREACH_SAFE (serverObsList, out, tmp) + { + DeleteObserverUsingToken (&(out->token)); + } + serverObsList = NULL; +} diff --git a/resource/csdk/stack/src/ocresource.c b/resource/csdk/stack/src/ocresource.c new file mode 100644 index 000000000..f2267d1a7 --- /dev/null +++ b/resource/csdk/stack/src/ocresource.c @@ -0,0 +1,866 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#define _POSIX_C_SOURCE 200112L +#include +#include "ocstack.h" +#include "ocstackconfig.h" +#include "ocstackinternal.h" +#include "ocresourcehandler.h" +#include "ocobserve.h" +#include "occollection.h" +#include "occoap.h" +#include "logger.h" +#include "debug.h" +#include "cJSON.h" + +/// Module Name +#define TAG PCF("ocresource") +#define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \ + {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} } + +#define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \ + TAG, PCF(#arg " is NULL")); return (retVal); } } + +extern OCResource *headResource; +static cJSON *savedDeviceInfo = NULL; + +static const char * VIRTUAL_RSRCS[] = { + "/oc/core", + "/oc/core/d", + "/oc/core/types/d", + #ifdef WITH_PRESENCE + "/oc/presence" + #endif +}; + +//----------------------------------------------------------------------------- +// Default resource entity handler function +//----------------------------------------------------------------------------- +OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag, + OCEntityHandlerRequest * request) { + TODO ("Implement me!!!!"); + // TODO: remove silence unused param warnings + (void) flag; + (void) request; + return OC_EH_OK; // Making sure that the Default EH and the Vendor EH have matching signatures +} + +static OCStackResult ValidateUrlQuery (unsigned char *url, unsigned char *query, + uint8_t *filterOn, char **filterValue) +{ + char *filterParam; + + OC_LOG(INFO, TAG, PCF("Entering ValidateUrlQuery")); + if (!url) + return OC_STACK_INVALID_URI; + + if (strcmp ((char *)url, GetVirtualResourceUri(OC_WELL_KNOWN_URI)) == 0 || + strcmp ((char *)url, GetVirtualResourceUri(OC_DEVICE_URI)) == 0) { + *filterOn = STACK_RES_DISCOVERY_NOFILTER; + if (query && *query) { + char* strTokPtr; + filterParam = strtok_r((char *)query, "=", &strTokPtr); + *filterValue = strtok_r(NULL, " ", &strTokPtr); + if (!(*filterValue)) { + return OC_STACK_INVALID_QUERY; + } else if (strcmp (filterParam, OC_RSRVD_INTERFACE) == 0) { + // Resource discovery with interface filter + *filterOn = STACK_RES_DISCOVERY_IF_FILTER; + } else if (strcmp (filterParam, OC_RSRVD_RESOURCE_TYPE) == 0) { + // Resource discovery with resource type filter + *filterOn = STACK_RES_DISCOVERY_RT_FILTER; + } else if (strcmp (filterParam, OC_RSRVD_DEVICE_ID) == 0) { + //Device ID filter + *filterOn = STACK_DEVICE_DISCOVERY_DI_FILTER; + } else if (strcmp (filterParam, OC_RSRVD_DEVICE_NAME) == 0) { + //Device Name filter + *filterOn = STACK_DEVICE_DISCOVERY_DN_FILTER; + } else { + // Other filter types not supported + return OC_STACK_INVALID_QUERY; + } + } + } + #ifdef WITH_PRESENCE + else if (strcmp((char *)url, GetVirtualResourceUri(OC_PRESENCE)) == 0) { + //Nothing needs to be done, except for pass a OC_PRESENCE query through as OC_STACK_OK. + OC_LOG(INFO, TAG, PCF("OC_PRESENCE Request")); + *filterOn = STACK_RES_DISCOVERY_NOFILTER; + } + #endif + else { + // Other URIs not yet supported + return OC_STACK_INVALID_URI; + } + OC_LOG(INFO, TAG, PCF("Exiting ValidateUrlQuery")); + return OC_STACK_OK; +} + +OCStackResult BuildVirtualResourceResponse(OCResource *resourcePtr, uint8_t filterOn, + char *filterValue, char * out, uint16_t *remaining) +{ + OCResourceType *resourceTypePtr; + OCResourceInterface *interfacePtr; + cJSON *resObj, *propObj, *rtArray; + char *jsonStr; + uint8_t encodeRes = 0; + OCStackResult ret = OC_STACK_OK; + uint16_t jsonLen; + + OC_LOG(INFO, TAG, PCF("Entering BuildVirtualResourceResponse")); + resObj = cJSON_CreateObject(); + + if (resourcePtr) + { + encodeRes = 0; + if (filterOn == STACK_RES_DISCOVERY_RT_FILTER) { + resourceTypePtr = resourcePtr->rsrcType; + while (resourceTypePtr) { + if (strcmp (resourceTypePtr->resourcetypename, filterValue) == 0) { + encodeRes = 1; + break; + } + resourceTypePtr = resourceTypePtr->next; + } + } else if (filterOn == STACK_RES_DISCOVERY_IF_FILTER) { + interfacePtr = resourcePtr->rsrcInterface; + while (interfacePtr) { + if (strcmp (interfacePtr->name, filterValue) == 0) { + encodeRes = 1; + break; + } + interfacePtr = interfacePtr->next; + } + } else if (filterOn == STACK_RES_DISCOVERY_NOFILTER) { + encodeRes = 1; + } else { + //TODO: Unsupported query filter + return OC_STACK_INVALID_QUERY; + } + + if (encodeRes) { + // Add URIs + cJSON_AddItemToObject (resObj, OC_RSRVD_HREF, cJSON_CreateString(resourcePtr->uri)); + + cJSON_AddItemToObject (resObj, "prop", propObj = cJSON_CreateObject()); + // Add resource types + cJSON_AddItemToObject (propObj, OC_RSRVD_RESOURCE_TYPE, rtArray = cJSON_CreateArray()); + resourceTypePtr = resourcePtr->rsrcType; + while (resourceTypePtr) { + cJSON_AddItemToArray (rtArray, + cJSON_CreateString(resourceTypePtr->resourcetypename)); + resourceTypePtr = resourceTypePtr->next; + } + // Add interface types + cJSON_AddItemToObject (propObj, OC_RSRVD_INTERFACE, rtArray = cJSON_CreateArray()); + interfacePtr = resourcePtr->rsrcInterface; + while (interfacePtr) { + cJSON_AddItemToArray (rtArray, cJSON_CreateString(interfacePtr->name)); + interfacePtr = interfacePtr->next; + } + // If resource is observable, set observability flag. + // Resources that are not observable will not have the flag. + if (resourcePtr->resourceProperties & OC_OBSERVABLE) { + cJSON_AddItemToObject (propObj, OC_RSRVD_OBSERVABLE, + cJSON_CreateNumber(OC_RESOURCE_OBSERVABLE)); + } + // Set secure flag for secure resources + if (resourcePtr->resourceProperties & OC_SECURE) { + uint16_t port; + cJSON_AddNumberToObject (propObj, OC_RSRVD_SECURE, OC_RESOURCE_SECURE); + //Set the IP port also as secure resources are hosted on a different port + if (OCGetResourceEndPointInfo (resourcePtr, &port) == OC_STACK_OK) { + cJSON_AddNumberToObject (propObj, OC_RSRVD_HOSTING_PORT, port); + } + } + + } + } + jsonStr = cJSON_PrintUnformatted (resObj); + + jsonLen = strlen(jsonStr); + if (jsonLen < *remaining) + { + strcpy(out, jsonStr); + *remaining = *remaining - jsonLen; + } + else + { + ret = OC_STACK_ERROR; + } + cJSON_Delete (resObj); + free (jsonStr); + + OC_LOG(INFO, TAG, PCF("Exiting BuildVirtualResourceResponse")); + return ret; +} + +OCStackResult BuildVirtualResourceResponseForDevice(uint8_t filterOn, char *filterValue, + char *out, uint16_t *remaining) +{ + OCStackResult ret = OC_STACK_ERROR; + + if (savedDeviceInfo != NULL) + { + char *jsonStr = NULL; + uint16_t jsonLen = 0; + cJSON *repObj = cJSON_GetObjectItem(savedDeviceInfo, "rep"); + + OC_LOG(INFO, TAG, PCF("Entering BuildVirtualResourceResponseForDevice")); + + if (filterOn == STACK_DEVICE_DISCOVERY_DI_FILTER) + { + if((cJSON_GetObjectItem(repObj,"di") != NULL) && + strcmp(cJSON_GetObjectItem(repObj,"di")->valuestring, filterValue) == 0) + { + ret = OC_STACK_OK; + } + } + else if (filterOn == STACK_DEVICE_DISCOVERY_DN_FILTER) + { + if((cJSON_GetObjectItem(repObj,"dn") != NULL) && + strcmp(cJSON_GetObjectItem(repObj,"dn")->valuestring, filterValue) == 0) + { + ret = OC_STACK_OK; + } + } + else if (filterOn == STACK_RES_DISCOVERY_NOFILTER) + { + ret = OC_STACK_OK; + } + else + { + ret = OC_STACK_INVALID_QUERY; + } + + if (ret == OC_STACK_OK) + { + jsonStr = cJSON_PrintUnformatted (savedDeviceInfo); + + if(jsonStr) + { + jsonLen = strlen(jsonStr); + + if (jsonLen < *remaining) + { + strncpy(out, jsonStr, (jsonLen + 1)); + *remaining = *remaining - jsonLen; + ret = OC_STACK_OK; + } + else + { + ret = OC_STACK_ERROR; + } + + free(jsonStr); + } + else + { + ret = OC_STACK_ERROR; + } + } + else + { + ret = OC_STACK_INVALID_DEVICE_INFO; + } + } + else + { + //error so that stack won't respond with empty payload + ret = OC_STACK_INVALID_DEVICE_INFO; + } + + OC_LOG(INFO, TAG, PCF("Exiting BuildVirtualResourceResponseForDevice")); + return ret; +} + +TODO ("Does it make sense to make this method as inline") +const char * GetVirtualResourceUri( OCVirtualResources resource) +{ + if (resource < OC_MAX_VIRTUAL_RESOURCES) + { + return VIRTUAL_RSRCS[resource]; + } + + return NULL; +} + +uint8_t IsVirtualResource(const char* resourceUri) +{ + for (int i = 0; i < OC_MAX_VIRTUAL_RESOURCES; i++) + { + if (strcmp(resourceUri, GetVirtualResourceUri((OCVirtualResources)i)) == 0) + { + return 1; + } + } + return 0; +} + +uint8_t IsCollectionResource (OCResource *resource) +{ + for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++) + { + if (resource->rsrcResources[i]) + { + return 1; + } + } + return 0; +} + +OCResource *FindResourceByUri(const char* resourceUri) +{ + OCResource * pointer = headResource; + while (pointer) { + if (strcmp(resourceUri, pointer->uri) == 0) { + return pointer; + } + pointer = pointer->next; + } + OC_LOG(INFO, TAG, PCF("Resource not found")); + return NULL; +} + + +OCStackResult DetermineResourceHandling (OCServerRequest *request, + ResourceHandling *handling, + OCResource **resource) +{ + + OC_LOG(INFO, TAG, PCF("Entering DetermineResourceHandling")); + + // Check if virtual resource + if (IsVirtualResource((const char*)request->resourceUrl)) + { + *handling = OC_RESOURCE_VIRTUAL; + *resource = headResource; + return OC_STACK_OK; + } + if (NULL == request->resourceUrl || (strlen((const char*)(request->resourceUrl)) == 0)) + { + // Resource URL not specified + *handling = OC_RESOURCE_NOT_SPECIFIED; + return OC_STACK_OK; + } + else + { + OCResource *resourcePtr = NULL; + resourcePtr = FindResourceByUri((const char*)request->resourceUrl); + *resource = resourcePtr; + if (!resourcePtr) + { + if(defaultDeviceHandler) + { + *handling = OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER; + return OC_STACK_OK; + } + + // Resource does not exist + // and default device handler does not exist + *handling = OC_RESOURCE_NOT_SPECIFIED; + return OC_STACK_NO_RESOURCE; + } + + // secure resource will entertain only authorized requests + if ((resourcePtr->resourceProperties & OC_SECURE) && (request->secured == 0)) + { + OC_LOG(INFO, TAG, PCF("Un-authorized request. Ignore it!")); + return OC_STACK_RESOURCE_ERROR; + } + + if (IsCollectionResource (resourcePtr)) + { + // Collection resource + if (resourcePtr->entityHandler != defaultResourceEHandler) + { + *handling = OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER; + return OC_STACK_OK; + } else { + *handling = OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER; + return OC_STACK_OK; + } + } else { + // Resource not a collection + if (resourcePtr->entityHandler != defaultResourceEHandler) + { + *handling = OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER; + return OC_STACK_OK; + } else { + *handling = OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER; + return OC_STACK_OK; + } + } + } +} + +OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult) +{ + OCStackResult result; + + switch (ehResult) + { + case OC_EH_OK: + result = OC_STACK_OK; + break; + case OC_EH_SLOW: + result = OC_STACK_SLOW_RESOURCE; + break; + case OC_EH_ERROR: + result = OC_STACK_ERROR; + break; + case OC_EH_FORBIDDEN: + result = OC_STACK_RESOURCE_ERROR; + break; + case OC_EH_RESOURCE_CREATED: + result = OC_STACK_RESOURCE_CREATED; + break; + case OC_EH_RESOURCE_DELETED: + result = OC_STACK_RESOURCE_DELETED; + break; + default: + result = OC_STACK_ERROR; + } + + return result; +} + +static OCStackResult +HandleVirtualResource (OCServerRequest *request, OCResource* resource) +{ + OCStackResult result = OC_STACK_ERROR; + char *filterValue = NULL; + uint8_t filterOn = 0; + uint16_t remaining = 0; + unsigned char * ptr = NULL; + uint8_t firstLoopDone = 0; + unsigned char discoveryResBuf[MAX_RESPONSE_LENGTH] = {0}; + + OC_LOG(INFO, TAG, PCF("Entering HandleVirtualResource")); + + result = ValidateUrlQuery (request->resourceUrl, + request->query, &filterOn, + &filterValue); + + if (result == OC_STACK_OK) + { + if (strcmp ((char *)request->resourceUrl, GetVirtualResourceUri(OC_WELL_KNOWN_URI)) == 0) + { + ptr = discoveryResBuf; + remaining = MAX_RESPONSE_LENGTH; + + while(resource) + { + if((resource->resourceProperties & OC_ACTIVE) + && (resource->resourceProperties & OC_DISCOVERABLE)) + { + // if there is data on the buffer, we have already added a response, + // so we need to add a comma before we do anything + if(firstLoopDone + && remaining >= (sizeof(OC_JSON_SEPARATOR)+1)) + { + *ptr = OC_JSON_SEPARATOR; + ptr++; + remaining--; + } + firstLoopDone = 1; + result = BuildVirtualResourceResponse(resource, filterOn, filterValue, + (char*)ptr, &remaining); + + if (result != OC_STACK_OK) + { + // if this failed, we need to remove the comma added above. + if(!firstLoopDone) + { + ptr--; + *ptr = '\0'; + remaining++; + } + break; + } + ptr += strlen((char *)ptr); + *(ptr + 1) = '\0'; + } + resource = resource->next; + } + + if(strlen((const char *)discoveryResBuf) > 0) + { + OCEntityHandlerResponse response = {0}; + + response.ehResult = OC_EH_OK; + response.payload = discoveryResBuf; + response.payloadSize = strlen((const char *)discoveryResBuf) + 1; + response.persistentBufferFlag = 0; + response.requestHandle = (OCRequestHandle) request; + response.resourceHandle = (OCResourceHandle) resource; + + result = OCDoResponse(&response); + } + } + else if (strcmp ((char *)request->resourceUrl, GetVirtualResourceUri(OC_DEVICE_URI)) == 0) + { + remaining = MAX_RESPONSE_LENGTH; + ptr = discoveryResBuf; + + result = BuildVirtualResourceResponseForDevice(filterOn, filterValue, + (char*)ptr, &remaining); + + if(result == OC_STACK_OK) + { + ptr += strlen((char*)ptr); + } + + if(remaining < MAX_RESPONSE_LENGTH) + { + OCEntityHandlerResponse response = {0}; + + response.ehResult = OC_EH_OK; + response.payload = discoveryResBuf; + response.payloadSize = strlen((const char *)discoveryResBuf) + 1; + response.persistentBufferFlag = 0; + response.requestHandle = (OCRequestHandle) request; + response.resourceHandle = (OCResourceHandle) resource; + + result = OCDoResponse(&response); + } + } + #ifdef WITH_PRESENCE + else + { + if(resource->resourceProperties & OC_ACTIVE){ + SendPresenceNotification(NULL); + } + } + #endif + } + result = OC_STACK_VIRTUAL_DO_NOT_HANDLE; + return result; +} + +static OCStackResult +HandleDefaultDeviceEntityHandler (OCServerRequest *request) +{ + OCStackResult result = OC_STACK_OK; + OCEntityHandlerResult ehResult = OC_EH_ERROR; + OCEntityHandlerRequest ehRequest = {0}; + + OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithDefaultDeviceEntityHandler")); + result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request, + request->method, (OCResourceHandle) NULL, request->query, + request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions, + request->rcvdVendorSpecificHeaderOptions, (OCObserveAction)request->observationOption, (OCObservationId)0); + VERIFY_SUCCESS(result, OC_STACK_OK); + + // At this point we know for sure that defaultDeviceHandler exists + ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest, + (char*) request->resourceUrl); + if(ehResult == OC_EH_SLOW) + { + OC_LOG(INFO, TAG, PCF("This is a slow resource")); + request->slowFlag = 1; + } + else if(ehResult == OC_EH_ERROR) + { + FindAndDeleteServerRequest(request); + } + result = EntityHandlerCodeToOCStackCode(ehResult); +exit: + return result; +} + +static OCStackResult +HandleResourceWithEntityHandler (OCServerRequest *request, + OCResource *resource, + uint8_t collectionResource) +{ + OCStackResult result = OC_STACK_ERROR; + OCEntityHandlerResult ehResult = OC_EH_ERROR; + OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG; + ResourceObserver *resObs = NULL; + + OCEntityHandlerRequest ehRequest = {0}; + + OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithEntityHandler")); + result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request, + request->method, (OCResourceHandle) resource, request->query, + request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions, + request->rcvdVendorSpecificHeaderOptions, + (OCObserveAction)request->observationOption, 0); + VERIFY_SUCCESS(result, OC_STACK_OK); + + if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION) + { + OC_LOG(INFO, TAG, PCF("No observation requested")); + ehFlag = OC_REQUEST_FLAG; + } + else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER && + !collectionResource) + { + OC_LOG(INFO, TAG, PCF("Registering observation requested")); + result = GenerateObserverId(&ehRequest.obsInfo.obsId); + VERIFY_SUCCESS(result, OC_STACK_OK); + + result = AddObserver ((const char*)(request->resourceUrl), + (const char *)(request->query), + ehRequest.obsInfo.obsId, &request->requestToken, + &request->requesterAddr, resource, request->qos); + if(result == OC_STACK_OK) + { + OC_LOG(DEBUG, TAG, PCF("Added observer successfully")); + request->observeResult = OC_STACK_OK; + ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG); + } + else + { + result = OC_STACK_OK; + request->observeResult = OC_STACK_ERROR; + OC_LOG(DEBUG, TAG, PCF("Observer Addition failed")); + ehFlag = OC_REQUEST_FLAG; + } + + } + else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER && + !collectionResource) + { + OC_LOG(INFO, TAG, PCF("Deregistering observation requested")); + resObs = GetObserverUsingToken (&request->requestToken); + if (NULL == resObs) + { + // Stack does not contain this observation request + // Either token is incorrect or observation list is corrupted + result = OC_STACK_ERROR; + goto exit; + } + ehRequest.obsInfo.obsId = resObs->observeId; + ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG); + + result = DeleteObserverUsingToken (&request->requestToken); + if(result == OC_STACK_OK) + { + OC_LOG(DEBUG, TAG, PCF("Removed observer successfully")); + request->observeResult = OC_STACK_OK; + } + else + { + result = OC_STACK_OK; + request->observeResult = OC_STACK_ERROR; + OC_LOG(DEBUG, TAG, PCF("Observer Removal failed")); + } + } + else + { + result = OC_STACK_ERROR; + goto exit; + } + + ehResult = resource->entityHandler(ehFlag, &ehRequest); + if(ehResult == OC_EH_SLOW) + { + OC_LOG(INFO, TAG, PCF("This is a slow resource")); + request->slowFlag = 1; + } + else if(ehResult == OC_EH_ERROR) + { + FindAndDeleteServerRequest(request); + } + result = EntityHandlerCodeToOCStackCode(ehResult); +exit: + return result; +} + +static OCStackResult +HandleCollectionResourceDefaultEntityHandler (OCServerRequest *request, + OCResource *resource) +{ + OCStackResult result = OC_STACK_ERROR; + OCEntityHandlerRequest ehRequest = {0}; + + result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request, + request->method, (OCResourceHandle) resource, request->query, + request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions, + request->rcvdVendorSpecificHeaderOptions, + (OCObserveAction)request->observationOption, (OCObservationId) 0); + if(result != OC_STACK_OK) + { + return result; + } + + return (DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest)); +} + +OCStackResult +ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request) +{ + OCStackResult ret = OC_STACK_OK; + + switch (resHandling) + { + case OC_RESOURCE_VIRTUAL: + { + ret = HandleVirtualResource (request, resource); + break; + } + case OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER: + { + ret = HandleDefaultDeviceEntityHandler(request); + break; + } + case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER: + { + OC_LOG(INFO, TAG, PCF("OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER")); + return OC_STACK_ERROR; + } + case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER: + { + ret = HandleResourceWithEntityHandler (request, resource, 0); + break; + } + case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER: + { + ret = HandleResourceWithEntityHandler (request, resource, 1); + break; + } + case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER: + { + ret = HandleCollectionResourceDefaultEntityHandler (request, resource); + break; + } + case OC_RESOURCE_NOT_SPECIFIED: + { + ret = OC_STACK_NO_RESOURCE; + break; + } + default: + { + OC_LOG(INFO, TAG, PCF("Invalid Resource Determination")); + return OC_STACK_ERROR; + } + } + return ret; +} + +void DeleteDeviceInfo() +{ + if(savedDeviceInfo) + { + cJSON_Delete(savedDeviceInfo); + } +} + +OCStackResult SaveDeviceInfo(OCDeviceInfo deviceInfo) +{ + DeleteDeviceInfo(); + + savedDeviceInfo = cJSON_CreateObject(); + cJSON *repObj = NULL; + + cJSON_AddItemToObject (savedDeviceInfo, OC_RSRVD_HREF, + cJSON_CreateString(GetVirtualResourceUri(OC_DEVICE_URI))); + + cJSON_AddItemToObject (savedDeviceInfo, "rep", repObj = cJSON_CreateObject()); + + if (deviceInfo.contentType) + { + cJSON_AddItemToObject (repObj, "ct", + cJSON_CreateString(deviceInfo.contentType)); + } + + if (deviceInfo.dateOfManufacture) + { + cJSON_AddItemToObject (repObj, "mndt", + cJSON_CreateString(deviceInfo.dateOfManufacture)); + } + + if (deviceInfo.deviceName) + { + cJSON_AddItemToObject (repObj, "dn", + cJSON_CreateString(deviceInfo.deviceName)); + } + + if (deviceInfo.deviceUUID) + { + cJSON_AddItemToObject (repObj, "di", + cJSON_CreateString(deviceInfo.deviceUUID)); + } + + if (deviceInfo.firmwareVersion) + { + cJSON_AddItemToObject (repObj, "mnfv", + cJSON_CreateString(deviceInfo.firmwareVersion)); + } + + if (deviceInfo.hostName) + { + cJSON_AddItemToObject (repObj, "hn", cJSON_CreateString(deviceInfo.hostName)); + } + + if (deviceInfo.manufacturerName) + { + if(strlen(deviceInfo.manufacturerName) > MAX_MANUFACTURER_NAME_LENGTH) + { + DeleteDeviceInfo(); + return OC_STACK_INVALID_PARAM; + } + + cJSON_AddItemToObject (repObj, "mnmn", + cJSON_CreateString(deviceInfo.manufacturerName)); + } + + if (deviceInfo.manufacturerUrl) + { + if(strlen(deviceInfo.manufacturerUrl) > MAX_MANUFACTURER_URL_LENGTH) + { + DeleteDeviceInfo(); + return OC_STACK_INVALID_PARAM; + } + + cJSON_AddItemToObject (repObj, "mnml", + cJSON_CreateString(deviceInfo.manufacturerUrl)); + } + + if (deviceInfo.modelNumber) + { + cJSON_AddItemToObject (repObj, "mnmo", + cJSON_CreateString(deviceInfo.modelNumber)); + } + + if (deviceInfo.platformVersion) + { + cJSON_AddItemToObject (repObj, "mnpv", + cJSON_CreateString(deviceInfo.platformVersion)); + } + + if (deviceInfo.supportUrl) + { + cJSON_AddItemToObject (repObj, "mnsl", + cJSON_CreateString(deviceInfo.supportUrl)); + } + + if (deviceInfo.version) + { + cJSON_AddItemToObject (repObj, "icv", + cJSON_CreateString(deviceInfo.version)); + } + + return OC_STACK_OK; +} + diff --git a/resource/csdk/stack/src/ocsecurity.c b/resource/csdk/stack/src/ocsecurity.c new file mode 100644 index 000000000..0dd7aae22 --- /dev/null +++ b/resource/csdk/stack/src/ocsecurity.c @@ -0,0 +1,86 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "ocstack.h" +#include "ocmalloc.h" +#include "ocsecurity.h" +#include "ocsecurityconfig.h" +#include + +static OCDtlsPskCredsBlob* pskCredsBlob; +static int pskCredsBlobLen; + +// Internal API. Invoked by OC stack to cleanup memory +void DeinitOCSecurityInfo() +{ + if (pskCredsBlob) + { + // Initialize sensitive data to zeroes before freeing. + memset(pskCredsBlob, 0, pskCredsBlobLen); + + OCFree(pskCredsBlob); + pskCredsBlob = NULL; + } +} + +// Internal API. Invoked by OC stack to retrieve credentials from this module +void OCGetDtlsPskCredentials(OCDtlsPskCredsBlob **credInfo) +{ + *credInfo = pskCredsBlob; +} + +/** + * Provides the DTLS PSK credetials blob to OC stack. + * + * @param credInfo + * binary blob containing credentials + * @param len + * length of binary blob + * + * @retval OC_STACK_OK for Success, otherwise some error value + */ +OCStackResult OCSetDtlsPskCredentials(const OCDtlsPskCredsBlob *credInfo, + size_t len) +{ + if(credInfo && len > 0) + { + if (credInfo->blobVer != DtlsPskCredsBlobVer_CurrentVersion) + { + return OC_STACK_INVALID_PARAM; + } + + // Remove existing blob + DeinitOCSecurityInfo(); + // Allocate storage for new blob + pskCredsBlob = (OCDtlsPskCredsBlob*)OCMalloc(len); + if (pskCredsBlob) + { + memcpy(pskCredsBlob, credInfo, len); + pskCredsBlobLen = len; + return OC_STACK_OK; + } + + return OC_STACK_NO_MEMORY; + } + + return OC_STACK_INVALID_PARAM; +} + + diff --git a/resource/csdk/stack/src/ocserverrequest.c b/resource/csdk/stack/src/ocserverrequest.c new file mode 100644 index 000000000..3398857d0 --- /dev/null +++ b/resource/csdk/stack/src/ocserverrequest.c @@ -0,0 +1,379 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "ocstack.h" +#include "ocserverrequest.h" +#include "ocresourcehandler.h" + +// Module Name +#define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} } + +#define TAG PCF("ocserverrequest") + +static struct OCServerRequest * serverRequestList = NULL; +static struct OCServerResponse * serverResponseList = NULL; + +OCServerRequest * GetServerRequestUsingToken (const OCCoAPToken token) +{ + OCServerRequest * out = NULL; + LL_FOREACH (serverRequestList, out) + { + OC_LOG(INFO, TAG,PCF("comparing tokens")); + OC_LOG_BUFFER(INFO, TAG, token.token, token.tokenLength); + OC_LOG_BUFFER(INFO, TAG, out->requestToken.token, out->requestToken.tokenLength); + if((out->requestToken.tokenLength == token.tokenLength) && + (memcmp(out->requestToken.token, token.token, token.tokenLength) == 0)) + { + return out; + } + } + OC_LOG(INFO, TAG, PCF("Server Request not found!!")); + return NULL; +} + +OCServerRequest * GetServerRequestUsingHandle (const OCServerRequest * handle) +{ + OCServerRequest * out = NULL; + LL_FOREACH (serverRequestList, out) + { + if(out == handle) + { + return out; + } + } + OC_LOG(INFO, TAG, PCF("Server Request not found!!")); + return NULL; +} + +OCServerResponse * GetServerResponseUsingHandle (const OCServerRequest * handle) +{ + OCServerResponse * out = NULL; + LL_FOREACH (serverResponseList, out) + { + if(out->requestHandle == handle) + { + return out; + } + } + OC_LOG(INFO, TAG, PCF("Server Response not found!!")); + return NULL; +} + +OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID, + uint8_t delayedResNeeded, uint8_t secured, uint8_t notificationFlag, OCMethod method, + uint8_t numRcvdVendorSpecificHeaderOptions, uint32_t observationOption, + OCQualityOfService qos, unsigned char * query, + OCHeaderOption * rcvdVendorSpecificHeaderOptions, + unsigned char * reqJSONPayload, OCCoAPToken * requestToken, + OCDevAddr * requesterAddr, unsigned char * resourceUrl, uint32_t reqTotalSize) +{ + OCServerRequest * serverRequest = NULL; + + serverRequest = (OCServerRequest *) OCCalloc(1, sizeof(OCServerRequest) + reqTotalSize - 1); + VERIFY_NON_NULL(serverRequest); + + serverRequest->coapID = coapID; + serverRequest->delayedResNeeded = delayedResNeeded; + serverRequest->secured = secured; + serverRequest->notificationFlag = notificationFlag; + + serverRequest->method = method; + serverRequest->numRcvdVendorSpecificHeaderOptions = numRcvdVendorSpecificHeaderOptions; + serverRequest->observationOption = observationOption; + serverRequest->observeResult = OC_STACK_ERROR; + serverRequest->qos = qos; + serverRequest->ehResponseHandler = HandleSingleResponse; + serverRequest->numResponses = 1; + if(query) + { + memcpy(serverRequest->query, query, strlen((const char *)query) + 1); + } + if(rcvdVendorSpecificHeaderOptions) + { + memcpy(serverRequest->rcvdVendorSpecificHeaderOptions, rcvdVendorSpecificHeaderOptions, + MAX_HEADER_OPTIONS * sizeof(OCHeaderOption)); + } + if(reqJSONPayload) + { + memcpy((void *)serverRequest->reqJSONPayload, (void *)reqJSONPayload, + strlen((const char *)reqJSONPayload) + 1); + } + serverRequest->requestComplete = 0; + if(requestToken) + { + memcpy(&serverRequest->requestToken, requestToken, sizeof(OCCoAPToken)); + } + if(requesterAddr) + { + memcpy(&serverRequest->requesterAddr, requesterAddr, sizeof(OCDevAddr)); + } + if(resourceUrl) + { + memcpy(serverRequest->resourceUrl, resourceUrl, strlen((const char *)resourceUrl) + 1); + } + *request = serverRequest; + OC_LOG(INFO, TAG, PCF("Server Request Added!!")); + LL_APPEND (serverRequestList, serverRequest); + return OC_STACK_OK; + +exit: + if (serverRequest) + { + OCFree(serverRequest); + serverRequest = NULL; + } + *request = NULL; + return OC_STACK_NO_MEMORY; +} + +OCStackResult AddServerResponse (OCServerResponse ** response, OCRequestHandle requestHandle) +{ + OCServerResponse * serverResponse = NULL; + + serverResponse = (OCServerResponse *) OCCalloc(1, sizeof(OCServerResponse)); + VERIFY_NON_NULL(serverResponse); + + serverResponse->payload = (unsigned char *) OCMalloc(MAX_RESPONSE_LENGTH); + VERIFY_NON_NULL(serverResponse->payload); + memset(serverResponse->payload, 0, sizeof(MAX_RESPONSE_LENGTH)); + + serverResponse->remainingPayloadSize = MAX_RESPONSE_LENGTH; + serverResponse->requestHandle = requestHandle; + + *response = serverResponse; + OC_LOG(INFO, TAG, PCF("Server Response Added!!")); + LL_APPEND (serverResponseList, serverResponse); + return OC_STACK_OK; + +exit: + if (serverResponse) + { + OCFree(serverResponse); + serverResponse = NULL; + } + *response = NULL; + return OC_STACK_NO_MEMORY; +} + +// Form the OCEntityHandlerRequest struct +OCStackResult FormOCEntityHandlerRequest(OCEntityHandlerRequest * entityHandlerRequest, OCRequestHandle request, + OCMethod method, OCResourceHandle resource, unsigned char * queryBuf, unsigned char * bufReqPayload, + uint8_t numVendorOptions, OCHeaderOption * vendorOptions, OCObserveAction observeAction, + OCObservationId observeID) +{ + if (entityHandlerRequest) + { + memset(entityHandlerRequest, 0, sizeof(OCEntityHandlerRequest)); + entityHandlerRequest->requestHandle = request; + entityHandlerRequest->method = method; + entityHandlerRequest->resource = (OCResourceHandle) resource; + entityHandlerRequest->query = queryBuf; + entityHandlerRequest->reqJSONPayload = bufReqPayload; + entityHandlerRequest->numRcvdVendorSpecificHeaderOptions = numVendorOptions; + entityHandlerRequest->rcvdVendorSpecificHeaderOptions = vendorOptions; + + entityHandlerRequest->obsInfo.action = observeAction; + entityHandlerRequest->obsInfo.obsId = observeID; + return OC_STACK_OK; + } + + return OC_STACK_INVALID_PARAM; +} + +void FindAndDeleteServerResponse(OCServerResponse * serverResponse) +{ + OCServerResponse* tmp; + if(serverResponse) + { + LL_FOREACH(serverResponseList, tmp) + { + if (serverResponse == tmp) + { + DeleteServerResponse(tmp); + return; + } + } + } +} + +void DeleteServerResponse(OCServerResponse * serverResponse) +{ + if(serverResponse) { + LL_DELETE(serverResponseList, serverResponse); + OCFree(serverResponse->payload); + OCFree(serverResponse); + OC_LOG(INFO, TAG, PCF("Server Response Removed!!")); + } +} + +void FindAndDeleteServerRequest(OCServerRequest * serverRequest) +{ + OCServerRequest* tmp; + if(serverRequest) + { + LL_FOREACH(serverRequestList, tmp) + { + if (serverRequest == tmp) + { + DeleteServerRequest(tmp); + return; + } + } + } +} + +void DeleteServerRequest(OCServerRequest * serverRequest) +{ + if(serverRequest) { + LL_DELETE(serverRequestList, serverRequest); + OCFree(serverRequest); + serverRequest = NULL; + OC_LOG(INFO, TAG, PCF("Server Request Removed!!")); + } +} + +OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse) +{ + OCStackResult result = OC_STACK_ERROR; + OCServerProtocolResponse protocolResponse = {0}; + + OC_LOG_V(INFO, TAG, "Inside HandleSingleResponse: %s", ehResponse->payload); + + OCServerRequest *serverRequest = (OCServerRequest *)ehResponse->requestHandle; + // Format protocol response structure with data needed for + // sending the response + protocolResponse.qos = serverRequest->qos; + + if((OCResource *)ehResponse->resourceHandle && + ((OCResource *)ehResponse->resourceHandle)->resourceProperties == (OCResourceProperty) 0) + { + ehResponse->ehResult = OC_EH_RESOURCE_DELETED; + } + protocolResponse.result = EntityHandlerCodeToOCStackCode(ehResponse->ehResult); + protocolResponse.requesterAddr = &serverRequest->requesterAddr; + protocolResponse.requestToken = &serverRequest->requestToken; + protocolResponse.numSendVendorSpecificHeaderOptions = ehResponse->numSendVendorSpecificHeaderOptions; + protocolResponse.sendVendorSpecificHeaderOptions = ehResponse->sendVendorSpecificHeaderOptions; + protocolResponse.resourceUri = ehResponse->resourceUri; + protocolResponse.delayedResNeeded = serverRequest->delayedResNeeded; + protocolResponse.secured = serverRequest->secured; + protocolResponse.slowFlag = serverRequest->slowFlag; + protocolResponse.notificationFlag = serverRequest->notificationFlag; + + //should we put the prefix and suffix here? + protocolResponse.payload = (unsigned char *) OCMalloc(MAX_RESPONSE_LENGTH); + if(!protocolResponse.payload) + { + return OC_STACK_NO_MEMORY; + } + strcpy((char *)protocolResponse.payload, (const char *)OC_JSON_PREFIX); + strcat((char *)protocolResponse.payload, (const char *)ehResponse->payload); + strcat((char *)protocolResponse.payload, (const char *)OC_JSON_SUFFIX); + protocolResponse.payloadSize = strlen((const char *)protocolResponse.payload) + 1; + protocolResponse.resourceUri = ehResponse->resourceUri; + + //revise the following + protocolResponse.coapID = serverRequest->coapID; + if(serverRequest->observeResult == OC_STACK_OK) + { + protocolResponse.observationOption = serverRequest->observationOption; + } + else + { + protocolResponse.observationOption = OC_OBSERVE_NO_OPTION; + } + // Make call to OCCoAP layer + result = OCDoCoAPResponse(&protocolResponse); + + OCFree(protocolResponse.payload); + //Delete the request + FindAndDeleteServerRequest(serverRequest); + return result; +} + +OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse) +{ + OCStackResult stackRet = OC_STACK_ERROR; + OCServerRequest * serverRequest = NULL; + OCServerResponse * serverResponse = NULL; + + OC_LOG_V(INFO, TAG, "Inside HandleAggregateResponse: %s", ehResponse->payload); + + serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle); + serverResponse = GetServerResponseUsingHandle((OCServerRequest *)ehResponse->requestHandle); + + if(serverRequest) + { + if(!serverResponse) + { + OC_LOG(INFO, TAG, PCF("This is the first response fragment")); + stackRet = AddServerResponse(&serverResponse, ehResponse->requestHandle); + if (OC_STACK_OK != stackRet) + { + OC_LOG(ERROR, TAG, PCF("Error adding server response")); + return stackRet; + } + VERIFY_NON_NULL(serverResponse); + VERIFY_NON_NULL(serverResponse->payload); + } + + if((serverResponse->remainingPayloadSize >= ehResponse->payloadSize + 1 && + serverRequest->numResponses == 1) || + (serverResponse->remainingPayloadSize >= ehResponse->payloadSize + 2 && + serverRequest->numResponses > 1)) + { + OC_LOG(INFO, TAG, PCF("There is room in response buffer")); + // append + snprintf((char *)serverResponse->payload, serverResponse->remainingPayloadSize, "%s%s", (char *)serverResponse->payload, (char *)ehResponse->payload); + OC_LOG_V(INFO, TAG, "Current aggregated response ...%s", serverResponse->payload); + serverResponse->remainingPayloadSize -= ehResponse->payloadSize; + (serverRequest->numResponses)--; + if(serverRequest->numResponses == 0) + { + OC_LOG(INFO, TAG, PCF("This is the last response fragment")); + ehResponse->payload = serverResponse->payload; + ehResponse->payloadSize = strlen((char *) serverResponse->payload) + 1; + stackRet = HandleSingleResponse(ehResponse); + //Delete the request and response + FindAndDeleteServerRequest(serverRequest); + FindAndDeleteServerResponse(serverResponse); + } + else + { + OC_LOG(INFO, TAG, PCF("More response fragment to come")); + // TODO: we should consider using strcat rather than setting a char by char here! + snprintf((char *)serverResponse->payload, serverResponse->remainingPayloadSize, "%s%c", (char *)serverResponse->payload,OC_JSON_SEPARATOR); + OC_LOG_V(INFO, TAG, "Current aggregated response ...%s", serverResponse->payload); + (serverResponse->remainingPayloadSize)--; + stackRet = OC_STACK_OK; + } + } + else + { + OC_LOG(INFO, TAG, PCF("No room in response buffer")); + //Delete the request and response + FindAndDeleteServerRequest(serverRequest); + FindAndDeleteServerResponse(serverResponse); + stackRet = OC_STACK_NO_MEMORY; + } + } +exit: + return stackRet; +} diff --git a/resource/csdk/stack/src/ocstack.c b/resource/csdk/stack/src/ocstack.c new file mode 100644 index 000000000..b2aec918d --- /dev/null +++ b/resource/csdk/stack/src/ocstack.c @@ -0,0 +1,2409 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#define _POSIX_C_SOURCE 200112L +#include + +#include "ocstack.h" +#include "ocstackinternal.h" +#include "ocresourcehandler.h" +#include "occlientcb.h" +#include "ocobserve.h" +#include "ocrandom.h" +#include "debug.h" +#include "occoap.h" +#include "ocmalloc.h" +#include "ocserverrequest.h" + +//----------------------------------------------------------------------------- +// Typedefs +//----------------------------------------------------------------------------- +typedef enum { + OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED, OC_STACK_UNINIT_IN_PROGRESS +} OCStackState; + +#ifdef WITH_PRESENCE +typedef enum { + OC_PRESENCE_UNINITIALIZED = 0, OC_PRESENCE_INITIALIZED +} OCPresenceState; +#endif + +//----------------------------------------------------------------------------- +// Private variables +//----------------------------------------------------------------------------- +static OCStackState stackState = OC_STACK_UNINITIALIZED; + +OCResource *headResource = NULL; +#ifdef WITH_PRESENCE +static OCPresenceState presenceState = OC_PRESENCE_UNINITIALIZED; +static PresenceResource presenceResource; +uint8_t PresenceTimeOutSize = 0; +uint32_t PresenceTimeOut[] = {50, 75, 85, 95, 100}; +#endif + +OCMode myStackMode; +OCDeviceEntityHandler defaultDeviceHandler; + +//----------------------------------------------------------------------------- +// Macros +//----------------------------------------------------------------------------- +#define TAG PCF("OCStack") +#define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \ + TAG, PCF(#arg " is NULL")); return (retVal); } } + +//TODO: we should allow the server to define this +#define MAX_OBSERVE_AGE (0x2FFFFUL) +//----------------------------------------------------------------------------- +// Externs +//----------------------------------------------------------------------------- +extern void DeinitOCSecurityInfo(); + +//----------------------------------------------------------------------------- +// Internal API function +//----------------------------------------------------------------------------- + +// This internal function is called to update the stack with the status of +// observers and communication failures +OCStackResult OCStackFeedBack(OCCoAPToken * token, uint8_t status) +{ + OCStackResult result = OC_STACK_ERROR; + ResourceObserver * observer = NULL; + OCEntityHandlerRequest ehRequest = {0}; + + switch(status) + { + case OC_OBSERVER_NOT_INTERESTED: + OC_LOG(DEBUG, TAG, PCF("observer is not interested in our notifications anymore")); + observer = GetObserverUsingToken (token); + if(observer) + { + result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL, + OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0, + NULL, OC_OBSERVE_DEREGISTER, observer->observeId); + if(result != OC_STACK_OK) + { + return result; + } + observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest); + } + //observer is not observing anymore + result = DeleteObserverUsingToken (token); + if(result == OC_STACK_OK) + { + OC_LOG(DEBUG, TAG, PCF("Removed observer successfully")); + } + else + { + result = OC_STACK_OK; + OC_LOG(DEBUG, TAG, PCF("Observer Removal failed")); + } + break; + case OC_OBSERVER_STILL_INTERESTED: + //observer is still interested + OC_LOG(DEBUG, TAG, PCF("observer is interested in our \ + notifications, reset the failedCount")); + observer = GetObserverUsingToken(token); + if(observer) + { + observer->forceHighQos = 0; + observer->failedCommCount = 0; + result = OC_STACK_OK; + } + else + { + result = OC_STACK_OBSERVER_NOT_FOUND; + } + break; + case OC_OBSERVER_FAILED_COMM: + //observer is not reachable + OC_LOG(DEBUG, TAG, PCF("observer is unreachable")); + observer = GetObserverUsingToken(token); + if(observer) + { + if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM) + { + result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL, + OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0, + NULL, OC_OBSERVE_DEREGISTER, observer->observeId); + if(result != OC_STACK_OK) + { + return OC_STACK_ERROR; + } + observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest); + //observer is unreachable + result = DeleteObserverUsingToken (token); + if(result == OC_STACK_OK) + { + OC_LOG(DEBUG, TAG, PCF("Removed observer successfully")); + } + else + { + result = OC_STACK_OK; + OC_LOG(DEBUG, TAG, PCF("Observer Removal failed")); + } + } + else + { + observer->failedCommCount++; + result = OC_STACK_CONTINUE; + } + observer->forceHighQos = 1; + OC_LOG_V(DEBUG, TAG, "Failed count for this observer is %d",observer->failedCommCount); + } + break; + default: + OC_LOG(ERROR, TAG, PCF("Unknown status")); + result = OC_STACK_ERROR; + break; + } + return result; +} + +//This function will be called back by occoap layer when a request is received +OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest) +{ + OC_LOG(INFO, TAG, PCF("Entering HandleStackRequests (OCStack Layer)")); + + OCStackResult result = OC_STACK_ERROR; + ResourceHandling resHandling; + OCResource *resource; + + OCServerRequest * request = GetServerRequestUsingToken(protocolRequest->requestToken); + if(!request) + { + OC_LOG(INFO, TAG, PCF("This is a new Server Request")); + result = AddServerRequest(&request, protocolRequest->coapID, + protocolRequest->delayedResNeeded, protocolRequest->secured, 0, + protocolRequest->method, protocolRequest->numRcvdVendorSpecificHeaderOptions, + protocolRequest->observationOption, protocolRequest->qos, + protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions, + protocolRequest->reqJSONPayload, &protocolRequest->requestToken, + &protocolRequest->requesterAddr, protocolRequest->resourceUrl, + protocolRequest->reqTotalSize); + if (OC_STACK_OK != result) + { + OC_LOG(ERROR, TAG, PCF("Error adding server request")); + return result; + } + VERIFY_NON_NULL(request, ERROR, OC_STACK_NO_MEMORY); + + if(!protocolRequest->reqMorePacket) + { + request->requestComplete = 1; + } + } + else + { + OC_LOG(INFO, TAG, PCF("This is either a repeated Server Request or blocked Server Request")); + } + + if(request->requestComplete) + { + OC_LOG(INFO, TAG, PCF("This Server Request is complete")); + result = DetermineResourceHandling (request, &resHandling, &resource); + if (result == OC_STACK_OK) + { + result = ProcessRequest(resHandling, resource, request); + } + else + { + result = OC_STACK_ERROR; + } + } + else + { + OC_LOG(INFO, TAG, PCF("This Server Request is incomplete")); + result = OC_STACK_CONTINUE; + } + return result; +} + +//This function will be called back by occoap layer when a response is received +void HandleStackResponses(OCResponse * response) +{ + OCStackApplicationResult result = OC_STACK_DELETE_TRANSACTION; + OC_LOG(INFO, TAG, PCF("Entering HandleStackResponses (OCStack Layer)")); + + if (response->cbNode) + { + OC_LOG(INFO, TAG, PCF("Calling into application address space")); + result = response->cbNode->callBack(response->cbNode->context, + response->cbNode->handle, response->clientResponse); + if (result == OC_STACK_DELETE_TRANSACTION || + response->clientResponse->result == OC_STACK_COMM_ERROR || + response->clientResponse->result == OC_STACK_RESOURCE_DELETED) + { + FindAndDeleteClientCB(response->cbNode); + } + } +} + +int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr, uint16_t * port) +{ + size_t index = 0; + unsigned char *itr, *coap; + uint8_t dotCount = 0; + + ipAddr[index] = 0; + *port = 0; + /* search for scheme */ + itr = ipAddrStr; + if (!isdigit((unsigned char) *ipAddrStr)) + { + coap = (unsigned char *) OC_COAP_SCHEME; + while (*coap && tolower(*itr) == *coap) + { + coap++; + itr++; + } + } + ipAddrStr = itr; + + while (*ipAddrStr) { + if (isdigit((unsigned char) *ipAddrStr)) + { + ipAddr[index] *= 10; + ipAddr[index] += *ipAddrStr - '0'; + } + else if ((unsigned char) *ipAddrStr == '.') + { + index++; + dotCount++; + ipAddr[index] = 0; + } + else + { + break; + } + ipAddrStr++; + } + if(*ipAddrStr == ':') + { + ipAddrStr++; + while (*ipAddrStr){ + if (isdigit((unsigned char) *ipAddrStr)) + { + *port *= 10; + *port += *ipAddrStr - '0'; + } + else + { + break; + } + ipAddrStr++; + } + } + + + if (ipAddr[0] < 255 && ipAddr[1] < 255 && ipAddr[2] < 255 && ipAddr[3] < 255 + && dotCount == 3) + { + return 1; + } + else + { + return 0; + } +} + +//----------------------------------------------------------------------------- +// Private internal function prototypes +//----------------------------------------------------------------------------- + +static OCDoHandle GenerateInvocationHandle(); +static OCStackResult initResources(); +static void insertResource(OCResource *resource); +static OCResource *findResource(OCResource *resource); +static void insertResourceType(OCResource *resource, + OCResourceType *resourceType); +static OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, + uint8_t index); +static void insertResourceInterface(OCResource *resource, + OCResourceInterface *resourceInterface); +static OCResourceInterface *findResourceInterfaceAtIndex( + OCResourceHandle handle, uint8_t index); +static void deleteResourceType(OCResourceType *resourceType); +static void deleteResourceInterface(OCResourceInterface *resourceInterface); +static void deleteResourceElements(OCResource *resource); +static int deleteResource(OCResource *resource); +static void deleteAllResources(); +static void incrementSequenceNumber(OCResource * resPtr); +static OCStackResult verifyUriQueryLength(const char * inputUri, + uint16_t uriLen); +static uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size); +OCStackResult getResourceType(const char * uri, unsigned char** resourceType, char ** newURI); + +//----------------------------------------------------------------------------- +// Public APIs +//----------------------------------------------------------------------------- + +/** + * Initialize the OC Stack. Must be called prior to starting the stack. + * + * @param ipAddr + * IP Address of host device + * @param port + * Port of host device + * @param mode + * Host device is client, server, or client-server + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack init error + */ +OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode) +{ + OCStackResult result = OC_STACK_ERROR; + OC_LOG(INFO, TAG, PCF("Entering OCInit")); + + if (ipAddr) + { + OC_LOG_V(INFO, TAG, "IP Address = %s", ipAddr); + } + + switch (mode) + { + case OC_CLIENT: + OC_LOG(INFO, TAG, PCF("Client mode")); + break; + case OC_SERVER: + OC_LOG(INFO, TAG, PCF("Server mode")); + break; + case OC_CLIENT_SERVER: + OC_LOG(INFO, TAG, PCF("Client-server mode")); + break; + default: + OC_LOG(ERROR, TAG, PCF("Invalid mode")); + return OC_STACK_ERROR; + break; + } + myStackMode = mode; + + defaultDeviceHandler = NULL; + +#ifdef WITH_PRESENCE + PresenceTimeOutSize = sizeof(PresenceTimeOut)/sizeof(PresenceTimeOut[0]) - 1; +#endif // WITH_PRESENCE + + // Make call to OCCoAP layer + result = OCInitCoAP(ipAddr, (uint16_t) port, myStackMode); + if (result == OC_STACK_OK) + { + stackState = OC_STACK_INITIALIZED; + } + // Initialize resource + if(result == OC_STACK_OK && myStackMode != OC_CLIENT) + { + result = initResources(); + } + if(result != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, PCF("Stack initialization error")); + } + return result; +} + +/** + * Stop the OC stack. Use for a controlled shutdown. + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack not initialized + */ +OCStackResult OCStop() +{ + OCStackResult result = OC_STACK_ERROR; + + OC_LOG(INFO, TAG, PCF("Entering OCStop")); + + if (stackState == OC_STACK_UNINIT_IN_PROGRESS) + { + OC_LOG(DEBUG, TAG, PCF("Stack already stopping, exiting")); + return OC_STACK_OK; + } + else if (stackState != OC_STACK_INITIALIZED) + { + OC_LOG(ERROR, TAG, PCF("Stack not initialized")); + return OC_STACK_ERROR; + } + + stackState = OC_STACK_UNINIT_IN_PROGRESS; + + #ifdef WITH_PRESENCE + // Ensure that the TTL associated with ANY and ALL presence notifications originating from + // here send with the code "OC_STACK_PRESENCE_STOPPED" result. + presenceResource.presenceTTL = 0; + #endif // WITH_PRESENCE + + // Free memory dynamically allocated for resources + deleteAllResources(); + DeleteDeviceInfo(); + + // Make call to OCCoAP layer + if (OCStopCoAP() == OC_STACK_OK) + { + // Remove all observers + DeleteObserverList(); + // Remove all the client callbacks + DeleteClientCBList(); + stackState = OC_STACK_UNINITIALIZED; + result = OC_STACK_OK; + } else { + stackState = OC_STACK_INITIALIZED; + result = OC_STACK_ERROR; + } + + // Deinit security blob + DeinitOCSecurityInfo(); + + if (result != OC_STACK_OK) { + OC_LOG(ERROR, TAG, PCF("Stack stop error")); + } + + return result; +} + +/** + * Verify the lengths of the URI and the query separately + * + * @param inputUri - Input URI and query. + * @param uriLen - The length of the initial URI with query. + * + * Note: The '?' that appears after the URI is not considered as + * a part of the query. + */ +OCStackResult verifyUriQueryLength(const char *inputUri, uint16_t uriLen) +{ + char *query; + + query = strchr (inputUri, '?'); + + if (query != NULL) + { + if((query - inputUri) > MAX_URI_LENGTH) + { + return OC_STACK_INVALID_URI; + } + + if((inputUri + uriLen - 1 - query) > MAX_QUERY_LENGTH) + { + return OC_STACK_INVALID_QUERY; + } + } + else if(uriLen > MAX_URI_LENGTH) + { + return OC_STACK_INVALID_URI; + } + return OC_STACK_OK; +} + +/** + * Discover or Perform requests on a specified resource (specified by that Resource's respective URI). + * + * @param handle - @ref OCDoHandle to refer to the request sent out on behalf of calling this API. + * @param method - @ref OCMethod to perform on the resource + * @param requiredUri - URI of the resource to interact with + * @param referenceUri - URI of the reference resource + * @param request - JSON encoded request + * @param qos - quality of service + * @param cbData - struct that contains asynchronous callback function that is invoked + * by the stack when discovery or resource interaction is complete + * @param options - The address of an array containing the vendor specific header + * header options to be sent with the request + * @param numOptions - Number of vendor specific header options to be included + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_INVALID_CALLBACK - invalid callback function pointer + * OC_STACK_INVALID_METHOD - invalid resource method + * OC_STACK_INVALID_URI - invalid required or reference URI + */ + +OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri, + const char *referenceUri, const char *request, + OCQualityOfService qos, OCCallbackData *cbData, + OCHeaderOption * options, uint8_t numOptions) +{ + OCStackResult result = OC_STACK_ERROR; + OCCoAPToken token; + ClientCB *clientCB = NULL; + unsigned char * requestUri = NULL; + unsigned char * resourceType = NULL; + char * newUri = (char *)requiredUri; + (void) referenceUri; + + OC_LOG(INFO, TAG, PCF("Entering OCDoResource")); + + // Validate input parameters + VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK); + VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK); + + TODO ("Need to form the final query by concatenating require and reference URI's"); + VERIFY_NON_NULL(requiredUri, FATAL, OC_STACK_INVALID_URI); + + uint16_t uriLen = strlen(requiredUri); + + // ToDo: We should also check if the requiredUri has a mutlicast address, then qos has to be OC_Low_QOS + switch (method) + { + case OC_REST_GET: + case OC_REST_PUT: + case OC_REST_POST: + case OC_REST_DELETE: + case OC_REST_OBSERVE: + case OC_REST_OBSERVE_ALL: + case OC_REST_CANCEL_OBSERVE: + break; + #ifdef WITH_PRESENCE + case OC_REST_PRESENCE: + break; + #endif + default: + result = OC_STACK_INVALID_METHOD; + goto exit; + } + + if((result = verifyUriQueryLength(requiredUri, uriLen)) != OC_STACK_OK) + { + goto exit; + } + + if((request) && (strlen(request) > MAX_REQUEST_LENGTH)) + { + result = OC_STACK_INVALID_PARAM; + goto exit; + } + +#ifdef WITH_PRESENCE + if(method == OC_REST_PRESENCE) + { + result = getResourceType(requiredUri, &resourceType, &newUri); + if(resourceType) { + OC_LOG_V(DEBUG, TAG, "Got Resource Type: %s", resourceType); + } + else + { + OC_LOG(DEBUG, TAG, "Got Resource Type is NULL."); + } + if(result != OC_STACK_OK) + { + goto exit; + } + } +#endif // WITH_PRESENCE + + requestUri = (unsigned char *) OCMalloc(uriLen + 1); + if(requestUri) + { + memcpy(requestUri, newUri, (uriLen + 1)); + } + else + { + result = OC_STACK_NO_MEMORY; + goto exit; + } + + *handle = GenerateInvocationHandle(); + if(!*handle) + { + result = OC_STACK_NO_MEMORY; + goto exit; + } + + // Generate token which will be used by OCStack to match responses received + // with the request + OCGenerateCoAPToken(&token); + + if((result = AddClientCB(&clientCB, cbData, &token, handle, method, requestUri, resourceType)) + != OC_STACK_OK) + { + result = OC_STACK_NO_MEMORY; + goto exit; + } + + // Make call to OCCoAP layer + result = OCDoCoAPResource(method, qos, &token, newUri, request, options, numOptions); + +exit: + if(newUri != requiredUri) + { + OCFree(newUri); + } + if (result != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, PCF("OCDoResource error")); + FindAndDeleteClientCB(clientCB); + } + return result; +} + +/** + * Cancel a request associated with a specific @ref OCDoResource invocation. + * + * @param handle - Used to identify a specific OCDoResource invocation. + * @param qos - used to specify Quality of Service (read below for more info) + * @param options- used to specify vendor specific header options when sending + * explicit observe cancellation + * @param numOptions- Number of header options to be included + * + * @return + * OC_STACK_OK - No errors; Success + * OC_STACK_INVALID_PARAM - The handle provided is invalid. + */ +OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options, + uint8_t numOptions) { + /* + * This ftn is implemented one of two ways in the case of observation: + * + * 1. qos == OC_NON_CONFIRMABLE. When observe is unobserved.. + * Remove the callback associated on client side. + * When the next notification comes in from server, + * reply with RESET message to server. + * Keep in mind that the server will react to RESET only + * if the last notification was sent ans CON + * + * 2. qos == OC_CONFIRMABLE. When OCCancel is called, + * and it is associated with an observe request + * (i.e. ClientCB->method == OC_REST_OBSERVE || OC_REST_OBSERVE_ALL), + * Send CON Observe request to server with + * observe flag = OC_RESOURCE_OBSERVE_DEREGISTER. + * Remove the callback associated on client side. + */ + OCStackResult ret = OC_STACK_OK; + + if(!handle) { + return OC_STACK_INVALID_PARAM; + } + + OC_LOG(INFO, TAG, PCF("Entering OCCancel")); + + ClientCB *clientCB = GetClientCB(NULL, handle, NULL); + + if(clientCB) { + switch (clientCB->method) + { + case OC_REST_OBSERVE: + case OC_REST_OBSERVE_ALL: + if(qos == OC_HIGH_QOS) + { + ret = OCDoCoAPResource(OC_REST_CANCEL_OBSERVE, qos, + &(clientCB->token), (const char *) clientCB->requestUri, NULL, options, + numOptions); + } + else + { + FindAndDeleteClientCB(clientCB); + } + break; + #ifdef WITH_PRESENCE + case OC_REST_PRESENCE: + FindAndDeleteClientCB(clientCB); + break; + #endif + default: + return OC_STACK_INVALID_METHOD; + } + } + return ret; +} +#ifdef WITH_PRESENCE +OCStackResult OCProcessPresence() +{ + OCStackResult result = OC_STACK_OK; + uint8_t ipAddr[4] = { 0 }; + uint16_t port = 0; + + OC_LOG(INFO, TAG, PCF("Entering RequestPresence")); + ClientCB* cbNode = NULL; + OCDevAddr dst; + OCClientResponse clientResponse; + OCResponse * response = NULL; + + LL_FOREACH(cbList, cbNode) { + if(OC_REST_PRESENCE == cbNode->method) + { + if(cbNode->presence) + { + uint32_t now = GetTime(0); + OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel); + OC_LOG_V(DEBUG, TAG, "----------------current ticks %d", now); + + + if(cbNode->presence->TTLlevel >= (PresenceTimeOutSize + 1)) + { + goto exit; + } + + if(cbNode->presence->TTLlevel < PresenceTimeOutSize){ + OC_LOG_V(DEBUG, TAG, "----------------timeout ticks %d", + cbNode->presence->timeOut[cbNode->presence->TTLlevel]); + } + + if(cbNode->presence->TTLlevel >= PresenceTimeOutSize) + { + OC_LOG(DEBUG, TAG, PCF("----------------No more timeout ticks")); + if (ParseIPv4Address( cbNode->requestUri, ipAddr, &port)) + { + OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], port, + &dst); + result = FormOCClientResponse(&clientResponse, OC_STACK_PRESENCE_TIMEOUT, + (OCDevAddr *) &dst, 0, NULL); + if(result != OC_STACK_OK) + { + goto exit; + } + result = FormOCResponse(&response, cbNode, 0, &clientResponse); + if(result != OC_STACK_OK) + { + goto exit; + } + + // Increment the TTLLevel (going to a next state), so we don't keep + // sending presence notification to client. + cbNode->presence->TTLlevel++; + OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d", + cbNode->presence->TTLlevel); + } + else + { + result = OC_STACK_INVALID_IP; + goto exit; + } + HandleStackResponses(response); + } + if(now >= cbNode->presence->timeOut[cbNode->presence->TTLlevel]) + { + OC_LOG(DEBUG, TAG, PCF("time to test server presence ==========")); + OCCoAPToken token; + OCGenerateCoAPToken(&token); + result = OCDoCoAPResource(OC_REST_GET, OC_LOW_QOS, + &token, (const char *)cbNode->requestUri, NULL, NULL, 0); + if(result != OC_STACK_OK) + { + goto exit; + } + cbNode->presence->TTLlevel++; + OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d", cbNode->presence->TTLlevel); + } + } + } + } +exit: + if (result != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, PCF("OCProcessPresence error")); + } + return result; +} +#endif + +/** + * Called in main loop of OC client or server. Allows low-level processing of + * stack services. + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ +OCStackResult OCProcess() { + + OC_LOG(INFO, TAG, PCF("Entering OCProcess")); + #ifdef WITH_PRESENCE + OCProcessPresence(); + #endif + OCProcessCoAP(); + + return OC_STACK_OK; +} + +#ifdef WITH_PRESENCE +/** + * When operating in @ref OCServer or @ref OCClientServer mode, this API will start sending out + * presence notifications to clients via multicast. Once this API has been called with a success, + * clients may query for this server's presence and this server's stack will respond via multicast. + * + * Server can call this function when it comes online for the first time, or when it comes back + * online from offline mode, or when it re enters network. + * + * @param ttl - Time To Live in seconds + * Note: If ttl is '0', then the default stack value will be used (60 Seconds). + * + * @return + * OC_STACK_OK - No errors; Success + */ +OCStackResult OCStartPresence(const uint32_t ttl) +{ + OCChangeResourceProperty( + &(((OCResource *)presenceResource.handle)->resourceProperties), + OC_ACTIVE, 1); + + if(ttl > 0) + { + presenceResource.presenceTTL = ttl; + } + + if(OC_PRESENCE_UNINITIALIZED == presenceState) + { + OCDevAddr multiCastAddr; + OCCoAPToken token; + + presenceState = OC_PRESENCE_INITIALIZED; + OCGenerateCoAPToken(&token); + OCBuildIPv4Address(224, 0, 1, 187, 5683, &multiCastAddr); + //add the presence observer + AddObserver(OC_PRESENCE_URI, NULL, 0, &token, &multiCastAddr, + (OCResource *)presenceResource.handle, OC_LOW_QOS); + } + + // Each time OCStartPresence is called + // a different random 32-bit integer number is used + ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom(); + + return SendPresenceNotification(NULL); +} + +/** + * When operating in @ref OCServer or @ref OCClientServer mode, this API will stop sending out + * presence notifications to clients via multicast. Once this API has been called with a success, + * this server's stack will not respond to clients querying for this server's presence. + * + * Server can call this function when it is terminating, going offline, or when going + * away from network. + * + * @return + * OC_STACK_OK - No errors; Success + */ +OCStackResult OCStopPresence() +{ + OCStackResult result = OC_STACK_ERROR; + //make resource inactive + result = OCChangeResourceProperty( + &(((OCResource *) presenceResource.handle)->resourceProperties), + OC_ACTIVE, 0); + result = SendPresenceNotification(NULL); + + return result; +} +#endif + + +OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandler) +{ + defaultDeviceHandler = entityHandler; + + return OC_STACK_OK; +} + +OCStackResult OCSetDeviceInfo(OCDeviceInfo deviceInfo) +{ + OC_LOG(INFO, TAG, PCF("Entering OCSetDeviceInfo")); + + if(myStackMode == OC_CLIENT) + { + return OC_STACK_ERROR; + } + + return SaveDeviceInfo(deviceInfo); +} + +/** + * Create a resource + * + * @param handle - pointer to handle to newly created resource. Set by ocstack. Used to refer to resource + * @param resourceTypeName - name of resource type. Example: "core.led" + * @param resourceInterfaceName - name of resource interface. Example: "core.rw" + * @param uri - URI of the resource. Example: "/a/led" + * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc + * NULL for default entity handler + * @param resourceProperties - properties supported by resource. Example: OC_DISCOVERABLE|OC_OBSERVABLE + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ +OCStackResult OCCreateResource(OCResourceHandle *handle, + const char *resourceTypeName, + const char *resourceInterfaceName, + const char *uri, OCEntityHandler entityHandler, + uint8_t resourceProperties) { + + OCResource *pointer = NULL; + char *str = NULL; + size_t size; + OCStackResult result = OC_STACK_ERROR; + + OC_LOG(INFO, TAG, PCF("Entering OCCreateResource")); + + if(myStackMode == OC_CLIENT) + { + return result; + } + // Validate parameters + if(!uri || (strlen(uri) == 0)) + { + OC_LOG(ERROR, TAG, PCF("URI is invalid")); + return OC_STACK_INVALID_URI; + } + // Is it presented during resource discovery? + if (!handle || !resourceTypeName) { + OC_LOG(ERROR, TAG, PCF("Input parameter is NULL")); + return OC_STACK_INVALID_PARAM; + } + + if(!resourceInterfaceName || strlen(resourceInterfaceName) == 0) { + resourceInterfaceName = OC_RSRVD_INTERFACE_DEFAULT; + } + + // Make sure resourceProperties bitmask has allowed properties specified + if (resourceProperties + > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW | OC_SECURE)) { + OC_LOG(ERROR, TAG, PCF("Invalid property")); + return OC_STACK_INVALID_PARAM; + } + + // If the headResource is NULL, then no resources have been created... + pointer = headResource; + if (pointer) { + // At least one resources is in the resource list, so we need to search for + // repeated URLs, which are not allowed. If a repeat is found, exit with an error + while (pointer) { + if (strcmp(uri, pointer->uri) == 0) { + OC_LOG(ERROR, TAG, PCF("URI already in use")); + return OC_STACK_INVALID_PARAM; + } + pointer = pointer->next; + } + } + // Create the pointer and insert it into the resource list + pointer = (OCResource *) OCCalloc(1, sizeof(OCResource)); + if (!pointer) { + goto exit; + } + pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER; + + insertResource(pointer); + + // Set the uri + size = strlen(uri) + 1; + str = (char *) OCMalloc(size); + if (!str) { + goto exit; + } + strncpy(str, uri, size); + pointer->uri = str; + + // Set properties. Set OC_ACTIVE + pointer->resourceProperties = (OCResourceProperty) (resourceProperties + | OC_ACTIVE); + + // Add the resourcetype to the resource + result = BindResourceTypeToResource(pointer, resourceTypeName); + if (result != OC_STACK_OK) { + OC_LOG(ERROR, TAG, PCF("Error adding resourcetype")); + goto exit; + } + + // Add the resourceinterface to the resource + result = BindResourceInterfaceToResource(pointer, resourceInterfaceName); + if (result != OC_STACK_OK) { + OC_LOG(ERROR, TAG, PCF("Error adding resourceinterface")); + goto exit; + } + + // If an entity handler has been passed, attach it to the newly created + // resource. Otherwise, set the default entity handler. + if (entityHandler) + { + pointer->entityHandler = entityHandler; + } + else + { + pointer->entityHandler = defaultResourceEHandler; + } + + *handle = pointer; + result = OC_STACK_OK; + + #ifdef WITH_PRESENCE + if(presenceResource.handle) + { + ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom(); + SendPresenceNotification(pointer->rsrcType); + } + #endif +exit: + if (result != OC_STACK_OK) + { + // Deep delete of resource and other dynamic elements that it contains + deleteResource(pointer); + OCFree(str); + } + return result; +} + + + +/** + * Create a resource. with host ip address for remote resource + * + * @param handle - pointer to handle to newly created resource. Set by ocstack. + * Used to refer to resource + * @param resourceTypeName - name of resource type. Example: "core.led" + * @param resourceInterfaceName - name of resource interface. Example: "core.rw" + * @param host - HOST address of the remote resource. Example: "coap://xxx.xxx.xxx.xxx:xxxxx" + * @param uri - URI of the resource. Example: "/a/led" + * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc + * NULL for default entity handler + * @param resourceProperties - properties supported by resource. + * Example: OC_DISCOVERABLE|OC_OBSERVABLE + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ + +OCStackResult OCCreateResourceWithHost(OCResourceHandle *handle, + const char *resourceTypeName, + const char *resourceInterfaceName, + const char *host, + const char *uri, + OCEntityHandler entityHandler, + uint8_t resourceProperties) +{ + char *str = NULL; + size_t size; + OCStackResult result = OC_STACK_ERROR; + + result = OCCreateResource(handle, resourceTypeName, resourceInterfaceName, + uri, entityHandler, resourceProperties); + + if (result != OC_STACK_ERROR) + { + // Set the uri + size = strlen(host) + 1; + str = (char *) OCMalloc(size); + if (!str) + { + return OC_STACK_ERROR; + } + strncpy(str, host, size); + ((OCResource *) *handle)->host = str; + } + + return result; +} + +/** + * Add a resource to a collection resource. + * + * @param collectionHandle - handle to the collection resource + * @param resourceHandle - handle to resource to be added to the collection resource + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + * OC_STACK_INVALID_PARAM - invalid collectionhandle + */ +OCStackResult OCBindResource( + OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) { + OCResource *resource; + uint8_t i; + + OC_LOG(INFO, TAG, PCF("Entering OCBindResource")); + + // Validate parameters + VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR); + VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR); + // Container cannot contain itself + if (collectionHandle == resourceHandle) { + OC_LOG(ERROR, TAG, PCF("Added handle equals collection handle")); + return OC_STACK_INVALID_PARAM; + } + + // Use the handle to find the resource in the resource linked list + resource = findResource((OCResource *) collectionHandle); + if (!resource) { + OC_LOG(ERROR, TAG, PCF("Collection handle not found")); + return OC_STACK_INVALID_PARAM; + } + + // Look for an open slot to add add the child resource. + // If found, add it and return success + for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) { + if (!resource->rsrcResources[i]) { + resource->rsrcResources[i] = (OCResource *) resourceHandle; + OC_LOG(INFO, TAG, PCF("resource bound")); + return OC_STACK_OK; + } + } + + #ifdef WITH_PRESENCE + if(presenceResource.handle) + { + ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom(); + SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType); + } + #endif + + // Unable to add resourceHandle, so return error + return OC_STACK_ERROR; +} + +/** + * Remove a resource from a collection resource. + * + * @param collectionHandle - handle to the collection resource + * @param resourceHandle - handle to resource to be added to the collection resource + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + * OC_STACK_INVALID_PARAM - invalid collectionHandle + */ +OCStackResult OCUnBindResource( + OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) { + OCResource *resource; + uint8_t i; + + OC_LOG(INFO, TAG, PCF("Entering OCUnBindResource")); + + // Validate parameters + VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR); + VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR); + // Container cannot contain itself + if (collectionHandle == resourceHandle) { + OC_LOG(ERROR, TAG, PCF("removing handle equals collection handle")); + return OC_STACK_INVALID_PARAM; + } + + // Use the handle to find the resource in the resource linked list + resource = findResource((OCResource *) collectionHandle); + if (!resource) { + OC_LOG(ERROR, TAG, PCF("Collection handle not found")); + return OC_STACK_INVALID_PARAM; + } + + // Look for an open slot to add add the child resource. + // If found, add it and return success + for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) { + if (resourceHandle == resource->rsrcResources[i]) { + resource->rsrcResources[i] = (OCResource *) NULL; + OC_LOG(INFO, TAG, PCF("resource unbound")); + return OC_STACK_OK; + } + } + + OC_LOG(INFO, TAG, PCF("resource not found in collection")); + + #ifdef WITH_PRESENCE + if(presenceResource.handle) + { + ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom(); + SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType); + } + #endif + + // Unable to add resourceHandle, so return error + return OC_STACK_ERROR; +} + +OCStackResult BindResourceTypeToResource(OCResource* resource, + const char *resourceTypeName) +{ + OCResourceType *pointer = NULL; + char *str = NULL; + size_t size; + OCStackResult result = OC_STACK_ERROR; + + OC_LOG(INFO, TAG, PCF("Entering BindResourceTypeToResource")); + + // Validate parameters + VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM); + // TODO: Does resource attribute resentation really have to be maintained in stack? + // Is it presented during resource discovery? + + TODO ("Make sure that the resourcetypename doesn't already exist in the resource"); + + // Create the resourcetype and insert it into the resource list + pointer = (OCResourceType *) OCCalloc(1, sizeof(OCResourceType)); + if (!pointer) { + goto exit; + } + + // Set the resourceTypeName + size = strlen(resourceTypeName) + 1; + str = (char *) OCMalloc(size); + if (!str) { + goto exit; + } + strncpy(str, resourceTypeName, size); + pointer->resourcetypename = str; + + insertResourceType(resource, pointer); + result = OC_STACK_OK; + + exit: if (result != OC_STACK_OK) { + OCFree(pointer); + OCFree(str); + } + + return result; +} + +OCStackResult BindResourceInterfaceToResource(OCResource* resource, + const char *resourceInterfaceName) +{ + OCResourceInterface *pointer = NULL; + char *str = NULL; + size_t size; + OCStackResult result = OC_STACK_ERROR; + + OC_LOG(INFO, TAG, PCF("Entering BindResourceInterfaceToResource")); + + // Validate parameters + VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM); + + TODO ("Make sure that the resourceinterface name doesn't already exist in the resource"); + + // Create the resourceinterface and insert it into the resource list + pointer = (OCResourceInterface *) OCCalloc(1, sizeof(OCResourceInterface)); + if (!pointer) { + goto exit; + } + + // Set the resourceinterface name + size = strlen(resourceInterfaceName) + 1; + str = (char *) OCMalloc(size); + if (!str) { + goto exit; + } + strncpy(str, resourceInterfaceName, size); + pointer->name = str; + + // Bind the resourceinterface to the resource + insertResourceInterface(resource, pointer); + + result = OC_STACK_OK; + + exit: if (result != OC_STACK_OK) { + OCFree(pointer); + OCFree(str); + } + + return result; +} + +/** + * Bind a resourcetype to a resource. + * + * @param handle - handle to the resource + * @param resourceTypeName - name of resource type. Example: "core.led" + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ +OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle, + const char *resourceTypeName) { + + OCStackResult result = OC_STACK_ERROR; + OCResource *resource; + + // Make sure resource exists + resource = findResource((OCResource *) handle); + if (!resource) { + OC_LOG(ERROR, TAG, PCF("Resource not found")); + return OC_STACK_ERROR; + } + + // call internal function + result = BindResourceTypeToResource(resource, resourceTypeName); + + #ifdef WITH_PRESENCE + if(presenceResource.handle) + { + ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom(); + SendPresenceNotification(resource->rsrcType); + } + #endif + + return result; +} + +/** + * Bind a resourceinterface to a resource. + * + * @param handle - handle to the resource + * @param resourceInterfaceName - name of resource interface. Example: "oc.mi.b" + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ + +OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle, + const char *resourceInterfaceName) { + + OCStackResult result = OC_STACK_ERROR; + OCResource *resource; + + // Make sure resource exists + resource = findResource((OCResource *) handle); + if (!resource) { + OC_LOG(ERROR, TAG, PCF("Resource not found")); + return OC_STACK_ERROR; + } + + // call internal function + result = BindResourceInterfaceToResource(resource, resourceInterfaceName); + + #ifdef WITH_PRESENCE + if(presenceResource.handle) + { + ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom(); + SendPresenceNotification(resource->rsrcType); + } + #endif + + return result; +} + +/** + * Get the number of resources that have been created in the stack. + * + * @param numResources - pointer to count variable + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + + */ +OCStackResult OCGetNumberOfResources(uint8_t *numResources) { + OCResource *pointer = headResource; + + OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResources")); + VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM); + *numResources = 0; + while (pointer) { + *numResources = *numResources + 1; + pointer = pointer->next; + } + return OC_STACK_OK; +} + +/** + * Get a resource handle by index. + * + * @param index - index of resource, 0 to Count - 1 + * + * @return + * Resource handle - if found + * NULL - if not found + */ +OCResourceHandle OCGetResourceHandle(uint8_t index) { + OCResource *pointer = headResource; + uint8_t i = 0; + + OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandle")); + + // Iterate through the list + while ((i < index) && pointer) { + i++; + pointer = pointer->next; + } + return (OCResourceHandle) pointer; +} + +/** + * Delete resource specified by handle. Deletes resource and all resourcetype and resourceinterface + * linked lists. + * + * @param handle - handle of resource to be deleted + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + * OC_STACK_NO_RESOURCE - resource not found + * OC_STACK_INVALID_PARAM - invalid param + */ +OCStackResult OCDeleteResource(OCResourceHandle handle) { + OC_LOG(INFO, TAG, PCF("Entering OCDeleteResource")); + + if (!handle) { + OC_LOG(ERROR, TAG, PCF("Invalid param")); + return OC_STACK_INVALID_PARAM; + } + + OCResource *resource = findResource((OCResource *) handle); + if (resource == NULL) { + OC_LOG(ERROR, TAG, PCF("Resource not found")); + return OC_STACK_NO_RESOURCE; + } + + if (deleteResource((OCResource *) handle) == 0) { + OC_LOG(ERROR, TAG, PCF("Error deleting resource")); + return OC_STACK_ERROR; + } + + return OC_STACK_OK; +} + +/** + * Get the URI of the resource specified by handle. + * + * @param handle - handle of resource + * @return + * URI string - if resource found + * NULL - resource not found + */ +const char *OCGetResourceUri(OCResourceHandle handle) { + OCResource *resource; + OC_LOG(INFO, TAG, PCF("Entering OCGetResourceUri")); + + resource = findResource((OCResource *) handle); + if (resource) { + return resource->uri; + } + return (const char *) NULL; +} + +/** + * Get the properties of the resource specified by handle. + * NOTE: that after a resource is created, the OC_ACTIVE property is set + * for the resource by the stack. + * + * @param handle - handle of resource + * @return + * property bitmap - if resource found + * NULL - resource not found + */ +uint8_t OCGetResourceProperties(OCResourceHandle handle) { + OCResource *resource; + OC_LOG(INFO, TAG, PCF("Entering OCGetResourceProperties")); + + resource = findResource((OCResource *) handle); + if (resource) { + return resource->resourceProperties; + } + return 0; +} + +/** + * Get the number of resource types of the resource. + * + * @param handle - handle of resource + * @param numResourceTypes - pointer to count variable + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ +OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle, + uint8_t *numResourceTypes) { + OCResource *resource; + OCResourceType *pointer; + + OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceTypes")); + VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM); + VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM); + + *numResourceTypes = 0; + + resource = findResource((OCResource *) handle); + if (resource) { + pointer = resource->rsrcType; + while (pointer) { + *numResourceTypes = *numResourceTypes + 1; + pointer = pointer->next; + } + } + return OC_STACK_OK; +} + +/** + * Get name of resource type of the resource. + * + * @param handle - handle of resource + * @param index - index of resource, 0 to Count - 1 + * + * @return + * resource type name - if resource found + * NULL - resource not found + */ +const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index) { + OCResourceType *resourceType; + + OC_LOG(INFO, TAG, PCF("Entering OCGetResourceTypeName")); + + resourceType = findResourceTypeAtIndex(handle, index); + if (resourceType) { + return resourceType->resourcetypename; + } + return (const char *) NULL; +} + + + +/** + * Get the number of resource interfaces of the resource. + * + * @param handle - handle of resource + * @param numResources - pointer to count variable + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ +OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle, + uint8_t *numResourceInterfaces) { + OCResourceInterface *pointer; + OCResource *resource; + + OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceInterfaces")); + + VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM); + VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM); + + *numResourceInterfaces = 0; + resource = findResource((OCResource *) handle); + if (resource) { + pointer = resource->rsrcInterface; + while (pointer) { + *numResourceInterfaces = *numResourceInterfaces + 1; + pointer = pointer->next; + } + } + return OC_STACK_OK; +} + +/** + * Get name of resource interface of the resource. + * + * @param handle - handle of resource + * @param index - index of resource, 0 to Count - 1 + * + * @return + * resource interface name - if resource found + * NULL - resource not found + */ +const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index) { + OCResourceInterface *resourceInterface; + + OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceName")); + + resourceInterface = findResourceInterfaceAtIndex(handle, index); + if (resourceInterface) { + return resourceInterface->name; + } + return (const char *) NULL; +} + +/** + * Get resource handle from the collection resource by index. + * + * @param collectionHandle - handle of collection resource + * @param index - index of contained resource, 0 to Count - 1 + * + * @return + * handle to resource - if resource found + * NULL - resource not found + */ +OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle, + uint8_t index) { + OCResource *resource; + + OC_LOG(INFO, TAG, PCF("Entering OCGetContainedResource")); + + if (index >= MAX_CONTAINED_RESOURCES) { + return NULL; + } + + resource = findResource((OCResource *) collectionHandle); + if (!resource) { + return NULL; + } + + return resource->rsrcResources[index]; +} + +/** + * Bind an entity handler to the resource. + * + * @param handle - handle to the resource that the contained resource is to be bound + * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ +OCStackResult OCBindResourceHandler(OCResourceHandle handle, + OCEntityHandler entityHandler) { + OCResource *resource; + + OC_LOG(INFO, TAG, PCF("Entering OCBindResourceHandler")); + + // Validate parameters + VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM); + //VERIFY_NON_NULL(entityHandler, ERROR, OC_STACK_INVALID_PARAM); + + // Use the handle to find the resource in the resource linked list + resource = findResource((OCResource *)handle); + if (!resource) { + OC_LOG(ERROR, TAG, PCF("Resource not found")); + return OC_STACK_ERROR; + } + + // Bind the handler + resource->entityHandler = entityHandler; + + #ifdef WITH_PRESENCE + if(presenceResource.handle) + { + ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom(); + SendPresenceNotification(resource->rsrcType); + } + #endif + + return OC_STACK_OK; +} + +/** + * Get the entity handler for a resource. + * + * @param handle - handle of resource + * + * @return + * entity handler - if resource found + * NULL - resource not found + */ +OCEntityHandler OCGetResourceHandler(OCResourceHandle handle) { + OCResource *resource; + + OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandler")); + + // Use the handle to find the resource in the resource linked list + resource = findResource((OCResource *)handle); + if (!resource) { + OC_LOG(ERROR, TAG, PCF("Resource not found")); + return NULL; + } + + // Bind the handler + return resource->entityHandler; +} + +void incrementSequenceNumber(OCResource * resPtr) +{ + // Increment the sequence number + resPtr->sequenceNum += 1; + if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER) + { + resPtr->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER+1; + } + return; +} + +#ifdef WITH_PRESENCE +/** + * Notify Presence subscribers that a resource has been modified + * + * @param resourceType - Handle to the resourceType linked list of resource + * that was modified. + * @param qos - Quality Of Service + * + */ +OCStackResult SendPresenceNotification(OCResourceType *resourceType) +{ + OCResource *resPtr = NULL; + OCStackResult result; + OCMethod method = OC_REST_PRESENCE; + uint32_t maxAge = 0; + resPtr = findResource((OCResource *) presenceResource.handle); + if(NULL == resPtr) + { + return OC_STACK_NO_RESOURCE; + } + if((((OCResource *) presenceResource.handle)->resourceProperties) & OC_ACTIVE) + { + maxAge = presenceResource.presenceTTL; + } + else + { + maxAge = 0; + } + + result = SendAllObserverNotification(method, resPtr, maxAge, resourceType, OC_LOW_QOS); + return result; +} +#endif + +/** + * Notify observers that an observed value has changed. + * + * @param handle - handle of resource + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_NO_RESOURCE - invalid resource handle + * OC_STACK_NO_OBSERVERS - no more observers intrested in resource + */ +OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos) { + + OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers")); + + OCResource *resPtr = NULL; + OCStackResult result; + OCMethod method = OC_REST_NOMETHOD; + uint32_t maxAge = 0; + + OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers")); + #ifdef WITH_PRESENCE + if(handle == presenceResource.handle) + { + return OC_STACK_OK; + } + #endif // WITH_PRESENCE + VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR); + + // Verify that the resource exists + resPtr = findResource ((OCResource *) handle); + if (NULL == resPtr) + { + return OC_STACK_NO_RESOURCE; + } + else + { + //only increment in the case of regular observing (not presence) + incrementSequenceNumber(resPtr); + method = OC_REST_OBSERVE; + maxAge = MAX_OBSERVE_AGE; + #ifdef WITH_PRESENCE + result = SendAllObserverNotification (method, resPtr, maxAge, NULL, qos); + #else + result = SendAllObserverNotification (method, resPtr, maxAge, qos); + #endif + return result; + } +} + +OCStackResult +OCNotifyListOfObservers (OCResourceHandle handle, + OCObservationId *obsIdList, + uint8_t numberOfIds, + unsigned char *notificationJSONPayload, + OCQualityOfService qos) +{ + OC_LOG(INFO, TAG, PCF("Entering OCNotifyListOfObservers")); + + OCResource *resPtr = NULL; + //TODO: we should allow the server to define this + uint32_t maxAge = MAX_OBSERVE_AGE; + + VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR); + VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR); + VERIFY_NON_NULL(notificationJSONPayload, ERROR, OC_STACK_ERROR); + + // Verify that the resource exists + resPtr = findResource ((OCResource *) handle); + if (NULL == resPtr || myStackMode == OC_CLIENT) + { + return OC_STACK_NO_RESOURCE; + } + else + { + incrementSequenceNumber(resPtr); + } + return (SendListObserverNotification(resPtr, obsIdList, numberOfIds, + notificationJSONPayload, maxAge, qos)); +} + +/** + * Send a response to a request. + * The response can be a regular, slow, or block (i.e. a response that + * is too large to be sent in a single PDU and must span multiple transmissions) + * + * @param response - pointer to structure that contains response parameters + * + * @return + * OC_STACK_OK - No errors; Success + * OC_STACK_INVALID_PARAM - Invalid pointer to OCServerResponse + * OC_STACK_INVALID_REQUEST_HANDLE - Request handle not found + * OC_STACK_PERSISTENT_BUFFER_REQUIRED - Block transfer needed for response, so a + * persistent response buffer is necessary + */ +OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse) +{ + OCStackResult result = OC_STACK_ERROR; + OCServerRequest *serverRequest = NULL; + + OC_LOG(INFO, TAG, PCF("Entering OCDoResponse")); + + // Validate input parameters + VERIFY_NON_NULL(ehResponse, ERROR, OC_STACK_INVALID_PARAM); + VERIFY_NON_NULL(ehResponse->requestHandle, ERROR, OC_STACK_INVALID_PARAM); + + // TODO: Placeholder for creating a response entry when implementing + // block transfer feature + + // If a response payload is present, check if block transfer is required + if (ehResponse->payload && OCIsPacketTransferRequired(NULL, + (const char *)ehResponse->payload, ehResponse->payloadSize)) + { + OC_LOG(INFO, TAG, PCF("Block transfer required")); + + // Persistent response buffer is needed for block transfer + if (!ehResponse->persistentBufferFlag) + { + OC_LOG(WARNING, TAG, PCF("Persistent response buffer required")); + return OC_STACK_PERSISTENT_BUFFER_REQUIRED; + } + // TODO: Placeholder for block transfer handling + // TODO: Placeholder for setting the the response handle in the OCServerResponse struct + // when implementing the block transfer feature + } + else + { + // Normal response + + // Get pointer to request info + serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle); + if(serverRequest) + { + result = serverRequest->ehResponseHandler(ehResponse); + } + } + return result; +} + +/** + * Cancel a response. Applies to a block response + * + * @param responseHandle - response handle set by stack in OCServerResponse after + * OCDoResponse is called + * + * @return + * OC_STACK_OK - No errors; Success + * OC_STACK_INVALID_PARAM - The handle provided is invalid. + */ +OCStackResult OCCancelResponse(OCResponseHandle responseHandle) +{ + OCStackResult result = OC_STACK_NOTIMPL; + + OC_LOG(INFO, TAG, PCF("Entering OCCancelResponse")); + + // TODO: validate response handle + + return result; +} + +//----------------------------------------------------------------------------- +// Private internal function definitions +//----------------------------------------------------------------------------- +/** + * Generate handle of OCDoResource invocation for callback management. + */ +static OCDoHandle GenerateInvocationHandle() +{ + OCDoHandle handle = NULL; + // Generate token here, it will be deleted when the transaction is deleted + handle = (OCDoHandle) OCMalloc(sizeof(uint8_t[MAX_TOKEN_LENGTH])); + if (handle) + { + OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[MAX_TOKEN_LENGTH])); + } + + return handle; +} +#ifdef WITH_PRESENCE +OCStackResult OCChangeResourceProperty(OCResourceProperty * inputProperty, + OCResourceProperty resourceProperties, uint8_t enable) +{ + if (resourceProperties + > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW)) { + OC_LOG(ERROR, TAG, PCF("Invalid property")); + return OC_STACK_INVALID_PARAM; + } + if(!enable) + { + *inputProperty = (OCResourceProperty) (*inputProperty & ~(resourceProperties)); + } + else + { + *inputProperty = (OCResourceProperty) (*inputProperty | resourceProperties); + } + return OC_STACK_OK; +} +#endif + +/** + * Initialize resource data structures, variables, etc. + */ +OCStackResult initResources() { + OCStackResult result = OC_STACK_OK; + // Init application resource vars + headResource = NULL; + // Init Virtual Resources + #ifdef WITH_PRESENCE + presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL; + //presenceResource.token = OCGenerateCoAPToken(); + result = OCCreateResource(&presenceResource.handle, + OC_RSRVD_RESOURCE_TYPE_PRESENCE, + "core.r", + OC_PRESENCE_URI, + NULL, + OC_OBSERVABLE); + //make resource inactive + result = OCChangeResourceProperty( + &(((OCResource *) presenceResource.handle)->resourceProperties), + OC_ACTIVE, 0); + #endif + return result; +} + +/** + * Add a resource to the end of the linked list of resources. + * + * @param resource - resource to be added + */ +void insertResource(OCResource *resource) { + OCResource *pointer; + + if (!headResource) { + headResource = resource; + } else { + pointer = headResource; + + while (pointer->next) { + pointer = pointer->next; + } + pointer->next = resource; + } + resource->next = NULL; +} + +/** + * Find a resource in the linked list of resources. + * + * @param resource - resource to be found + * @return + * NULL - resource not found + * pointer to resource - pointer to resource that was found in the linked list + */ +OCResource *findResource(OCResource *resource) { + OCResource *pointer = headResource; + + while (pointer) { + if (pointer == resource) { + return resource; + } + pointer = pointer->next; + } + return NULL; +} + +void deleteAllResources() +{ + OCResource *pointer = headResource; + OCResource *temp; + + while (pointer) + { + temp = pointer->next; + #ifdef WITH_PRESENCE + if(pointer != (OCResource *) presenceResource.handle) + { + #endif // WITH_PRESENCE + deleteResource(pointer); + #ifdef WITH_PRESENCE + } + #endif // WITH_PRESENCE + pointer = temp; + } + + #ifdef WITH_PRESENCE + // Ensure that the last resource to be deleted is the presence resource. This allows for all + // presence notification attributed to their deletion to be processed. + deleteResource((OCResource *) presenceResource.handle); + #endif // WITH_PRESENCE +} + +/** + * Delete the resource from the linked list. + * + * @param resource - resource to be deleted + * @return + * 0 - error + * 1 - success + */ +int deleteResource(OCResource *resource) { + OCResource *prev = NULL; + OCResource *temp; + + temp = headResource; + while (temp) { + if (temp == resource) { + // Invalidate all Resource Properties. + resource->resourceProperties = (OCResourceProperty) 0; + #ifdef WITH_PRESENCE + if(resource != (OCResource *) presenceResource.handle) + { + #endif // WITH_PRESENCE + OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS); + #ifdef WITH_PRESENCE + } + + if(presenceResource.handle) + { + ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom(); + if(resource != (OCResource *) presenceResource.handle) + { + SendPresenceNotification(resource->rsrcType); + } + else + { + SendPresenceNotification(NULL); + } + } + #endif + + if (temp == headResource) { + headResource = temp->next; + } else { + prev->next = temp->next; + } + + deleteResourceElements(temp); + OCFree(temp); + return 1; + } else { + prev = temp; + temp = temp->next; + } + } + + return 0; +} + +/** + * Delete all of the dynamically allocated elements that were created for the resource. + * + * @param resource - specified resource + */ +void deleteResourceElements(OCResource *resource) { + if (!resource) { + return; + } + + // remove URI + OCFree(resource->uri); + + // Delete resourcetype linked list + deleteResourceType(resource->rsrcType); + + // Delete resourceinterface linked list + deleteResourceInterface(resource->rsrcInterface); +} + +/** + * Delete all of the dynamically allocated elements that were created for the resource type. + * + * @param resourceType - specified resource type + */ +void deleteResourceType(OCResourceType *resourceType) { + OCResourceType *pointer = resourceType; + OCResourceType *next; + + while (pointer) { + next = pointer->next; + OCFree(pointer->resourcetypename); + OCFree(pointer); + pointer = next; + } +} + +/** + * Delete all of the dynamically allocated elements that were created for the resource interface. + * + * @param resourceInterface - specified resource interface + */ +void deleteResourceInterface(OCResourceInterface *resourceInterface) { + OCResourceInterface *pointer = resourceInterface; + OCResourceInterface *next; + + while (pointer) { + next = pointer->next; + OCFree(pointer->name); + OCFree(pointer); + pointer = next; + } +} + +/** + * Insert a resource type into a resource's resource type linked list. + * + * @param resource - resource where resource type is to be inserted + * @param resourceType - resource type to be inserted + */ +void insertResourceType(OCResource *resource, OCResourceType *resourceType) { + OCResourceType *pointer; + + if (resource && !resource->rsrcType) { + resource->rsrcType = resourceType; + } else { + if(resource) + { + pointer = resource->rsrcType; + } + else + { + pointer = resourceType; + } + while (pointer->next) { + pointer = pointer->next; + } + pointer->next = resourceType; + } + resourceType->next = NULL; +} + +/** + * Get a resource type at the specified index within a resource. + * + * @param handle - handle of resource + * @param index - index of resource type + * + * @return + * resourcetype - if found + * NULL - not found + */ +OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index) { + OCResource *resource; + OCResourceType *pointer; + uint8_t i; + + // Find the specified resource + resource = findResource((OCResource *) handle); + if (!resource) { + return NULL; + } + + // Make sure a resource has a resourcetype + if (!resource->rsrcType) { + return NULL; + } + + // Iterate through the list + pointer = resource->rsrcType; + i = 0; + while ((i < index) && pointer) { + i++; + pointer = pointer->next; + } + return pointer; +} + +/** + * Finds a resource type in an OCResourceType link-list. + * + * @param resourceTypeList - the link-list to be searched through + * @param resourceTypeName - the key to search for + * + * @return + * resourceType that matches the key (ie. resourceTypeName) + * NULL - either an invalid parameter or this function was unable to find the key. + */ +OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName) +{ + if(resourceTypeList && resourceTypeName) + { + OCResourceType * rtPointer = resourceTypeList; + while(resourceTypeName && rtPointer) + { + if(rtPointer->resourcetypename && + strcmp(resourceTypeName, (const char *) + (rtPointer->resourcetypename)) == 0) + { + break; + } + rtPointer = rtPointer->next; + } + return rtPointer; + } + return NULL; +} +/** + * Insert a resource interface into a resource's resource interface linked list. + * + * @param resource - resource where resource interface is to be inserted + * @param resourceInterface - resource interface to be inserted + */ +void insertResourceInterface(OCResource *resource, + OCResourceInterface *resourceInterface) { + OCResourceInterface *pointer; + + if (!resource->rsrcInterface) { + resource->rsrcInterface = resourceInterface; + } else { + pointer = resource->rsrcInterface; + while (pointer->next) { + pointer = pointer->next; + } + pointer->next = resourceInterface; + } + resourceInterface->next = NULL; +} + +/** + * Get a resource interface at the specified index within a resource. + * + * @param handle - handle of resource + * @param index - index of resource interface + * + * @return + * resourceinterface - if found + * NULL - not found + */ +OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle, + uint8_t index) { + OCResource *resource; + OCResourceInterface *pointer; + uint8_t i = 0; + + // Find the specified resource + resource = findResource((OCResource *) handle); + if (!resource) { + return NULL; + } + + // Make sure a resource has a resourceinterface + if (!resource->rsrcInterface) { + return NULL; + } + + // Iterate through the list + pointer = resource->rsrcInterface; + + while ((i < index) && pointer) { + i++; + pointer = pointer->next; + } + return pointer; +} + +/** + * Determine if a request/response must be sent in a block transfer because it is too large to be + * sent in a single PDU. This function can be used for either a request or a response + * + * @param request - NULL or pointer to request + * @param response - NULL or pointer to response + * @param size - 0 or size of the request/response. If 0, strlen is used for determining + * the length of the request/response + * + * @return + * 0 - packet transfer NOT required (i.e. normal request/response) + * 1 - packet transfer required (i.e. block transfer needed) + */ +uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size) +{ + uint8_t result = 0; + + // Determine if we are checking a request or a response + if (request) + { + // If size is greater than 0, use it for the request size value, otherwise + // assume request is null terminated and use strlen for size value + if ((size > MAX_REQUEST_LENGTH) || (strlen(request) > MAX_REQUEST_LENGTH)) + { + result = 1; + } + } + else if (response) + { + // If size is greater than 0, use it for the response size value, otherwise + // assume response is null terminated and use strlen for size value + if ((size > MAX_RESPONSE_LENGTH) || (strlen(response) > MAX_RESPONSE_LENGTH)) + { + result = 1; + } + } + return result; +} + +/** + * Retrieves a resource type based upon a uri string if the uri string contains only just one + * resource attribute (and that has to be of type "rt"). + * + * @remark This API malloc's memory for the resource type and newURI. Do not malloc resourceType + * or newURI before passing in. + * + * @param uri - Valid URI for "requiredUri" parameter to OCDoResource API. + * @param resourceType - The resource type to be populated; pass by reference. + * @param newURI - Return URI without resourceType appended to the end of it. This is used to + * ensure that the uri parameter is not modified; pass by reference. + * + * @return + * OC_STACK_INVALID_URI - Returns this if the URI is invalid/NULL. + * OC_STACK_INVALID_PARAM - Returns this if the resourceType parameter is invalid/NULL. + * OC_STACK_OK - Success + */ +OCStackResult getResourceType(const char * uri, unsigned char** resourceType, char ** newURI) +{ + if(!uri) + { + return OC_STACK_INVALID_URI; + } + if(!resourceType || !newURI) + { + return OC_STACK_INVALID_PARAM; + } + char * leftToken = NULL; + char * tempURI = (char *) OCMalloc(strlen(uri) + 1); + if(!tempURI) + { + goto exit; + } + strcpy(tempURI, uri); + char* strTokPtr; + leftToken = strtok_r((char *)tempURI, "?", &strTokPtr); + + while(leftToken != NULL) + { + if(strncmp(leftToken, "rt=", 3) == 0) + { + *resourceType = (unsigned char *) OCMalloc(strlen(leftToken)-3); + if(!*resourceType) + { + goto exit; + } + strcpy((char *)*resourceType, ((const char *)&leftToken[3])); + break; + } + leftToken = strtok_r(NULL, "?", &strTokPtr); + } + + *newURI = tempURI; + + return OC_STACK_OK; + + exit: + return OC_STACK_NO_MEMORY; +} diff --git a/resource/csdk/stack/src/oicgroup.c b/resource/csdk/stack/src/oicgroup.c new file mode 100644 index 000000000..b9f70aca3 --- /dev/null +++ b/resource/csdk/stack/src/oicgroup.c @@ -0,0 +1,864 @@ +//****************************************************************** +// +// Copyright 2014 Samsung Electronics All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#define _POSIX_C_SOURCE 200112L +#include + +#include "cJSON.h" +#include "ocmalloc.h" +#include "oicgroup.h" +#include "ocresource.h" +#include "occollection.h" + +#define TAG PCF("OICGROUP") + +#define DESC_DELIMITER "\"" +#define ACTION_DELIMITER "*" +#define ATTR_DELIMITER "|" + +typedef struct aggregatehandleinfo +{ + OCServerRequest *ehRequest; + OCDoHandle required; + OCResource *collResource; + + struct aggregatehandleinfo *next; +} ClientRequstInfo; + +// unsigned int nHandleIdx = 0; +// ClientRequstInfo g_AggregateResponseHandle[10]; + +ClientRequstInfo *clientRequstList = NULL; + +void AddClientRequestInfo(ClientRequstInfo **head, ClientRequstInfo* add) +{ + ClientRequstInfo *tmp = NULL; + + if (*head != NULL) + { + tmp = *head; + + while (tmp->next) + { + tmp = tmp->next; + } + tmp->next = add; + } + else + { + *head = add; + } +} + +ClientRequstInfo* GetClientRequestInfo(ClientRequstInfo *head, OCDoHandle handle) +{ + ClientRequstInfo *tmp = NULL; + + tmp = head; + + if (tmp) + { + while (tmp) + { +// printf("%p :: %p\n", tmp->required, handle); + if (tmp->required == handle) + { + break; + } + + tmp = tmp->next; + } + + return tmp; + } + return NULL; +} + +void RemoveClientRequestInfo(ClientRequstInfo **head, ClientRequstInfo* del) +{ + ClientRequstInfo *tmp = NULL; + + if (*head == del) + { + *head = (*head)->next; + } + else + { + tmp = *head; + while (tmp->next && (tmp->next != del)) + { + tmp = tmp->next; + } + if (tmp->next) + { + tmp->next = del->next; + } + } +} + + + +void AddCapability(OCCapability** head, OCCapability* node) +{ + OCCapability *pointer = *head; + if (NULL == pointer) + { + *head = node; + } + else + { + while (pointer->next != NULL) + { + pointer = pointer->next; + } + + pointer->next = node; + } +} + +void AddAction(OCAction** head, OCAction* node) +{ + OCAction *pointer = *head; + if (NULL == pointer) + { + *head = node; + } + else + { + + while (pointer->next != NULL) + { + pointer = pointer->next; + } + + pointer->next = node; + } +} + +void AddActionSet(OCActionSet **head, OCActionSet* node) +{ + OCActionSet *pointer = *head; + if (NULL == pointer) + { + *head = node; + } + else + { + + while (pointer->next != NULL) + { + pointer = pointer->next; + } + + pointer->next = node; + } +} + +void DeleteCapability(OCCapability *del) +{ + free(del->capability); + del->capability = NULL; + free(del->status); + del->status = NULL; +} + +void DeleteAction(OCAction** action) +{ + OCCapability* pointer = (*action)->head; + OCCapability* pDel = NULL; + + while (pointer) + { + pDel = pointer; + pointer = pointer->next; + + DeleteCapability(pDel); + pDel->next = NULL; + } + OCFree((*action)->resourceUri); + (*action)->resourceUri = NULL; + (*action)->next = NULL; +} + +void DeleteActionSet(OCActionSet** actionset) +{ + OCAction* pointer = (*actionset)->head; + OCAction* pDel = NULL; + + while (pointer) + { + pDel = pointer; + pointer = pointer->next; + + DeleteAction(&pDel); + pDel->next = NULL; + } + + OCFree((*actionset)->actionsetName); + (*actionset)->head = NULL; +} + +OCStackResult FindAndDeleteActionSet(OCResource **resource, const char * actionsetName) +{ + + if (*resource != NULL) + { + + OCActionSet *pointer = NULL; + OCActionSet *pDel = NULL; + + pointer = (*resource)->actionsetHead; + + if (pointer == NULL) + { + return OC_STACK_ERROR; + } + else + { + if (strcmp(pointer->actionsetName, actionsetName) == 0) + { + if (pointer->next != NULL) + (*resource)->actionsetHead = pointer->next; + else + (*resource)->actionsetHead = NULL; + + DeleteActionSet(&pointer); + + } + else if (pointer->next != NULL) + { + while (pointer) + { + if (pointer->next != NULL) + { + if (strcmp(pointer->next->actionsetName, actionsetName) == 0) + { + pDel = pointer->next; + pointer->next = pointer->next->next; + + DeleteActionSet(&pDel); + } + } + } + } + + return OC_STACK_OK; + } + + } + + return OC_STACK_ERROR; +} + +OCStackResult DeleteActionSets(OCResource** resource) +{ + OCActionSet *pointer = (*resource)->actionsetHead; + OCActionSet *pDel = pointer; + + while (pointer) + { + pDel = pointer; + pointer = pointer->next; + + DeleteActionSet(&pDel); + pDel->next = NULL; + } + + (*resource)->actionsetHead = NULL; + return OC_STACK_OK; +} + +OCStackResult GetActionSet(const char *actionName, OCActionSet *head, OCActionSet** actionset) +{ + OCActionSet *pointer = head; + + while (pointer) + { + if (strcmp(pointer->actionsetName, actionName) == 0) + { + *actionset = pointer; + return OC_STACK_OK; + } + + pointer = pointer->next; + } + + return OC_STACK_ERROR; + +} + +OCStackResult GetActionSetFromString(OCResource **resource, unsigned char *request, char** method, + char **actionsetName) +{ + char *acitonRequest; + char *iterTokenPtr = NULL; + char *iterToken = NULL; + char *description = NULL; + char *iterDescPtr = NULL; + + char *attributes = NULL; + char *iterAttrbutesPtr = NULL; + + char *attr = NULL; + char *iterAttrPtr = NULL; + + OCActionSet* actionset = NULL; + OCAction* action = NULL; + + acitonRequest = (char *) OCMalloc(strlen((char *) request) + 1); + strncpy(acitonRequest, (char *) request, strlen((char *) request) + 1); + + //printf("\t%s\n", acitonRequest); + if (acitonRequest != NULL) + { + iterToken = (char *) strtok_r(acitonRequest, DESC_DELIMITER, &iterTokenPtr); + + while (iterToken != NULL) + { + if (strcmp(iterToken, "ActionSet") == 0) + { // if iterToken is ActionSet, will be created and added a new action set. + + *method = (char *) OCMalloc(strlen(iterToken) + 1); + strncpy(*method, iterToken, strlen(iterToken) + 1); + + //GetActionName(iterToken, &actionsetName); + // printf("%s\n", iterToken, &iterTokenPtr); + iterToken = (char *) strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr); // it is mean ':'. + // printf("%s\n", iterToken); + iterToken = (char *) strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr); // it is body of action description. + // printf("%s\n", iterToken); + + // printf("DESC :: %s\n", iterToken); + description = (char *) OCMalloc(strlen(iterToken) + 1); + strncpy(description, iterToken, strlen(iterToken) + 1); + // printf("DESC Copied :: %s\n", description); + + // Find the action name from description. + iterDescPtr = NULL; + iterToken = (char *) strtok_r(description, ACTION_DELIMITER, &iterDescPtr); + //while(iterToken != NULL) + if (iterToken != NULL) + { + if (*actionsetName != NULL) + { + // printf("ERROR :: ACTIONSET NAME as ActionSet(%s)\n", iterToken); + return OC_STACK_ERROR; // ERROR OCCURED. + } + else + { + // Actionset name. + // printf("ACTION SET NAME :: %s\n", iterToken); + *actionsetName = (char *) OCMalloc(strlen(iterToken) + 1); + + strncpy(*actionsetName, iterToken, strlen(iterToken) + 1); + // printf("ACTION SET NAME :: %s\n", *actionsetName); + // break; + } + + iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterDescPtr); + } + else + { + return OC_STACK_ERROR; + + } // end Action Set Name. + + // New ActionSet Add to OCResource's ActionSet list. + // 1. Allocate a new pointer for actionset. + actionset = (OCActionSet*) OCMalloc(sizeof(OCActionSet)); + // 2. Initiate actionset. + memset(actionset, 0, sizeof(OCActionSet)); + actionset->actionsetName = (char *) OCMalloc(strlen(*actionsetName) + 1); + strncpy(actionset->actionsetName, *actionsetName, strlen(*actionsetName) + 1); + // printf("ACTION SET NAME :: %s\n", actionset->actionsetName); + + while (iterToken != NULL) + { + action = (OCAction *) OCMalloc(sizeof(OCAction)); + memset(action, 0, sizeof(OCAction)); + + // printf("ATTR Copied :: %s\n", iterToken); + attributes = (char *) OCMalloc(strlen(iterToken) + 1); + strncpy(attributes, iterToken, strlen(iterToken) + 1); + // printf("ATTR Copied :: %s\n", attributes); + + iterToken = (char *) strtok_r(attributes, ATTR_DELIMITER, &iterAttrbutesPtr); + while (iterToken != NULL) + { + attr = (char *) OCMalloc(strlen(iterToken) + 1); + strncpy(attr, iterToken, strlen(iterToken) + 1); + + iterToken = (char *) strtok_r(attr, "=", &iterAttrPtr); + while (iterToken != NULL) + { + // Find the URI from description. + if (strcmp(iterToken, "uri") == 0) + { + iterToken = (char *) strtok_r(NULL, "=", &iterAttrPtr); + //printf("uri :: %s\n", iterToken); + action->resourceUri = (char *) OCMalloc(strlen(iterToken) + 1); + strncpy(action->resourceUri, iterToken, strlen(iterToken) + 1); + } + else + { + OCCapability* capa = (OCCapability*) OCMalloc(sizeof(OCCapability)); + memset(capa, 0, sizeof(OCCapability)); + //printf("%s :: ", iterToken); + capa->capability = (char *) OCMalloc(strlen(iterToken) + 1); + strncpy(capa->capability, iterToken, strlen(iterToken) + 1); + iterToken = (char *) strtok_r(NULL, "=", &iterAttrPtr); + //printf("%s\n", iterToken); + capa->status = (char *) OCMalloc(strlen(iterToken) + 1); + strncpy(capa->status, iterToken, strlen(iterToken) + 1); + + AddCapability(&action->head, capa); + } + + iterToken = (char *) strtok_r(NULL, "=", &iterAttrPtr); + } + + iterToken = (char *) strtok_r(NULL, ATTR_DELIMITER, &iterAttrbutesPtr); + } // End of Action + + AddAction(&actionset->head, action); + + iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterDescPtr); + } + + // 3. Add the pointer OCResource's ActionSet list. + AddActionSet(&(*resource)->actionsetHead, actionset); + return OC_STACK_OK; + } + else if (strcmp(iterToken, "DoAction") == 0 || strcmp(iterToken, "DelActionSet") == 0 + || strcmp(iterToken, "GetActionSet") == 0) + { + *method = (char *) OCMalloc(strlen(iterToken) + 1); + strncpy(*method, iterToken, strlen(iterToken) + 1); + + iterToken = (char *) strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr); // it is mean ':'. + // printf("%s\n", iterToken); + iterToken = (char *) strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr); // it is body of action description. + // printf("%s\n", iterToken); + + description = (char *) OCMalloc(strlen(iterToken) + 1); + strncpy(description, iterToken, strlen(iterToken) + 1); + + // Find the action name from description. + iterDescPtr = NULL; + iterToken = (char *) strtok_r(description, ACTION_DELIMITER, &iterDescPtr); + if (iterToken != NULL) + { + if (*actionsetName != NULL) + { + // printf("ERROR :: ACTIONSET NAME as ActionSet(%s)\n", iterToken); + return OC_STACK_ERROR; // ERROR OCCURED. + } + else + { + // Actionset name. + // printf("ACTION SET NAME :: %s\n", iterToken); + *actionsetName = (char *) OCMalloc(strlen(iterToken) + 1); + + strncpy(*actionsetName, iterToken, strlen(iterToken) + 1); + // printf("ACTION SET NAME :: %s\n", *actionsetName); + } + + iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterDescPtr); + return OC_STACK_OK; + } + else + { + return OC_STACK_ERROR; + + } // end Action Set Name. + break; + } + + iterToken = (char *) strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr); + } + } + + return OC_STACK_ERROR; +} + +OCStackResult GetStringFromActionSet(OCActionSet* actionset, char** desc) +{ + char temp[1024] = + { 0 }; + int remaining = 1023; + + // OCActionSet *as = resource->actionsetHead; + // while(as != NULL) + // { + printf("\n\n\nAction Set Name :: %s\n", actionset->actionsetName); + OCAction *action = actionset->head; + + if (remaining >= strlen(actionset->actionsetName) + 1) + { + strcat(temp, actionset->actionsetName); + remaining -= strlen(actionset->actionsetName); + strcat(temp, "*"); + remaining--; + } + else + { + return OC_STACK_ERROR; + } + + while (action != NULL) + { + printf("\tURI :: %s\n", action->resourceUri); + strcat(temp, "uri="); + remaining -= strlen("uri="); + strcat(temp, action->resourceUri); + remaining -= strlen(action->resourceUri); + strcat(temp, "|"); + remaining--; + + OCCapability *capas = action->head; + while (capas != NULL) + { + printf("\t\t%s = %s\n", capas->capability, capas->status); + strcat(temp, capas->capability); + remaining -= strlen(capas->capability); + strcat(temp, "="); + remaining--; + strcat(temp, capas->status); + remaining -= strlen(capas->capability); + + capas = capas->next; + if (capas != NULL) + { + strcat(temp, "|"); + } + } + + action = action->next; + if (action != NULL) + { + strcat(temp, "*"); + remaining--; + } + } + // as = as->next; + // } + + *desc = (char *) OCMalloc(1024 - remaining); + strcpy(*desc, temp); + // printf("\t\tPlain Text = %s(%i)\n", *desc, 1024 - remaining); + + return OC_STACK_OK; +} + +OCStackApplicationResult ActionSetCB(void* context, OCDoHandle handle, + OCClientResponse* clientResponse) +{ + printf("\n\n\tcallback is called\n\n"); + + ClientRequstInfo *info = GetClientRequestInfo(clientRequstList, handle); + + if (info) + { + int idx; + + unsigned char *responseJson; + responseJson = (unsigned char *) OCMalloc( + (unsigned int) (strlen((char *) clientResponse->resJSONPayload) + 1)); + + // We need the body of response. + // Copy the body from the response + strcpy((char *) responseJson, ((char *) clientResponse->resJSONPayload + + OC_JSON_PREFIX_LEN)); + idx = strlen((char *) responseJson) - OC_JSON_SUFFIX_LEN; + // And insert NULL at the end of body. + (responseJson[idx]) = 0; + + OCEntityHandlerResponse response = { 0 }; + response.ehResult = OC_EH_OK; + response.payload = responseJson; + response.payloadSize = (unsigned int) strlen((char *) responseJson) + 1; + response.persistentBufferFlag = 0; + response.requestHandle = (OCRequestHandle) info->ehRequest; + response.resourceHandle = (OCResourceHandle) info->collResource; + + OCDoResponse(&response); + + RemoveClientRequestInfo(&clientRequstList, info); + OCFree(responseJson); + } + + // g_AggregateResponseHandle + + return OC_STACK_KEEP_TRANSACTION; +} + +void ActionSetCD(void *context) +{ + // printf("\n\t\tCD is called\n"); + + // free( context ); +} + +OCStackResult BuildActionJSON(OCAction* action, unsigned char* bufferPtr, uint16_t *remaining) +{ + OCStackResult ret = OC_STACK_ERROR; + cJSON *json; + cJSON *body; + + char *jsonStr; + uint16_t jsonLen; + + OC_LOG(INFO, TAG, PCF("Entering BuildActionJSON")); + json = cJSON_CreateObject(); + + cJSON_AddItemToObject(json, "rep", body = cJSON_CreateObject()); + + OCCapability* pointerCapa = action->head; + while (pointerCapa) + { + cJSON_AddStringToObject(body, pointerCapa->capability, pointerCapa->status); + pointerCapa = pointerCapa->next; + } + + jsonStr = cJSON_PrintUnformatted(json); + + jsonLen = strlen(jsonStr); + if (jsonLen < *remaining) + { + strcat((char*) bufferPtr, jsonStr); + *remaining -= jsonLen; + bufferPtr += jsonLen; + ret = OC_STACK_OK; + } + + cJSON_Delete(json); + free(jsonStr); + + return ret; +} + +unsigned int GetNumOfTargetResource(OCAction *actionset) +{ + int numOfREsource = 0; + + OCAction *pointerAction = actionset; + + while (pointerAction != NULL) + { + numOfREsource++; + pointerAction = pointerAction->next; + } + + return numOfREsource; +} + +OCStackResult SendAction(OCDoHandle *handle, const char *targetUri, const unsigned char *action) +{ + OCCallbackData cbdata = + { 0 }; + cbdata.cb = &ActionSetCB; + cbdata.cd = &ActionSetCD; + cbdata.context = (void *) 0x99; + + return OCDoResource(handle, OC_REST_PUT, targetUri, + //temp->rsrcType->resourcetypename, + NULL, (char *) action, OC_NA_QOS, &cbdata, NULL, 0); +} + +OCStackResult BuildCollectionGroupActionJSONResponse(OCMethod method/*OCEntityHandlerFlag flag*/, + OCResource *resource, OCEntityHandlerRequest *ehRequest) +{ + OCStackResult stackRet = OC_STACK_ERROR; + + OC_LOG(INFO, TAG, PCF("Group Action is requested.")); + // if (stackRet == OC_STACK_OK) + { + + char *doWhat = NULL; + char *actionName = NULL; + + size_t bufferLength = 0; + unsigned char buffer[MAX_RESPONSE_LENGTH] = + { 0 }; + unsigned char *bufferPtr = NULL; + + bufferPtr = buffer; + + OCResource * collResource = (OCResource *) ehRequest->resource; + + char *jsonResponse; + + cJSON *json; + cJSON *format; + + if (method == OC_REST_PUT) + { + json = cJSON_CreateObject(); + cJSON_AddStringToObject(json, "href", resource->uri); + cJSON_AddItemToObject(json, "rep", format = cJSON_CreateObject()); + + OC_LOG(INFO, TAG, PCF("Group Action[PUT].")); + + unsigned char *actionPtr = (unsigned char *) ehRequest->reqJSONPayload; + GetActionSetFromString(&resource, actionPtr, &doWhat, &actionName); + + if (strcmp(doWhat, "DelActionSet") == 0) + { + if (FindAndDeleteActionSet(&resource, actionName) == OC_STACK_OK) + { + stackRet = OC_STACK_OK; + } + else + { + stackRet = OC_STACK_ERROR; + } + } + + jsonResponse = cJSON_Print(json); + cJSON_Delete(json); + + strcat((char *) bufferPtr, jsonResponse); + + bufferLength = strlen((const char *) buffer); + if (bufferLength > 0) + { + OCEntityHandlerResponse response = + { 0 }; + response.ehResult = OC_EH_OK; + response.payload = buffer; + response.payloadSize = bufferLength + 1; + response.persistentBufferFlag = 0; + response.requestHandle = (OCRequestHandle) ehRequest->requestHandle; + response.resourceHandle = (OCResourceHandle) collResource; + stackRet = OCDoResponse(&response); + } + + stackRet = OC_STACK_OK; + } + + if (method == OC_REST_POST) + { + OC_LOG(INFO, TAG, PCF("Group Action[POST].")); + + OCActionSet *actionset = NULL; + unsigned char *actionPtr = (unsigned char *) ehRequest->reqJSONPayload; + + GetActionSetFromString(&resource, actionPtr, &doWhat, &actionName); + + json = cJSON_CreateObject(); + cJSON_AddStringToObject(json, "href", resource->uri); + + if (strcmp(doWhat, "DoAction") == 0) + { + if (GetActionSet(actionName, resource->actionsetHead, &actionset) != OC_STACK_OK) + { + OC_LOG(INFO, TAG, PCF("ERROR")); + stackRet = OC_STACK_ERROR; + } + + if (actionset == NULL) + { + OC_LOG(INFO, TAG, PCF("ERROR")); + stackRet = OC_STACK_ERROR; + } + else + { + + OCAction *pointerAction = actionset->head; + + unsigned int num = GetNumOfTargetResource(pointerAction); + + ((OCServerRequest *) ehRequest->requestHandle)->ehResponseHandler = + HandleAggregateResponse; + ((OCServerRequest *) ehRequest->requestHandle)->numResponses = num + 1; + +// printf("ActionSet Name :: %s\n", actionset->actionsetName); + while (pointerAction != NULL) + { + unsigned char actionDesc[MAX_RESPONSE_LENGTH] = { 0 }; + unsigned char* actionDescPtr = actionDesc; + uint16_t remaining = MAX_RESPONSE_LENGTH; + + strcpy((char *) actionDescPtr, (const char *) OC_JSON_PREFIX); + BuildActionJSON(pointerAction, actionDescPtr, &remaining); + strcat((char *) actionDescPtr, (const char *) OC_JSON_SUFFIX); + + ClientRequstInfo *info = (ClientRequstInfo *) OCMalloc( + sizeof(ClientRequstInfo)); + memset(info, 0, sizeof(ClientRequstInfo)); + + info->collResource = resource; + info->ehRequest = (OCServerRequest *) ehRequest->requestHandle; + + SendAction(&info->required, pointerAction->resourceUri, actionDescPtr); + + AddClientRequestInfo(&clientRequstList, info); + + + pointerAction = pointerAction->next; + } + + + stackRet = OC_STACK_OK; + } + } + else if (strcmp(doWhat, "GetActionSet") == 0) + { + char *plainText = NULL; + OCActionSet *actionset = NULL; + + cJSON_AddItemToObject(json, "rep", format = cJSON_CreateObject()); + GetActionSet(actionName, resource->actionsetHead, &actionset); + if (actionset != NULL) + { + GetStringFromActionSet(actionset, &plainText); + + if (plainText != NULL) + { + cJSON_AddStringToObject(format, "ActionSet", plainText); + } + + stackRet = OC_STACK_OK; + } + } + + jsonResponse = cJSON_Print(json); + cJSON_Delete(json); + + strcat((char *) bufferPtr, jsonResponse); + + bufferLength = strlen((const char *) buffer); + if (bufferLength > 0) + { + OCEntityHandlerResponse response = + { 0 }; + response.ehResult = OC_EH_OK; + response.payload = buffer; + response.payloadSize = bufferLength + 1; + response.persistentBufferFlag = 0; + response.requestHandle = (OCRequestHandle) ehRequest->requestHandle; + response.resourceHandle = (OCResourceHandle) collResource; + stackRet = OCDoResponse(&response); + } + } + } + + return stackRet; +} diff --git a/resource/csdk/stack/test/README b/resource/csdk/stack/test/README new file mode 100644 index 000000000..0e3dfa478 --- /dev/null +++ b/resource/csdk/stack/test/README @@ -0,0 +1,52 @@ +//--------------------------------------------------------------------- +// NOTICE - Transition to SCONS +//--------------------------------------------------------------------- + +The IoTivity build system is transitioning to SCONS. Although the +makefiles are still available (until v1.0) and some developers are +still using them, they are currently no longer supported. To learn more +about building using SCONS see Readme.scons.txt in the repository root +directory. The build steps used in continuous integration can be found +in auto_build.sh which is also in the the repository root directory. + +//--------------------------------------------------------------------- + +stacktests.cpp is a unit test of the APIs in ocstack.c. +It uses Google Test for the unit tests. Note that +the unit tests are only to test the functionality of +ocstack.c. It is not a system or end-to-end test. + +Unit Test Requirements: + +1. Install Google Test on a Linux build machine +2. Create a file called "local.properties" in the + root/csdk/stack/test. local.properties is used + by the makefile and specifies the path to the + Google Test directory on the build machine. + Since local.properties is specific to each build + system, do not add local.properties to the code repo. + + local.properties should contain GTEST_DIR. + For example: + + + GTEST_DIR := /home/johndoe/utils/gtest-1.7.0 + +3. The unit test assumes that the "eth0" interface is + available. If not, the unit tests will FAIL. +4. To run the unit test, first build the C OCStack. + At the time of this writing this was done by running + + root/csdk/make deepclean + root/csdk/make BUILD=release *default + root/csdk/make BUILD=debug + +5. Next, build the ocstack + root/csdk/stack/test/make clean + root/csdk/stack/test/make BUILD=release *default + root/csdk/stack/test/make BUILD=debug + +6. Run the unit test by + root/csdk/stack/test/release/stacktests + root/csdk/stack/test/debug/stacktests + diff --git a/resource/csdk/stack/test/android/README b/resource/csdk/stack/test/android/README new file mode 100644 index 000000000..0c510978e --- /dev/null +++ b/resource/csdk/stack/test/android/README @@ -0,0 +1,26 @@ +//--------------------------------------------------------------------- +// NOTICE - Transition to SCONS +//--------------------------------------------------------------------- + +The IoTivity build system is transitioning to SCONS. Although the +makefiles are still available (until v1.0) and some developers are +still using them, they are currently no longer supported. To learn more +about building using SCONS see Readme.scons.txt in the repository root +directory. The build steps used in continuous integration can be found +in auto_build.sh which is also in the the repository root directory. + +//--------------------------------------------------------------------- + +stacktests.cpp contain several stack tests that can be used in an Android JNI app. + +Note: to enable the logger for Android, TB_LOG should be defined in the ./jni/Android.mk file as +LOCAL_CFLAGS := -DTB_LOG + +Note: add the following to the ./jni/Android.mk file +LOCAL_SRC_FILES += logger.c +LOCAL_SRC_FILES += loggertests.cpp +LOCAL_SRC_FILES += ocstack.c +LOCAL_SRC_FILES += occoap.c +LOCAL_SRC_FILES += stacktests.cpp + + diff --git a/resource/csdk/stack/test/android/stacktests.cpp b/resource/csdk/stack/test/android/stacktests.cpp new file mode 100644 index 000000000..926083674 --- /dev/null +++ b/resource/csdk/stack/test/android/stacktests.cpp @@ -0,0 +1,133 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +extern "C" { + #include "logger.h" + #include "ocstack.h" + #include "ocstackinternal.h" +} + +#include +#include +#include +#include +#include +#include +#include +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include +#include + +#include +using namespace std; + + +//----------------------------------------------------------------------------- +// Private variables +//----------------------------------------------------------------------------- +static const char TAG[] = "TestHarness"; +static OCUri SERVICE_URI = "coap://127.0.0.1:5683/"; + +void EXPECT_EQ(int a, int b) { + if (a == b) { + OC_LOG(INFO, TAG, "PASS"); + } else { + OC_LOG(ERROR, TAG, "**FAIL**"); + } +} + +void EXPECT_STREQ(const char *a, const char *b) { + if (strcmp(a, b) == 0) { + OC_LOG(INFO, TAG, "PASS"); + } else { + OC_LOG(ERROR, TAG, "**FAIL**"); + } +} +//----------------------------------------------------------------------------- +// Callback functions +//----------------------------------------------------------------------------- + +extern "C" void asyncDoResourcesCallback(OCStackResult result, OCRepresentationHandle representation) { + OC_LOG(INFO, TAG, "Entering asyncDoResourcesCallback"); + + EXPECT_EQ(OC_STACK_OK, result); + OCResource *resource = (OCResource *)representation; + OC_LOG_V(INFO, TAG, "URI = %s", resource->uri); + EXPECT_STREQ(SERVICE_URI, resource->uri); +} + +//----------------------------------------------------------------------------- +// Tests +//----------------------------------------------------------------------------- +void test0() { + EXPECT_EQ(OC_STACK_OK, OCInit(0, 5683, OC_SERVER)); +} + +void test1() { + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 0, OC_SERVER)); +} + +void test2() { + EXPECT_EQ(OC_STACK_OK, OCInit(0, 0, OC_SERVER)); +} + +void test3() { + EXPECT_EQ(OC_STACK_ERROR, OCInit(0, 0, (OCMode)10)); +} + +void test4() { + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT)); + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_SERVER)); + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT_SERVER)); +} + +void test5() { + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT)); + EXPECT_EQ(OC_STACK_OK, OCDoResource(OC_REST_GET, OC_EXPLICIT_DEVICE_DISCOVERY_URI, 0, 0, asyncDoResourcesCallback), NULL, 0); + EXPECT_EQ(OC_STACK_OK, OCUpdateResources(SERVICE_URI)); + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +void test6() { + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT)); + EXPECT_EQ(OC_STACK_OK, OCStop()); + EXPECT_EQ(OC_STACK_ERROR, OCStop()); +} + +void test7() { + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT)); + EXPECT_EQ(OC_STACK_OK, OCDoResource(OC_REST_GET, OC_EXPLICIT_DEVICE_DISCOVERY_URI, 0, 0, asyncDoResourcesCallback), NULL, 0); + EXPECT_EQ(OC_STACK_INVALID_URI, OCUpdateResources(0)); + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +void stacktests() { + test0(); + test1(); + test2(); + test3(); + test4(); + test5(); + test6(); + test7(); +} diff --git a/resource/csdk/stack/test/arduino/ArduinoStackTest.cpp b/resource/csdk/stack/test/arduino/ArduinoStackTest.cpp new file mode 100644 index 000000000..a4954d71f --- /dev/null +++ b/resource/csdk/stack/test/arduino/ArduinoStackTest.cpp @@ -0,0 +1,220 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +// Do not remove the include below +#include "ArduinoStackTest.h" + +#include "logger.h" +#include "ocstack.h" +#include "ocstackinternal.h" +#include + +#define PCF(str) ((PROGMEM const char *)(F(str))) + +PROGMEM const char TAG[] = "Arduino"; +static OCUri SERVICE_URI = "coap://127.0.0.1:5683/"; + +#if 0 // Turn off logger test stuff +PROGMEM const char tag[] = "Arduino"; +PROGMEM const char msg[] = "Arduino Logger Test"; + +PROGMEM const char debugMsg[] = "this is a DEBUG message"; +PROGMEM const char infoMsg[] = "this is a INFO message"; +PROGMEM const char warningMsg[] = "this is a WARNING message"; +PROGMEM const char errorMsg[] = "this is a ERROR message"; +PROGMEM const char fatalMsg[] = "this is a FATAL message"; + +PROGMEM const char multiLineMsg[] = "this is a DEBUG message\non multiple\nlines"; +#endif + +void EXPECT_EQ(int a, int b) { + if (a == b) { + OC_LOG(INFO, TAG, PCF("PASS")); + } else { + OC_LOG(ERROR, TAG, PCF("FAIL")); + } +} + +void EXPECT_STREQ(const char *a, const char *b) { + if (strcmp(a, b) == 0) { + OC_LOG(INFO, TAG, PCF("PASS")); + } else { + OC_LOG(ERROR, TAG, PCF("FAIL")); + } +} +//----------------------------------------------------------------------------- +// Tests +//----------------------------------------------------------------------------- +#if 0 // Turn off logger tests +void test0() { + OC_LOG(INFO, tag, msg); +} + +void test1() { + OC_LOG(INFO, 0, msg); +} + +void test2() { + OC_LOG(INFO, tag, 0); +} + +void test3() { + OC_LOG(INFO, 0, 0); +} + +void test4() { + OC_LOG(DEBUG, tag, debugMsg); + OC_LOG(INFO, tag, infoMsg); + OC_LOG(WARNING, tag, warningMsg); + OC_LOG(ERROR, tag, errorMsg); + OC_LOG(FATAL, tag, fatalMsg); +} + +void test5() { + OC_LOG(DEBUG, tag, multiLineMsg); +} + + +void test6() { + // Log buffer + uint8_t buffer[50]; + for (int i = 0; i < (int)(sizeof buffer); i++) { + buffer[i] = i; + } + OC_LOG_BUFFER(DEBUG, tag, buffer, sizeof buffer); + + // Log buffer, 128 bytes is a good boundary (8 rows of 16 values) + uint8_t buffer1[128]; + for (int i = 0; i < (int)(sizeof buffer1); i++) { + buffer1[i] = i; + } + OC_LOG_BUFFER(DEBUG, tag, buffer1, sizeof buffer1); + + // 1 below 128 byte boundary + uint8_t buffer2[127]; + for (int i = 0; i < (int)(sizeof buffer2); i++) { + buffer2[i] = i; + } + OC_LOG_BUFFER(DEBUG, tag, buffer2, sizeof buffer2); + + // 1 above 128 byte boundary + uint8_t buffer3[129]; + for (int i = 0; i < (int)(sizeof buffer3); i++) { + buffer3[i] = i; + } + OC_LOG_BUFFER(DEBUG, tag, buffer3, sizeof buffer3); +} +#endif + +extern "C" void asyncDoResourcesCallback(OCStackResult result, OCRepresentationHandle representation) { + OC_LOG(INFO, TAG, PCF("Entering asyncDoResourcesCallback")); + + EXPECT_EQ(OC_STACK_OK, result); + OCResource *resource = (OCResource *)representation; + OC_LOG_V(INFO, TAG, "URI = %s", resource->uri); + EXPECT_STREQ(SERVICE_URI, resource->uri); +} + +void test0() { + OC_LOG(INFO, TAG, PCF("test0")); + EXPECT_EQ(OC_STACK_OK, OCInit(0, 5683, OC_SERVER)); +} + +void test1() { + OC_LOG(INFO, TAG, PCF("test1")); + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 0, OC_SERVER)); +} + +void test2() { + OC_LOG(INFO, TAG, PCF("test2")); + EXPECT_EQ(OC_STACK_OK, OCInit(0, 0, OC_SERVER)); +} + +void test3() { + OC_LOG(INFO, TAG, PCF("test3")); + EXPECT_EQ(OC_STACK_ERROR, OCInit(0, 0, (OCMode)10)); +} + +void test4() { + OC_LOG(INFO, TAG, PCF("test4")); + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT)); + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_SERVER)); + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT_SERVER)); +} + +void test5() { + OC_LOG(INFO, TAG, PCF("test5")); + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT)); + EXPECT_EQ(OC_STACK_OK, OCDoResource(OC_REST_GET, OC_EXPLICIT_DEVICE_DISCOVERY_URI, 0, 0, asyncDoResourcesCallback), NULL, 0); + EXPECT_EQ(OC_STACK_OK, OCUpdateResources(SERVICE_URI)); + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +void test6() { + OC_LOG(INFO, TAG, PCF("test6")); + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT)); + EXPECT_EQ(OC_STACK_OK, OCStop()); + EXPECT_EQ(OC_STACK_ERROR, OCStop()); +} + +void test7() { + OC_LOG(INFO, TAG, PCF("test7")); + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT)); + EXPECT_EQ(OC_STACK_OK, OCDoResource(OC_REST_GET, OC_EXPLICIT_DEVICE_DISCOVERY_URI, 0, 0, asyncDoResourcesCallback), NULL, 0); + EXPECT_EQ(OC_STACK_INVALID_URI, OCUpdateResources(0)); + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + + + +//The setup function is called once at startup of the sketch +void setup() +{ + // Add your initialization code here + OC_LOG_INIT(); + + test0(); + delay(2000); + test1(); + delay(2000); + test2(); + delay(2000); + test3(); + delay(2000); + test4(); + delay(2000); + test5(); + delay(2000); + test6(); + delay(2000); + +#if 1 + test7(); + delay(2000); +#endif + +} + +// The loop function is called in an endless loop +void loop() +{ + delay(2000); +} diff --git a/resource/csdk/stack/test/arduino/ArduinoStackTest.h b/resource/csdk/stack/test/arduino/ArduinoStackTest.h new file mode 100644 index 000000000..064b77f82 --- /dev/null +++ b/resource/csdk/stack/test/arduino/ArduinoStackTest.h @@ -0,0 +1,49 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// Only modify this file to include +// - function definitions (prototypes) +// - include files +// - extern variable definitions +// In the appropriate section + +#ifndef ArduinoStackTest_H_ +#define ArduinoStackTest_H_ +#include "Arduino.h" +//add your includes for the project ArduinoDummyTestFramework here + + +//end of add your includes here +#ifdef __cplusplus +extern "C" { +#endif +void loop(); +void setup(); +#ifdef __cplusplus +} // extern "C" +#endif + +//add your function definitions for the project ArduinoDummyTestFramework here + + + + +//Do not add code below this line +#endif /* ArduinoStackTest_H_ */ diff --git a/resource/csdk/stack/test/arduino/README b/resource/csdk/stack/test/arduino/README new file mode 100644 index 000000000..b2e46d0ba --- /dev/null +++ b/resource/csdk/stack/test/arduino/README @@ -0,0 +1,34 @@ +//--------------------------------------------------------------------- +// NOTICE - Transition to SCONS +//--------------------------------------------------------------------- + +The IoTivity build system is transitioning to SCONS. Although the +makefiles are still available (until v1.0) and some developers are +still using them, they are currently no longer supported. To learn more +about building using SCONS see Readme.scons.txt in the repository root +directory. The build steps used in continuous integration can be found +in auto_build.sh which is also in the the repository root directory. + +//--------------------------------------------------------------------- + +ArduinoStackTest.cpp contains several logger tests and can be used in an +Arduino sketch. + +On Arduino, the logger outputs to the serial port using Serial.print. + +Run a serial terminal program such as CuteCom at 115200,8,N,1 to view the +log outputs. + +Note: to enable the logger for Arduino, TB_LOG should be defined in +Properties|C/C++ Build|Settings|Tool Settings|AVR Compiler|Symbols +and +Properties|C/C++ Build|Settings|Tool Settings|AVR C++ Compiler|Symbols + +Copy logger.c/h, occoap.c/h, and ocstack.c/h, and ocstackinternal.h to the Arduino project +Note: when building for Arduino, force the compiler to use avr-g++ to build logger.c, stack.c, and occoap.c + +Note: when building for Arduino, several warnings are generated when trying to place strings in +PROGMEM +"warning: only initialized variables can be placed into program memory area" +This appears to be a known gcc bug - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734 + diff --git a/resource/csdk/stack/test/arduino/makefile b/resource/csdk/stack/test/arduino/makefile new file mode 100644 index 000000000..f753da898 --- /dev/null +++ b/resource/csdk/stack/test/arduino/makefile @@ -0,0 +1,114 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +BUILD := release +PLATFORM := arduinomega + +ROOT_DIR = ../../.. +include $(ROOT_DIR)/local.properties +LIBCOAP_DIR = $(ROOT_DIR)/libcoap-4.1.1 +OCSOCK_DIR = $(ROOT_DIR)/ocsocket +OCCOAP_DIR = $(ROOT_DIR)/occoap +LOGGER_DIR = $(ROOT_DIR)/logger +RANDOM_DIR = $(ROOT_DIR)/ocrandom +JSON_DIR = $(ROOT_DIR)/../../extlibs/cjson +OCSTACK_DIR = $(ROOT_DIR)/stack +BIN_DIR = $(OCSTACK_DIR)/bin/arduino/ +OBJ_DIR = $(OCSTACK_DIR)/obj/arduino/ + +#Source directories +SDIR_ARD_CORE = $(ARDUINO_DIR)/hardware/arduino/cores/arduino +SDIR_ARD_SPI = $(ARDUINO_DIR)/libraries/SPI +SDIR_ARD_ETH = $(ARDUINO_DIR)/libraries/Ethernet +SDIR_ARD_ETH_UTIL = $(ARDUINO_DIR)/libraries/Ethernet/utility +SDIR_ARD_TIME = $(ARDUINO_DIR)/libraries/Time + +VPATH = $(SDIR_ARD_CORE):$(SDIR_ARD_SPI):$(SDIR_ARD_ETH):$(SDIR_ARD_ETH_UTIL):$(SDIR_ARD_TIME):$(RANDOM_DIR)/src:$(OCSTACK_DIR)/src:$(OCCOAP_DIR)/src:$(JSON_DIR) + +#include directories +IDIR_ARD_CORE = $(ARDUINO_DIR)/hardware/arduino/cores/arduino +IDIR_ARD_VARIANT = $(ARDUINO_DIR)/hardware/arduino/variants/mega +IDIR_ARD_SPI = $(ARDUINO_DIR)/libraries/SPI +IDIR_ARD_ETH = $(ARDUINO_DIR)/libraries/Ethernet +IDIR_ARD_ETH_UTIL = $(ARDUINO_DIR)/libraries/Ethernet/utility +IDIR_ARD_TIME = $(ARDUINO_DIR)/libraries/Time + +INC_DIRS = -I$(IDIR_ARD_CORE) -I$(IDIR_ARD_VARIANT) -I$(IDIR_ARD_SPI) \ + -I$(IDIR_ARD_ETH) -I$(IDIR_ARD_ETH_UTIL) -I$(IDIR_ARD_TIME) \ + -I$(OCSOCK_DIR)/include -I$(LOGGER_DIR)/include -I$(RANDOM_DIR)/include \ + -I$(OCSTACK_DIR)/include -I$(OCSTACK_DIR)/include/internal \ + -I$(LIBCOAP_DIR)/ -I$(OCCOAP_DIR)/include -I$(JSON_DIR) + +#Compiler/Linker flags +COPTIONS_ARDUINO = -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=156 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR -MMD -DNDEBUG +CFLAGS += -c -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions -felide-constructors -std=c++0x -DATMEGA2560 -DTB_LOG -DWITH_ARDUINO + +#Compilers +CXX=avr-g++ +CC=avr-gcc +AR=avr-ar +RANLIB=avr-ranlib + +TESTAPP = ocserver + +CORE_COBJ = WInterrupts.o wiring.o wiring_digital.o +CORE_CPPOBJ = main.o Stream.o WMath.o WString.o HardwareSerial.o Print.o SPI.o IPAddress.o wiring_analog.o +ETH_CPPOBJ = Dhcp.o Dns.o Ethernet.o EthernetUdp.o +ETH_UTIL_CPPOBJ = socket.o w5100.o +OCSTACK_CPPOBJ = ocrandom.o ocresource.o occollection.o ocobserve.o ocserverrequest.o ocstack.o occoaphelper.o occoap.o occlientcb.o +OCDEPENDENT_CPPOBJ = wiring_analog.o +CJSON_COBJ = cJSON.o + +all: core.a $(TESTAPP).o $(TESTAPP).elf $(TESTAPP).hex + mkdir -p $(BIN_DIR) + cp $(TESTAPP).hex $(BIN_DIR) + mkdir -p $(OBJ_DIR) + cp *.o $(OBJ_DIR) + cp *.elf $(OBJ_DIR) + +# Note for Arduino: The C files are compiled using C++ compiler since Arduino +# build includes Time.h header file which has C++ style definitions. +%.o: %.c + $(CXX) $(CFLAGS) $(COPTIONS_ARDUINO) $(INC_DIRS) $< -o $@ + +%.o: %.cpp + $(CXX) $(CFLAGS) $(COPTIONS_ARDUINO) $(INC_DIRS) $< -o $@ + +core.a: $(CORE_COBJ) $(CORE_CPPOBJ) $(ETH_CPPOBJ) $(ETH_UTIL_CPPOBJ) $(LIBCOAP_DIR)/$(BUILD)/libcoap.a + $(AR) rcs $@ $^ + $(RANLIB) $@ + +$(TESTAPP).elf: $(TESTAPP).o core.a $(OCSTACK_CPPOBJ) $(OCDEPENDENT_CPPOBJ) $(LIBCOAP_DIR)/$(BUILD)/libcoap.a $(CJSON_COBJ) + $(CC) -Os -Wl,--gc-sections,--relax $(COPTIONS_ARDUINO) $^ -lm -o $@ + +$(TESTAPP).hex: $(TESTAPP).elf + avr-objcopy -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 $< $(TESTAPP).eep + avr-objcopy -O ihex -R .eeprom $< $@ + +install: all + avrdude -C$(ARDUINO_DIR)/hardware/tools/avrdude.conf -v -v -v -v -patmega2560 -cstk500v2 -P/dev/ttyACM0 -b115200 -D -Uflash:w:$(TESTAPP).hex:i + +.PHONY: clean + +clean: + rm -f *.o *.d *.elf *.eep *.a *.hex *- + rm -fr $(BIN_DIR) + rm -fr $(OBJ_DIR) + diff --git a/resource/csdk/stack/test/arduino/ocserver.cpp b/resource/csdk/stack/test/arduino/ocserver.cpp new file mode 100644 index 000000000..3c4770174 --- /dev/null +++ b/resource/csdk/stack/test/arduino/ocserver.cpp @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include + +static uint8_t ETHERNET_MAC[] = {0x90, 0xA2, 0xDA, 0x0F, 0x2B, 0x72 }; + +#define TAG PCF("ocserver") + +void ocInitialize () { + char ipAddr[16] = ""; + OCGetInterfaceAddress (NULL, 0, AF_INET, (uint8_t *)ipAddr, 16); + OC_LOG(DEBUG, TAG, PCF("IP addr is:")); + OC_LOG_BUFFER(INFO, TAG, (uint8_t*)ipAddr, sizeof(ipAddr)); + delay(2000); + OCInit (ipAddr, 8001, OC_SERVER); +} + +void setup() { + Serial.begin(115200); + + Serial.println ("Trying to get an IP addr using DHCP"); + if (Ethernet.begin(ETHERNET_MAC) == 0) { + Serial.println("DHCP failed"); + } + ocInitialize (); +} + +void loop() { + Serial.println ("Processing CoAP messages!\n"); + OCProcess (); + delay(1000); +} diff --git a/resource/csdk/stack/test/linux/makefile b/resource/csdk/stack/test/linux/makefile new file mode 100644 index 000000000..43ebff71a --- /dev/null +++ b/resource/csdk/stack/test/linux/makefile @@ -0,0 +1,98 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +VERSION:=4.1.1 + +# override with `make BUILD=release` +# default to release build +BUILD := release + +#other options are android, arduino +PLATFORM=linux + +ROOT_DIR = ../../.. +OCSOCK_DIR = $(ROOT_DIR)/ocsocket +OCSTACK_DIR = $(ROOT_DIR)/stack +LOGGER_DIR = $(ROOT_DIR)/logger +OC_LOG_DIR = $(ROOT_DIR)/../oc_logger +RANDOM_DIR = $(ROOT_DIR)/ocrandom + +OBJ_DIR = ./ + +INC_DIRS := -I$(OCSTACK_DIR)/include +INC_DIRS += -I$(OCSOCK_DIR)/include +INC_DIRS += -I$(LOGGER_DIR)/include +INC_DIRS += -I$(OC_LOG_DIR)/include +INC_DIRS += -I$(RANDOM_DIR)/include + +ifeq ($(PLATFORM),android) + CXX=arm-linux-androideabi-g++ + CC=arm-linux-androideabi-gcc + AR=arm-linux-androideabi-ar + RANLIB=arm-linux-androideabi-ranlib + CFLAGS_ANDROID = -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 + LDFLAGS_ANDROID = -march=armv7-a -Wl,--fix-cortex-a8 -llog +else ifeq ($(PLATFORM),linux) + CXX=g++ + CC=gcc + AR=ar + RANLIB=ranlib +else + $(error Wrong value for PLATFORM !!) +endif + +DEP_LIBS = $(ROOT_DIR)/linux/$(BUILD)/liboctbstack.a + +CFLAGS += -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions \ + -Wextra -Wno-variadic-macros -pedantic -std=gnu99 -DWITH_POSIX -DTB_LOG + +PROGRAMS = ocserver occlient + +SOURCES:= occlient.c ocserver.c + +OBJECTS:= $(patsubst %.c, %.o, $(SOURCES)) + +all: objdirs $(PROGRAMS) + +%.o: %.c + $(CC) -c $(CFLAGS) $(CFLAGS_ANDROID) $(INC_DIRS) $< -o $(BUILD)/$@ + +objdirs: $(ROOT_DIR) + mkdir -p $(BUILD) + +##Added -lm as needed by json calling floor() +occlient: occlient.o $(DEP_LIBS) + $(CC) -Os -Wl,--gc-sections $(LDFLAGS_ANDROID) $(BUILD)/$^ -o $(BUILD)/$@ -lm + +ocserver: ocserver.o $(DEP_LIBS) + $(CC) -Os -Wl,--gc-sections $(LDFLAGS_ANDROID) $(BUILD)/$^ -o $(BUILD)/$@ -lm + +install: all + @echo "Installing for PLATFORM $(PLATFORM)" +ifeq ($(PLATFORM),android) + adb push coap-client /data/local/tmp/ + adb push coap-server /data/local/tmp/ +endif + +.PHONY: clean + +clean: + rm -rf debug + rm -rf release diff --git a/resource/csdk/stack/test/linux/occlient.c b/resource/csdk/stack/test/linux/occlient.c new file mode 100644 index 000000000..ec48462b6 --- /dev/null +++ b/resource/csdk/stack/test/linux/occlient.c @@ -0,0 +1,99 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +#include +#include +#include +#include +#include +#include +#include + +#define TAG PCF("occlient") + +int gQuitFlag = 0; + +/* SIGINT handler: set gQuitFlag to 1 for graceful termination */ +void handleSigInt(int signum) { + if (signum == SIGINT) { + gQuitFlag = 1; + } +} + +// This is a function called back when a device is discovered +OCStackApplicationResult applicationDiscoverCB( + OCClientResponse * clientResponse) { + uint8_t remoteIpAddr[4]; + uint16_t remotePortNu; + OC_LOG(INFO, TAG, "Entering applicationDiscoverCB (Application Layer CB)"); + OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddr, + remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3); + OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNu); + OC_LOG_V(INFO, TAG, "Device =============> Discovered %s @ %d.%d.%d.%d:%d",clientResponse->resJSONPayload,remoteIpAddr[0], remoteIpAddr[1], remoteIpAddr[2], remoteIpAddr[3], remotePortNu); + //return OC_STACK_DELETE_TRANSACTION; + return OC_STACK_KEEP_TRANSACTION; +} + +int main() { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + OCDoHandle handle; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + OC_LOG_V(INFO, TAG, "Starting occlient on address %s",addr); + + /* Initialize OCStack*/ + if (OCInit((char *) addr, port, OC_CLIENT) != OC_STACK_OK) { + OC_LOG(ERROR, TAG, "OCStack init error"); + return 0; + } + + /* Start a discovery query*/ + char szQueryUri[64] = { 0 }; + strcpy(szQueryUri, OC_EXPLICIT_DEVICE_DISCOVERY_URI); + if (OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, + 0, 0, 0) != OC_STACK_OK) { + OC_LOG(ERROR, TAG, "OCStack resource error"); + return 0; + } + + // Break from loop with Ctrl+C + OC_LOG(INFO, TAG, "Entering occlient main loop..."); + signal(SIGINT, handleSigInt); + while (!gQuitFlag) { + + if (OCProcess() != OC_STACK_OK) { + OC_LOG(ERROR, TAG, "OCStack process error"); + return 0; + } + + sleep(1); + }OC_LOG(INFO, TAG, "Exiting occlient main loop..."); + + if (OCStop() != OC_STACK_OK) { + OC_LOG(ERROR, TAG, "OCStack stop error"); + } + + return 0; +} diff --git a/resource/csdk/stack/test/linux/ocserver.c b/resource/csdk/stack/test/linux/ocserver.c new file mode 100644 index 000000000..580ea0c92 --- /dev/null +++ b/resource/csdk/stack/test/linux/ocserver.c @@ -0,0 +1,104 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +#include +#include +#include +#include +#include +#include +#include +#include + +#define TAG PCF("ocserver") + +int gQuitFlag = 0; +OCStackResult createLightResource(); + +typedef struct LIGHTRESOURCE{ + OCResourceHandle handle; + bool power; +} LightResource; + +static LightResource Light; + +/* SIGINT handler: set gQuitFlag to 1 for graceful termination */ +void handleSigInt(int signum) { + if (signum == SIGINT) { + gQuitFlag = 1; + } +} + +int main() { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + if (OCInit((char *) addr, port, OC_SERVER) != OC_STACK_OK) { + OC_LOG(ERROR, TAG, "OCStack init error"); + return 0; + } + + /* + * Declare and create the example resource: Light + */ + if(createLightResource() != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "OCStack cannot create resource..."); + } + + // Break from loop with Ctrl-C + OC_LOG(INFO, TAG, "Entering ocserver main loop..."); + signal(SIGINT, handleSigInt); + while (!gQuitFlag) { + + if (OCProcess() != OC_STACK_OK) { + OC_LOG(ERROR, TAG, "OCStack process error"); + return 0; + } + + sleep(1); + } + + OC_LOG(INFO, TAG, "Exiting ocserver main loop..."); + + if (OCStop() != OC_STACK_OK) { + OC_LOG(ERROR, TAG, "OCStack process error"); + } + + return 0; +} + +OCStackResult createLightResource() { + Light.power = false; + OCStackResult res = OCCreateResource(&Light.handle, + "core.light", + "core.rw", + "/a/light", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE); + return res; +} diff --git a/resource/csdk/stack/test/makefile b/resource/csdk/stack/test/makefile new file mode 100644 index 000000000..ac76a4797 --- /dev/null +++ b/resource/csdk/stack/test/makefile @@ -0,0 +1,106 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +# override with `make BUILD=debug` +# default to release build +BUILD := release +PLATFORM := linux +CC := g++ + +ifeq ($(ROOT_DIR), ) +ROOT_DIR = $(PWD)/../.. +endif + +# You must create the file "local.properties" on your local machine which contains any local paths, etc +# local.properties should NOT be committed to repo +include $(ROOT_DIR)/local.properties +# GTEST_DIR contains the path to Google Test libs and must be defined in local.properties +# Example: +# GTEST_DIR := /home/johndoe/utils/gtest-1.7.0 + +# NOTE: to run app, make sure that LD_LIBRARY_PATH env variable +# contains $(GTEST_DIR)/lib/.libs + +OUT_DIR := $(PWD)/$(BUILD) +OBJ_DIR := $(OUT_DIR)/obj + + +OUT_DIR := $(PWD) + +LOGGER_DIR = $(ROOT_DIR)/logger +OC_LOG_DIR = $(ROOT_DIR)/../oc_logger +OCRANDOM_DIR = $(ROOT_DIR)/ocrandom +OCSOCKET_DIR = $(ROOT_DIR)/ocsocket +LCOAP_DIR = $(ROOT_DIR)/libcoap-4.1.1 +OCCOAP_DIR = $(ROOT_DIR)/occoap +OCTBSTACK_DIR = $(ROOT_DIR)/stack + +LOGGER_INC = $(LOGGER_DIR)/include +OC_LOG_INC = $(OC_LOG_DIR)/include +OCRANDOM_INC = $(OCRANDOM_DIR)/include +OCSOCKET_INC = $(OCSOCKET_DIR)/include +LCOAP_INC = $(LCOAP_DIR) +OCCOAP_INC = $(OCCOAP_DIR)/include +OCTBSTACK_INC = $(OCTBSTACK_DIR)/include + +INC_DIRS := -I$(LOGGER_INC) +INC_DIRS += -I$(OC_LOG_INC) +INC_DIRS += -I$(OCRANDOM_INC) +INC_DIRS += -I$(OCSOCKET_INC) +INC_DIRS += -I$(LCOAP_INC) +INC_DIRS += -I$(OCCOAP_INC) +INC_DIRS += -I$(OCTBSTACK_INC) +INC_DIRS += -I$(OCTBSTACK_INC)/internal +INC_DIRS += -I$(GTEST_DIR)/include + +CC_FLAGS.debug := -g -O0 -g3 -Wall -ffunction-sections -fdata-sections -fno-exceptions \ + -std=c++0x -pedantic $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD) -DTB_LOG +CC_FLAGS.release := -Os -Wall -fdata-sections -Wl,--gc-sections -Wl,-s -fno-exceptions \ + -std=c++0x $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD) + +LDLIBS += -loctbstack -lpthread -lgtest -lgtest_main +CPPFLAGS += $(CC_FLAGS.$(BUILD)) $(LDLIBS) -L$(GTEST_DIR)/lib/.libs + +SOURCES := stacktests.cpp + +OBJECTS:= $(patsubst %.c, $(OBJ_DIR)/%.o, $(SOURCES)) + +PROGRAMS := stacktests + +all: prep_dirs $(OBJECTS) $(PROGRAMS) + +prep_dirs: + -mkdir -p $(OUT_DIR) + -mkdir -p $(OBJ_DIR) + +$(OBJ_DIR)/%.o: %.cpp + $(CC) -c $(CPPFLAGS) $< -o $@ + +stacktests: $(OBJ_DIR)/stacktests.o + $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@ + +.PHONY: clean + +clean: legacy_clean + -rm -rf release + -rm -rf debug + +legacy_clean: + rm -f *.o $(PROGRAMS) diff --git a/resource/csdk/stack/test/stacktests.cpp b/resource/csdk/stack/test/stacktests.cpp new file mode 100644 index 000000000..31c8dff37 --- /dev/null +++ b/resource/csdk/stack/test/stacktests.cpp @@ -0,0 +1,1420 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +extern "C" { + #include "ocstack.h" + #include "ocstackinternal.h" + #include "logger.h" +} + +#include "gtest/gtest.h" +#include +#include +#include +#include +#include +#include + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include +#include + +#include +#include +using namespace std; + +#define DEFAULT_CONTEXT_VALUE 0x99 +//----------------------------------------------------------------------------- +// Private variables +//----------------------------------------------------------------------------- +static const char TAG[] = "TestHarness"; + +//----------------------------------------------------------------------------- +// Callback functions +//----------------------------------------------------------------------------- +extern "C" OCStackApplicationResult asyncDoResourcesCallback(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) { + OC_LOG(INFO, TAG, "Entering asyncDoResourcesCallback"); + + EXPECT_EQ(OC_STACK_OK, clientResponse->result); + + if(ctx == (void*)DEFAULT_CONTEXT_VALUE) { + OC_LOG_V(INFO, TAG, "Callback Context recvd successfully"); + } + OC_LOG_V(INFO, TAG, "result = %d", clientResponse->result); + + return OC_STACK_KEEP_TRANSACTION; +} + + +//----------------------------------------------------------------------------- +// Tests +//----------------------------------------------------------------------------- +#if 1 +TEST(StackTest, StackInitNullAddr) { + EXPECT_EQ(OC_STACK_OK, OCInit(0, 5683, OC_SERVER)); + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, StackInitNullPort) { + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 0, OC_SERVER)); + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, StackInitNullAddrAndPort) { + EXPECT_EQ(OC_STACK_OK, OCInit(0, 0, OC_SERVER)); + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, StackInitInvalidMode) { + EXPECT_EQ(OC_STACK_ERROR, OCInit(0, 0, (OCMode)10)); + EXPECT_EQ(OC_STACK_ERROR, OCStop()); +} + +TEST(StackTest, StackStartSuccessClient) { + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT)); + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, StackStartSuccessServer) { + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_SERVER)); + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, StackStartSuccessClientServer) { + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT_SERVER)); + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, StackStartSuccessiveInits) { + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_SERVER)); + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.2", 5683, OC_SERVER)); + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, DoResourceDeviceDiscovery) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + OCCallbackData cbData; + OCDoHandle handle; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + OC_LOG_V(INFO, TAG, "Starting DoResourceDeviceDiscovery test on address %s",addr); + + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_CLIENT)); + /* Start a discovery query*/ + char szQueryUri[64] = { 0 }; + strcpy(szQueryUri, OC_WELL_KNOWN_QUERY); + cbData.cb = asyncDoResourcesCallback; + cbData.context = (void*)DEFAULT_CONTEXT_VALUE; + cbData.cd = NULL; + + EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0)); + //EXPECT_EQ(OC_STACK_OK, OCUpdateResources(SERVICE_URI)); + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, StackStopWithoutInit) { + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT)); + EXPECT_EQ(OC_STACK_OK, OCStop()); + EXPECT_EQ(OC_STACK_ERROR, OCStop()); +} + +TEST(StackTest, UpdateResourceNullURI) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + OCCallbackData cbData; + OCDoHandle handle; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + OC_LOG_V(INFO, TAG, "Starting UpdateResourceNullURI test on address %s",addr); + + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_CLIENT)); + /* Start a discovery query*/ + char szQueryUri[64] = { 0 }; + strcpy(szQueryUri, OC_WELL_KNOWN_QUERY); + cbData.cb = asyncDoResourcesCallback; + cbData.context = (void*)DEFAULT_CONTEXT_VALUE; + cbData.cd = NULL; + EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0)); + //EXPECT_EQ(OC_STACK_INVALID_URI, OCUpdateResources(0)); + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, CreateResourceBadParams) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle; + + EXPECT_EQ(OC_STACK_INVALID_PARAM, OCCreateResource(NULL, //&handle, + "core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + EXPECT_EQ(OC_STACK_INVALID_PARAM, OCCreateResource(&handle, + NULL, //"core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + // Property bitmask out of range + EXPECT_EQ(OC_STACK_INVALID_PARAM, OCCreateResource(&handle, + "core.led", + "core.rw", + "/a/led", + 0, + 16));//OC_DISCOVERABLE|OC_OBSERVABLE)); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} +#endif + +TEST(StackTest, CreateResourceSuccess) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, + "core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + const char *url = OCGetResourceUri(handle); + EXPECT_STREQ("/a/led", url); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, CreateResourceFailDuplicateUri) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, + "core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + const char *url = OCGetResourceUri(handle); + EXPECT_STREQ("/a/led", url); + + EXPECT_EQ(OC_STACK_INVALID_PARAM, OCCreateResource(&handle, + "core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, CreateResourceMultipleResources) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle1; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle1, + "core.led", + "core.rw", + "/a/led1", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + OCResourceHandle handle2; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle2, + "core.led", + "core.rw", + "/a/led2", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + OCResourceHandle handle3; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle3, + "core.led", + "core.rw", + "/a/led3", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + const char *url = OCGetResourceUri(handle1); + EXPECT_STREQ("/a/led1", url); + + url = OCGetResourceUri(handle2); + EXPECT_STREQ("/a/led2", url); + + url = OCGetResourceUri(handle3); + EXPECT_STREQ("/a/led3", url); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, CreateResourceBadResoureType) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_INVALID_PARAM, OCCreateResource(&handle, + NULL, //"core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, CreateResourceGoodResourceType) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, + "core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, ResourceTypeName) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, + "core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + uint8_t numResourceTypes; + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceTypes(handle, &numResourceTypes)); + EXPECT_EQ(1, numResourceTypes); + const char *resourceTypeName = OCGetResourceTypeName(handle, 0); + EXPECT_STREQ("core.led", resourceTypeName); + + // try getting resource type names with an invalid index + resourceTypeName = OCGetResourceTypeName(handle, 1); + EXPECT_STREQ(NULL, resourceTypeName); + // try getting resource type names with an invalid index + resourceTypeName = OCGetResourceTypeName(handle, 10); + EXPECT_STREQ(NULL, resourceTypeName); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, BindResourceTypeNameBad) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, + "core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + uint8_t numResourceTypes; + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceTypes(handle, &numResourceTypes)); + EXPECT_EQ(1, numResourceTypes); + const char *resourceTypeName = OCGetResourceTypeName(handle, 0); + EXPECT_STREQ("core.led", resourceTypeName); + + EXPECT_EQ(OC_STACK_INVALID_PARAM, OCBindResourceTypeToResource(handle, NULL)); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, BindResourceTypeNameGood) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, + "core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + uint8_t numResourceTypes; + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceTypes(handle, &numResourceTypes)); + EXPECT_EQ(1, numResourceTypes); + const char *resourceTypeName = OCGetResourceTypeName(handle, 0); + EXPECT_STREQ("core.led", resourceTypeName); + + EXPECT_EQ(OC_STACK_OK, OCBindResourceTypeToResource(handle, "core.brightled")); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceTypes(handle, &numResourceTypes)); + EXPECT_EQ(2, numResourceTypes); + resourceTypeName = OCGetResourceTypeName(handle, 1); + EXPECT_STREQ("core.brightled", resourceTypeName); + + EXPECT_EQ(OC_STACK_OK, OCBindResourceTypeToResource(handle, "core.reallybrightled")); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceTypes(handle, &numResourceTypes)); + EXPECT_EQ(3, numResourceTypes); + resourceTypeName = OCGetResourceTypeName(handle, 2); + EXPECT_STREQ("core.reallybrightled", resourceTypeName); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, ResourceTypeAttrRepresentation) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, + "core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + uint8_t numResourceTypes; + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceTypes(handle, &numResourceTypes)); + EXPECT_EQ(1, numResourceTypes); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, BindResourceTypeAttribRepGood) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, + "core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + uint8_t numResourceTypes; + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceTypes(handle, &numResourceTypes)); + EXPECT_EQ(1, numResourceTypes); + + EXPECT_EQ(OC_STACK_OK, OCBindResourceTypeToResource(handle, "core.brightled")); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceTypes(handle, &numResourceTypes)); + EXPECT_EQ(2, numResourceTypes); + + EXPECT_EQ(OC_STACK_OK, OCBindResourceTypeToResource(handle, "core.reallybrightled")); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceTypes(handle, &numResourceTypes)); + EXPECT_EQ(3, numResourceTypes); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, ResourceTypeInterface) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, + "core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + uint8_t numResourceInterfaces; + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceInterfaces(handle, &numResourceInterfaces)); + EXPECT_EQ(1, numResourceInterfaces); + const char *resourceInterfaceName = OCGetResourceInterfaceName(handle, 0); + EXPECT_STREQ("core.rw", resourceInterfaceName); + + // try getting resource interface names with an invalid index + resourceInterfaceName = OCGetResourceInterfaceName(handle, 1); + EXPECT_STREQ(NULL, resourceInterfaceName); + // try getting resource interface names with an invalid index + resourceInterfaceName = OCGetResourceInterfaceName(handle, 10); + EXPECT_STREQ(NULL, resourceInterfaceName); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, BindResourceInterfaceNameBad) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, + "core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + uint8_t numResourceInterfaces; + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceInterfaces(handle, &numResourceInterfaces)); + EXPECT_EQ(1, numResourceInterfaces); + const char *resourceInterfaceName = OCGetResourceInterfaceName(handle, 0); + EXPECT_STREQ("core.rw", resourceInterfaceName); + + EXPECT_EQ(OC_STACK_INVALID_PARAM, OCBindResourceInterfaceToResource(handle, NULL)); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, BindResourceInterfaceNameGood) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, + "core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + uint8_t numResourceInterfaces; + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceInterfaces(handle, &numResourceInterfaces)); + EXPECT_EQ(1, numResourceInterfaces); + const char *resourceInterfaceName = OCGetResourceInterfaceName(handle, 0); + EXPECT_STREQ("core.rw", resourceInterfaceName); + + EXPECT_EQ(OC_STACK_OK, OCBindResourceInterfaceToResource(handle, "core.r")); + + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceInterfaces(handle, &numResourceInterfaces)); + EXPECT_EQ(2, numResourceInterfaces); + resourceInterfaceName = OCGetResourceInterfaceName(handle, 1); + EXPECT_STREQ("core.r", resourceInterfaceName); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, ResourceTypeInterfaceMethods) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, + "core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + uint8_t numResourceInterfaces; + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceInterfaces(handle, &numResourceInterfaces)); + EXPECT_EQ(1, numResourceInterfaces); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, BindResourceInterfaceMethodsBad) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, + "core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + uint8_t numResourceInterfaces; + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceInterfaces(handle, &numResourceInterfaces)); + EXPECT_EQ(1, numResourceInterfaces); + + EXPECT_EQ(OC_STACK_INVALID_PARAM, OCBindResourceInterfaceToResource(handle, 0)); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, BindResourceInterfaceMethodsGood) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, + "core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + uint8_t numResourceInterfaces; + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceInterfaces(handle, &numResourceInterfaces)); + EXPECT_EQ(1, numResourceInterfaces); + + EXPECT_EQ(OC_STACK_OK, OCBindResourceInterfaceToResource(handle, "core.r")); + + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceInterfaces(handle, &numResourceInterfaces)); + EXPECT_EQ(2, numResourceInterfaces); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, BindContainedResourceBad) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle containerHandle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&containerHandle, + "core.led", + "core.rw", + "/a/kitchen", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + OCResourceHandle handle0; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle0, + "core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + EXPECT_EQ(OC_STACK_INVALID_PARAM, OCBindResource(containerHandle, containerHandle)); + + EXPECT_EQ(OC_STACK_ERROR, OCBindResource((OCResourceHandle) 0, handle0)); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, BindContainedResourceGood) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + uint8_t numResources = 0; + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(0, numResources); + + OCResourceHandle containerHandle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&containerHandle, + "core.led", + "core.rw", + "/a/kitchen", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(1, numResources); + + OCResourceHandle handle0; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle0, + "core.led", + "core.rw", + "/a/led0", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(2, numResources); + + OCResourceHandle handle1; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle1, + "core.led", + "core.rw", + "/a/led1", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(3, numResources); + + OCResourceHandle handle2; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle2, + "core.led", + "core.rw", + "/a/led2", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(4, numResources); + + OCResourceHandle handle3; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle3, + "core.led", + "core.rw", + "/a/led3", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(5, numResources); + + OCResourceHandle handle4; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle4, + "core.led", + "core.rw", + "/a/led4", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(6, numResources); + + OCResourceHandle handle5; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle5, + "core.led", + "core.rw", + "/a/led5", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(7, numResources); + + + EXPECT_EQ(OC_STACK_OK, OCBindResource(containerHandle, handle0)); + EXPECT_EQ(OC_STACK_OK, OCBindResource(containerHandle, handle1)); + EXPECT_EQ(OC_STACK_OK, OCBindResource(containerHandle, handle2)); + EXPECT_EQ(OC_STACK_OK, OCBindResource(containerHandle, handle3)); + EXPECT_EQ(OC_STACK_OK, OCBindResource(containerHandle, handle4)); + EXPECT_EQ(OC_STACK_ERROR, OCBindResource(containerHandle, handle5)); + + EXPECT_EQ(handle0, OCGetResourceHandleFromCollection(containerHandle, 0)); + EXPECT_EQ(handle1, OCGetResourceHandleFromCollection(containerHandle, 1)); + EXPECT_EQ(handle2, OCGetResourceHandleFromCollection(containerHandle, 2)); + EXPECT_EQ(handle3, OCGetResourceHandleFromCollection(containerHandle, 3)); + EXPECT_EQ(handle4, OCGetResourceHandleFromCollection(containerHandle, 4)); + + EXPECT_EQ(NULL, OCGetResourceHandleFromCollection(containerHandle, 5)); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, GetResourceByIndex) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + uint8_t numResources = 0; + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(0, numResources); + + OCResourceHandle containerHandle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&containerHandle, + "core.led", + "core.rw", + "/a/kitchen", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(1, numResources); + + OCResourceHandle handle0; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle0, + "core.led", + "core.rw", + "/a/led0", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(2, numResources); + + OCResourceHandle handle1; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle1, + "core.led", + "core.rw", + "/a/led1", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(3, numResources); + + OCResourceHandle handle2; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle2, + "core.led", + "core.rw", + "/a/led2", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(4, numResources); + + OCResourceHandle handle3; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle3, + "core.led", + "core.rw", + "/a/led3", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(5, numResources); + + OCResourceHandle handle4; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle4, + "core.led", + "core.rw", + "/a/led4", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(6, numResources); + + OCResourceHandle handle5; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle5, + "core.led", + "core.rw", + "/a/led5", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(7, numResources); + + EXPECT_EQ(containerHandle, OCGetResourceHandle(0)); + EXPECT_EQ(handle0, OCGetResourceHandle(1)); + EXPECT_EQ(handle1, OCGetResourceHandle(2)); + EXPECT_EQ(handle2, OCGetResourceHandle(3)); + EXPECT_EQ(handle3, OCGetResourceHandle(4)); + EXPECT_EQ(handle4, OCGetResourceHandle(5)); + EXPECT_EQ(handle5, OCGetResourceHandle(6)); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, BindEntityHandlerBad) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, + "core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + EXPECT_EQ(OC_STACK_INVALID_PARAM, OCBindResourceHandler(handle, NULL)); + EXPECT_EQ(OC_STACK_INVALID_PARAM, OCBindResourceHandler(NULL, NULL)); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + + +OCEntityHandlerResult entityHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest) { + OC_LOG(INFO, TAG, "Entering entityHandler"); + + return OC_EH_OK; +} + +TEST(StackTest, BindEntityHandlerGood) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, + "core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + OCEntityHandler myHandler = entityHandler; + + EXPECT_EQ(OC_STACK_OK, OCBindResourceHandler(handle, myHandler)); + + EXPECT_EQ(myHandler, OCGetResourceHandler(handle)); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, DeleteHeadResource) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + uint8_t numResources = 0; + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(0, numResources); + + OCResourceHandle handle0; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle0, + "core.led", + "core.rw", + "/a/led0", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(1, numResources); + + EXPECT_EQ(OC_STACK_OK, OCDeleteResource(handle0)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(0, numResources); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, DeleteHeadResource2) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + uint8_t numResources = 0; + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(0, numResources); + + OCResourceHandle handle0; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle0, + "core.led", + "core.rw", + "/a/led0", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(1, numResources); + + OCResourceHandle handle1; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle1, + "core.led", + "core.rw", + "/a/led1", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(2, numResources); + + EXPECT_EQ(OC_STACK_OK, OCDeleteResource(handle0)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(1, numResources); + + EXPECT_EQ(handle1, OCGetResourceHandle(0)); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + + +TEST(StackTest, DeleteLastResource) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + uint8_t numResources = 0; + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(0, numResources); + + OCResourceHandle handle0; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle0, + "core.led", + "core.rw", + "/a/led0", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(1, numResources); + + OCResourceHandle handle1; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle1, + "core.led", + "core.rw", + "/a/led1", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(2, numResources); + + EXPECT_EQ(OC_STACK_OK, OCDeleteResource(handle1)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(1, numResources); + + EXPECT_EQ(handle0, OCGetResourceHandle(0)); + + OCResourceHandle handle2; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle2, + "core.led", + "core.rw", + "/a/led2", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(2, numResources); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, DeleteMiddleResource) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + uint8_t numResources = 0; + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(0, numResources); + + OCResourceHandle handle0; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle0, + "core.led", + "core.rw", + "/a/led0", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(1, numResources); + + OCResourceHandle handle1; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle1, + "core.led", + "core.rw", + "/a/led1", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(2, numResources); + + OCResourceHandle handle2; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle2, + "core.led", + "core.rw", + "/a/led2", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(3, numResources); + + EXPECT_EQ(OC_STACK_OK, OCDeleteResource(handle1)); + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(2, numResources); + + EXPECT_EQ(handle0, OCGetResourceHandle(0)); + EXPECT_EQ(handle2, OCGetResourceHandle(1)); + + // Make sure the resource elements are still correct + uint8_t numResourceInterfaces; + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceInterfaces(handle2, &numResourceInterfaces)); + EXPECT_EQ(1, numResourceInterfaces); + const char *resourceInterfaceName = OCGetResourceInterfaceName(handle2, 0); + EXPECT_STREQ("core.rw", resourceInterfaceName); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, GetResourceProperties) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, + "core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + + EXPECT_EQ(OC_ACTIVE|OC_DISCOVERABLE|OC_OBSERVABLE, OCGetResourceProperties(handle)); + EXPECT_EQ(OC_STACK_OK, OCDeleteResource(handle)); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, StackTestResourceDiscoverOneResourceBad) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, + "core.led", + "core.rw", + "/a1/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + const char *url = OCGetResourceUri(handle); + EXPECT_STREQ("/a1/led", url); + + //EXPECT_EQ(OC_STACK_INVALID_URI, OCHandleServerRequest(&res, uri, query, req, rsp)); + EXPECT_EQ(OC_STACK_OK, OCDeleteResource(handle)); + uint8_t numResources = 0; + EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources)); + EXPECT_EQ(0, numResources); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, StackTestResourceDiscoverOneResource) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, + "core.led", + "core.rw", + "/a/led", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + const char *url = OCGetResourceUri(handle); + EXPECT_STREQ("/a/led", url); + + //EXPECT_EQ(OC_STACK_OK, OCHandleServerRequest(&res, uri, query, req, rsp)); + EXPECT_EQ(OC_STACK_OK, OCDeleteResource(handle)); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + +TEST(StackTest, StackTestResourceDiscoverManyResources) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + + /*Get Ip address on defined interface and initialize coap on it with random port number + * this port number will be used as a source port in all coap communications*/ + OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)); + + OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port); + EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER)); + + OCResourceHandle handle1; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle1, + "core.led", + "core.rw", + "/a/led1", + 0, + OC_DISCOVERABLE)); + const char *url = OCGetResourceUri(handle1); + EXPECT_STREQ("/a/led1", url); + + OCResourceHandle handle2; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle2, + "core.led", + "core.rw", + "/a/led2", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + url = OCGetResourceUri(handle2); + EXPECT_STREQ("/a/led2", url); + + EXPECT_EQ(OC_STACK_OK, OCBindResourceTypeToResource(handle2, "core.brightled")); + EXPECT_EQ(OC_STACK_OK, OCBindResourceTypeToResource(handle2, "core.colorled")); + + OCResourceHandle handle3; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle3, + "core.led", + "core.rw", + "/a/led3", + 0, + OC_DISCOVERABLE|OC_OBSERVABLE)); + url = OCGetResourceUri(handle3); + EXPECT_STREQ("/a/led3", url); + + EXPECT_EQ(OC_STACK_OK, OCBindResourceInterfaceToResource(handle3, "oc.mi.ll")); + EXPECT_EQ(OC_STACK_OK, OCBindResourceInterfaceToResource(handle3, "oc.mi.b")); + + OCResourceHandle handle4; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle4, + "core.led", + "core.rw", + "/a/led4", + 0, + OC_DISCOVERABLE)); + url = OCGetResourceUri(handle4); + EXPECT_STREQ("/a/led4", url); + + EXPECT_EQ(OC_STACK_OK, OCBindResourceTypeToResource(handle4, "core.brightled")); + EXPECT_EQ(OC_STACK_OK, OCBindResourceInterfaceToResource(handle4, "oc.mi.ll")); + EXPECT_EQ(OC_STACK_OK, OCBindResourceInterfaceToResource(handle4, "oc.mi.b")); + + //EXPECT_EQ(OC_STACK_OK, OCHandleServerRequest(&res, uri, query, req, rsp)); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} + + +#if 0 +TEST(StackTest, StackTestResourceDiscoverIfFilteringBad) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + char uri[] = "/oc/core"; + char query[] = "if"; + char req[1024] = {}; + char rsp[1024] = {}; + //OCServerRequestResult res; + + //EXPECT_EQ(OC_STACK_INVALID_QUERY, OCHandleServerRequest(&res, uri, query, req, rsp)); +} + +TEST(StackTest, StackTestResourceDiscoverRtFilteringBad) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + char uri[] = "/oc/core"; + char query[] = "rt"; + char req[1024] = {}; + char rsp[1024] = {}; + //OCServerRequestResult res; + + //EXPECT_EQ(OC_STACK_INVALID_QUERY, OCHandleServerRequest(&res, uri, query, req, rsp)); +} +TEST(StackTest, StackTestResourceDiscoverIfFiltering) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + char uri[] = "/oc/core"; + char query[] = "if=oc.mi.ll"; + char req[1024] = {}; + char rsp[1024] = {}; + //OCServerRequestResult res; + + //EXPECT_EQ(OC_STACK_OK, OCHandleServerRequest(&res, uri, query, req, rsp)); +} + +TEST(StackTest, StackTestResourceDiscoverRtFiltering) { + uint8_t addr[20]; + uint16_t port = USE_RANDOM_PORT; + uint8_t ifname[] = "eth0"; + char uri[] = "/oc/core"; + char query[] = "rt=core.brightled"; + char req[1024] = {}; + char rsp[1024] = {}; + //OCServerRequestResult res; + + //EXPECT_EQ(OC_STACK_OK, OCHandleServerRequest(&res, uri, query, req, rsp)); +} +#endif diff --git a/resource/docs/Doxyfile b/resource/docs/Doxyfile new file mode 100644 index 000000000..27e9c0ff7 --- /dev/null +++ b/resource/docs/Doxyfile @@ -0,0 +1,1856 @@ +# Doxyfile 1.8.2 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = "C++ SDK" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = "M1 Release" + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = docs + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. Note that you specify absolute paths here, but also +# relative paths, which will be relative from the directory where doxygen is +# started. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 16 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, +# and language is one of the parsers supported by doxygen: IDL, Java, +# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, +# C++. For instance to make doxygen treat .inc files as Fortran files (default +# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note +# that for custom extensions you also need to set FILE_PATTERNS otherwise the +# files are not read by doxygen. + +EXTENSION_MAPPING = + +# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all +# comments according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you +# can mix doxygen, HTML, and XML commands with Markdown formatting. +# Disable only in case of backward compatibilities issues. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented classes, +# or namespaces to their corresponding documentation. Such a link can be +# prevented in individual cases by by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES (the +# default) will make doxygen replace the get and set methods by a property in +# the documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +SYMBOL_CACHE_SIZE = 0 + +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 125 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = doxygenLayout.xml + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = . \ + ../include/OCApi.h \ + ../include/OCPlatform.h \ + ../include/OCPlatformHandler.h \ + ../include/OCResourceRequest.h \ + ../include/OCResourceResponse.h \ + ../include/OCResource.h \ + ../include/OCResourceHandler.h \ + guides \ + ../RELEASE.txt + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.for \ + *.vhd \ + *.vhdl \ + *.txt + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = img + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C, C++ and Fortran comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = html/footer.html + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If left blank doxygen will +# generate a default style sheet. Note that it is recommended to use +# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this +# tag will in the future become obsolete. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional +# user-defined cascading style sheet that is included after the standard +# style sheets created by doxygen. Using this option one can overrule +# certain style aspects. This is preferred over using HTML_STYLESHEET +# since it does not replace the standard style sheet and is therefor more +# robust against future updates. Doxygen will copy the style sheet file to +# the output directory. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of +# entries shown in the various tree structured indices initially; the user +# can expand and collapse entries dynamically later on. Doxygen will expand +# the tree to such a level that at most the specified number of entries are +# visible (unless a fully collapsed tree already exceeds this amount). +# So setting the number of entries 1 will produce a full collapsed tree by +# default. 0 is a special value representing an infinite number of entries +# and will result in a full expanded tree by default. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely +# identify the documentation publisher. This should be a reverse domain-name +# style string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. + +GENERATE_TREEVIEW = YES + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you may also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to +# the MathJax Content Delivery Network so you can quickly see the result without +# installing MathJax. However, it is strongly recommended to install a local +# copy of MathJax from http://www.mathjax.org before deployment. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. For each +# tag file the location of the external documentation should be added. The +# format of a tag file without this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths +# or URLs. Note that each tag file must have a unique name (where the name does +# NOT include the path). If a tag file is not located in the directory in which +# doxygen is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = NO + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside +# the class node. If there are many fields or methods and many nodes the +# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS +# threshold limits the number of items for each type to make the size more +# managable. Set this to 0 for no limit. Note that the threshold may be +# exceeded by 50% before the limit is enforced. + +UML_LIMIT_NUM_FIELDS = 10 + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/resource/docs/doxygenLayout.xml b/resource/docs/doxygenLayout.xml new file mode 100644 index 000000000..6cc3fa7df --- /dev/null +++ b/resource/docs/doxygenLayout.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/resource/docs/guides/AboutOIC.txt b/resource/docs/guides/AboutOIC.txt new file mode 100644 index 000000000..04ee0bc0f --- /dev/null +++ b/resource/docs/guides/AboutOIC.txt @@ -0,0 +1,51 @@ +/*! + +@page AboutOIC About Open Interconnect Consortium + +@section WhoAreWe Who are we? + +\li We want to connect the next 25 billion devices for the Internet of Things. + +\li We want to provide secure and reliable device discovery and connectivity across multiple OSs and platforms. + +\li There are multiple proposals and forums driving different approaches... but no single solution addresses the majority of key requirements. + +\li We need industry consolidation around a common, interoperable approach. + +\li We need a broad industry consortium of companies to create a scalable solution. + + +@section WhyAreWeDoingThis Why are we doing this? + +\li We are defining the specification, certification & branding to deliver reliable interoperability - a connectivity framework that abstracts complexity + +\li This standard will be an open specification that anyone can implement and is easy for developers to use + +\li It will include IP protection & branding for certified devices (via compliance testing) and service-level interoperability + +\li There will also be an Open Source implementation of the standard + +\li This Open Source implementation will be designed to enable application developers and device manufacturers to deliver interoperable products across Android, iOS, Windows, Linux, Tizen, and more. + +@section WhoNeedsThis Who needs this? + +\li Consumers, Enterprise, Industrial, Automotive, Health, etc. who want smart devices to easily interconnect and communicate with appliances, embedded devices, etc. + +\li Developers of operating systems, platforms, and applications who want their products to interoperate seamlessly across many brands and ecosystems. + +\li End users who want consistent levels of security and identity across smart devices down to the smallest connected appliance + +@section HowWillWeDeliverIt How will we deliver it? + +\li Our goal is to define a comprehensive communications framework to enable emerging applications in all key vertical markets. + +\li The framework must enable multiple new modes of communication, such as Peer-to-Peer, Mesh & Bridging, Reporting & Control, etc. + +\li The framework should include a consistent implementation of identity, authentication and security across the modes of User ID, Enterprise / Industrial ID & Credentials. + +\li It should include a sense of proximity for the Internet of Things and Wearable devices and include support for Onboarding and Provisioning. + +\li And the framework must support a "building block" architecture and provide an Open Source implementation + + +*/ \ No newline at end of file diff --git a/resource/docs/guides/Home.txt b/resource/docs/guides/Home.txt new file mode 100644 index 000000000..5202e8a8b --- /dev/null +++ b/resource/docs/guides/Home.txt @@ -0,0 +1,15 @@ +/*! + +@mainpage Welcome + +IoTivity runs as an open source project. This infrastructure can be used by OIC partners to contribute and co-work for the project. This document is for any developer trying to utilize the IoTivity project in building applications. This document includes: + +\li \ref OCGuides - High level overview of the API and how to use them + +\li \ref OCHowTo - contains guides and tutorials to help developers get started + +\li API Reference - provides a reference to all public APIs available to utilize the power of IoTivity. + + + +*/ diff --git a/resource/docs/guides/HowToGuidesIndex.txt b/resource/docs/guides/HowToGuidesIndex.txt new file mode 100644 index 000000000..0d8c717b7 --- /dev/null +++ b/resource/docs/guides/HowToGuidesIndex.txt @@ -0,0 +1,1556 @@ +/*! + +@page OCHowTo How To... Guides + +@ref Guide_Representative_Devices "Sample representative devices used in these tutorials" + +@ref Guide_Stack_Init "How to initialize the stack" + +@ref Guide_Register_Resource "How to register a resource" + +@ref Guide_Find_Resource "How to find a resource" + +@ref Guide_PUT "How to set resource state [PUT]" + +@ref Guide_GET "How to query resource state [GET]" + +@ref Guide_Observe "How to observe resource state [Observe]" + + + +******************************************************************** + + +@page Guide_Representative_Devices Representative Devices + +The best way to understand the concepts for IoTivity is through following an example and understanding the use case. The following devices are referred to throughout this document for use cases and basic operations. The details are listed here for reference so that implementers can compare the responses from these devices with their configuration to develop an understanding of what the responses mean. + +@section Rep_Light_Device Light devices (192.168.1.11-13) + +A lighting device that can handle up to two light bulbs with dimmers. Each light bulb resource has two attributes: +\li Power: controls power and can have a value of 0 (off) or 1 (on) +\li Level: current dimmer level with a value from 1 (low) to 10 (full) + +The separation of the attributes allows the light to return to the previous light level when the power is toggled. + +@subsection Rep_Light_Device_Description Description of resources on this device type + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ResourceDescription

/oc/core

Standard resource listing in JSON format.

/oc/core/d

Virtual (hidden) resource that describes the device. It is searchable and supports the JSON attributes listed in the appendix.

/lights

The resource collection that contains light resources

+ +

rt=alpha.light

+ +

if=oc.mi.ll (linked-list)

/light/1

The resource associated with the first light bulb attached to this device

+ +

rt=alpha.light

+ +

if=oc.mi.def (default)

/light/2

The resource associated with the second light bulb attached to this device

+ +

rt=alpha.light

+ +

if=oc.mi.def (default)

+ + + +@subsection Rep_Light_Device_Resource_11 Resource(s) at 192.168.1.11 + +This device contains a single light resource. The following lists the valid resources and their typical state: + + + + + + + + + + + + + + + + + + + + + + + +
ResourceRepresentation

/oc/core

[

+ +

{ "href" : "/lights", "rt" : ["alpha.light"], "if" : ["oc.mi.ll"]},

+ +

{ "href" : "/light/1", "rt" : ["alpha.light"], "if" : ["oc.mi.def"], "obs" : 1}

+ +

]

/oc/core/d

{

+ +

"di" : "12345678-1234-1234-0000000000000011",

+ +

"dn" : "Alpha Light Controller",

+ +

"dd" : "A Light Controller"

+ +

}

/light/1

{ "power" : 0, "level" : 4 }

+ + + + +@subsection Rep_Light_Device_Resource_12 Resource(s) at 192.168.1.12 + +This device contains a single light resource. The following lists the valid resources and their typical state: + + + + + + + + + + + + + + + + + + + + + + + +
ResourceRepresentation

/oc/core

[

+ +

{ "href" : "/lights", "rt" : ["alpha.light"], "if" : ["oc.mi.ll"]},

+ +

{ "href" : "/light/2", "rt" : ["alpha.light"], "if" : ["oc.mi.def"], "obs":1}

+ +

]

/oc/core/d

{

+ +

"di" : "12345678-1234-1234-0000000000000012",

+ +

"dn" : "Alpha Light Controller",

+ +

"dd" : "A Light Controller"

+ +

}

/light/2

{ "power" : 1, "level" : 6 }

+ + + +@subsection Rep_Light_Device_Resource_13 Resource(s) at 192.168.1.13 + +This device contains two light resources. The following lists the valid resources and their typical state: + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Resource

Representation

/oc/core

[

+ +

{ "href" : "/lights", "rt" : ["alpha.light"], "if" : ["oc.mi.ll"]},

+ +

{ "href" : "/light/1", "rt" : ["alpha.light"], "if" : ["oc.mi.def"], "obs":1},

+ +

{ "href" : "/light/2", "rt" : ["alpha.light"], "if" : ["oc.mi.def"], "obs":1}

+ +

]

/oc/core/d

{

+ +

"di" : "12345678-1234-1234-0000000000000013",

+ +

"dn" : "Alpha Light Controller",

+ +

"dd" : "A Light Controller"

+ +

}

/light/1

{ "power" : 0, "level" : 8 }

/light/2

{ "power" : 1, "level" : 10 }

+ + + +@page Guide_Stack_Init Stack Initialization + +@section Stack_Init_SD Sequence Diagram + +@image html seq_stack_init.png + +@note API calls take only important parameters. We omitted some of the parameters for clarity. + +The asynchronous processing block handles incoming network traffic including packet processing, scheduled tasks including communication timeouts and callbacks to the application resulting from these activities. + +@section Stack_Init_CPP Stack Initialization in C++ + +@code {.cpp} + // Create PlatformConfig object + PlatformConfig cfg; + cfg.ipAddress = "134.134.161.33"; + cfg.port = 5683; + cfg.mode = ModeType::Client; + cfg.serviceType = ServiceType::InProc; + + // Create a OCPlatform instance. + // Note: Platform creation is synchronous call. + try + { + OCPlatform platform(cfg); + }catch(OCException& e) + { + //Handle error + } + @endcode + +Stack initialization in C++ consists of: +@li Creating a OCPlatform object with Platform configuration which allows definition of role operation (server or client), stack operation (in-process or out-of-process), etc. +@note +@li This is a synchronous call. The application will receive an exception if platform object creation fails. +@li The C++ SDK handles all of the memory allocation and collection. Therefore, the application need not worry about memory management related to the stack. +@li Platform creation happens on the main thread while the message pump happens on a worker thread. + + + + + +******************************************************************** + +@page Guide_Register_Resource Registering A Resource + +Registering a resource requires two basic items: +\li A handler to process requests from the stack, and +\li A URI path to register the resource. +The URI path should be rooted (in other words, start with a slash). The stack will construct the fully qualified URI by adding the URI authority to the provided URI path. For example, given a service running on port 5683 in a device at IP address 192.168.1.1, if the application registers a resource with a URI path "/light/1", the resulting fully qualified URI is "oc://192.168.1.1:5683/light/1", which uniquely identifies the resource's location (IP address port and path). +@note Only one resource can be registered at a given URI. + +@image HTML seq_register_resource_2.png + +@section Register_Resource_SD Sequence Diagram +The following call sequence diagram outlines the operations performed in the stack when a resource is registered: + +@image HTML seq_register_resource.png + +Step 1: +Assuming the application has created a valid OCPlatform object, the application registers a new resource with the stack by calling OCPlatform::registerResource(...). + +In this example, the call would take the form: + + platform.registerResource(&handle, "/light/1", "light", "oc.mi.def", handler, OC_DISCOVERABLE) + +The handle is a reference to the resource that is used on other APIs. The URI path ("/light/1") is where on this server that the resource can be located. The URI path is unique; this call will fail if the application attempts to register another resource using an existing URI. The resource type ("light") and interface ("oc.mi.def") are properties of the resource used in the discovery process. The handler is a function called from the stack to process requests. The flags control how the stack should handle the resource. The OC_DISCOVERABLE flag indicates that the resource should be reported if a client performs a resource discovery on this server. + +Step 2: + +The OCPlatform::registerResource(...) method delegates the call to the appropriate instance of the stack (in-process or out-of-process via IPC). + +Step 3: +The internal registerResource(...) method constructs a C++ entity handler and registers it with the C SDK using OCCreateResource(...). + +In this example, the call would take the form: + + OCCreateResource(&handle, "light", "oc.mi.def", "/light/1", handler, OC_ DISCOVERABLE) + +Many of these parameters are passed through to the C SDK directly. However, the entity handler is a proxy function for the handler passed from OCPlatform::registerResource(...). + +@section Register_Resource_CPP Register Resource in C++ [Server] + +@code{.cpp} + OCResourceHandle resourceHandle; + std::string resourceURI = "/light/1"; + std::string resourceTypeName = "alpha.light + std::string resourceInterface = DEFAULT_INTERFACE; + uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE; + + OCStackResult result = platform.registerResource(resourceHandle, + resourceURI, + resourceTypeName, + resourceInterface, + &entityHandler, + resourceProperty); + + if (OC_STACK_OK == result) + { + //Successfull + } + + +@endcode + + + +******************************************************************** + +@page Guide_Find_Resource Finding A Resource + +This operation returns all resources of given type on the network service. This operation is sent via multicast to all services. However, the filter limits the responders to just those that support the resource type in the query. Currently only exact matches are supported. + +@image HTML seq_find_resource_2.png + +@section Find_Resource_SD Sequence Diagram + +The following sequence diagram illustrates the resource discovery process over the network when using CoAP. The mechanism is different for Bluetooth, SSDP/HTTP, etc. In the case of CoAP, a 'get' request is sent via multicast to all IoTivity devices. Each device processes the query and responds if the request filter is satisfied. + +In the following example, the client requests all of the light resources with a resource type (rt). Both lights respond to the request, but the fan does not. + +@image HTML seq_find_resource_3.png + + +The following sequence diagram describes the call sequence for discovery from the client side. +@image HTML seq_find_resource.png + +Notes: +\li Assuming that the client has a properly initialized OCPlatform object, a C++ SDK client can discover resources by calling OCPlatform::findResources(...). + +In this example, the call would take the form: + + platform.findResources("", "/oc/core?rt=alpha.light", findHandler) + +The first parameter is the URI authority (target host), which, when empty, indicates that this is for all nodes. The second parameter ("/oc/core?rt=alpha.light") is the URI path and URI query. The URI path ("/oc/core") indicates the resource and the URI query ("rt=alpha.light") is the filter. + +\li The SDK call findResources(...) internally delegates the call directly to the in-process or to the out-of process stack via IPC based on the stack configuration. +\li Within the stack, findResource(...) calls the C API function OCDoResource(...). In this example, the call is OCDoResource(&handle, OC_REST_GET, "/oc/core?rt=alpha.light", 0, 0, OC_NON_CONFIRMABLE, ...) +\li OCDoResource determines which transport is needed to dispatch the request and delegates the call. In the case of CoAP, the following calls are made: + - Calls OCDoCoapResource(OC_REST_GET, OC_NON_CONFIRMABLE, token, "/oc/core?rt=alpha.light", 0). The token in this example is a nonce that ties a CoAP response back to the CoAP request. Internally, this method creates the CoAP PDU for dispatching. + - Calls coap_send(context, host, pdu), which is a wrapper for the implementation below. + - Calls coap_send_impl(context, host, packet), which dispatches the packet to the socket and does the appropriate CoAP bookkeeping. + - Calls OCSend(socket, buffer, size...), which is a wrapper for the socket implementation as the functions for dispatching a UDP packet can vary in the embedded systems. +\li Servers that offer the resource on the network will reply to the query. The message pump that is evoked from the OCProcess(...) function in the C SDK receives these response packets and dispatches them to the callback associated with the original request based on the CoAP message ID. These responses will come back at the timing defined by their servers. The client stack has timeouts for these responses that are listed in the appendices. +\li As previously mentioned, the stack matches the response to the original request using the message ID and send the results to the callback associated with the request. At this level, the raw payload is presented in JSON format. It is the responsibility of the callback passed to OCDoResource(...) to parse this result. +\li The C++ SDK provides a callback to OCDoResource(...) that will parse the results, construct collections of OCResource objects from the response, and pass them to a C++ client using the handler passed to the platform.findResource(...) method. The handler will be called once for each resource server that responds to the query. + +Notes: +\li Some of the API call parameters have been omitted for brevity. +\li The findResource() method can be used in the following ways: + - Find all resources on the network that match the provided criteria + - Query a specific (single) server for the resources that it provides matching the provided criteria +\li The findResource() method may be used multiple times to find a resource +\li The findResource() callback is called from the message pump thread in multithreaded environments +\li Blocking in the findResource() callback will block other stack processing including servicing the network I/O which can cause delays and missed packets. + +Detailed server call sequence diagram +The following sequence diagram illustrates the call sequence for discovery from the server side. + +@note When the request is sent to all nodes, all nodes will run through this sequence. + +@image HTML seq_find_resource_4.png + +Notes: +\li The discovery request under CoAP is handled like any other resource GET request. The request can be received via unicast or multicast, but the response, if any, is always sent via unicast. +\li The stack dispatches the request to an entity handler that is defined by the stack. +\li The handler for "/oc/core", processes the URI query, if any, and builds a list of resources that match the criteria and returns the result in JSON to the network transport. +\li In the case of CoAP, if the request is made to all nodes (multicast) and the resource list is empty, no response is sent to the clients. If the request is directed (unicast) or the resource list has results, the response is sent unicast back the client. + + +@section Find_Resource_CPP Register Resource in C++ [Client] + +@code{.cpp} +// Callback to found resources + void foundResource(std::shared_ptr resource) + { + + std::string resourceURI; + std::string hostAddress; + try + { + // Do some operations with resource object. + if(resource) + { + std::cout<<"DISCOVERED Resource:"<uri(); + std::cout << "\tURI of the resource: " << resourceURI << std::endl; + + // Get the resource host address + hostAddress = resource->host(); + std::cout << "\tHost address of the resource: " << hostAddress << std::endl; + + // Get the resource types + std::cout << "\tList of resource types: " << std::endl; + for(auto &resourceTypes : resource->getResourceTypes()) + { + std::cout << "\t\t" << resourceTypes << std::endl; + } + + // Get the resource interfaces + std::cout << "\tList of resource interfaces: " << std::endl; + for(auto &resourceInterfaces : resource->getResourceInterfaces()) + { + std::cout << "\t\t" << resourceInterfaces << std::endl; + } + + if(resourceURI == "/a/light1") + { + // Found interested resource + } + } + else + { + // Resource is invalid + std::cout << "Resource is invalid" << std::endl; + } + + } + catch(std::exception& e) + { + //log + } + + } + + + try + { + OCPlatform platform(cfg); + + // Find all resources + platform.findResource("", "coap://224.0.1.187/oc/core?rt=alpha.light", &foundResource); + + }catch(OCException& e) + { + //Handle Error + } + + +@endcode + +@section Find_Resource_OTA_Request Over the air Request + +The request is sent to all nodes on the network: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Field

Value

Note(s)

Address

224.0.1.187:5683

Multicast packet

Header

NON, GET, MID=0x7d40

Multicast discovery request should be non-confirmable

URI-Path

oc

"/oc/core?rt=alpha.light"

URI-Path

core

URI-Query

rt=alpha.light


+

Accept

application/json


+

+ + + +@section Find_Resource_OTA_Response Over the air Response(s) + +Assuming that all of the representative devices (see @ref Guide_Representative_Devices "Representative Devices") are online, three responses are expected. Only the three devices with light resources respond; the list of resources has been filtered to contain just the resources that match the criteria. + +From 192.168.1.11: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Field

Value

Explanation

Address

192.168.1.1:5683

Client Address

Header

ACK, CONTENT, MID=0x7d40

Success w/content

Content

+ +

Format

application/json


+

Payload

[

+ +

{ "href" : "/light/1", "rt":["alpha.light"], "if":["oc.mi.def"], "obs":1}

+ +

]


+

+ +From 192.168.1.12: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Field

Value

Explanation

Address

192.168.1.1:5683

Client Address

Header

ACK, CONTENT, MID=0x7d40

Success w/content

Content

+ +

Format

application/json


+

Payload

[

+ +

{ "href" : "/light/2", "rt":["alpha.light"], "if":["oc.mi.def"], "obs":1}

+ +

]


+

+ + + +From 192.168.1.13: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Field

Value

Explanation

Address

192.168.1.1:5683

Client Address

Header

ACK, CONTENT, MID=0x7d40

Success w/content

Content

+ +

Format

application/json


+

Payload

[

+ +

{ "href" : "/light/1", "rt":["alpha.light"], "if":["oc.mi.def"], "obs":1},

+ +

{ "href" : "/light/2", "rt":["alpha.light"], "if":["oc.mi.def"], "obs":1}

+ +

]


+

+ + + +******************************************************************** + +@page Guide_PUT Setting a resource state [PUT] + +This operation sets the value of a simple resource. In this example, we turn on a light resource and set the brightness to 50%. + +@section PUT_SD Sequence Diagram + +@image HTML seq_put.png + +Steps: +1. The client application calls resource.put(...) to set representation of resource. +Example call: +resource.put(attributeMap, queryParamsMap, &onPut); +2. Client SDK internally calls the setResourceAttributes function of the client wrapper. +Example call: +OCDoResource(OC_REST_PUT, "//192.168.1.11/light/1, 0, 0, OC_CONFIRMABLE, callback); +3. Send PUT request to remote device +4. The OCProcess() service function (server-side message pump) reads the packet from the socket and dispatches the request to the entity handler for the provided URI. +5. The entity handler, which was provided by an upper layer when the resource was registered, parses the representation and in the case of the C++ API passes the results to the upper layer handler. In a C only environment, the results would also be processed in the entity handler. +6. The upper layer entity handler written by the app developer/vendor is invoked, and response is formed accordingly. +7. The upper layer entity handler returns success or failure with a response. +8. Returns success or failure to lower layer for transmission to client. +9. Returns success or failure to lower layer for transmission to client. +10. Returns success or failure to lower layer for transmission to client. +11. Result is formatted and sent over network to client +12. The OCProcess() service function (client-side message pump) reads results and passes the results back to the client application via the callback passed to OCDoResource + + +@section PUT__Client_CPP Set Resource's State [PUT] in C++ [Client] + +@code{.cpp} +void putLightRepresentation(std::shared_ptr resource) +{ + if(resource) + { + OCRepresentation rep; + + std::cout << "Putting light representation..."<put(rep, queryParamsMap, &onPut); + } +} + +// callback handler on PUT request +void onPut(const OCRepresentation& rep, const int eCode) +{ + if(eCode == SUCCESS_RESPONSE) + { + std::cout << "PUT request was successful" << std::endl; + + AttributeMap attributeMap = rep.getAttributeMap(); + + for(auto it = attributeMap.begin(); it != attributeMap.end(); ++it) + { + std::cout << "\tAttribute name: "<< it->first << " value: "; + for(auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr) + { + std::cout <<"\t"<< *valueItr << " "; + } + + std::cout << std::endl; + } + + std::vector children = rep.getChildren(); + + for(auto oit = children.begin(); oit != children.end(); ++oit) + { + attributeMap = oit->getAttributeMap(); + + for(auto it = attributeMap.begin(); it != attributeMap.end(); ++it) + { + std::cout << "\tAttribute name: "<< it->first << " value: "; + for(auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr) + { + std::cout <<"\t"<< *valueItr << " "; + } + + std::cout << std::endl; + } + } + + } + else + { + std::cout << "onPut Response error: " << eCode << std::endl; + std::exit(-1); + } +} + +@endcode + +@section PUT_Server_CPP Set Resource's State [PUT] in C++ [Server] + +@code{.cpp} +//Entity handle sample for PUT + if(requestType == "PUT") + { + cout << "\t\t\trequestType : PUT\n"; + + // Check for query params (if any) + QueryParamsMap queryParamsMap = request->getQueryParameters(); + + cout << "\t\t\tquery params: \n"; + for(auto it = queryParamsMap.begin(); it != queryParamsMap.end(); it++) + { + cout << "\t\t\t\t" << it->first << ":" << it->second << endl; + } + + // Get the representation from the request + OCRepresentation rep = request->getResourceRepresentation(); + + myLightResource.setRepresentation(rep); // See code snippet below + + // Do related operations related to PUT request // See code snippet below + rep = myLightResource.getRepresentation(); + + if(response) + { + + response->setErrorCode(200); + + auto findRes = queryParamsMap.find("if"); + + if(findRes != queryParamsMap.end()) + { + response->setResourceRepresentation(rep, findRes->second); + } + else + { + response->setResourceRepresentation(rep, DEFAULT_INTERFACE); + } + } +} + + void setRepresentation(OCRepresentation& light) + { + AttributeMap attributeMap = light.getAttributeMap(); + + if(attributeMap.find("state") != attributeMap.end() && attributeMap.find("power") != attributeMap.end()) + { + cout << "\t\t\t" << "Received representation: " << endl; + cout << "\t\t\t\t" << "power: " << attributeMap["power"][0] << endl; + cout << "\t\t\t\t" << "state: " << attributeMap["state"][0] << endl; + + m_state = attributeMap["state"][0].compare("true") == 0; + m_power= std::stoi(attributeMap["power"][0]); + } + } + + OCRepresentation getRepresentation() + { + OCRepresentation light; + + light.setUri(m_lightUri); + + std::vector interfaces; + //interfaces.push_back(m_lightInterface); + + light.setResourceInterfaces(interfaces); + + std::vector types; + //types.push_back(m_lightType); + + light.setResourceTypes(types); + + AttributeMap attributeMap; + AttributeValues stateVal; + if(m_state) + { + stateVal.push_back("true"); + } + else + { + stateVal.push_back("false"); + } + + AttributeValues powerVal; + powerVal.push_back(to_string(m_power)); + + attributeMap["state"] = stateVal; + attributeMap["power"] = powerVal; + + light.setAttributeMap(attributeMap); + + return light; + } + +@endcode + + +@section PUT_OTA_Response Over the air request + +In this example, we are pushing state to one of the lights. At this point, the resource was discovered by its type, and we understand its interface and the attributes exposed by the resource. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Field

Value

Note(s)

Address

192.168.1.13:5683

Unicast packet

Header

CON, PUT, MID=0x7d41

Confirmation is requested

URI-Path

light

"/light/1"

URI-Path

1

Content-Type

application/json


+

Payload

{

+ +

"power" : 1,

+ +

"level" : 5

+ +

}


+

+ + +@section PUT_OTA_Response Over the air response(s) + +Assuming that the request is valid and the resource is able to complete the transition, the following represents a successful change in state. + +From 192.168.1.13: + + + + + + + + + + + + + + + + + + + + + +

Field

Value

Explanation

Address

192.168.1.1:5683

Client Address

Header

ACK, CHANGED, MID=0x7d41

Success (changed)

+ + + +********************************************************************** + +@page Guide_GET Querying resource State [GET] + +This operation fetches the value of a simple resource. In this example, we fetch the state from the light resource. + +@section GET_SD Sequence Diagram +@image HTML seq_get.png + +Steps: +1. The client application calls resource.get(...) to retrieve a representation from the resources. +2. The call is marshalled to the stack which is either running in-process or out-of-process (daemon). +3. The C API is called to dispatch the request. The call may look like the following: +OCDoResource(OC_REST_GET, "//192.168.1.11/light/1, 0, 0, OC_CONFIRMABLE, callback); +4. Where CoAP is used as a transport, the lower stack will send a GET request to the target server. +5. On the server side, the OCProcess() function (message pump) receives and parses the request from the socket, then dispatches it to the correct entity handler based on the URI of the request. +6. Where the C++ API is used, the C++ entity handler parses the payload and marshals it to the client application depending on if the server stack is running in-process or out-of-process (daemon). +7. The C++ SDK passes it up the C++ handler associated with the OCResource. +8. The handler returns the result code and representation to the SDK. +9. The SDK marshals the result code and representation to the C++ entity handler. +10. The entity handler returns the result code and representation to the CoAP protocol. +11. The CoAP protocol transports the results to the client device. +12. The results are returned the OCDoResource callback. +13. The results are returned to the C++ client application's asyncResultCallback. + +@section GET_Client_CPP Querying resource State [GET] in C++ [Client] +@code{.cpp} +// Local function to get representation of light resource +void getLightRepresentation(std::shared_ptr resource) +{ + if(resource) + { + std::cout << "Getting Light Representation..."<get(test, &onGet); + } +} + +// callback handler on GET request +void onGet(const OCRepresentation& rep, const int eCode) +{ + if(eCode == SUCCESS_RESPONSE) + { + std::cout << "GET request was successful" << std::endl; + + AttributeMap attributeMap = rep.getAttributeMap(); + + std::cout << "Resource URI: " << rep.getUri() << std::endl; + + for(auto it = attributeMap.begin(); it != attributeMap.end(); ++it) + { + std::cout << "\tAttribute name: "<< it->first << " value: "; + for(auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr) + { + std::cout <<"\t"<< *valueItr << " "; + } + + std::cout << std::endl; + } + + std::vector children = rep.getChildren(); + + for(auto oit = children.begin(); oit != children.end(); ++oit) + { + std::cout << "Child Resource URI: " << oit->getUri() << std::endl; + + attributeMap = oit->getAttributeMap(); + + for(auto it = attributeMap.begin(); it != attributeMap.end(); ++it) + { + std::cout << "\tAttribute name: "<< it->first << " value: "; + for(auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr) + { + std::cout <<"\t"<< *valueItr << " "; + } + + std::cout << std::endl; + } + } + + putLightRepresentation(curResource); + } + else + { + std::cout << "onGET Response error: " << eCode << std::endl; + std::exit(-1); + } +} + + +@endcode + +@section GET_Server_CPP Querying resource State [GET] in C++ [Server] +@code{.cpp} + +// Handling GET request in Entity handler +if(requestType == "GET") + { + cout << "\t\t\trequestType : GET\n"; + + // Check for query params (if any) + QueryParamsMap queryParamsMap = request->getQueryParameters(); + + cout << "\t\t\tquery params: \n"; + for(QueryParamsMap::iterator it = queryParamsMap.begin(); it != queryParamsMap.end(); it++) + { + cout << "\t\t\t\t" << it->first << ":" << it->second << endl; + } + + // Process query params and do required operations .. + + // Get the representation of this resource at this point and send it as response + // AttributeMap attributeMap; + OCRepresentation rep; + rep = myLightResource.getRepresentation(); + + if(response) + { + // TODO Error Code + response->setErrorCode(200); + + auto findRes = queryParamsMap.find("if"); + + if(findRes != queryParamsMap.end()) + { + response->setResourceRepresentation(rep, findRes->second); + } + else + { + response->setResourceRepresentation(rep, DEFAULT_INTERFACE); + } + } + } + + +@endcode + + +@section GET_OTA_Response Over the air request + +In this example, we are querying state from one of the lights. At this point, the resource was discovered by its type, and we understand its interface and the attributes that the resource exposes. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Field

Value

Note(s)

Address

192.168.1.11:5683

Unicast packet

Header

CON, GET, MID=0x7d42

Confirmation is requested

URI-Path

light

"/light/1"

URI-Path

1

Accept

application/json


+

+ + + +@section GET_OTA_Response Over the air response(s) + +Assuming that the request is valid, we expect the following reply from the resource. + +From 192.168.1.11: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Field

Value

Explanation

Address

192.168.1.1:5683

Client Address

Header

ACK, CONTENT, MID=0x7d42

Success w/Content

Content

+ +

Type

application/json


+

Payload

{

+ +

"power" : 0,

+ +

"level" : 10

+ +

}


+

+ + + + +********************************************************************** + +@page Guide_Observe Observing resource state [Observe] + +This operation fetches and registers as an observer for the value of a simple resource. In this example, we fetch the state of the light resource. For more implementation details, see "Observing Resources in CoAP" listed in the referenced documents. (https://datatracker.ietf.org/doc/draft-ietf-core-observe/?include_text=1) + +The handling of observation registration is application specific. It should not be assumed that a resource is observable, or a resource can handle any specific number of observers. If the server responds with a success (2.xx) code, the registration is considered successful. + +Notifications from the server to the client may be confirmable or non-confirmable. If the client returns a RST message, the observation registration should be dropped immediately. If the client fails to acknowledge a number of confirmable requests, the server should assume that the client has abandoned the observation and drop the registration. + +If the observed resource is removed, the server sends a NOTFOUND status to all observers. + +If an observed resource fails to notify a client before the max-age of a resource value update, the client should attempt to re-register the observation. + + +@section Observe_SD Sequence Diagram +@image HTML seq_observe.png + +Steps: +1. The client application calls resource.observe(...) to retrieve a representation from the resources. +2. The call is marshalled to the stack which is either running in-process or out-of-process (daemon). +3. The C API is called to dispatch the request. The call may look like this: +OCDoResource(OC_REST_GET | OC_REST_OBSERVE, "//192.168.1.11/light/1, 0, 0, OC_CONFIRMABLE, callback); +4. Where CoAP is used as a transport, the lower stack will send a GET request to the target server. The primary difference between a GET request and an observe request is that the observe request contains an observe option indicating that, in addition to querying this resource, the client wishes to get notifications if/when the resource state changes. +5. On the server side, the OCProcess() function (message pump) receives and parses the request from the socket, then dispatches it to the correct entity handler based on the URI of the request. The request to the entity handler will indicate that the request is both a query and subscription request. The entity handler MAY take note of this, but it is not responsible to tracking the observers. The stack tracks the observers of record. +6. Where the C++ API is used the C++ entity handler parses the payload and marshals it to the client application depending on if the server stack is running in-process or out-of-process (daemon). +7. The C++ SDK passes it up the C++ handler associated with the OCResource. +8. The handler returns the result code and representation to the SDK. +9. The SDK marshals the result code and representation to the C++ entity handler. +10. The entity handler returns the result code and representation to the CoAP protocol. +11. The CoAP protocol transport the results to the client device. +12. The results are returned to the OCDoResource callback. +13. The results are returned to the C++ client application's asyncResultCallback. +14. If the entity handler has registered observers, it will periodically be called with the observe flag set so that it may sample or poll underlying hardware to determine if the state has changes. +15. When the application has deemed that the resource state has changed either via polling (entity handler observe) or via external signal, the application should call OCNotifyObservers(). This tells the stack the observers need updating. +16. For each observer of a changed resource, the entity handler is called to generate a representation that is transmitted to the observing clients. +17. Where CoAP is used as a transport, a packet with content is sent to the devices that have observing clients. The packets may be confirmable or non-confirmable based on application needs. +18. The client-side OCProcess function (message pump) receives the message and matches it to the original request based on the CoAP token ID and dispatches the appropriate +C API callback. +19. The C API callback passes the final results to the C++ client application's asyncResultCallback. +20. When the C++ client no longer desires to receive notifications from the server, it calls observation cancellation method cancelObserve(). +21. The C++ cancellation method calls the OCCancel() function from the C API. +22. OCCancel() finds the observation that is associated with the operation and sends an observe deregistration request to the server. + + +@section Observe_Client_CPP Observing resource state [Observe] in C++ [Client] +@code{.cpp} + if (OBSERVE_TYPE_TO_USE == ObserveType::Observe) + std::cout << endl << "Observe is used." << endl << endl; + else if (OBSERVE_TYPE_TO_USE == ObserveType::ObserveAll) + std::cout << endl << "ObserveAll is used." << endl << endl; + + QueryParamsMap test; + + curResource->observe(OBSERVE_TYPE_TO_USE, test, &onObserve); + +// callback +void onObserve(const OCRepresentation& rep, const int& eCode, const int& sequenceNumber) +{ + if(eCode == SUCCESS_RESPONSE) + { + AttributeMap attributeMap = rep.getAttributeMap(); + + std::cout << "OBSERVE RESULT:"<first << " value: "; + for(auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr) + { + std::cout <<"\t"<< *valueItr << " "; + } + + std::cout << std::endl; + } + + if(observe_count() > 30) + { + std::cout<<"Cancelling Observe..."<cancelObserve(); + + std::cout << "Cancel result: "<< result < + +

Fields

+

Value

+

Notes

+ + + +

Address

+

192.168.1.11:5683

+

Unicast packet

+ + + +

Header

+

CON, GET, MID=0x7d44, TOK=0x3f

+

Confirmation requested

+ + + +

Observe

+

Register (0)

+

This indicates registration

+ + + +

URI-Path

+

Light

+

"/light/1 "

+ + + +

URI-Path

+

1

+


+

+ + + +

Accept

+

application/json

+

Requesting result in JSON

+ + + + + + +@section Observe_OTA_Response Over the air response(s) + +A successful observe request would be similar to the following: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Field

Value

Explanation

Address

192.168.1.1:5683

Client Address

Header

ACK, CONTENT, MID=0x7d44, TOK=0x3f

Success w/content

Observe

12

Sequence number for ordering

Max-Age

30

Indicates that the value is fresh for 30 seconds.

+ +

It also indicates that the server should send an

+ +

update within this time period.

Content

+ +

Type

application/json


+

Payload

{

+ +

"power" : 0,

+ +

"level" : 10

+ +

}


+

+ +Subsequent Notifications from 192.168.1.1 + +If the light resource is being observed and the light transitions from an off state to an on state, a notification is sent to the client from the server. The following is an example of such a notification: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Field

Value

Explanation

Address

192.168.1.1:5683

Client Address

Header

CON, CONTENT, MID=0x7D45, TOK=0x3f

Content, Can be confirmable or non-confirmable

Observe

15

Monotonically increasing until overflow

Max-Age

30

Indicates that the value is fresh for 30 seconds.

+ +

It also indicates that the server should send an

+ +

update within this time period.

Payload

{

+ +

"power" : 1,

+ +

"level" : 10

+ +

}


+

+ +Since the above notification was marked confirmable, the client should acknowledge the notification with a packet such as the following: + + + + + + + + + + + + + + + + + + + + + +

Field

Value

Explanation

Address

192.168.1.11:5683

Unicast packet

Header

ACK, MID=0x7D45, TOK=0x3f

Success

+ + + + + +********************************************************************** + + +*/ diff --git a/resource/docs/guides/ProgrammersGuide.txt b/resource/docs/guides/ProgrammersGuide.txt new file mode 100644 index 000000000..78f7d46ed --- /dev/null +++ b/resource/docs/guides/ProgrammersGuide.txt @@ -0,0 +1,308 @@ +/*! + + +@page OCGuides Programmer's Guide + + +This document covers the architecture and basic operations of the Iotivity Resource API stack, including sample coverage of protocol, flows, APIs and some use cases. It is intended to provide context for the developers using IoTivity APIs and provide a high level architectural overview. + +@section Stack_Blocks Stack Blocks + +The Resource API stack consists of several thin layers of software. In unconstrained environments such as Android*, iOS*, or Microsoft* Windows*, the stack provides APIs in C and C++ which allow developers to talk to both constrained and unconstrained devices via IP networks, with potential support for additional network protocols and wireless technologies. In the first release, the key technologies for connectivity include UDP/IP and the Constrained Application Protocol (CoAP). + +@image html stack_diagram.png + +@section Terminology Terminology + +Device +A constrained device that has the Thin Block stack installed which enabled one or more services for other Thin Block or Unified Block devices to consume. + +Resource +A resource is a component in a server that can be viewed and controlled by another Thin Block or Unified Block device. There are different resource types, for example a temperature sensor, a light controller etc. + +Resources can be arranged in a hierarchal manner to form a tree of resources. This generic method of structure enables one to model many different topologies of resources. + +@li Example: A light controller could be a resource. +@li Example: A light array could be a set of resources organized in a flat (non-hierarchical) manner. +@li Example: A garage door opener could be a resource; it could host two resources - light and lock. + +A more detailed description of resources and management of resources along with code snippets is provided later in this document. + +Operations +Operations are actions that a Thin Block or Unified Block can perform on attributes associated with a particular resource. Resource attributes can have different operations on it based on the nature of the resource type. Fundamentally, these are GET and PUT operations. Additionally, attributes can also be declared to be observable to enable remote devices to subscribe to changes. + +@li Example: One of the child resources on the garage door opener is the light control; it has a GET operation that allows a device to get the current light state (on / off). + +@section Functionally Functionally + +The initial release of IoTivity includes functionally for: + @li @ref Guide_Register_Resource "Resource registration" + @li @ref Guide_Find_Resource "Resource discovery" + @li Device discovery with filtering + @li Property attributes (@ref Guide_GET "get"/ @ref Guide_PUT "set"/ @ref Guide_Observe "observe") + @li Resource tree (resources having sub-resources) + @li Presence notification service defined as a virtual resource (not detailed in this document) + +@section External_References External References + +The following references may provide guidance to this document. + @note In some places, the IoTivity design may differ from the CoRE specifications. In these cases, please consider the CoRE specifications as informative but not definitive on the Iotivity design and architecture. + + @li The Constrained Application Protocol (CoAP) - https://datatracker.ietf.org/doc/rfc7252 + @li Constrained RESTful Environments (CoRE) Link Format - https://datatracker.ietf.org/doc/rfc6690 + @li Observing Resources in CoAP - https://datatracker.ietf.org/doc/draft-ietf-core-observe + @li CoRE Interfaces (expired draft) - https://datatracker.ietf.org/doc/draft-ietf-core-interfaces + +@section Protocol Protocol Message Format(s) + +The OIC protocol (abbreviated to OC in code) is a REST-like interface similar to HTTP and CoAP. However, it is a one level up abstraction of the those protocols to allow the addition of additional transports including Bluetooth Classic, Bluetooth Smart (BLE), Zigbee or others in the future. To that end, every attempt has been made to keep CoAP and HTTP specific aspects from being expressed directly in the OIC protocol. The following sections describe how specific transports are used to support the OIC protocol and abstractions. + +@subsection Protocol_CoAP Constrained Application Protocol (CoAP) + +Constrained Application Protocol is one of the IoTivity supported transports. It is designed to be used in very simple devices and is particularly targeted for small, low power devices like sensors, switches, etc. The protocol is modeled after HTTP and provides easy translation between HTTP and CoAP. It is UDP-based (instead of TCP), providing support for multicast. + +CoAP is now a standard (RFC7252) as defined by the Internet Engineering Task Force (IETF) Constrained RESTful environments (CoRE) Working Group. Additional RFCs and drafts cover higher order behaviors. + +Message format +The following table contains a brief overview of the contents of a CoAP packet. Use it as a cheat sheet for the following discussion. For details on the Constrain Resource Protocol, see http://datatracker.ietf.org/doc/rfc7252/?include_text=1. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Field

Value

Short

+ +

Hand

Notes

Address

<Device IPD>:<port>

+ +

224.0.1.187:5683


+

Device IP address and port multicast group IP address and port

Version

Version 1 (01b)


+

Constant

Type

Confirmable (00b)

+ +

Non-confirmable (01b)

+ +

Acknowledgement (10b)

+ +

Reset (11b)

CON

+ +

NON

+ +

ACK

+ +

RST


+

Token

+ +

Length

Xxxxb


+

Length of the token. Valid values are between 0 and 8.

Code

Request (0.xx)

+ +

Success (2.xx)

+ +

Client error (4.xx)

+ +

Server error (5.xx)


+

Common requests and responses:

+ +

GET (0.01)

+ +

CREATED (2.01)

+ +

CHANGED (2.04)

+ +

CONTENT (2.05)

Message

+ +

ID

0xXXXX

MID

Generated by sender

+ +

Allows receiver to de-duplicate requests

Token


+

TOK

Generated by client to match REQ to RESP

Options


+

*

Contains the URI path and query, request and response headers

Payload


+


+


+

+ + +Short-hand notation + +The following two tables provide examples of request and response packets with explanations on the meaning of the short-hand notation used through the description of the queries and replies. + +@note Acknowledgements can come back separate from content. For the purposes of understanding the semantics of the query and responses, we will assume that all responses come back immediately. In production, requests can be acknowledged and the contents sent back at a later time. In addition, retry logic, de-duplication, congestion control and other features of the CoAP protocol libraries are neglected here. + +Request example + +In this example, the request is to the CoRE "core" resource in the well-known namespace. It provides a simple example of a multicast request to a compound URI with a query section. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Fields

Sample Values

Explanation

Address

224.0.1.187:5683

Multicast packet address

Header

NON, GET, MID=0x7D40

Non-confirmable

+ +

GET (code=0.01)

+ +

Message ID = 0x7D40

Token

0x75, 0x55

Token Length = s

+ +

Token = 0x75, 0x55

URI-Path

oc

"/oc/core?rt=sensor&if=core.ll"

URI-Path

core

URI-Query

rt=sensor


+

URI-Query

if=core.ll


+

+ +Acknowledged response example + +In this example, the response is returned. +@note The payload in this example is for demonstration of the packet format and not a valid discovery response. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Fields

Sample Values

Explanation

Address

192.168.0.0:5683

Unicast packet

Header

ACK, CONTENT, MID=0x7D40

Non-confirmable

+ +

Content (code=2.05)

+ +

Message ID = 0x7D40

Token

0x75, 0x55

Token Length = 2

+ +

Token = 0x75, 0x55

Payload

"Sample Payload"

Raw content

+ + + + +*/ diff --git a/resource/docs/html/footer.html b/resource/docs/html/footer.html new file mode 100644 index 000000000..f39218592 --- /dev/null +++ b/resource/docs/html/footer.html @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/resource/docs/img/seq_find_resource.png b/resource/docs/img/seq_find_resource.png new file mode 100644 index 0000000000000000000000000000000000000000..4bef8a9061d6ef814a403a872e52c5886632f8c9 GIT binary patch literal 129118 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 literal 0 HcmV?d00001 diff --git a/resource/docs/img/seq_find_resource_2.png b/resource/docs/img/seq_find_resource_2.png new file mode 100644 index 0000000000000000000000000000000000000000..671cb17d233d44b67ab2e7c682fc3f25c6b92785 GIT binary patch literal 72559 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 J=@;D}{~r`&oRRa#J`_0T+-~Mq{?97Oala6>I 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 literal 0 HcmV?d00001 diff --git a/resource/docs/img/seq_get.png b/resource/docs/img/seq_get.png new file mode 100644 index 0000000000000000000000000000000000000000..f905bb30293d88121f7aed817b3fe792ee7f73ed GIT binary patch literal 87635 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

QV&KnT)SOOc znQW?>BM!SF5~V7%N!64q1SrWiJ;Si@M53y*1p5X_=R+L_+21x(tUgO=Kbz`8_7!Y& zWP34sO?lG^t8preiB}YIXLIBu@4#vDGD!~vVN8)@jvD9+FKZ9@ z%6MBYTvh5rdKidW7=mDb#2wWm{-+@E@QxygG>CP7YN8jPl}T|M_>ySA|e#;iI%gX2%f#lFHSe0=oN)navL0y8Y?0gr`6 zy0%0sK!^x2-5uq_c_$Aem!G56Aa&cpGB;mEuSD;wIL7DCrp9NpSs&vAOKw-pE8nlX zEA4K}#4(0~wS^eYZTD?DDMGV^CU!r9(XO%|F6Pcmq+ED=02#}3%BkP*w|0|^`4(7f z9Q`xblp4Er(zmMnfipC8*6dRTA(Hpw%RDx;w#>ksRDqxwp-WrA{rha3JPS7=Yp3P? zt7HpJZ{e|`IQZAq=H_?Xs6nl*pRd|RM^21KoS>`_aGd$s2cGX#3GUVtr#Zsk!qxJH z!<2BDsEn{=9`x<1?ylR;eTH-h&!>-EMNWFnpbcz4N@}$R&k4V*H0(-Rzvf?daF&Hn zCbfzKbBvsLzjkQQoNCC~biC7MtU0~Irn4*$GithE&J(8UmUP?gex#<3GygzM zVy)?}js?jcCL2;+Qp2zAw)b;#*}lUttF-Rj?rC?~NK^T)VL@AX`QEwmQb0NgK*vq5|mx zV7KPeUe`PL(@#pt$L4kk-bIoj`Ve{cjj3`+_#8(|M%NGgL_nSp;ba(X$>4eWiixHe z>eAgRUtwO(ZgL^rLGbBzK0tjz+G zSg6m5X<4A9NSfc`&O*VTQ1=ySM}+bUyQE796{~UlLC=4ZfzZt)N(fzlG^v&2FmTN+ zD;ps@e|a$?%ImDSZHv>`XA_H>jz1GReTe0u6`P%INpmovp^qwPslON7jeis9P?drZEFwOfTc*je%d8w{F$3 z2E?SXA^o8EkR82x*Rnf#dJd$4`20!i4m$hr4}y=Bq5#*R$m-3goTvoUdoKTUmTQvOabokfy6a zOpK&6xZk7=0YD7UhWNg{tP`gema=V?1Tejt&T7Q~&cXpP*?q~X@9cI8l0vQsL8en2 zIoV-9XPc71w@pqszHOB!liwplC*KOc85C*0eDC@C@{R(>yhH6)q#LEscIoBlRi{c* zYvJK^2l1yExy_pHh$tkmeCH-#fQqm`#fWYg(zpKUU^LcS+YazRY8CUtV=aI$J7GdYF3-p%qx zM~%H>e~c$qaaJ@(4Gno3mrzkb{Z)-zZhtoArlPzA)+?31kXk^d#{!#BwSKAW!4vW8Dn;}A`_N#r>`S77dM4SQ+LO7wlO`!y0&~2 zmeNxYS#~iizQAP|nA3=f-Q+30SqnMOCo<_F{Y2$fg`!Q3^6aPPHZwMD+A-g&&ix2M zaw^6~369)2JtmF-y8w@+x76M`N+xT`$%I{NERqA;`MRjo)7y0GGDkmn#^OfWAtgu3 z5Btg@Wu}EY@hHFjuVMl07^ECMJ$rd&A70(%LZ< z<8I4q0W~PTYMhb%Lf>Hf#6zuS55+tFz}b$$eJ?K#AXi~PXx;3Akj}%pJg80{nS$~a zmnWkOPThnIMGHr`4#A5q{}+b|rp35f<9Vz=pf6IT{`Kg6GTWM{S3HOevSHz}gZo+P z(vmaxy-3}@H+-eJ^3}L6tB7I<4CTJgc*!WV{I^xERp&Joo1Zpk^lTf^51j*A{gTBYqa{;Rh5rS1GS5?C zC=xjTL#mkmhixSP3|-YOf_r>Oc~ea#{PVL{dAYY*gvK-p1BHuo0U{8TM1T7{Z|J4gD-V;o1jl zTo|u36@1!~h>Uj#=Hazc+R|tg?=^B1*H8!dm8oK>7UAyde8>0gpB>3AV=h#cy`r6D zpR(8cn$xC7xGaXf41ocs-|v~RXh^5=0rgwNd#wTsc}KuG@^(dvNGR*pQb_vhL z!C6qfDZH19(y3lyQ$K^U43Tl5;1c^@%|0niF(9;{*1{zPt4%DoZ;8;w>jRNrtmiTU zO-1PyP*$D)Dj$WaD@Z?N(tgFo>2UMx@q5*6(cvw7O7K!57lcU%Si=~wg%c8U@l?j= z2Sq&C(9>^L>bN+W8BFOfotE5OSGGTH>=!~HdmNXDqg}@fNWB2|I;^;FriXzn1utAmtr{JSLv z7yy`<&#-Qk{|U?gL!OBP+H}-~{QtnIT@H|sSUe19VNu~tI*-5Ozaqgwvw}BGu!+h9 zK!}YDyH29(FuDHkMR(% zWPUXN!%AZf)W47O*5*A73;>)+^Jx}q$=N|is@GGUO9Ut|5+)EZ;Bq1MdHe+a&(x3{ zq6L)!L>IeAK_fsW@eD)r3IBf~E5Nkv{vp!(NtwRvTXf^7i6~KkWIe6S3cJfo zao(T?5?I&Z@|E5tIh9?e0qC@k)FQp5j{V_a^yTp1yg>kHdT@gd&nsz7VmwG~N}#6( zdb#4gaT~yV`r7>cSPBlhJZ0dnJEE=K)Rf4x{qYN|@VeY~kVA!r^zJStT3DPMs~=rvG@Y z|6)g>$!l##lZ@kuD6a@+!>#gTImtP3WXTCu;D`QZm2WO#4J8Ac){Xk)fp=;dr~lFVGz`cF?}e-@T>v3JpH#2lvo z@aaB6YT9k+{`Zx{H0D~6iIl`q;=KA@$_voaS z0S%))Jy(mc5qM};rKHxnv_jooPe=dX@PdwzXx;yr?)Lc}zN1$dd*cp??tK|~B*AzX ztG%znHm)7NFD>B)UG*W>z~4wdgH+VyBQM3oME0?n2LBDnwK?r&l}Lod5uiJU3-H-8 zHD>E3HM6>tmCIB~0kv*(48nFdCf8O;ZfMp<0zl0r;}DAQ9LC8U3%~mUvNTXwWsZIx zu1f9{9bFjdEI4-MvnxAo^O`atNT%BrZ+{T|Wv=AOOLSDiyA8zrvPz7_hApzyF-CQd z%3F>ME}n|S&I&{Ngx_vr0+Z3QJoJ#NnvCh_iCV$^cb1=zFK=ZBP;R_|tj^x+(sO6r z?w+hBT3Ixh*u86P^xLNwKLj(rAnTRVUyhyC4(g#w0%EwdSGbUF$6S^l#rjtsy-@kK zQxo}7iasG7>S)Z3*mxpG@|Q~41~9@Kht9IE9mql$tl3#~$l5%(p$a2r8m?D`X003T zktLtFf~l>-YAHYl%k@$wzXJjYLDmYkSWLNi@X8oR&LDwh|HNk`wlW|knD&G~At#_S zv)FM{yqq7XIYm`MM*39&Uj53EM4XL4NJ4xaJ559?k=o9$uQK)n@U*&m-R)pQ=k_ES z&g)U#sP?X_-PIS0L;4uoVcDHCHOUevQ}4~v?*0u09Nx&JLfu~*Q#oEK2dK#>eIh84 z`O;XeRFFZtBGV8G{qr?Wm04+f^)kVYbXv#SFgE_BOCQC z-mpcmc#m{a*lNhiD#1KLw|wnLyveFEl%2W)JXx|6{&E$@UP*AW(twvwWajU877z21 z^)&15eg@r7JS8{dXieco1lLy1aiV(9(Zp*(&}N}yx-n4XuWxY zd!u$}(G%&-SRS6tgx1-((za0MZdrC{YS7y>PM5hK=M1MQ$uKk@{mwiL&$2_qENmk> zi(TL17?PTc*Z+~Tm+ zVx?~Sf<8`1DZIexOZ(WdqKswg(9Y1iK5)C{_|xZAm$)&}0;k!){I7#LzB|Vo^;lYG z;&PhoVAO?j`A%q7roDY!rsof;?}tx864(IbEbl=m!vu# zR}oAqiugBnj`*i{QyCcamxD5)ueMJuO*y_+&3{urKOQ^pGiI(BurElDJYX&g`qf)GJ$BZx^J}i0zv0X13lo1;34Omz={&MRWf#}hkUsdn?&^Vm1w5|>$|ocJDu121p_R zq!Yf|yI!d^3wr{sSdXwJ)@XY^7c3C)ieV$i7@$;*ntL1RIKfPlbBhzkQiK){y&o{Lc5{1m+3CT+c2@%LU z*qWGI8H0d`!&R!9Dk&|YZ8l5mr(%xvK#60z|14BJ(Uy;;8t7wSVi3X%@e>%dfeq86 zDN(BtW~MTjH~UV4CVUPtXhVa*LP7CMttR(&3O8I`-R)~r`z-Tq!}hBFs`-iMslpMY z;XDvp1g{D%mYyC!CL9b!R#*sw@#F`prRUG_3?&j2zWw~H_MEenf$gg>R4%Jj@pbZe z1%X>zAphNWkl3-PMLsd+njVBiwLl&X^p6IjEl0k%z>aL-L!vlAA3kMf<&aYW-aR8^ zP0}hkB_WFMC0vgYOwgDWhz-Ur_+XwDN(i;+vN~PzD3VT;ov%2RFwPTJU;gb~F>yr@ z!Lsout?c7gjeIHxjv~bb-Vj);ypSIz8MV^>57Sco&m3*vsEiUMZ%^@sERyZ+O`Ihh zL_#0GON+Rvqn63e{OATJe6CKmZ0tXT4N1?>RJW!!~!eI7s?2x<0<1c%E=Ip8j2jrnkY<&-X;*3m?(tQv)wSP%bjwhr2@SmZg zK@uJp$rt;fm8HE7TEdcb3kn=mtzN+RdPlGN{iCNCwi0ySf$Db$NMJHZ2tL^Lrsocg zZl10Mc+bo@QBobSC#JxLSuYn{5dpRrg{Bw&U>`br8&Uufevbe?o&c^WuS|*%zcd@v zQI9ZDkfXwvr3SRAhjkg8uNSl=gxKzzY(IDl?9vW=IyUY#tot_Hy*|cJ4?6||)4&9S zN12CwMxK8B<_%`-cb$fIqM_HS)Yyp zzTG#|J@=L$HUTlcoi}>i5ORIR+bcj&9e?_vl%2C{3r_@{kenX+?WG%+cg#&GkX(uD zAC7%t*JOfW>_k~3M2Q33d66X~WnrDd#IK90VJ>+YK)G27JW7JBKkt!52@*)^{8Pj! z@z^8UMz|}2I;8lqJo~0tAtus}1uwIC<_Tsi4VVo84N_~!3&abQS65Cm+hZrr92==8 z!7mdmo)F%QuEegeu9!_>+kC#fCq@idpBBp~0kqOB|o5Np+sE0pIa)O(J8-uGwGlSI(lZPClF0i7oQkXfJU)4BiG?V$L z!;<(ddKx9Xi&;LqhBjhezcBRdl| z2D&D_2Y2kO*ab43WRXlUi-R5G9dquY$M>QSMI8s%U)HH?aG#)`T9bp58&zr+l`4@d zB`X6oQX1MCSsJVxgc^fZ?;6S*5G=RmFBf)BT8;-!_RnY*Rw^B3ixpFHE%ULfs28;> z+GU;!E{XAa>-U3hg*&R<*4&DLxb99onw@5yIGqliIrkb5?)T0Q8xM;2rl+bW_zSj2 zKRvO%nfYS6Gktu00>1PEM?<%f;*q38&vEUI2Q&lXAOs+g0~iCmAeP{GF`!}l;T+*q zu@F#!5U2HpRQ+^5Tq%5hC9=FxXreWErxpJ0_p=?5o2{B?`j& zj5p_^(RxIlGOys~{{q+R0^|F48{4un#!ZWU7+_KoT z*fiC*jI*j8F~}L@kxDLXHcmdU7&jTmqh>0{y0!qgPui2LYb z%2mrrd#IJh!Q9F1}6hMtiqw1Ycb^T=PuLMQRuXXuG|*U7Fd_h3&+dB>&4?4jwP20 zqs!Z}*eBYj;8*461*pGoq%Z!rRj^60Aio7agaDd=0Rb-m?C)!kN8hi0c;oHjF z+_KKIIoX&gVj!Vms-P`mRbgl2bP>LL2Z{*02wMxw6^QMhj}%d8C`r$cm1NA2&Ey@Y zA7|U^>>Wm1hUpKJ3|WP`VVohBM_S{=#Ne}eFFd#ZtRNpDpC1;`a#}BI@wjQa0l(>% zEs%@MQDeEW_m}F+3}g!H7%&fO|G7mHL_#aqmSB}qA!#E!Bbk;7NVsKXp=l&)^qNhT za3t3jXOc`PWGP^pRh)G#c=AU5Tu86xB=eA_%kne~zer3|oRVQlPiK2LX09~vGlyg{ z!z{&YXX1t43tZ^ioH(9{O5@3spV63MvX2Eewn**Lm&S6B-cFZ|oK8GW>m+TE!X>Im zwj1Zx!PTL2C~#;xY#t6BTuxj}OHHn&OixUY@X;(K9gS%gWyt1mbjs|MP$)N`KciJp z9xDt{xS|*YDMDk1-~Ty$$s3b>h&mOp=eJkBX~(2wf}fgCqs(!$PwuZEtf=B-gqYsoM94_tsCMf*cptpuLKCK2Zj5bYaNV(u$V6ABasO~WU5bj3 zL8DiDKh7AjwUBBp9GlJ9di82Q;JW2najleEPp;6tZI#w?=~{2?sC(Z7%*@_xwR?77 zzI__2k87lO&~0`2cL{dw4vqCBwNp7!NmAieVs)31u~v&eysqy4*C)5@NKN4)-_bE z6}4NVx+;Nddl!^z)9=S0hLiC5xCdOk7l~I^TS+zLg+t{bcFzx97L9r+)8+&tg8)ch5ck3BSXDO~|KDgOBkcp$;KqXSI!rwrqEEFApIN zp|u_RkPPe(EQAlv*QG46i5Ml^1-`a-jI-rk!;fL9=qFan^fo!89N;{6<;&El1bKC% zw3Rszs^jVTN$4E;^!FSN@5Qh4ILEFd_?#zRU7y}N!3~j^h!F3)=L`9AQ_Bs~YALuB zFFLlSC~Gbk((AFXa(z`f-H0xio!7uKYqogX^)`+dlQ-I%%BeNCX5Dw4caNWNW@}1}e@-e2ypdIT! zdL)EALdHR8E_>3XF8ts!e5|h&OdTd zLfNr3?*wCHdVt>a$oB`AQD`yRrCTC$8=Y0)j^R&j~64Ah`ws0nIX3Qgc$1 zk>)hCwWiZIvNbTK16tetr3L}v26FzrwKjIrCjeSo**J0nd5Hc+!TI<8pJsX@f`5@X zS@IC6$;cB3**X{#u+TBnF%a=W6A%z^I~bX80)$2XFZy|)Z(!@} z#6v{%kD~uR{>x5dp!xr3vT^*sZvAzT{+}NDUvv!g|1JA3EB8OGobu*CV=Fabb8BN8 z$GG>ax|G}yLpPY>U$@w2W|Cf`S{vQYa!=e8gt$(%t9WGvIZu=i))!|V8J{n!xl7iK^QM!VwfEHx>s6W6f(+}7ruJNtmlhnt9q~{wKMXs&bBq84 zegers;_SV5iP^ctnuzAfWsp z|8vQU@TF)Q6fpM%Apn5_`Sw2-enb!foK3L*r2WfD00HGofCu&`SNwlUHQ{2@f3|Bp@(P{e^9-2ZKffiDQu?k^DB@bCZ2M1I5&*Z;8iUrItjzs3JH zcF$yX;P4kE_0p5H&POYP@jtCm47CXl4cX0>6OI5t^_4I}Y#DOF03k4H{0 zap%TM8AnaX+pCw46DNri241JROJ&KDuV0b%1aX01V)YRNk+J+Z-hQAJ5~!c^_Ue#d zWVOc^(1>s^fRa4_zQSe7*m@2Lyadjbcd*OluirR@6Ir^ikdHfGrk`{yGOJr5hwwG! zQt-Lt`}XgcnVE?j08KX=IyyQ?rIJGjYtv}-Dc^SoBZ!HKnQX-!3`SF{Ay=?S`sW zk&p=6j!A@++8K_3H|E!%ZSG1?Q-UgmOv~aghs_ zbyvR^JnVnXz2C?`L1AR~o$7yL?O&0{ul7%9p=rfpAVT^13g-eSQItYa5K&>i`_k9) zKg{ArNbJY_%&4w9|uR6kHxrO^ziwm8NdN>yS z@84zwvC{EI_uw}c3t#TheId*(^zfe_Hf*a|H~HvBRNWTmZtnMm?b?leQyL=CbT<`a z4DUzu;8o$xoh4n(-}pE;+d1DqDG717efb*@3P`xkMYZd6;sUE}%)oMYp9UFq1Ujwil6GZIc??f^9h5 zYbK%kp3mz<71}J;UJJc@_I5K>WxGwUvEvZ)m|>(SJTudoiwQDjHH!I?dqSDp&%d84 z3KEo(NNoM)C~OiViVML7H6!QM(EQB8hZNrl?26Y=I^kX$!Rw%%wYvQ|8)s#VsR*7@ zU(JK;42tFZci!bKT{hWdp@&}z)s64I$%Q(=VbQ?qAC(M}XNM@G6jhQi%`kfd+P;-rf{XJeH{yxPaKZ1;-wM8YJ+E5Y~?_*MTjgxb5JV$1$HLYv* za-nPQceA3}?Qg2maBfvd#~#dwmWn_Lx#k#cBf&gPV+!kNVt#X*@{#Sss{Yj?CK-)p zBA=DhQ<0b58(mfnk5?gAmo}hyG3vcvV%cveohE4#ht;S~4gCe3Jh~CNpIi_gu;SVk zlqym@vi&mF-D%QlltG+AV|bvHDyRo#v<)jDYBz5pMpvL za%i+_^~w|MYup9&`;Qcg`Ii;*XrxZRsWKXR#5FivPEBuFP6sZCH@J?~YBUJeRkMyS6#4oohAOorY*`m91JX!PIFvQL9K zQCjbq{n`13+WqqmR#`-GUi!t2d(Jo%8qVmN+OA7CH-@kYklrAEE5g2I8ohKQ1Z~wf z;zH<@5sO)Txt4h(bXex^<0>?pZN{`{(%gmfT|a>jq5yRdTjwxpKeWWBqDWW9A0j<9H=6`U#xux$?TD)uG50nz=o9Xb<$ZSM*( z!pMX=!k_Whej3Bz6{uu3`=smmw%8a{@qJn)Qw1$QNW|#DwC3RWhL!jcrJ~hRN(AE3 zOm2}S+Wc}uCrT#QP4xn&!|52vgtkH+?{IwD22{_M%Tf9&-AyuH7fh=>>D)UX`EAKp zZD|`Xu64Iae`kBK`#>`<8;&VNayqsx-WR$bgZ2Cq#4j*~#A{ET=1&u_HLaE8!Y}2{ z+fJ>^CPW_YmDx0lh_XAP()iR`Dorir!zn8k_FoG;_L@zHi%awSj{ua*JaD+5y6ET* zj5_4`DFFJl0jV9?h#*wBl5iPp2MH58QXQGct0+>-#S*0TzTrL0Q@(3b6waA&M-GmQ z&=RYQ=#a~;whAR$6x`hp*VdJ2q5@~^>Zdw{(^ah!{!+kaFF;{!ipF z{iJ%EIrv-xS#0_rT1-ZXdt!-$Lx$|$a=$xAPs@vEms|PzGKYtPzaBER$vTY$<8s130S4{X_N_f zcggQ&it<-&ce_7c&s!-C?s`ISNC|DMg}^U(E&rO}KBVd6;`qq?oIME;%TN=NB>@~M z@C;*nP8Y zo&WP^ety>DV~l`UKcX&N>IREKdCWShY5jasCw|(qj)qOP+iP2Xqbos6Y&LR@zc&sG zsyb%~EOKW-pvuUaD{jsPftp;IlaxeX7#c=d9EbQHk0UG1p>JKdxvsC4nDE}(Xi_x& zxPSBR3ygb!gaxNQ(2N|F8xP zkWnYRX;GD5ZMJ?RN44i#Hgd=zxSVIpGF#jkS-do!_!T-}Gk#FF$}W>X%xTf&uONx| z+mBv=Kg>IJ{Lky7zTyS0r4(aJvqpNO+1lYw+v^Nv$5%Erc?`?l@Hg`ZCs{(W_+Q=P zdBu_|n~Wt3V++l-7l7o-jkH#1rtCfJ+R>9AzerC?!+kvm719;43Q^&@-dl({IMcKrk87 zGYq>a&AE89vYc!6kLgYubdq9T`s|x6KHhz4wR2X7^Voa1!_+{~q7GAmsXdb#jk_rW zj|9Wf?HLnj!7fC)dTHq7fERP&3FZ#0gc;R8aY@Y$mRBFhPb3we;G{!e&&)0bd>J_m zV@a~Ppv2jp`E=MfRoaxxk?uvXai}A-$9==Sr}K1?l)OBIHTWJ{`Cap(-YR9+Ii&c) zsLVM6pB@?3&L)m=G%ulig-%BajaEl{!D0W~SDrX@xTC1YEBQf|^T441O4?mI7QByD zUaH~!M#K0)Q(EPSToM~4I5JWd7B5L{LHPHs0WdC7s>XFIlIDsTQR@$n_z*m@jHI~X z3;37MX=)>CdeLXifrwovgeKXU{m|Hsf^g*?f^nHFRAaa`#F<3mxuoEjRT+o%gmr1L zJZo=D5zqp))6v)Q3@>5@QDf!aL6~>KU&zV=yewFG3;DURu*)vI9C5-}aUG)%l31}m+qq~vQQcT?SOSe#tUR3+X(`#)kmQr>A1(m_eH)ZXt z4O#W6_n>sxaGQ$qy@T7Zf?%=p(3t~c8nsNXwga-feGUO$=ZmC@)b4;$PHjJmT2yo)^NB!rv)eiSVjb(?sLOlF5;#p7|w=~@bL zq0zqs>X6pyu`gYAmA&5!QBkYZG((SvWDy6z^u2g8(pn)f2S8ZFTt{tR<^Gn(GVBo0$y0S9HLHsOI6ai3I2yyNtV}G5Tz=%DvnL`H65sF9gI6W1LR-)3!*WZafP6(hEM;R;@Ph618 z>YT!i1j)@T)vMHkQvML&C4bXh0{U^W1r2Z%{}v!WIZOrX8c5$!u|9kD)}LeT^eKyg z-6Gul>e1P=1g~t*JK~BQcKU!ebvLN+xoXh!ohp1(gAffx;l-rHpE0_h;X!}w-eNY} z>or&v&uE+0{u2#Ga{cRjJOhzEJ@lgW$4#6_Oa=XV7m@9owTSMP^5@vpxshiWa-Ga5 zi9``F08_3twdg8WwT)9Lk6#Lfe1%ozp8Esj<;C{W`i@1;>kSLrRuZS!> z*RXJ^IJgl`Fjd&sszryT84^MYNQg|GVZ9q59=BCCD|w!solQ^2s%2+oq6_J_KbU;!ZKdXjOb_ zHk2e`^s@CRyP=^0iYP$BYu?851GX6qSeEGMpzA?^-)#gsW&N^)Uu6mAzx%r5v!xEG zXJArMcFMR9;9JM2oZS(P$dEcs*stYe#ehmAziNYkxu;N>6ss~|U_}vmYq@ZA{ zB_X9RYY~jxT^8Q09PQv-CxzA#vVwHGY{|z#aWy5_%5c~V&;q>pmP95+0SN$BcvJhqf>-n%Hq@(Ddco+k{J5 zh-A|UKC`1Ud~Ow|oTH*!KP44#-&7z1gXNjwPXIB&wrZh5!YFxt&!M4FU#O69VQckgB zI@o8bc)K5a(j2i*u(V|UGNpW}(tX~(m165?Z>IIEnJ;$pvFkkBL#XiN=lzO zwYBj?RB10&G?A1^6#ft{d8+>2S##LhNNB6!>7k1|(6XzqU_ApEz4{O#-;^(0JZ z_&I8~??va5Ihzi*)8#Nx?R)d)c!s@{vn3cYEk%(FRjoGgt<>d`Zj|fRIL3UZ@m!Zw z>R}181cTUDn2{~JeGNmwmRnq9rs!VULVxEVfA0ms#E5JP5Ul%eq>n%WkwNE- zYm>gDZ~z7k^>fcqs!KsO+C5|UXknh|IwZ#9i4EZdgE8J}!Q`DMr4(%^VX6k3C95H{ znO^@2rFaXtcgtkk_;rd*-AH{&bEi2z1bM_%0Pi$0cKNM{_4=pOcTdF*wZ(5^*|4Cx zrm)kDR{HSG^M#8jA8Xm36DHtzFbphd-)%4Vv)(oWmd}0oAmqjoV!Mf6E?J#UjO3M$)nY2%FuuYRavsA46QCd!@UmLmBBPnM;eo6GTz2@twB+Dx~g7iT-Kc3UilAR@va|7{RA z6!3IeZW1&GKA=S~o3J<^vn7-B#=TIyl ztJlW}^@LGp-E`*;cW7IV%I$Yh@-rbKLEcMH02>|RHIw4FR{`+4nI}_+n^sXlhGR;) z%Ua0RiHH$g3=Ee|w?q60Ksj=O>+E*!qKYrLUOCfjMbxc%ko-Gbc5;ez>40* zC>WpTk-8kK(KVf-<&F+JRnX%0A4{R8-o*GPxq} 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

3eIYsZ+<{#5_#;+y0F5BHH_xir^1Ul)W77SGNK6 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 Ce_7rD literal 0 HcmV?d00001 diff --git a/resource/docs/img/seq_register_resource_2.png b/resource/docs/img/seq_register_resource_2.png new file mode 100644 index 0000000000000000000000000000000000000000..25c4523381ff9d47db9bcd1d46c2a3252174190e GIT binary patch literal 52712 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

ym?k})OZ9qxW&gx4?`duZfVq`_Gk7U^U>P~v}J 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 literal 0 HcmV?d00001 diff --git a/resource/docs/img/seq_stack_init.png b/resource/docs/img/seq_stack_init.png new file mode 100644 index 0000000000000000000000000000000000000000..aa15e686746e2c52059cf3a23ed1b81d49423aed GIT binary patch literal 116787 zcmZ^~1y~%*vp$R^NFYEUKyY`L;E)7&cXwOdJ%r$Hi!Z@-afbzhySux)JAZP{{mH%O z`EbAPkJuKOt zRGrk_@ZXd;LRBCBL=qt^MTur&Qlu0PM4-&geTQ@72d%CDgZmaiBp`J4_E!BiVVk@>tNLnrOD%+2UWekQ=Ba2%Fuxz8v>Cq(=m$XA;H`vanmjYeUayqPCvoE|Q4bP!!#2nZ`F*0KQ{F^0DMaO|w<}ium=MmqwZce?EK&m}&|cQn zUXJrK0@@Bp%gODAwt$d;Q22C)rlH_8PAsb+D~A&vwbOe+DSrXm^?OI0Voa$1n<5S< z*ewToq%T%Pm@K^IV@t7cN_;5ucnBxvfFdRFph$f#GiS{Bm#zjyQj}b`nkdDDFBY}m zyv%^CKl;({&<-EJ{hT~Qd>14C#0cBjge?)5g%;KQp~6r?ovVEp(n%h|=Pr**qJkM9 zZ%_U5K?LOCLzXTaK+Y7q&VaV8tDeTie(e;)8nUji6pY8+Za?WIk`j_1n&nnR84q$r zdzXp!7Dhf3h&Vw4Zwy|#TH3W}`vCn-{@Z8qHjC&_xG_bwy$Tr!6sJ_ZF>-6C^=LIJ zFkQhf?1S&aoqy2R)Tr~5ViRU_ZpMikL+y!mX9*y1sEwyye!`_1#T}PG%?}#O-bHtM zAbBe+?o4PY8U6GQ+aK^DKK;Yhc_w~KXEuLc%^2Z$>BPK69m$(#d9hD}PAPyG2l3x_ zn`fhuSt!aPKWHg~N=b;u-xgjI3yJ&Y5Lr;&<)CxL98<^Xv!ZQn`^{$VD-@}8%(qNB z6dVir#9RJealqefc&{Dx^<%P-MkW)ta)__!onee0j(gYRMBHs8mv|b9EZR;mnJ_;> z@P;s~eGHf6+SeiU{e5H9R)()SW7_flfZm>l>4t&3jnN6a(r=yeNCmdvw|!%bP0>?) z(Rg%Nq-X|!ScpHyXz9^~2Sl>P5Vg~F7NH9`($AsYy41?1a9$pi zHADRbLIn}Qo-TW>(d%XDS-xo-8z4=nbZd*sv0>NGe4~Vl{2P=0_xr6)B+x4SSG4yV z#P4H?QS!2iq)3PgLC}u+B=O(4OTKfIL)W%_o_!e!hk}XxB9)vV$?(@Tf<$@sIiqIn(ERE7zXCI_Czh`-7=FaqZyL(hF5L zD5H&Ob>__F@zb&tRHno!qGNl=Ddo2iF4FW~()doktndQzq7aBM+5NOyh)Y(go7}hr zAq{c*=wmo(oCLbYmtnHRSiD{xV}iMFx)emw{F`RDL8j7y3k8yOWT5w;v4-O0 zhF^vAhi`<_g}?9S&7+(M-|G+8&tuyf6d9D*8&RCg(P%n_G_p_+jCi|XQPRI8QA(+W zIk2N_zEWbQRW@EJ-Ly_glgv%dF&W|Ss?C6N;pQ^;1^0Y60uLvCEr>Y;AL0PXxYWGz zxOBc+x>C9{+gIBonzG%&@WS(97mR96^ZoAY|6=g7FL)I_7F|m8kig!gQ_DZ*?bo*- z{8|0I-_D>2;2`U^aBmc?6RvSLigP{SXWa5!C< zWtlI*r#r~ z{JIvXSym%p^fcW)O*yr#mFkfys|CAYzVKl|bD_xvzv)X8Op|4k)wPqS?SuA%%ylAx z9Xu+0p-@5xh1lZQgu-@xUxhWMb^HkRUBSKrXZoz{Z`m%{8d+4)3$dO^UG_$w%L^7& zqw$^+d`HtkGc(j3zMZ3CS8XSq?gn}X3n%xz{Z(2Aumfbf+dj-L^<;YWx_xO(XT4?a z2?#%8)Z9}?I7FDi2jNQqdGa?kmo&3BfA(0qoW6*>(cSl+4%)_8XIt3`9`V$ZTOnP6 zZSlS1zT3J#x<0_S;#FmJd6*S@#(Mtt0)9S%{_#EhI}yx0>=0~#-;^J!KfQnFSKc2W zxCQtfxD!Ml!gc&CWNys!&y$=^Hs(q==vbdrv8HiL@j&=3B#%BnMTA|1t%c=s#5NCm z^QbkIr6>CfQpYIAvUXE;LH4>E+mTiw20i56fM9o=1GM6BYy7AvB2J&F+a`<>s$Qze zp0Ca?qw8u6rZd# zEW?qK!g;mJ4z_5wfM+xRRQRchO#o@*=T!Uh;O<~VGJlr*nC2LpeY9Imz0^8WVKiUg z`AAXk{^0e9Zo(1;O1!FMlSyVJN+mY80=JgK@^<&u@!-*j)X+lW$lyq?ApK0jPQO-O zs%!=~L}smkTBREM7ORA2SD~BQ71J<42?;Osa&-GHt6%miV*jiC7kibnrcX3%?}sOo zX)@gHfgL3jRiJp`_(!hPG=`KVz8Q9p*!aatlUM8U!?TITfM%j6<4W_7mTxWV-TiF|O|(w5lC*?i+}0wS8hz)v z{TZt~Ft^&CZi5Mf71+}Hp>ft3Ts6kX(v7s1Imck2@8Hjyy&HTA}Z zWlphWs{^%?$i_NiQB%!YNv9#A1?;x4aYVB)^0@nCH1s~3V2fAaDEd>ZH$ zY8EnaR$nS<1bJ9^dkSd^Ev(rGrQ$u|qCWB5&!meDMky0a2{u0B9L%m8J@rUM-h8G> zX_Pb0aGT@<-wpRkP?gn411$JII_@9t1y4|oz-4gzOurn)IJWG(&$toL^ZkACZAm05 zEXe2L_DH_i%xa0EObR8@n~}3N!kX8G;x+V zczD6RPVZ6o(Q_sJjjM(0z_G%HLh%iPTIoX_RgS^qFp45DRsa*xZysCGdC z7kZyTckR2*LkXFDtDTtA;L-uPR*(5J>9dlurc1eWK~8}>&*uTXuf95m$&(Xj-|n(r zw#L;0%UoJqe3usSRy<#1o>N=uOiqwjjyz7Do(F>_QRVJUy^OuIZ~C5Z8VW4-v#S?jfMNJ!^hMgB`8z%m~ z`39;&1}asdN;E0rc=DQ;2EmTAZY>aJpLWo}Q3W;}EUXph`t(#L4TTc{l@b5+Ft)&A}_$;*T4eNPF%wg3JQzj z&p)(;BKav46g0>}S=~upMw-XS)|%14*w)a5(aqZK^=c?6J~y7%Lu(T!17bI8fQ=)M z8$an^SMaO8nO)PFDP+>N4`gLbeVj#2k$5jLf70NW{d%d=AE@Jc`1i|1lF-+?lw*aZVWb#WPeZcuX%(` z9E}_-?3^rYZHWKOYhY;W?8Hw>`e&hkfBwEt6E}rlQwXL;l;+)M!K!WPyhHjb}r2(YlRvhw{k;2&N8S@OSzYW!y?7uWw9`CmQ%Gm?+# z&lCLD6a6i&zs|nOO8|+F>EE&!KuY8yXM%$I0wp2*RoM;t5c19obH@Ef&~rk(X*@Kc zx{;Vf-9H+c8pgoScjS0~r(&*{2m`$aC9RNs_pn+Y!G7518?)&=c!PH-Hhg)WuF z#_b1~?rt=U@R%5rHhlw<=xBY4%m+zLi<+kSxus<9k-#TRb9-g;5#2mM^K^JK! z$M1KzU;oU%WugVVgZl#YkEYLqXr8acW$X`y@ckd{6i(k~!xIXI_#bUT7Ha#ZnoRV~ zKf8#bF7Q^M(V+g(l3ZZ!Ey|!j{&O8^0%)L#w*b){uQMsh-aJB1ZmtD;iWQxZ0&{Cw z0?zsWy}34e47Z(h*TA44GmQ|qQlAkJKf8<`9TZoF9v#aj{6AKP^0T63UOsdUMyY)N zz!4_w*M~9s$?4M@+$Fb+_RRniDg<(3XhzI^Lc+GgY151y3}a{ET>0JW}4Z;MRI03z`M>& zVM~^IBp4-W{mBvjy9Xc*7Lq+J%pT1>5x;g;=od7&FZ#5I%*YqpskXAY!o4XxFbxe2 zTD5>=9`|UtKLY2v`Tvok4~+T)|5LaE>_1-Emv)Trcj>2k(61Ka|H?nf2Zp&dKZC{c zpIzc^uU#0=bWl+Le3=t+ukZPiO%&yyU5Ik}&Hg>6MDKMHlobl4B#bWOX;pI+*f>#A6BxMI=C! z_mN6>)zFdn?SHl?7Cv-bjh%+iF{xu^q#>+8#>ANW)bfUg-H@>VpRKHK^C4+syRP=! zegI-6Y?sOExN@8n19ksr}|T6tzwc~;xI!3v72T{^s-&Ssf* zcAr-R$!2!Z|BlJSZhoIY4)^un+M&OO{>!mgpe2_$U0R+x(OSgb-Q?F+XKMbufj^x( z8qBM7{VYhC>(WR3p&RB%XmXmK62i?Fc+>Lwz*%5Sjzy*|3bwW4SaIpegjQZ|fTt4X z0@n8i`eo4{R0p}}8r-L1JJ#}QPjog0guI1^ZCZ1p5+dRxkO`bbwHBx8RnUPa* zGT;li-kNv(!l9(RoNsa|`ylexBdXa$8I9du1k-wy zpqA6#!mL?9Lv{H4V?Q}6#5fr+j3=x@se)dykgM?h(qZnJ(isjW=@FOYf>g8~O z_hQP{6WidT#fw#Mm4h(pBJ~f|KpR@wMBbpZs;2A}Fd#NgrIAFBrI1YOTu!q?9FuZ^cHBUMY8!0$0?`aXxkjDHJv? zI`2h60N(4IZ>wV4(|8yJ&5>;0p{9@f0@LUqrE`?8Hy8Y0H`fM-e|6$Y4XhZI2Uq;6 zUtbQo0cfVvaV$34I0G@aQDWM= zrsxoVg%1GMKy$3A^uT><8;a?hD;43QeVd|I{S$L5n}D4LWZXZdz+G5>Ie7*1X7~xV zY>Jw$jbe6w5#^H{K`zBRzVVl4W)m_&{!;L5y|I^)_65;eE&1;bf`3^#eFF?Tl@opd zk!oIL?)13S!0~JYNrrC@c5WX*$J+J<|5yG7>Y`#P4Z0R;P9<9ECCK#*Dt@tTL9u}9 z#IeC4SeC}GpGKSZr{g=55l740bCnTiRbd6|nld6@B|SAQ9i@R)cTGt zr<$pQ(EsB(`~qb4%dc09Wom2i1|;c4=Z3fO(p%PR$AM~0xu#Of>*PglBOP58Uy%DG zu}C=Vj*m32gsZdXhD$1gldClX?v%Z4TV$3mfd{rn$cmTi2L-`Mml?$s#l@jh?^*ts zLFO4m;byO$#!Aa4?I3ZrJBeF=&k{$bPpi>nfZ?kG-0acdW#cAMN|vfs$yeMR>@zHa zwARPXJxfk69pp$3;j*sNme?Srzd$mUx---z7?%_$KqI(0I)WN*AgSj6*dlRun9b%2 zp)wcS#*@>P`IUtsR}E(M>^+C}ntr;jF;vv;56 zlrK@^Rb&^bUk*jlE}Hm93IA;HJpb=gs_{JYALmX8@No@HE>f?mK+Dj9v}jM=+&f!F zv`p<*iV{b@vbC;p5w@kR>29Dnt0LM)N^tZixG%)O?=-EK*9(#pxff5H$hC%*hKUE( z-0qL@{L^pq9o1GU3hA4Bg&CEai_(ysW?EfKTH>Oz|MuI8)&J$RDe$z*@|`!q7{*Bj zLnI~*oLC5zonvAEz3)m|(VUdmZzZE_eMTC5z%Ey0+f6g_8E&(#_s%CFiT+PQ^I3vy zf|tLHJ>y1(i?{n9G7?K{q7|7haoxJbmF@xFvR8Mh)L6clHLhLli|qj zz_4pZs$#bJejA1X1)e47j6}ocoD5vuT5AnwGmDWi4+qgCyRq$W3o;FqBModr7&kHQ zFBcA}02e9qrbD&%--SiuvEjV0{@NL>mjQASsc2#?9u8+c9NNE>ya)e&s?hi96NL(I z|2sq0F!aFYajme@L+k6L;^PJ~z9j7Qsq$*`zCsrRtd!cLc_o@s6jL6{8&$boZ43r0 z0f9fy3&DC55Fp7Tbqj!yG0~UVbw(H z=fpk@`Yo)ZeR5~Y`pKkqR!2963U^gmc8>rx(Jcr9EmS!s9%L4!9WfL!UZN6@JZ1Fr zr2&)49TaC~T0|Rbyzx4zT?E|jW54-As?p-+jck6P@9~c>{w7ldR=lWF+`?xb2lGu? z*0zjo{)szXeTE6^e-I!N0G~aAr^SU8sYY9b9rbVYIC+ev>eIRn)W@J!|pK` zS2+U0i7XdC&UL=qf9O+zSh_6BIx`pV!H7cB&}bm+o+_hbS%%fQq+l1g44rq`qz z^>q)2&qiw>XSN@wJ{}}K@I15^dR(1o5dfu>s`~(+apQUgF#q7Ct@8r2^#lNU=Z-WR zrNU%^tMMqu8gnKnFGL!M*xfuynj`zvvG}P0E{a_#&Rhl`}Gu8x9&aIS+|wEgEv|A{S7wch=JLqGE;BqaVnX$iB#`3f=i%IIW!&&B=M1 z@Ti1BXCAqVg+`=jggk;L-QPZZXLU6>8-7Hdy)PN~%`{fMb>(DhCk^wU4zk@wM`fXl zkR2L9j8(#Wx$j2v+VdixhhSSrqqmuWTahDqEF*f=@1u zglH2$q(R0|`DQU8(qf90#*s?OziuksqQ3$pKCn#+ev@btmyiE!tFi@(t&H3bWHY;! zp}eKzTHPuzx5Xz3z_S;{+215sbB3qpQAvi+S1YUI2+S{Ww0*_OAy$#>;%!V+YOQ>? zU2N05$I5pjO-Eu@3jvm9$0KQ+t!D4vSpEs?{=50Tk^REY%RdX|3Mx(o*J^d?5KYq6 z^klHROt!96oD=rBVdq%((fs`Qri;jmS50Z+OQiB?n#TpoMphOtCw5r3L)+Zt`!nu* z=aLx-q+4%+^SbQ4?8b{B#^3lO)N{4jd~)N=fR61_y|Q^wyVlD!`g)?xFhhg0k~@}+ z$dL-V{@&C=e*%O7W=ZV*WH+8iG;K17ckpCy4XNwhREvOKDH$;>O_v_hi8KFv9{$Hz;8#QAu&`0? zsDU-ycoSz3&+R(RT?i`jJa5wZX*^GQj7ipQ$R&GKmZ-0{n@oLi{uvk&!4BSu`k5AX_=J#jfe94u|?qrHR`{d$G_0n#n10MMIBo5#3_(?RWbTWF2^?i z_nbBC%@erk!mM?u$gFR;4IF`I^;DLJ`bWRjQUO++zy$U1Sl)VhO7AY~T!ymgi`v?L z%!s*LZQEfcI-TUyWE*zMIAO3VMW;SmWpNLB(luS^m8@`7153a!p_e_uTCuzOcV}#; zVpH3n3Q$!3nRpsRf%)W~tZejijdnMes)@ZH$wP;X{7~gcF;7PI$d7R+3=w($;Qib| zue(vI4V@B!i1{ms{Pos|PNiQ<&2~YTvMGh`%t1V@QcZ5LxWl1#_j@%f-^Mm;Zi~!m=vC&6DqH_OfIw7gEzcPp>Q-T#90?W=tw=@7n=nKXkAlQ`JbMHX2$L za@f@FMaC;99eWTH{VT@!PhO)I(Mji6MVWbX3D+nXXv3g3WP_?_vjdqZ(`_k=&)U6m zEs0`nlW7o1NU&nNjGt099^fcsjaywE4K{44@}ZzN&BoR+vB+!ZbKmA)Z7#pbg#<10 zcwCO|;XLr}p7l}kTQ^Bq%ch=RfE8?(TS}{_jzUMgRQK|-s0qk8KzaGp;JiYt;5YxR zW`7+gdBaGX3AwgW5*?(gG(N>`-=i|sa`T7xDY{+U*GQ>o<+(2~1`p);^G8@qpDFf9 zPHTp`t|ZQlj*fCOr^Kf~9GoTm0@R0~cf^L=@#xO0m6NNoE7r0g1AY79wUt@}4$3>g zJ2)lHvXmCt8Z6T!k2qHB3Ru`8otb3lpj}c>t4|FeP6{p=^wrkh!|hj_qGpZDt-4MV zUH0jAe?;!y+v7tkCXOQEy;z!uiun%iW)_D@F#NAM#BmEu40FWz5x^6Y*4{C|^j zgA6dGY*$M+)H`kpz}#F{dWMMn?2Ai@Cd`w&Rquy!@aMglaoj3Nx>`}JjXFLf*hk=o zsMOcH?H>-@b@;0uBVjwfY{+wW+N?VhbS{fhm39!b8;-d1wO4o#Ot*kQE2*j$`K@zR z!luTzukhkA!UIfVHRQ_Xn~f4;`PL}{J%38^RCp0g)mYz1iUn9rgw@5f6InUY1mp=~ zj(y)Nd(ZLzp%#?TY8w?8GEW%hZQNFRypx3~1g1PzQE3M_t(f+7QP=cQ)NQX=iqC6Z ztsGLLR#Dxh4IODXkH-_QGgiIF?cRJO!J-q5O~x*{-s$36i%= z(^R75zLn}=<|2T*?Yi0Xlj?sPUT8G+UAXy?=BxQLM@R>YRFOmn?D8?zdXslAp(A;6 zcIJITM-74Ol&GbF{GwgiQzxEnEgL9KEONm!=p&vQ>E3Z2k*~FFx)94QUS#XST4Z^f zH(^#(@%?GYaj)C((!vok-d5TSS?bPF4SeKGafx##Bjc(K_meDHnU_3p_`c(6y470| ztR3&oNW-ghlgx3QU;Hup-9Pl$4h4=c9px3FQ1e^YCQZctTSW%9W=y1E2e>*mx4h8!>u>=V~}QI!C+*NmjNK8#Zf zm^tDkta90})J1HQ{$siU-C)k04HNIEi7PdM5j0Ll%FvB?a*T_onXuevKfkO!;^<#+ zKf(vr>aX97hFjS^Dt?_=T{Z6f@Rk4UysI0&ry3}sV?=||D*rgU_wsh|*PXQw^-~#0 zx|XsSFTr6zXA(pOVe+=w+|+R9YyaaOnG+F};~DNQw8nFXz6r}PXiX~)etD_8zHz!h z4`e#51Oq?AhFD6C_OR>hy_9M0{Guf(qdpm181D?$;dJ&nD_25Zn5KW)iCA+BMPl%1 zFvxJQ3@qaN@j7>iXq#~pxKi6=h%2hujk-BaakbpzK*vO599M|a^JE#fCIT$E<>bwT z$e0omh9rrC)<=o6ALPYiKQ`gJ&Wc zsFnL#3}R%;^-_w$it!rvk7I#r?$he!;WU_vo~$y-1B)(LnjnD1)0`2e%3YA&mqC{RpL|)v^MWbB>(>l*Q{My}M#Ak-6%E#ra0V_o+( z&Q{czYHoDvp&`lf3LyypKF7x2Vc=~#@R5wnI6HTDI9iv9o(lEEw)5m?Jmulf$(4=Z zVcNrAt>>O#BtLx$fyqv?YO2*a8fYQo7cloy3e@4_2(mum>dWI$C$8t0aif--8?&+shB^J(3CkGlQ7`7gZ-oO$&|mEvGeOpD^1Fr zD6BnQ#z3u~ve(Zisr1;y=9Y7Q4aYj%xY9Sdgt4;UmwznLdk6-2#tqw=t3S#GjU+e? z%NcXZBc^|ag5 z(dY-f=m275a5>k*{A7qpGMBh{_tz2cxdWf1AULQftU+lsl%ws?9g7v}xV62u?Vsacf z&g&8{zVVYsr@m5oVVfY~6~S(DY$n(&sggGJ&`qf`Mn&n<_KK5Oo zQ!k_%vzdZtTOMS6K8w~X*Cf7D8zT15dpUYEWPkBw%&Bmjb?29~zjZ%$t9B&p?hWbH z`kW}=!^#P(*v?*+^wHh`{QZEaPqHSG)D{aH66Y`2_Loyu_(U{ppB)DE#`m_Z-SkG_(t{W;XOdt zz01v|vI3JfaW;>SvxB|RGDC4!^E6mX zt#?Ue_~2EA2~N#>3m2oAutTv&Q^FM(f)n4_|K;42;5M=6FI924PD|wG2!soy%p_W_ z-c9cau&+EtE8iSX7HuhV?cQ}w|K2%q70}`FS|$+T-INnyA1l%1!fj>niSC_Iq9%^>Y~m1UmoZ1X!W-s>IyMOz4Nn z>7~P}a_5lpz#_>n<&0}ednMX)BcAnDN|i0yI1WoPSJ;OH)Lvw`u`aKfNJ~yi5nmTd2JdsXRgjg+i3qJ# zazt+puyi2S!D0Aa>w<4V<2_hyg^MAIJBLw&a;Qb>?kDe=ewmk^w`jx=ebL7Ti7ZAF4 z!8u1`kjptH+3H2+OzMF5Sxx3;BC5Ze`9`71-Z8Vlcf7|%QLKn&Kht>bB5j|L-y6tk z+X@P$wsbl%(^jaFgQW?6MN3H=aE(m5PimnL4-51PO!7+GS*`cTPXjC3pzs=ec>=b) z89FNy!v&Dz1nK_z7XY8(AFk{>+OD;$JYD-iTEw&$|5Pdc(RLssN41vPX7F`wQc42T z$QMWcBiaRZkt*=D^OeWmuoAo;U#?_c!B-ogr1Hns$IL<@(d+pJ&o#`;Dd{vE96P{_(?0b!6`eWSFR?f@1x$`uAzJxl}`Py z;zYn5h_*I#crd4M_cb_t<*6pmX*qgx|00h3xW5t?-Ee_<2weC*XPfT0FRlsRItoMX zwVtOhm)~X25h-o2gIzT;tRkmGQ)#*5gC@Ml1eE}`AFvC2f)*Zwsl}A!lZ6eZy}wtozrU6 zx3uk^z)xUqV{Eo!!07wh0ldUQOT^0zrG;g~(B(8e)kaoMwk30EN+v3>>RzQn;Orar zWvLyv1+99Vo@iH*S=GF7tV%DYc4f0h+^x8gA5Z+c{aDk>(Y4~XnrWGXz_Qs!vjB2s zXU@~*Ep#mJ)y0J$N8tXS#D7uV=rBcfJK^S-d}p_-bvDN@S5kh#*d`9+p#+;({Fz8B zY{FlMi8Ol8ShH_4b|}g;EU5J;cJznQMjR{8A9!f9zS+!;NdSXhG1eCtjMFJ2JhV>%Lbg z3R}@URa+;os7Xf_Hnyj1TdxpRshURC!y~M-UlOjDkYJ0+Z3@VutEC&bGonovM;QN8 zeW4$SP_P`yrc9=X!fgvU?ZCZI8p#!(SWQ8Gms=uBsAyh5PZWw%p?7F%;{&jN|f5UTi$x zdqBGERU1ybkynx$FF>)dAAEc`&a*A%yL&eWYp^04DtWg^#cK6lmamXe?GHx%(vF4@ zyS37_XK33~ZagJvfr?a`A9urWvX7H|3GxHMeUyu;b5Br=D5Oy)L zSzYm)q?M7O=L0A=lIo|4@<|(J+<3Z?5x_H4#UwW(_FTBgS2^Ju=o72%Y6xp@jn7O1 zFnI3LZJ+r4t723AVuD;OkK-?Aldl4J>~_PMS;bNZ*}GUlyA=5EJ|q_!AMHy&M|7f8 z`%KR6WnSK8EJCJ8o3rkjnx9m4Mv&P(0|Am9+f+_MVqQB_1GT8|@U2o3+pgx5Jsh0& zlRRgF0rDffLalC(_w!}ff-?z=6faaC_6sOLJDVv*p`~*C@vrVbX$4ME$%RR(h*uDx z#?i67X7V{tiZK@bNtQ&7x*d0<|91QH)E*-AN%HJeqH%W*|LFoSTukj}?s$W{Z_{`{ zcB{%H`m1$Az}U4o*$8FuLJiFh-y3JOvaHX~sMF)uAwZ@G-#RNi|6=gV(}9XM3F*R^ zmv^<gG`YX^WDV@#HArPZuMuY}NS1Q5ZL(Ig<5fCq)V7CWT40w^D{)G~5z7bnid7#D@rOet8M- zww)4r?=GWw{Mcvu7YWLRUr#~$;G=zBe`Ap%6Z1}L8Ol( z32@tk18YIAtX@pSYe~zOEVN#&Snri?ikC<8vl%)zfm-pzteN?9hLOYg{6Y!rn256- z_C;ehZ~B$$qwT@6WA*1SPwW9aB6LfX6IYH%=#$yAVl_-L=^}uXK^G1;`YQt&Jqm|^ zc zu_S-Xac_J(Nn!ys+;DXEYapLR!^uF8T<`SAHmchRVALscn;}&gyTk47@?;nKKOAE; z7hEU7fOFtfF;<*!#gUER%nAWU)AQ$r`y}xXzb~Dln(|XlczfWVFE$=EzP2Zv@9?t8 z5_KL%b;7#7LULwku^T&LDW_lYN%fu{IU)3Fb^bK+Lv(TU&^y{m|EbKQ|)^UyN2f3D#JBu1mK7$q_I`G`oz5U>@CEx%0Q zNqF5D1RMX`oVq@*~Zv*LFJzku3(brrmQcOHLyBrhQ1+z^+CV7gG0ipUqg@! z#j%ZU&-38HgP|UG_L`a3Ldo$1?FSJ`U6>yk*E{fjk3L5OuNc zDrLEuiy;!^ou4N#`G7(4I}&%N>VQwi+rV$|-LUUtD3$Io+J^D+OS0Up?$00R#h=lv zqA#-W1+Ol9L62ViEw1Dvjum;YOlMx6vF~lPZS0Fl@W)lASIg2)&g@orVMfFS@6B>j z1?9NyKh4x~99{c$N7V2lI#Gd`i))kHHS^(tDdS~3B>0#WL)rL!^c=z7{7q1#%T`FX z@q~8&_g58yLO|B75W^q+uxq`ie9u7mV3NO>Nm9;bR>fbGPY|!iR-$)o5~8g$6(r}> zwB;la>v-eB+i}iqdkB>Ad+)$pudewx(7=T63z6kWqNaKq$jd{nV3^bN(0&jU&r!f{ z_MV{B+5vtN1>xP*d)EwbRTyf?Zc3+Mr%fA)>2EzWac!8e#GT##+-Ccv~o%|bavRpL+*bg;Hn{{&7!bX}@7|DZ^7>QtrLKA_k+toK;BC3>dMC1Xo_ z99yI}H&e~hoOZL3J?|QmVw+^HXXx`+5zGWI2UAuONo0up7w~~|kn^-jvK;<+LDXWs zjRrLW45CEa5M1k{pbgGH zFtzk1mlNowQ`J!|spDDY6q9&h+PenG69b2BMr`_u%2fK_*^Rm&K(RMCk4{U`w*LAw zc`+gtfF+XneZuEb9^6bglGfU2XssaIc&i(8wI0a3zfx#}Kos@M=fWvt*|S7rFn>hn zg~}B(EN)f@A6EIO!aJRJTM3n5-K04Fl%X)& zBEW5=EXCe$1$mW!(nZg>}mMwr-vLBmH$)FmBH zgM)9iORS1x_=PwIVV4cNPt;J~Sp3*x_o~vQL<&hOpiejH>;XvcOI;w(~SZiSM>i&r@UtU#M;s*<&fY5)7J|1vrMCL%_<$kP0homKgQ)``ndmgQttll z_Lo&f|=940wXF91o@_&(!#J>@DozI0+Tz=>zO=?i}r>-iGd7;(Y z!)$(Mx$Eh>n_MuGq4%sm(ze#g0PkNL?g0W$AIqO6*Pyelv+;?{dCnre4FSfbDJ9m3th$DRsIFd@20D(jQdC9@AcFD2avq zugi`TSLchGpjxNQyf9FuHsy% zYm=U@zZkGK&}qNekbcNa)Qz{ogz*Qzr)2V4B~4Gau)OY^y@+{}Lj~J|ECSh>nrO4N9Ak!oQ^ZFEOishjY3& zf9GBqfq#I;s&c1J2D&Jw+*9EW__hCwn*Yo$s-;_Ni)R1_62QKh^vH zqPtC_p`<=Lgn693KyMZ-D*?j^DUAkQMp zuxKMq!vvJ0FB1#!!B+;)yUGr!*ceTGD@3x7_+Jo zsR959$052)yer5Q3dx+ffO{=W>cnlde`C6+Og+-YMkW+mu!q=X$-#g1h4!DzN@M6B z9#yiG3=PzYU%{JfBwqy`82~99yVtu|Y4J3Y4c?dc8&?&tr8^QhKxeAE9XX983k6xF zF8cKf3&8IX91Cb+3*_3B?87P8Pm-N|ReADR6L*wzygGZg6vOexgSRo41%4PqcZ5Js z-$%Dmo}f&t38IE1H>30EF{u=n82i6WqCO9Ty3`GT>EpIF3_}lU8q$fU@L#b#VbtVZ zT4d2qptO=rUk}hMc8+|QbJQ+xOypWi^Q8~m^}`u`*Vl7Ji=Xzvz@`A1;fp>N0#|7@ zysC!qjiZ!LOUv-@7gn4HKkTycO=$p7eSR%N(sRg9O?JE!FV$pnx-Q@4B`iOn1bqy1 z%e=s+&~Lb0GgyiD;D!fY=iJt2)Mxwq6S6x|^2GS9^7P4#$NyvNt)t>tm+s*tkO08~ z1b4UK?gV!a1c%@{xN8V*!QI^n?t{C#6N0b_T%B-UVBIS#f_s(!U!Is>Cz!nY!H6<;f?^N7U6xIK zqcKlz)t+Y3*KkAI`7rYoY_%zd$JEh0n@H`Ffz5}HuS;avD~gr(Hi^{ATl2JwO#ov^ zm=~Vn#Y+t)RE(A;U3jVR$t7W z*KYXc!7`i-EK#!_oQ#|5pcmxUINFwH+!KFalKJ{NO( zmTPXsfimhL$ZF$Pa>GdrF8x;BlOz+N&nK}v z;dz}<-a2}MU*7J$X6xGeyeaTpIh<_ohRn|J$26SY9Sw!1$np+drYz zpGUk?t?Bb2t@8RhV>A7jlREKn{S}%Sf^tpKy=gQv@u7F@#P~YZlrX#iwv|| zyHW`6U7&;JT6k2Nrj<(9i;K;~r8@mnOpK8q3Lv7LJ8{mtQ0bHn*f1Ma332ph@}v_VnORY9 z1qPjc#UM+o_HhdQUBTG?kiXS*jb!{QvzC}t6&U}jKx0j`>WdUNUd@7$a@9Co+x3KSKeR$)jp z>b?gdz%px)j%YB~-j+>H#QUD~Tz>{7eaC7VX&SjZWU+TLgVJm7?XxYR=!_NR3mC9g zD5(&1FA*X6ZXzF-w&{#AWXO8Pa2M|+y{YhB0sEA(V41E_a&bMMz^1Ips^XL4fg`J0 zLnGPu+=zLdE*-9ljpkPV;ae(DorE^%wpFGe6Q7d)yB_1pI)yfgaN!npL8wyW36v?@ z0A;FIMgC^W=Jiq-<6SA**@+24wI&G`L~P{fzgsW{rU+8=N2Bw+J~pWwS-Azunx}`4 z{#TFjj_b}Ns+^T-*hvhI&iUwt3;Ap9qF(7<3I*IE|3nhzJNOSWaW*@`kngM@c~0J> z+tHM^>E&GKJ~g|}kv^vGNN(xZ^V9O1AY(!7z2nn;*AXhlgx|WV)Qga+7a1Q42CBqE zFxf+;&Dv}mHA=#faLe@o;X{~cn=Vm<6V}Wf5)OZMK<$lR?8?{JbPNmW1lk~MU zM&~j{a`MH=bnER5H46UZ1x2Kjl6AU7gLi!&gNA1yzec2EUuMz%zDN>{=e3`v8ot=Z=64#&76!oyBibv`JJ z!=}rhz1wiE30pa$n7?b8(~LE)JUH3NIM}3TSgtE0Ya8VC2BE7K3CvTcAK6;kQEAHM zRs66pvJk;SdGH2btP#o+&t(8y5PA@CDOX(L_oR8{CIfC-3TA+`bVl}6n362g=zn#H z17NA#+{d!196q(GhUMR^9Pdn_f=*_j+M!b8v}DoRV;7j42oHF6omd-Uj|YVy{R3Tr z>&xY1NzTBnG4)^Rcq}&ppmamDrhgLV&Q;RR8lzD)#p2xBo!%VP6N;6eF>#HIQ8sJBHuC!ZE z^+4Z;C+F~{Mo}_^wu>4l14%LQxROw_xbXuctbBB<+d=!2JG_a@@7Js1#^+|@^%Fe5 zrqjVOej@$1%C!UI|EBrl!-X6Lhq$Gjf<=xsl#L=`GED1Nc0XuDpBBEC8>4N(Jni+@ zv=0T@VpxbAjDbuF=pET+BKwVV!_~{orE!tyPG+@w5!eK;PktGEd=GWb@^?z@#%2Z2 z$ub8k!`s|rHIfdQo?<@nFxUNX#W+`KWD*Tt%|QtVww$JgUY9&3{{L)eew}U9+2nEa zv-R3}9&5exmBZX9M!&oc529&YFwDQ`w%d5799t57O7u+!d)NkioD+{AM^OH4m&}f^ zyQ!cjrQxt@{8?@!_Sf2j>(+9!zC<7AYI(G8d^>3*Rc4viFC3#(Sz>>??_Vzily}LC zcpdhXnsc$2At>ZCYrEOTW_@E zyd|hOLqIGV3v5Vpkk529OBL6CN~Mov$WC=Ndqa@B2yI4C13b-`hQ1d_q=z#Okp0Q7 zYCjqiyJtzo%3jkqNf8>mbH}RQH8-qgW3~)I~5!{kTBmxG4#K+hd}E*rp9C zVM1GXO&_Lh-`Ye!tL8G0;>5FFUnt+$O~fvaY-8rSk=WV~+OkCvW(PS~Dc z$=@b-+N;I#hetNRAZ#{Ou5S?L_l4R*PoAZ>)-K(8@@GdvSdk zzunA6*pA%V=kCd;UMQz4IWv0dFd2pWX2vt$LSOLKd zcTP=0SWlQpX+D;Vz_+o7VdUpd(1HRS-^Rn*X5qSFJu;*E$m_N>`69}NEAF?0%kof~ z*v%%!T8yRL>AJ1iBF$bK5zBjh1BuE{hno)L;|ibROyvJu8-GpG>`|@>nVUnIW{kVL z484+^lHWW(B=^!@mC)I09dX7I6;@ElkBK}X= z)RlP%Q#HMd6wVS#aJEBe-@+gJgh#;dc>NPMj3RYL z$q!RX5Ntx*c2pGv3z1v#g*vDauVG>MKBR$b#5B)^0?j$#3uAL)p4hw=pJ-G4R zO}}ZOoyQp8;o!{lG0p#5>HPM5=~od?UmCY5GF$3sjAHw+yg0AI3Q9I5-gu-@Cf&c@ zux9@~(Zc6l^4>021_hUJ9<_p!k$&6+PXki^Kk!3mIw`YTrLxwG%CY8VrFCoTaT;#? zu=k0HA=*FUhSP*BlaVo%sDGbdgtUPzPgZov?q`Iknauu3>5_cRuFmEeqn%${)LD-F zv{Eqt7-h4FL3PKj_4MJWF$1<;{dLq2`*9s*m!RwYcBh6wZMkuptLEh+wY`OLrJLeE znNU9^^TZh7uzIg3nA$aYYuhmj5h?UvNsR`46W+w^IHvAy5K%;r&#++@ev2^TyJWpr ze6FYI>u*WC@!$tLR%S@>$^I92Dopi@A~0pns@lSSe7=fixN3gAQ1aMRyMY%r9hJ7p zOE1n6>WAV+`MxQj^9Fq~h6}UOf;@ZX>seh_puxL$@aF9I31d@LuLM(h9=e1pUVrpM za3BiOeJ9`CAORiZGFhJ>d`e6C?(G|P5BKozw3x_-Bv6IsAU@Js-obM^4`Y5Hn&4VI zDOCPppnwklCcs00N_KbK45nb0$G`E=^Kc~?VrzE64;bJm17@dBK%P*?&Ny#%*#a~f zUaWYkU*ui7D;lgXtqb`+UTPEHj53{8x9=_Ny|(#ifQ8_77um1M08?As8Lxr7;yD~6 zLIO|0?f=@uC;DOOMfeaH79x`eB4I8gYefx65D_7^}+TAc-md2F7OHzZ}9EiKhgKU>Mxw=&abIYdIxgCC?Oz5}r6BohAoLlOQ1&6Q^+b8zbaS?!)P$TZO;5p z*!oXE=p2QPs}Z;wRVM$Rx1a?xbdrr7F%RCq5~9C;yjH3+KA&s4MN`e7p>%#iy|4J+ zxY}R29LY-rYr64Los<+moW_9m3C(uE;PY$_==%}xCclZ~;FiEA{1e>%HeNsB zU+ABeYBxe3S#tj~M&O^z!mJ2?jq-R{g))I*QluiEyrC+MQS<*=!wcAcYP(AB{fcOh z{)t)=RYM=9!D!6Le?X1DLtnD??;GvCJ8S^G9kwrnIDa1~o6N4#rr4;n?9Y^;7qD0; z{&(7M9wd_kXNc-xfBRx#YUfv0U^M5o?!H_vC9LXGg&#lEdJo8y*7ix()n_OP9sbz2 zI>I}RY1uXM+R|5af5Ztq^1toFF_k_3pXmGdTA*4F=oF#*9?6;i^;y%f7o%q>WRV{K zd#32g(6?Zp&!?QAE5Il3)Zrfot#VPp{LAx6HsSZ#@iNro?8XXdk~a|Ub0);%L?f7b z*UiOAtKyuSMY-rqwT34a-qa}gj)43e9pGTA1?P9RlYidBidMQ57KFBMMtg#_c1=s~ zdI1kv&1>G<1I*ofyKt}-|6S28mH&#mskf=>=IX4CR{d9yK!w|0-TC*jm5pVw=hq$t zTPefkOp7z8XXdE98EA>jM_X;D=Rhe$hS`Us4nX{^z?1%}GmODXFtD-YjF{`%*GhMz z7TDp#vry65^m-2f^W=MJO1Sm43fRKuLT!xT>cZ!~xD%b& zU^_o7K`>z)L?S(_-W%I9_{KDdiv7>sPo{cBE6rQRi1E_j1_F2p5;#g}!_RVjWLjz0HXLfco#BOH~rr1}QwVChC*QP*vs+ik^^ zHGFfA^aw;AY4+~+GqC>FNfwu_yI5K}ue#L`pG=vuFLwWMh}-XAoa_rbiIL`;h06|2 zJd-tFg>|vj-YCf0WNlcoQ8E={$-_}KTr4~Zc}v8X)B8x7oxdJGLsa(mC(p7+0*^i{ z*~FUsbb;(q^UL?XDWqx90e(oc5*TGkN``@~G+r3I#e66KC9+vYwpDXLbNJJVXEQIi z2e;$OrIkvW6<8di=v%yWFLN7kl>hZ~iuVhpigXqzV<(ZH)**9!tr7q@Z&pu*Kmuqb znh|Pegl~Ttu17Qod@naAD|?Ujv$A6%x?<8d5i}cz0m+RhpzT{aEwlu*2Xyq|kT^RChV`YvPw-hf zkh?qBIsTohtKh?oV`kTjy(1ny8??) zNed9NzG9a=xVi3`3*_M19%o-`9BPG_l?Py-dLG#KZ#RkIbA_5j>qi2<>hx=K0OMkGJwf@wa3f-nUJURvJKQ&Yo||_0gx}dfs(p{6SDfZI+~f!d#LxQ{CplAsd6_~Hu|hW z51*C^_NXzSEPTi&=0;y$dUo1;1NBL*zI?;JC?Nm|{6HJp*N#+}>&;_|BUJBAW z1mQ34SW)e(Q(>1akGQnn3GE5AGl83}pG(~zJ*uvAl*pM-ea=Xd)GR=U*w^tho=@8-WDp6*BEHhQ@b zxH?V#v*GxQkt;ct0G|)fH@qB7ayj^;7-G!f(M#LADjoCNQ#qnb2y(<<%*U^|KB63N z2|k3Z)qWgs3Zd^&6;$TX6pWCxlROJw>x*nk;_D0S?X@m^5UH#k^?wYWE@f!U|G^L( zx;dafN;&Tnx*8xFt_ep>g1s=Ly{ncKu9e1lndhv>2N8oR-QW*a_do|7on|5LzR10S z(I^#-vRt?Ve}CC5qEPecGq=P2%BGZx_|HY`$MumyoG*cImy!>s^gmf#F%@d%`M`H& zli2NRmV8j|e~!xmAZvEqIjLMnFxxY2oM33>~3YT?^y1dcN|4c&r-81V968V6g>g%yl-LI@Z zfIO1+>E&9mj|`vo4X+z8>Vn0*?oEzt;Sa{BF~iRy4O`2SQ(rZjU8U|h)NsqU?r2r( zH%k;E&*h;t>jQXLV_k`g!&u^*3!v(Es&KR>|WUc72}i*2xsVV8rXJ(z#$2_XRsq zLj`N?CDKi1x*$>syamsX%)qrDs!K7i%Yw5Y)B)0~ZIOyO#BEt#1!P6KH1b_VY(Tms zSx$9Z>Rs33_LRKS=>r-Yx*yfFkzK`8l;Mc^98Rg`b5?Rg-Q5S-XWM$QlC38~ZYyaz zyjIIuPvK|ycaF2l{TGUFECRV%u*Egp2{*=&vJy-d9i65s0=Jjk?ljh@iIJ5*?G`-? z1Xel9FH^gq5-noCjQ}OE9P?VExx~&eJUShwo<*mhA=cd}P3^i`9vVRudP9?_8pB3m zqIn;_wv)%ti7b<``%ee0bnm5Rya@w32cZjU=88|=b$xW0*?5Ba;u+`1=&ITe08BF8ID?Jgc1J=Ky&*YVzBA5)r30986ma2K@67v_h0_6*h=YAWn7&)BaTXc#={7A_ zOe(gX*(c_Y@}w3>#;lYvW~XRP9x3|XKdf)$i-dr3_c@OfnaA+P`aJ+2trd!N4@u&u z`NGSRrI3%ZR{>U9a%KugMGXeu9CO}*8Vyndf_~Rvo$(mS^lO2%7N4c^wvZ$kY*NuJ z5LH6v2VF-+M7zgLV;GDX&mD8rOyB%a=D%H=rA@UzaDJ6RBbq@@=cO+o3Zey zo!p62ReO00zJdY1Ly0M@ac&^YVRZ0Ip#ymY#Nt-b5l3)E6B6PQF_QF&#G|WAE5F{d zCNGjfh8uco>9fG=U{U_*VfHJ@(yk3%<$<|D@eZr34F<#cy(oe`N0B3vX_&L_B{&P2 zh&JGPJfn0WIIUS}tOync&!&{h-X}l{6DCw{R+qDl4GwWv5PjIBsi`5Z=XR~X(` z!8!QU0Ie=c(|m4$Zwm?pS3@^^&l6Cad>;=PvIZ$R?$-rpuZhoiqge>Vt%yH=I!Et7Blg0zm5S6Ac!yA&-YgPhu!nH^gl~?$9wht&0F%aMQMw>WjPjdx|7?dW z8t@B!()7LR?9wDiKf>cIY|%TC=ZvQxKQic2+pSCvK$SuBOH}ZopI8-gnF-Gqi5%p# z=~zosDx8(X6(hfSOYqYMu(qpjdb-pbet7SEc9%tZH%Onk^I_*5rh(_163p0`iQ6A- z$XOM#)Vk_f@%CY7qzMN^O`k>c2T%@zwNMcnTt6+xP2j&?n29;VbmzPk^jUEQ9MI=gdSftp{bTRDzFG@Lx^Cob0f z8cc$-t}j>OrDWu{+1@E=wqED`bl>dDp5$|NYaV?SGm`YyceRTv8K=PM=V#y}yXD`wbK3=vKW5%l zJUOhL(T63^=JCJAEm$Tjdh3#21r>xVP@kJ?YSrjiec#}>509%nRJm=k>66p!oywZs z(4|(`mg`{XYcQXW{9LhQ$|3HeM7FkQ0S4S1FRIDc&a(hYabA;Hm z^-LC9HE+uk+e+C^XEj!>j?AZ{H^DE+?M&(2pdV3^_Dzu(MD`za#;^Td=R{_E9s6F9 z!L_KGhU#m*W|v5<9E}R6wem}6$Iol;k62UPEL zW*f^}zG6&+rVAx|{rR)DOUi(U@S5-L(KR^~n(nM=w(xJ2{F9@A~r%er3qU}_tP+VIpBvfod=PIgd5 zKak<$(OZV`0PGr6zKOkP6ADA$f5~kxjfUs3^3WY>D+s*H6QXu^cQ5S%^+#rIBekCnslT zY4xVlB^+@zNg&XSxAPG6uzGdO$8!ii)}+h2)b!>eczA2+hbzgc;az`v3s9q2WPJ%f zUUE2U_?1R8>OF;FvSCe)?m0SP%+ES1)!3n@d?`Ov`N1 zuuAhzA>M|isRDi_U(%zoW8-C4zf54jS1U!+GOn>U9tVjYV(q5-a&xW^Nef*Wn01H9 zCRN0F^jbUu&ZP_4yBVY1`;zXD=tojtc8)&Iy>ygXvbEi$-^?vo#a%7Mtst`Q8@@%! zDA(f>nFAR2)W=y{AnHg|I|6ZQCIk4@=Q-7U)EaifgbSzBW!c3XHWb>{>-0m58^=E^ zdFL5UCV4-Au5mNp#Uc-$6S+u9=$)ZnD+7pi+g}m zXajyzqb@^`QXoiw>mx5(iyLU6k~E@@Bw=q(u5n4~Bft}wue8aKStrNu^HQyGs^p7f z8rcCHAQG?bV074PnXOz8WV1Ug7QLZ|L@Z$@TKoYL<1Rzvv*jaH)Z)>S+*57uQ;Yr{ zLCn2A2x%_voj2rHNX#`b3Og^+OiWg9qe>@>PM>3bE_9Yyks%LmPyDVRZ%}n2Vdg|L zPW1E!>+tXpWJ`245VAl$N6;#fmBOMsZ_P{_sSrOH$bpb_t$l6vO=|OOdmF#$;-KFM zjIhN&Sdt4alPOKs4VQIcVTqly>1Ru$4uOw^r zrV%0D8v3%fy+K`O|LAi^deiZt58ntst1AV^Wn;~@>a23r;rgMpNl!&3tJJlY*z>g^ zeK*`6JlRhG4gSvY4w_Uf>k6MWu5s`PUAjjX3BGq@!I)KU945a;w(3TmuT5!&w=QWv;t^WXF^=z~E}+l*Nc1}31yoe)Gm|cHKvw#1pyYj2 z7S#8zsFts`<)SJxV;}V|z>+m1-z2l!moWMZg?if)g}gPo!h6=w%^*b@iG4n!NcJTy zm4gQ0%24l}?CUdHJzpW3IVKoW99I!?fp!V}&~g8~hsa#G@X8|9HNB#HsKzG)=42zVr7nYKaM^3BYTA&v$z%+H&;;LJW;+n)pJ|SRI zF6c^e?8xk^*x3B!ULVOOZh7?e4PJ)Dn2Zr!_D6nSnV;4D^qihjG0uW+jx4PQ+#~wv zcDgC6_uMMJ&8!>|^2@`LRzldk8AC@ja+Rh*q3wwed{lc2zHyo?g+hFt>qTd7c?0h% z)V_%d$oxF6FWqn)!HzmTI-J#tyDPRSCiso&mM8hi>#CSV>>r)jI;nnXANzteLMVow zImjHR>B*tuy^h={h4RH>3vVjl;*!(5ubkxsx2rGZ{j~k%ib9vuwv@YVf559{nz+5* zIL-{u$mNyqsb~B1v_Y=3AD_R&-5ZB90wisAbX;~E+nr|{#*qT1P9LjNA>SuwDmt#^ zZWKz}Z?3lEQfo_Px!^;capxC)R<(Owt@2aewSOQ2R$p~{4%-1-e_Svldm5Vb_@K0g zD}xvU@q-6wQ0ny^0%Nk1*_g+>WFQHD)F zG^=*2M_RVD)s1c}$M7;F%uBS-s3Akn$@ALH#8E+CZ1oG9x~&g_1F76)KXDz@O2moE z^T|oJ307lAs8BuuHj?jmoeNi1^bfb?9;cBHuV&{oxxEk-C2Yq1p<;UB0X{-OtpuCmOW^-Lr7p0kP zObX8b;oD_78kB=2mF=IgRpFlzJNRm>RXk2CfD%J;I`pnoW!$+0R{7fKT4qY=QfQ}; zhihS7x5FYZ@zP%V=kvYJ@>+$od$3CiPcOLM{+AykrtMtl+HQq?sAt{PavCpRQx!d- zjmezeO6!F)CZOH^zI_%wu%lJO@w_!$E{TJXb)4FZDcaphR`<4wLPE+hM_t*up&D6! zxbPfzR}{{4Zx6d_G?z>R+{t{}Zu>mh6%he4SZS`67ae!jxWuH4Y@dI?A_>{3nwNq{%A+6yZvd4^{M+y?X-tR0@G*C<)M?qv%Y&Nx{VdZ zff%-r8V*m9PZ7D9M2A!3qTUu#zyfwz4*r59 z+=KzEE>C=a<}T{NgSft�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

ie#8r+rf^jqH)mnGc-JDI|8D| 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�-dS|11dj(=L5CqK{=D(L@*0`cE)z>Dj^P%F7w{B2vJLi?ykfS^3;_NMRU|3P8u zC!PQxr0}J-_@B)1W5;8eSy))2&muIJZ-xBk%l`KU7uW^D1C!JpiUiIY&3u~>S={#g zH3XCj`HQeYoeO~OmcHZZI+HV!^#DMOK6=K5`gT#D&BUzLd6eh?ojH0&eV8hRdM+TO zO`$bTRs((wu!wum5w!oQil4)cs(;a!c)B9eqj`7&A{r zySBf%2fw@bH85tj0sW``RrQ4j2PDzI5u+IYB4GY!NL1NRzYUH2ap&5Te?7S;RpJi2 xrr!LYEB{)^wp5Ax>yxo>|J9ja^`?&gs2;?hJk~embPRZD-PgZYrS|y6{{d54s&oJV literal 0 HcmV?d00001 diff --git a/resource/docs/img/stack_diagram.png b/resource/docs/img/stack_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..2d2ae09b8e1dae15f93a2eab1c8686c765d2f301 GIT binary patch literal 81345 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 TKX4.9?) it isn't required, otherwise, it's required + if target_os != 'android': + examples_env.AppendUnique(LIBS = ['-lpthread']) + +examples_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')]) +examples_env.PrependUnique(LIBS = ['oc', 'octbstack', 'coap', 'oc_logger']) + +if target_os == 'android': + examples_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions']) + examples_env.AppendUnique(LIBS = ['gnustl_static']) + + if not env.get('RELEASE'): + examples_env.AppendUnique(LIBS = ['log']) + +if target_os in ['darwin', 'ios']: + examples_env.AppendUnique(CPPDEFINES = ['_DARWIN_C_SOURCE']) + +###################################################################### +# Source files and Targets +###################################################################### +simpleserver = examples_env.Program('simpleserver', 'simpleserver.cpp') +simpleserverHQ = examples_env.Program('simpleserverHQ', 'simpleserverHQ.cpp') +simpleclient = examples_env.Program('simpleclient', 'simpleclient.cpp') +simpleclientHQ = examples_env.Program('simpleclientHQ', 'simpleclientHQ.cpp') +fridgeserver = examples_env.Program('fridgeserver', 'fridgeserver.cpp') +fridgeclient = examples_env.Program('fridgeclient', 'fridgeclient.cpp') +presenceserver = examples_env.Program('presenceserver', 'presenceserver.cpp') +presenceclient = examples_env.Program('presenceclient', 'presenceclient.cpp') +simpleclientserver = examples_env.Program('simpleclientserver', 'simpleclientserver.cpp') +roomserver = examples_env.Program('roomserver', 'roomserver.cpp') +roomclient = examples_env.Program('roomclient', 'roomclient.cpp') +garageserver = examples_env.Program('garageserver', 'garageserver.cpp') +garageclient = examples_env.Program('garageclient', 'garageclient.cpp') +devicediscoveryserver = examples_env.Program('devicediscoveryserver', 'devicediscoveryserver.cpp') +devicediscoveryclient = examples_env.Program('devicediscoveryclient', 'devicediscoveryclient.cpp') + +Alias("examples", [simpleserver, simpleserverHQ, simpleclient, simpleclientHQ, + fridgeserver, fridgeclient, presenceserver, presenceclient, + simpleclientserver, roomserver, roomclient, garageserver, + garageclient, devicediscoveryserver, devicediscoveryclient]) +env.AppendTarget('examples') + +#ios doesn't allow run application from terminal, so won't build these examples +if target_os != 'ios': + SConscript('ocicuc/SConscript') diff --git a/resource/examples/devicediscoveryclient.cpp b/resource/examples/devicediscoveryclient.cpp new file mode 100644 index 000000000..f08a8c7fc --- /dev/null +++ b/resource/examples/devicediscoveryclient.cpp @@ -0,0 +1,147 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// +///This sample demonstrates the device discovery feature +///The client queries for the device related information +///stored by the server. +/// + +#include +#include + +#include "OCPlatform.h" +#include "OCApi.h" + +using namespace OC; + +//Callback after device information is received +void receivedDeviceInfo(const OCRepresentation& rep) +{ + std::cout << "\nDevice Information received ---->\n"; + + std::string contentType; + std::string dateOfManufacture; + std::string deviceName; + std::string deviceUUID; + std::string firmwareVersion; + std::string hostName; + std::string manufacturerName; + std::string manufacturerUrl; + std::string modelNumber; + std::string platformVersion; + std::string supportUrl; + std::string version; + + if(rep.getValue("ct", contentType)) + { + std::cout << "Content Type: " << contentType << std::endl; + } + + if(rep.getValue("mndt", dateOfManufacture)) + { + std::cout << "Date of manufacture: " << dateOfManufacture << std::endl; + } + + if(rep.getValue("dn", deviceName)) + { + std::cout << "Device Name: " << deviceName << std::endl; + } + + if(rep.getValue("di", deviceUUID)) + { + std::cout << "Device UUID: " << deviceUUID << std::endl; + } + + if(rep.getValue("mnfv", firmwareVersion)) + { + std::cout << "Firmware Version: " << firmwareVersion << std::endl; + } + + if(rep.getValue("hn", hostName)) + { + std::cout << "Host Name: " << hostName << std::endl; + } + + if(rep.getValue("mnmn", manufacturerName)) + { + std::cout << "Manufacturer Name: " << manufacturerName << std::endl; + } + + if(rep.getValue("mnml", manufacturerUrl)) + { + std::cout << "Manufacturer Url: " << manufacturerUrl << std::endl; + } + + if(rep.getValue("mnmo", modelNumber)) + { + std::cout << "Model No. : " << modelNumber << std::endl; + } + + if(rep.getValue("mnpv", platformVersion)) + { + std::cout << "Platform Version: " << platformVersion << std::endl; + } + + if(rep.getValue("mnsl", supportUrl)) + { + std::cout << "Support URL: " << supportUrl << std::endl; + } + + if(rep.getValue("icv", version)) + { + std::cout << "Version: " << version << std::endl; + } +} + +int main() { + + // Create PlatformConfig object + PlatformConfig cfg { + OC::ServiceType::InProc, + OC::ModeType::Client, + "0.0.0.0", + 0, + OC::QualityOfService::LowQos + }; + + OCPlatform::Configure(cfg); + try + { + OCPlatform::getDeviceInfo("", "coap://224.0.1.187/oc/core/d", &receivedDeviceInfo); + std::cout<< "Querying for device information... " < lock(blocker); + cv.wait(lock); + + }catch(OCException& e) + { + //log(e.what()); + } + + return 0; +} + diff --git a/resource/examples/devicediscoveryserver.cpp b/resource/examples/devicediscoveryserver.cpp new file mode 100644 index 000000000..9db7736c1 --- /dev/null +++ b/resource/examples/devicediscoveryserver.cpp @@ -0,0 +1,170 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// +///This sample demonstrates the device discovery feature +///The server sets the device related info. which can +///be later retrieved by a client. +/// + +#include +#include + +#include "OCPlatform.h" +#include "OCApi.h" + +using namespace OC; + +//Set of strings for each of deviceInfo fields +std::string contentType = "myContentType"; +std::string dateOfManufacture = "myDateOfManufacture"; +std::string deviceName = "myDeviceName"; +std::string deviceUUID = "myDeviceUUID"; +std::string firmwareVersion = "myFirmwareVersion"; +std::string hostName = "myHostName"; +std::string manufacturerName = "myManufacturerNa"; +std::string manufacturerUrl = "myManufacturerUrl"; +std::string modelNumber = "myModelNumber"; +std::string platformVersion = "myPlatformVersion"; +std::string supportUrl = "mySupportUrl"; +std::string version = "myVersion"; + +//OCDeviceInfo Contains all the device info to be stored +OCDeviceInfo deviceInfo; + +void DeleteDeviceInfo() +{ + delete[] deviceInfo.contentType; + delete[] deviceInfo.dateOfManufacture; + delete[] deviceInfo.deviceName; + delete[] deviceInfo.deviceUUID; + delete[] deviceInfo.firmwareVersion; + delete[] deviceInfo.hostName; + delete[] deviceInfo.manufacturerName; + delete[] deviceInfo.manufacturerUrl; + delete[] deviceInfo.modelNumber; + delete[] deviceInfo.platformVersion; + delete[] deviceInfo.supportUrl; + delete[] deviceInfo.version; +} + +void DuplicateString(char ** targetString, std::string sourceString) +{ + *targetString = new char[sourceString.length() + 1]; + strncpy(*targetString, sourceString.c_str(), (sourceString.length() + 1)); +} + +OCStackResult SetDeviceInfo(std::string contentType, std::string dateOfManufacture, + std::string deviceName, std::string deviceUUID, std::string firmwareVersion, + std::string hostName, std::string manufacturerName, std::string manufacturerUrl, + std::string modelNumber, std::string platformVersion, std::string supportUrl, + std::string version) +{ + if(manufacturerName.length() > MAX_MANUFACTURER_NAME_LENGTH) + { + return OC_STACK_INVALID_PARAM; + + } + + if(manufacturerUrl.length() > MAX_MANUFACTURER_URL_LENGTH) + { + return OC_STACK_INVALID_PARAM; + + } + + try + { + DuplicateString(&deviceInfo.contentType, contentType); + DuplicateString(&deviceInfo.dateOfManufacture, dateOfManufacture); + DuplicateString(&deviceInfo.deviceName, deviceName); + DuplicateString(&deviceInfo.deviceUUID, deviceUUID); + DuplicateString(&deviceInfo.firmwareVersion, firmwareVersion); + DuplicateString(&deviceInfo.hostName, hostName); + DuplicateString(&deviceInfo.manufacturerName, manufacturerName); + DuplicateString(&deviceInfo.manufacturerUrl, manufacturerUrl); + DuplicateString(&deviceInfo.modelNumber, modelNumber); + DuplicateString(&deviceInfo.platformVersion, platformVersion); + DuplicateString(&deviceInfo.supportUrl, supportUrl); + DuplicateString(&deviceInfo.version, version); + }catch(exception &e) + { + std::cout<<"String Copy failed!!\n"; + return OC_STACK_ERROR; + } + + return OC_STACK_OK; +} + + + +int main() +{ + + // Create PlatformConfig object + PlatformConfig cfg { + OC::ServiceType::InProc, + OC::ModeType::Server, + "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces + 0, // Uses randomly available port + OC::QualityOfService::LowQos + }; + + OCPlatform::Configure(cfg); + + std::cout<<"Starting server & setting device info\n"; + + OCStackResult result = SetDeviceInfo(contentType, dateOfManufacture, deviceName, + deviceUUID, firmwareVersion, hostName, manufacturerName, manufacturerUrl, + modelNumber, platformVersion, supportUrl, version); + + if(result != OC_STACK_OK) + { + std::cout << "Device Registration failed\n"; + return -1; + } + + result = OCPlatform::registerDeviceInfo(deviceInfo); + + if(result != OC_STACK_OK) + { + std::cout << "Device Registration failed\n"; + return -1; + } + + DeleteDeviceInfo(); + + // A condition variable will free the mutex it is given, then do a non- + // intensive block until 'notify' is called on it. In this case, since we + // don't ever call cv.notify, this should be a non-processor intensive version + // of while(true); + std::mutex blocker; + std::condition_variable cv; + std::unique_lock lock(blocker); + cv.wait(lock); + + // No explicit call to stop the platform. + // When OCPlatform::destructor is invoked, internally we do platform cleanup + + return 0; + +} + + + diff --git a/resource/examples/fridgeclient.cpp b/resource/examples/fridgeclient.cpp new file mode 100644 index 000000000..a37c5818b --- /dev/null +++ b/resource/examples/fridgeclient.cpp @@ -0,0 +1,256 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// This fridgeclient represents a client trying to discover the associated +/// fridgeserver. The device resource is the only one available for discovery +/// on the server, so we have to take the fact that we know the device tag +/// to then generate a Resource object + +#include +#include +#include +#include +#include "OCPlatform.h" +#include "OCApi.h" + +using namespace OC; +namespace PH = std::placeholders; + +// Option ID for API version and client token +const uint16_t API_VERSION = 2048; +const uint16_t TOKEN = 3000; + +class ClientFridge +{ + public: + ClientFridge() + { + std::cout << "Fridge Client has started " < lk(m_mutex); + m_cv.wait(lk); + } + } + + private: + void foundDevice(std::shared_ptr resource) + { + using namespace OC::OCPlatform; + if(resource && resource->uri() == "/device") + { + std::cout << "Discovered a device object"<host()<uri() < lightTypes = {"intel.fridge.light"}; + std::vector ifaces = {DEFAULT_INTERFACE}; + OCResource::Ptr light = constructResourceObject(resource->host(), + "/light", false, lightTypes, ifaces); + + if(!light) + { + std::cout << "Error: Light Resource Object construction returned null\n"; + return; + } + + std::vector doorTypes = {"intel.fridge.door"}; + + OCResource::Ptr leftdoor = constructResourceObject(resource->host(), + "/door/left", false, doorTypes, ifaces); + if(!leftdoor) + { + std::cout << "Error: Left Door Resource Object construction returned null\n"; + return; + } + + OCResource::Ptr rightdoor = constructResourceObject(resource->host(), + "/door/right", false, doorTypes, ifaces); + if(!rightdoor) + { + std::cout << "Error: Right Door Resource Object construction returned null\n"; + return; + } + + OCResource::Ptr randomdoor = constructResourceObject(resource->host(), + "/door/random", false, doorTypes, ifaces); + if(!randomdoor) + { + std::cout << "Error: Random Door Resource Object construction returned null\n"; + return; + } + + // Set header options with API version and token + HeaderOptions headerOptions; + try + { + // Set API version and client token + HeaderOption::OCHeaderOption apiVersion(API_VERSION, "v.1.0"); + HeaderOption::OCHeaderOption clientToken(TOKEN, "21ae43gf"); + headerOptions.push_back(apiVersion); + headerOptions.push_back(clientToken); + } + catch(OCException& e) + { + std::cout << "Error creating HeaderOption: " << e.what() << std::endl; + } + + + // Setting header options will send above options in all requests + // Header options are set per resource. + // Below, header options are set only for device resource + resource->setHeaderOptions(headerOptions); + + resource->get(QueryParamsMap(), GetCallback( + std::bind(&ClientFridge::getResponse, this, "Device", PH::_1, + PH::_2, PH::_3, resource, 0) + )); + light->get(QueryParamsMap(), GetCallback( + std::bind(&ClientFridge::getResponse, this, "Fridge Light", PH::_1, + PH::_2, PH::_3, light, 1) + )); + leftdoor->get(QueryParamsMap(), GetCallback( + std::bind(&ClientFridge::getResponse, this, "Left Door", PH::_1, + PH::_2, PH::_3, leftdoor, 2) + )); + rightdoor->get(QueryParamsMap(), GetCallback( + std::bind(&ClientFridge::getResponse, this, "Right Door", PH::_1, + PH::_2, PH::_3, rightdoor, 3) + )); + randomdoor->get(QueryParamsMap(), GetCallback( + std::bind(&ClientFridge::getResponse, this, "Random Door", PH::_1, + PH::_2, PH::_3, randomdoor, 4) + )); + resource->deleteResource(DeleteCallback( + std::bind(&ClientFridge::deleteResponse, this, "Device", PH::_1, + PH::_2, resource, 0) + )); + } + + // Note that resourceName, resource, and getId are all bound via the std::bind mechanism. + // it is possible to attach ANY arbitrary data to do whatever you would like here. It may, + // however be a better fit to wrap each call in an object so a fuller context (and additional + // requests) can be easily made inside of a simple context + void getResponse(const std::string& resourceName, const HeaderOptions& headerOptions, + const OCRepresentation rep, const int eCode, OCResource::Ptr resource, int getId) + { + std::cout << "Got a response from get from the " << resourceName << std::endl; + std::cout << "Get ID is "<uri() << std::endl; + + printHeaderOptions(headerOptions); + + std::cout << "The Attribute Data is: "<uri()<getOptionID() == API_VERSION) + { + std::cout << "Server API version in GET response: " << + it->getOptionData() << std::endl; + } + } + } + + std::mutex m_mutex; + std::condition_variable m_cv; +}; + +int main() +{ + PlatformConfig cfg + { + ServiceType::InProc, + ModeType::Client, + "0.0.0.0", + 0, + QualityOfService::LowQos + }; + + OCPlatform::Configure(cfg); + ClientFridge cf; + return 0; +} diff --git a/resource/examples/fridgeserver.cpp b/resource/examples/fridgeserver.cpp new file mode 100644 index 000000000..ae6eb32eb --- /dev/null +++ b/resource/examples/fridgeserver.cpp @@ -0,0 +1,481 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// The purpose of this server is to simulate a refrigerator that contains a device resource for +/// its description, a light resource for the internal light, and 2 door resources for the purpose +/// of representing the doors attached to this fridge. This is used by the fridgeclient to +/// demonstrate using std::bind to attach to instances of a class as well as using +/// constructResourceObject + +#include +#include +#include +#include + +#include "OCPlatform.h" +#include "OCApi.h" + +using namespace OC; +namespace PH = std::placeholders; + +// Option ID for API version and client token +const uint16_t API_VERSION = 2048; +const uint16_t TOKEN = 3000; + +// Setting API version and token (shared out of band with client) +// This assumes the fact that this server responds +// only with a server with below version and token +const std::string FRIDGE_CLIENT_API_VERSION = "v.1.0"; +const std::string FRIDGE_CLIENT_TOKEN = "21ae43gf"; + +class Resource +{ + protected: + OCResourceHandle m_resourceHandle; + OCRepresentation m_rep; + virtual OCEntityHandlerResult entityHandler(std::shared_ptr request)=0; +}; + +class DeviceResource : public Resource +{ + public: + + DeviceResource() + { + std::string resourceURI = "/device"; + std::string resourceTypeName = "intel.fridge"; + std::string resourceInterface = DEFAULT_INTERFACE; + EntityHandler cb = std::bind(&DeviceResource::entityHandler, this,PH::_1); + + EntityHandler defaultEH = std::bind(&DeviceResource::defaultEntityHandler + ,this, PH::_1); + + std::cout << "Setting device default entity handler\n"; + OCPlatform::setDefaultDeviceEntityHandler(defaultEH); + + uint8_t resourceProperty = OC_DISCOVERABLE; + OCStackResult result = OCPlatform::registerResource(m_resourceHandle, + resourceURI, + resourceTypeName, + resourceInterface, + cb, + resourceProperty); + + if(OC_STACK_OK != result) + { + throw std::runtime_error( + std::string("Device Resource failed to start")+std::to_string(result)); + } + } + private: + OCRepresentation get() + { + m_rep.setValue("device_name", std::string("Intel Powered 2 door, 1 light refrigerator")); + return m_rep; + } + + OCStackResult deleteDeviceResource() + { + OCStackResult result = OCPlatform::unregisterResource(m_resourceHandle); + if(OC_STACK_OK != result) + { + throw std::runtime_error( + std::string("Device Resource failed to unregister/delete") + std::to_string(result)); + } + return result; + } + + std::string m_modelName; + protected: + virtual OCEntityHandlerResult entityHandler(std::shared_ptr request) + { + OCEntityHandlerResult ehResult = OC_EH_ERROR; + if(request) + { + // Get the header options from the request + HeaderOptions headerOptions = request->getHeaderOptions(); + std::string clientAPIVersion; + std::string clientToken; + + // Search the header options map and look for API version and Client token + for (auto it = headerOptions.begin(); it != headerOptions.end(); ++it) + { + uint16_t optionID = it->getOptionID(); + if(optionID == API_VERSION) + { + clientAPIVersion = it->getOptionData(); + std::cout << " Client API version: " << clientAPIVersion << std::endl; + } + else if(optionID == TOKEN) + { + clientToken = it->getOptionData(); + std::cout << " Client token: " << clientToken << std::endl; + } + else + { + std::cout << " Invalid header option " << std::endl; + } + } + + // In this case Server entity handler verifies API version + // and client token. If they are valid, client requests are handled. + if(clientAPIVersion == FRIDGE_CLIENT_API_VERSION && clientToken == FRIDGE_CLIENT_TOKEN) + { + HeaderOptions serverHeaderOptions; + try + { + // Set API version from server side + HeaderOption::OCHeaderOption apiVersion(API_VERSION, FRIDGE_CLIENT_API_VERSION); + serverHeaderOptions.push_back(apiVersion); + } + catch(OCException& e) + { + std::cout << "Error creating HeaderOption in server: " << e.what() << std::endl; + } + + if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag) + { + auto pResponse = std::make_shared(); + pResponse->setRequestHandle(request->getRequestHandle()); + pResponse->setResourceHandle(request->getResourceHandle()); + pResponse->setHeaderOptions(serverHeaderOptions); + + if(request->getRequestType() == "GET") + { + std::cout<<"DeviceResource Get Request"<setErrorCode(200); + pResponse->setResponseResult(OC_EH_OK); + pResponse->setResourceRepresentation(get(), ""); + if(OC_STACK_OK == OCPlatform::sendResponse(pResponse)) + { + ehResult = OC_EH_OK; + } + } + else if(request->getRequestType() == "DELETE") + { + std::cout<<"DeviceResource Delete Request"<setErrorCode(200); + pResponse->setResponseResult(OC_EH_RESOURCE_DELETED); + ehResult = OC_EH_OK; + } + else + { + pResponse->setResponseResult(OC_EH_ERROR); + ehResult = OC_EH_ERROR; + } + OCPlatform::sendResponse(pResponse); + } + else + { + std::cout <<"DeviceResource unsupported request type " + << request->getRequestType() << std::endl; + pResponse->setResponseResult(OC_EH_ERROR); + OCPlatform::sendResponse(pResponse); + ehResult = OC_EH_ERROR; + } + } + else + { + std::cout << "DeviceResource unsupported request flag" < request) + { + OCEntityHandlerResult ehResult = OC_EH_ERROR; + if(request) + { + std::cout << "In Default Entity Handler, uri received: " + << request->getResourceUri() << std::endl; + + if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag) + { + auto pResponse = std::make_shared(); + pResponse->setRequestHandle(request->getRequestHandle()); + pResponse->setResourceHandle(request->getResourceHandle()); + + if(request->getRequestType() == "GET") + { + std::cout<<"Default Entity Handler: Get Request"<setErrorCode(200); + pResponse->setResourceRepresentation(get(), ""); + if(OC_STACK_OK == OCPlatform::sendResponse(pResponse)) + { + ehResult = OC_EH_OK; + } + } + else + { + std::cout <<"Default Entity Handler: unsupported request type " + << request->getRequestType() << std::endl; + pResponse->setResponseResult(OC_EH_ERROR); + OCPlatform::sendResponse(pResponse); + ehResult = OC_EH_ERROR; + } + } + else + { + std::cout << "Default Entity Handler: unsupported request flag" < request) + { + OCEntityHandlerResult ehResult = OC_EH_ERROR; + if(request) + { + std::cout << "In entity handler for Light, URI is : " + << request->getResourceUri() << std::endl; + + if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag) + { + auto pResponse = std::make_shared(); + pResponse->setRequestHandle(request->getRequestHandle()); + pResponse->setResourceHandle(request->getResourceHandle()); + + if(request->getRequestType() == "GET") + { + std::cout<<"Light Get Request"<setErrorCode(200); + pResponse->setResourceRepresentation(get(), ""); + if(OC_STACK_OK == OCPlatform::sendResponse(pResponse)) + { + ehResult = OC_EH_OK; + } + } + else if(request->getRequestType() == "PUT") + { + std::cout <<"Light Put Request"<getResourceRepresentation()); + pResponse->setErrorCode(200); + pResponse->setResourceRepresentation(get(), ""); + if(OC_STACK_OK == OCPlatform::sendResponse(pResponse)) + { + ehResult = OC_EH_OK; + } + } + else + { + std::cout << "Light unsupported request type" + << request->getRequestType() << std::endl; + pResponse->setResponseResult(OC_EH_ERROR); + OCPlatform::sendResponse(pResponse); + ehResult = OC_EH_ERROR; + } + } + else + { + std::cout << "Light unsupported request flag" < request) + { + std::cout << "EH of door invoked " << std::endl; + OCEntityHandlerResult ehResult = OC_EH_ERROR; + + if(request) + { + std::cout << "In entity handler for Door, URI is : " + << request->getResourceUri() << std::endl; + + if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag) + { + auto pResponse = std::make_shared(); + pResponse->setRequestHandle(request->getRequestHandle()); + pResponse->setResourceHandle(request->getResourceHandle()); + + if(request->getRequestType() == "GET") + { + // note that we know the side because std::bind gives us the + // appropriate object + std::cout<< m_side << " Door Get Request"<setErrorCode(200); + pResponse->setResourceRepresentation(get(), ""); + if(OC_STACK_OK == OCPlatform::sendResponse(pResponse)) + { + ehResult = OC_EH_OK; + } + } + else if(request->getRequestType() == "PUT") + { + std::cout << m_side <<" Door Put Request"<getResourceRepresentation()); + pResponse->setErrorCode(200); + pResponse->setResourceRepresentation(get(),""); + if(OC_STACK_OK == OCPlatform::sendResponse(pResponse)) + { + ehResult = OC_EH_OK; + } + } + else + { + std::cout <getRequestType() << std::endl; + pResponse->setResponseResult(OC_EH_ERROR); + OCPlatform::sendResponse(pResponse); + ehResult = OC_EH_ERROR; + } + } + else + { + std::cout << "Door unsupported request flag" < +#include +#include +#include +#include "OCPlatform.h" +#include "OCApi.h" + +using namespace OC; + +const int SUCCESS_RESPONSE = 0; +std::shared_ptr curResource; + +class Garage +{ +public: + + bool m_state; + std::string m_name; + std::vector m_lightStates; + std::vector m_lightPowers; + OCRepresentation m_lightRep; + std::vector m_reps; + + Garage() : m_state(false), m_name("") + { + } +}; + +Garage myGarage; + +void printRepresentation(const OCRepresentation& rep) +{ + + // Check if attribute "name" exists, and then getValue + if(rep.hasAttribute("name")) + { + myGarage.m_name = rep.getValue("name"); + } + std::cout << "\tname: " << myGarage.m_name << std::endl; + + // You can directly try to get the value. this function + // return false if there is no attribute "state" + if(!rep.getValue("state", myGarage.m_state)) + { + std::cout << "Attribute state doesn't exist in the representation\n"; + } + std::cout << "\tstate: " << myGarage.m_state << std::endl; + + OCRepresentation rep2 = rep; + + std::cout << "Number of attributes in rep2: " + << rep2.numberOfAttributes() << std::endl; + + if(rep2.erase("name")) + { + std::cout << "attribute: name, was removed successfully from rep2.\n"; + } + + std::cout << "Number of attributes in rep2: " + << rep2.numberOfAttributes() << std::endl; + + + if(rep.isNULL("nullAttribute")) + { + std::cout << "\tnullAttribute is null." << std::endl; + } + else + { + std::cout << "\tnullAttribute is not null." << std::endl; + } + + rep.getValue("light", myGarage.m_lightRep); + + myGarage.m_lightRep.getValue("states", myGarage.m_lightStates); + myGarage.m_lightRep.getValue("powers", myGarage.m_lightPowers); + + std::cout << "\tlightRep: states: "; + + int first = 1; + for(auto state: myGarage.m_lightStates) + { + if(first) + { + std::cout << state; + first = 0; + } + else + { + std::cout << "," << state; + } + } + + std::cout << std::endl; + std::cout << "\tlightRep: powers: "; + first = 1; + for(auto power: myGarage.m_lightPowers) + { + if(first) + { + std::cout << power; + first = 0; + } + else + { + std::cout << "," << power; + } + } + std::cout << std::endl; + + // Get vector of representations + rep.getValue("reps", myGarage.m_reps); + // Client know that server is sending two representations + // and has key1 and key2 repsectively + std::cout << "\treps[0].key1: " << myGarage.m_reps[0].getValue("key1") << std::endl; + std::cout << "\treps[0].key2: " << myGarage.m_reps[1].getValue("key2") << std::endl; + + std::cout << "\tjson: " << rep.getValue("json") << std::endl; +} +// callback handler on PUT request +void onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode) +{ + if(eCode == SUCCESS_RESPONSE) + { + std::cout << "PUT request was successful" << std::endl; + + printRepresentation(rep); + } + else + { + std::cout << "onPut Response error: " << eCode << std::endl; + std::exit(-1); + } +} + +// Local function to put a different state for this resource +void putLightRepresentation(std::shared_ptr resource) +{ + if(resource) + { + OCRepresentation rep; + + std::cout << "Putting light representation..."<put(rep, queryParamsMap, &onPut); + } +} + +// Callback handler on GET request +void onGet(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode) +{ + if(eCode == SUCCESS_RESPONSE) + { + std::cout << "GET request was successful" << std::endl; + std::cout << "Resource URI: " << rep.getUri() << std::endl; + + printRepresentation(rep); + + putLightRepresentation(curResource); + } + else + { + std::cout << "onGET Response error: " << eCode << std::endl; + std::exit(-1); + } +} + +// Local function to get representation of light resource +void getLightRepresentation(std::shared_ptr resource) +{ + if(resource) + { + std::cout << "Getting Light Representation..."<get(test, &onGet); + } +} + +// Callback to found resources +void foundResource(std::shared_ptr resource) +{ + if(curResource) + { + std::cout << "Found another resource, ignoring"<uri(); + std::cout << "\tURI of the resource: " << resourceURI << std::endl; + + // Get the resource host address + hostAddress = resource->host(); + std::cout << "\tHost address of the resource: " << hostAddress << std::endl; + + // Get the resource types + std::cout << "\tList of resource types: " << std::endl; + for(auto &resourceTypes : resource->getResourceTypes()) + { + std::cout << "\t\t" << resourceTypes << std::endl; + } + + // Get the resource interfaces + std::cout << "\tList of resource interfaces: " << std::endl; + for(auto &resourceInterfaces : resource->getResourceInterfaces()) + { + std::cout << "\t\t" << resourceInterfaces << std::endl; + } + + if(resourceURI == "/a/garage") + { + curResource = resource; + // Call a local function which will internally invoke + // get API on the resource pointer + getLightRepresentation(resource); + } + } + else + { + // Resource is invalid + std::cout << "Resource is invalid" << std::endl; + } + + } + catch(std::exception& e) + { + //log(e.what()); + } +} + +int main(int argc, char* argv[]) { + + // Create PlatformConfig object + PlatformConfig cfg { + OC::ServiceType::InProc, + OC::ModeType::Client, + "0.0.0.0", + 0, + OC::QualityOfService::LowQos + }; + + OCPlatform::Configure(cfg); + try + { + // Find all resources + OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.garage", + &foundResource); + std::cout<< "Finding Resource... " < lock(blocker); + cv.wait(lock); + } + catch(OCException& e) + { + std::cerr << "Exception in GarageClient: "< + +#include +#include +#include + +#include "OCPlatform.h" +#include "OCApi.h" + +using namespace OC; +using namespace std; + +// Forward declaring the entityHandler +OCEntityHandlerResult entityHandler(std::shared_ptr request); + +/// This class represents a single resource named 'lightResource'. This resource has + +class GarageResource +{ +public: + /// Access this property from a TB client + std::string m_name; + bool m_state; + std::string m_garageUri; + OCResourceHandle m_resourceHandle; + OCRepresentation m_garageRep; + ObservationIds m_interestedObservers; + + // array of lights representation with in GarageResource + OCRepresentation m_lightRep; + std::vector m_reps; + +public: + /// Constructor + GarageResource(): m_name("John's Garage"), m_state(false), m_garageUri("/a/garage") { + // Initialize representation + m_garageRep.setUri(m_garageUri); + + m_garageRep.setValue("state", m_state); + m_garageRep.setValue("name", m_name); + + // For demonstration purpose we are setting x to nullptr here. + // In reality it may happen else where. + int* x = nullptr; + + // Check for nullptr and set null for that attribute + if(x == nullptr) + { + m_garageRep.setNULL("nullAttribute"); + } + + std::vector lightStates; + std::vector lightPowers; + + for(int i = 0; i <= 9; i++) + { + lightStates.push_back(i % 2 == 0); + lightPowers.push_back(i); + } + + m_lightRep.setValue("states", lightStates); + m_lightRep.setValue("powers", lightPowers); + + // Storing another representation within a representation + m_garageRep.setValue("light", m_lightRep); + + OCRepresentation rep1; + int value1 = 5; + rep1.setValue("key1", value1); + OCRepresentation rep2; + int value2 = 10; + rep2.setValue("key2", value2); + + m_reps.push_back(rep1); + m_reps.push_back(rep2); + + // storing array of representations + m_garageRep.setValue("reps", m_reps); + + + // setting json string + std::string json = "{\"num\":10,\"rno\":23.5,\"aoa\":[[1,2],[3]],\"str\":\"john\",\ +\"object\":{\"bl1\":false,\"ar\":[2,3]}, \"objects\":[{\"bl2\":true,\"nl\":null},{\"ar1\":[1,2]}]}"; + m_garageRep.setValue("json", json); + } + + /* Note that this does not need to be a member function: for classes you do not have + access to, you can accomplish this with a free function: */ + + /// This function internally calls registerResource API. + void createResource() + { + std::string resourceURI = m_garageUri; // URI of the resource + std::string resourceTypeName = "core.garage"; // resource type name. + std::string resourceInterface = DEFAULT_INTERFACE; // resource interface. + + // OCResourceProperty is defined ocstack.h + uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE; + + // This will internally create and register the resource. + OCStackResult result = OCPlatform::registerResource( + m_resourceHandle, resourceURI, resourceTypeName, + resourceInterface, &entityHandler, resourceProperty); + + if (OC_STACK_OK != result) + { + cout << "Resource creation was unsuccessful\n"; + } + } + + OCResourceHandle getHandle() + { + return m_resourceHandle; + } + + // Puts representation. + // Gets values from the representation and + // updates the internal state + void put(OCRepresentation& rep) + { + try { + if (rep.getValue("state", m_state)) + { + cout << "\t\t\t\t" << "state: " << m_state << endl; + } + else + { + cout << "\t\t\t\t" << "state not found in the representation" << endl; + } + } + catch (exception& e) + { + cout << e.what() << endl; + } + + } + + // gets the updated representation. + // Updates the representation with latest internal state before + // sending out. + OCRepresentation get() + { + m_garageRep.setValue("state", m_state); + + return m_garageRep; + } + +}; + +// Create the instance of the resource class (in this case instance of class 'GarageResource'). +GarageResource myGarage; + +OCStackResult sendResponse(std::shared_ptr pRequest) +{ + auto pResponse = std::make_shared(); + pResponse->setRequestHandle(pRequest->getRequestHandle()); + pResponse->setResourceHandle(pRequest->getResourceHandle()); + pResponse->setResourceRepresentation(myGarage.get()); + pResponse->setErrorCode(200); + pResponse->setResponseResult(OC_EH_OK); + + return OCPlatform::sendResponse(pResponse); +} + +OCEntityHandlerResult entityHandler(std::shared_ptr request) +{ + cout << "\tIn Server CPP entity handler:\n"; + OCEntityHandlerResult ehResult = OC_EH_ERROR; + + if(request) + { + // Get the request type and request flag + std::string requestType = request->getRequestType(); + int requestFlag = request->getRequestHandlerFlag(); + + if(requestFlag & RequestHandlerFlag::InitFlag) + { + cout << "\t\trequestFlag : Init\n"; + + // entity handler to perform resource initialization operations + } + if(requestFlag & RequestHandlerFlag::RequestFlag) + { + cout << "\t\trequestFlag : Request\n"; + + // If the request type is GET + if(requestType == "GET") + { + cout << "\t\t\trequestType : GET\n"; + if(OC_STACK_OK == sendResponse(request)) + { + ehResult = OC_EH_OK; + } + } + else if(requestType == "PUT") + { + cout << "\t\t\trequestType : PUT\n"; + OCRepresentation rep = request->getResourceRepresentation(); + // Do related operations related to PUT request + myGarage.put(rep); + if(OC_STACK_OK == sendResponse(request)) + { + ehResult = OC_EH_OK; + } + } + else if(requestType == "POST") + { + // POST request operations + } + else if(requestType == "DELETE") + { + // DELETE request operations + } + } + if(requestFlag & RequestHandlerFlag::ObserverFlag) + { + // OBSERVE operations + } + } + else + { + std::cout << "Request invalid" << std::endl; + } + + return ehResult; +} + +int main(int argc, char* argv[1]) +{ + // Create PlatformConfig object + PlatformConfig cfg { + OC::ServiceType::InProc, + OC::ModeType::Server, + "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces + 0, // Uses randomly available port + OC::QualityOfService::LowQos + }; + + OCPlatform::Configure(cfg); + try + { + // Invoke createResource function of class light. + myGarage.createResource(); + + // A condition variable will free the mutex it is given, then do a non- + // intensive block until 'notify' is called on it. In this case, since we + // don't ever call cv.notify, this should be a non-processor intensive version + // of while(true); + std::mutex blocker; + std::condition_variable cv; + std::unique_lock lock(blocker); + cv.wait(lock); + } + catch(OCException e) + { + //log(e.what()); + } + + // No explicit call to stop the OCPlatform + // When OCPlatform destructor is invoked, internally we do Platform cleanup + + return 0; +} diff --git a/resource/examples/groupclient.cpp b/resource/examples/groupclient.cpp new file mode 100755 index 000000000..11afb80fa --- /dev/null +++ b/resource/examples/groupclient.cpp @@ -0,0 +1,234 @@ +//****************************************************************** +// +// Copyright 2014 Samsung Electronics All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "OCPlatform.h" +#include "OCApi.h" + +#include +#include +#include + +using namespace std; +using namespace OC; +namespace PH = std::placeholders; + +OCResourceHandle resourceHandle; + +shared_ptr< OCResource > g_resource; +vector< string > lights; + +bool isReady = false; + +void onGet(const HeaderOptions& opt, const OCRepresentation &rep, const int eCode); + +void onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode); + +void onPost(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode); + +void foundResource(std::shared_ptr< OCResource > resource) +{ + std::string resourceURI; + std::string hostAddress; + + try + { + cout << "FOUND Resource" << endl; + + if (resource) + { + string resourceURI = resource->uri(); + cout << resourceURI << endl; + if (resourceURI == "/core/a/collection") + { + g_resource = resource; + } + + g_resource->get("", DEFAULT_INTERFACE, QueryParamsMap(), onGet); + printf("HOST :: %s\n", resource->host().c_str()); + } + } + catch (std::exception& e) + { + std::cout << "" << std::endl; + } +} + +void onGet(const HeaderOptions& opt, const OCRepresentation &rep, const int eCode) +{ + // printf("onGet\n"); + + std::vector< OCRepresentation > children = rep.getChildren(); + + cout << "\n\n\nCHILD RESOURCE OF GROUP" << endl; + for (auto iter = children.begin(); iter != children.end(); ++iter) + { + lights.push_back((*iter).getUri()); + cout << "\tURI :: " << (*iter).getUri() << endl; + } + + isReady = true; +} + +void onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode) +{ + printf("\nonPut\n"); +} + +void onPost(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode) +{ + printf("\nonPost\n"); + + std::vector< OCRepresentation > children = rep.getChildren(); + + cout << "\n\n\nCHILD RESOURCE OF GROUP" << endl; + for (auto iter = children.begin(); iter != children.end(); ++iter) + { + std::string power; + (*iter).getValue("power", power); + + cout << "\tURI :: " << (*iter).getUri() << endl; + cout << "\t\tpower :: " << power << endl; + } + + if (rep.hasAttribute("ActionSet")) + { + std::string plainText; + + rep.getValue("ActionSet", plainText); + + printf("\tPlain Text :: %s\n", plainText.c_str()); + } + else + { + printf("Not found ActionSet\n"); + } +} + +int main() +{ + PlatformConfig config + { OC::ServiceType::InProc, ModeType::Client, "0.0.0.0", 0, OC::QualityOfService::LowQos }; + + bool isRun = true; + + try + { + OCPlatform::Configure(config); + + string resourceTypeName = "a.collection"; + OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=a.collection", &foundResource); + + isReady = false; + + while (isRun) + { + usleep(100); + while (isReady) + { + int n; + + cout << endl + << "1 :: CREATE ACTIONSET 2 :: EXECUTE ACTION SET 3 :: GET ACTIONSET\n"; + cout << "4 :: DELETE ACTIONSET 5 :: Quit\n"; + + cin >> n; + if (n == 1) + { + string actionsetDesc; + //"movieTime*uri=coap://10.251.44.228:49858/a/light|power=10*uri=coap://10.251.44.228:49858/a/light|power=10|"; + + actionsetDesc = "allbulboff"; + actionsetDesc.append("*"); + for (auto iter = lights.begin(); iter != lights.end(); ++iter) + { + actionsetDesc.append("uri=").append((*iter)); + actionsetDesc.append("|"); + actionsetDesc.append("power="); + actionsetDesc.append("off"); + if ((iter + 1) != lights.end()) + { + actionsetDesc.append("*"); + } + } + + cout << "ActionSet :: " << actionsetDesc << endl; + + OCRepresentation rep; + rep.setValue("ActionSet", actionsetDesc); + + if (g_resource) + { + g_resource->put("a.collection", GROUP_INTERFACE, rep, QueryParamsMap(), + &onPut); + } + } + else if (n == 2) + { + OCRepresentation rep; + + rep.setValue("DoAction", std::string("allbulboff")); + + if (g_resource) + { + g_resource->post("a.collection", GROUP_INTERFACE, rep, QueryParamsMap(), + &onPost); + } + } + else if (n == 3) + { + OCRepresentation rep; + + rep.setValue("GetActionSet", std::string("allbulboff")); + + if (g_resource) + { + g_resource->post("a.collection", GROUP_INTERFACE, rep, QueryParamsMap(), + &onPost); + } + } + else if (n == 4) + { + OCRepresentation rep; + + rep.setValue("DelActionSet", std::string("allbulboff")); + + if (g_resource) + { + g_resource->put("a.collection", GROUP_INTERFACE, rep, QueryParamsMap(), + &onPut); + } + } + else if (n == 5) + { + isRun = false; + break; + } + + fflush(stdin); + } + } + } + catch (OCException& e) + { + cout << e.what() << endl; + } + + return 0; +} diff --git a/resource/examples/groupserver.cpp b/resource/examples/groupserver.cpp new file mode 100755 index 000000000..4cebd44b1 --- /dev/null +++ b/resource/examples/groupserver.cpp @@ -0,0 +1,129 @@ +//****************************************************************** +// +// Copyright 2014 Samsung Electronics All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "OCPlatform.h" +#include "OCApi.h" + +#include +#include +#include + +using namespace std; +using namespace OC; + +namespace PH = std::placeholders; + +OCResourceHandle resourceHandle; +std::vector< OCResourceHandle > resourceHandleVector; + +void foundResource(std::shared_ptr< OCResource > resource) +{ + + std::string resourceURI; + std::string hostAddress; + + try + { + cout << "FOUND RESOURCE" << endl; + + if (resource) + { + resourceURI = resource->uri(); + hostAddress = resource->host(); + + cout << "\tResource URI : " << resourceURI << endl; + cout << "\tResource Host : " << hostAddress << endl; + cout << "\tResource Interfaces : " << resource->getResourceInterfaces().front() << endl; + cout << "\tResource Type : " << resource->getResourceTypes().front() << endl; + if (resourceURI == "/a/light" || resourceURI == "/a/fan") + { + OCResourceHandle foundResourceHandle; + OCStackResult result = OCPlatform::registerResource(foundResourceHandle, resource); + cout << "\tresource registed!" << endl; + if (result == OC_STACK_OK) + { + OCPlatform::bindResource(resourceHandle, foundResourceHandle); + resourceHandleVector.push_back(foundResourceHandle); + } + else + { + cout << "\tresource Error!" << endl; + } + } + + // p_platform.bindResource(resourceHandle, foundResourceHandle); + + } + } + catch (std::exception& e) + { + std::cout << "" << std::endl; + } + +} + +int main() +{ + PlatformConfig config + { OC::ServiceType::InProc, ModeType::Both, "0.0.0.0", 0, OC::QualityOfService::LowQos }; + + try + { + string resourceURI = "/core/a/collection"; + string resourceTypeName = "a.collection"; + string resourceInterface = BATCH_INTERFACE; + OCPlatform::Configure(config); + + // EntityHandler cb = std::bind(, PH::_1, PH::_2); + + OCPlatform::registerResource(resourceHandle, resourceURI, resourceTypeName, + resourceInterface, + NULL, + //&entityHandler, // entityHandler + OC_DISCOVERABLE); + + cout << "registerResource is called." << endl; + + OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.light", &foundResource); + OCPlatform::bindInterfaceToResource(resourceHandle, GROUP_INTERFACE); + OCPlatform::bindInterfaceToResource(resourceHandle, DEFAULT_INTERFACE); + + int selectedMenu; + while (true) + { + std::cin >> selectedMenu; + + if (selectedMenu == 1) + { + for (unsigned int i = 0; i < resourceHandleVector.size(); ++i) + { + OCPlatform::unregisterResource(resourceHandleVector.at(i)); + } + } + + } + } + catch (OCException& e) + { + + } + + return 0; +} diff --git a/resource/examples/lightserver.cpp b/resource/examples/lightserver.cpp new file mode 100755 index 000000000..f95722d45 --- /dev/null +++ b/resource/examples/lightserver.cpp @@ -0,0 +1,334 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// Copyright 2014 Samsung Electronics All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// +/// This sample provides steps to define an interface for a resource +/// (properties and methods) and host this resource on the server. +/// + +#include + +#include +#include +#include + +#include "OCPlatform.h" +#include "OCApi.h" + +using namespace OC; +using namespace std; +namespace PH = std::placeholders; + +int gObservation = 0; +void * ChangeLightRepresentation (void *param); +void * handleSlowResponse (void *param, std::shared_ptr pRequest); + +// Specifies secure or non-secure +// false: non-secure resource +// true: secure resource +bool isSecure = false; + +/// Specifies whether Entity handler is going to do slow response or not +bool isSlowResponse = false; + +// Forward declaring the entityHandler + +/// This class represents a single resource named 'lightResource'. This resource has +/// two simple properties named 'state' and 'power' + +class LightResource +{ + +public: + /// Access this property from a TB client + std::string m_power; + std::string m_lightUri; + OCResourceHandle m_resourceHandle; + OCRepresentation m_lightRep; + +public: + /// Constructor + LightResource() + :m_power(""), m_lightUri("/a/light") { + // Initialize representation + m_lightRep.setUri(m_lightUri); + + m_lightRep.setValue("power", m_power); + } + + /* Note that this does not need to be a member function: for classes you do not have + access to, you can accomplish this with a free function: */ + + /// This function internally calls registerResource API. + void createResource() + { + std::string resourceURI = m_lightUri; //URI of the resource + std::string resourceTypeName = "core.light"; //resource type name. In this case, it is light + std::string resourceInterface = DEFAULT_INTERFACE; // resource interface. + + EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1); + + // This will internally create and register the resource. + OCStackResult result = OCPlatform::registerResource( + m_resourceHandle, resourceURI, resourceTypeName, + resourceInterface, cb, OC_DISCOVERABLE | OC_OBSERVABLE); + + if (OC_STACK_OK != result) + { + cout << "Resource creation was unsuccessful\n"; + } + } + + OCResourceHandle getHandle() + { + return m_resourceHandle; + } + + // Puts representation. + // Gets values from the representation and + // updates the internal state + void put(OCRepresentation& rep) + { + try { + if (rep.getValue("power", m_power)) + { + cout << "\t\t\t\t" << "power: " << m_power << endl; + } + else + { + cout << "\t\t\t\t" << "power not found in the representation" << endl; + } + } + catch (exception& e) + { + cout << e.what() << endl; + } + + } + + // Post representation. + // Post can create new resource or simply act like put. + // Gets values from the representation and + // updates the internal state + OCRepresentation post(OCRepresentation& rep) + { + put(rep); + return get(); + } + + + // gets the updated representation. + // Updates the representation with latest internal state before + // sending out. + OCRepresentation get() + { + m_lightRep.setValue("power", m_power); + + return m_lightRep; + } + + void addType(const std::string& type) const + { + OCStackResult result = OCPlatform::bindTypeToResource(m_resourceHandle, type); + if (OC_STACK_OK != result) + { + cout << "Binding TypeName to Resource was unsuccessful\n"; + } + } + + void addInterface(const std::string& interface) const + { + OCStackResult result = OCPlatform::bindInterfaceToResource(m_resourceHandle, interface); + if (OC_STACK_OK != result) + { + cout << "Binding TypeName to Resource was unsuccessful\n"; + } + } + +private: +// This is just a sample implementation of entity handler. +// Entity handler can be implemented in several ways by the manufacturer +OCEntityHandlerResult entityHandler(std::shared_ptr request) +{ + cout << "\tIn Server CPP entity handler:\n"; + OCEntityHandlerResult ehResult = OC_EH_ERROR; + if(request) + { + // Get the request type and request flag + std::string requestType = request->getRequestType(); + int requestFlag = request->getRequestHandlerFlag(); + + if(requestFlag & RequestHandlerFlag::InitFlag) + { + cout << "\t\trequestFlag : Init\n"; + + // entity handler to perform resource initialization operations + } + if(requestFlag & RequestHandlerFlag::RequestFlag) + { + cout << "\t\trequestFlag : Request\n"; + auto pResponse = std::make_shared(); + pResponse->setRequestHandle(request->getRequestHandle()); + pResponse->setResourceHandle(request->getResourceHandle()); + + // If the request type is GET + if(requestType == "GET") + { + cout << "\t\t\trequestType : GET\n"; + if(isSlowResponse) // Slow response case + { + static int startedThread = 0; + if(!startedThread) + { + std::thread t(handleSlowResponse, (void *)this, request); + startedThread = 1; + t.detach(); + } + ehResult = OC_EH_SLOW; + } + else // normal response case. + { + pResponse->setErrorCode(200); + pResponse->setResponseResult(OC_EH_OK); + pResponse->setResourceRepresentation(get()); + if(OC_STACK_OK == OCPlatform::sendResponse(pResponse)) + { + ehResult = OC_EH_OK; + } + } + } + else if(requestType == "PUT") + { + cout << "\t\t\trequestType : PUT\n"; + OCRepresentation rep = request->getResourceRepresentation(); + + // Do related operations related to PUT request + // Update the lightResource + put(rep); + pResponse->setErrorCode(200); + pResponse->setResponseResult(OC_EH_OK); + pResponse->setResourceRepresentation(get()); + if(OC_STACK_OK == OCPlatform::sendResponse(pResponse)) + { + ehResult = OC_EH_OK; + } + } + else if(requestType == "POST") + { + cout << "\t\t\trequestType : POST\n"; + + OCRepresentation rep = request->getResourceRepresentation(); + + // Do related operations related to POST request + OCRepresentation rep_post = post(rep); + pResponse->setResourceRepresentation(rep_post); + pResponse->setErrorCode(200); + if(rep_post.hasAttribute("createduri")) + { + pResponse->setResponseResult(OC_EH_RESOURCE_CREATED); + pResponse->setNewResourceUri(rep_post.getValue("createduri")); + } + + if(OC_STACK_OK == OCPlatform::sendResponse(pResponse)) + { + ehResult = OC_EH_OK; + } + } + else if(requestType == "DELETE") + { + // DELETE request operations + } + } + } + else + { + std::cout << "Request invalid" << std::endl; + } + + return ehResult; +} +}; + +void * handleSlowResponse (void *param, std::shared_ptr pRequest) +{ + // This function handles slow response case + LightResource* lightPtr = (LightResource*) param; + // Induce a case for slow response by using sleep + std::cout << "SLOW response" << std::endl; + sleep (10); + + auto pResponse = std::make_shared(); + pResponse->setRequestHandle(pRequest->getRequestHandle()); + pResponse->setResourceHandle(pRequest->getResourceHandle()); + pResponse->setResourceRepresentation(lightPtr->get()); + pResponse->setErrorCode(200); + pResponse->setResponseResult(OC_EH_OK); + + // Set the slow response flag back to false + isSlowResponse = false; + OCPlatform::sendResponse(pResponse); + return NULL; +} + + +int main(int argc, char* argv[]) +{ + // Create PlatformConfig object + PlatformConfig cfg { + OC::ServiceType::InProc, + OC::ModeType::Server, + "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces + 0, // Uses randomly available port + OC::QualityOfService::LowQos + }; + + OCPlatform::Configure(cfg); + try + { + // Create the instance of the resource class + // (in this case instance of class 'LightResource'). + LightResource myLight; + + // Invoke createResource function of class light. + myLight.createResource(); + + myLight.addType(std::string("core.brightlight")); + myLight.addInterface(std::string("oc.mi.ll")); + + // A condition variable will free the mutex it is given, then do a non- + // intensive block until 'notify' is called on it. In this case, since we + // don't ever call cv.notify, this should be a non-processor intensive version + // of while(true); + std::mutex blocker; + std::condition_variable cv; + std::unique_lock lock(blocker); + cv.wait(lock); + } + catch(OCException e) + { + //log(e.what()); + } + + // No explicit call to stop the platform. + // When OCPlatform::destructor is invoked, internally we do platform cleanup + + return 0; +} diff --git a/resource/examples/makefile b/resource/examples/makefile new file mode 100755 index 000000000..ec87ec70e --- /dev/null +++ b/resource/examples/makefile @@ -0,0 +1,137 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +# override with `make BUILD=release` +# default to release build+ +BUILD := release +PLATFORM := linux +CXX := g++ +#CXX := clang +OUT_DIR := $(BUILD) + +CXX_FLAGS.debug := -O0 -g3 -std=c++0x -Wall -pthread + +CXX_FLAGS.release := -O3 -std=c++0x -Wall -pthread + +CXX_INC := -I../include/ +CXX_INC += -I../oc_logger/include +CXX_INC += -I../csdk/stack/include +CXX_INC += -I../csdk/ocsocket/include +CXX_INC += -I../csdk/ocrandom/include +CXX_INC += -I../csdk/logger/include +CXX_INC += -I../csdk/libcoap + +LIB_OC_LOGGER := ../oc_logger/lib/oc_logger.a + +CXX_LIBS := ../$(BUILD)/obj/liboc.a ../csdk/$(PLATFORM)/$(BUILD)/liboctbstack.a $(LIB_OC_LOGGER) + +# Force metatargets to build: +all.PHONY: prep_dirs oc_cpp_sdk simpleserver simpleserverHQ simpleclient simpleclientHQ simpleclientserver roomserver roomclient presenceserver presenceclient garageserver garageclient fridgeserver fridgeclient ocicuc_target threadingsample devicediscoveryserver devicediscoveryclient groupserver groupclient lightserver + +apps.PHONY: prep_dirs oc_cpp_sdk simpleserver simpleserverHQ simpleclient simpleclientHQ simpleclientserver roomserver roomclient presenceserver presenceclient garageserver garageclient fridgeserver fridgeclient threadingsample devicediscoveryserver devicediscoveryclient groupserver groupclient lightserver + +buildScript_all.PHONY: prep_dirs simpleserver simpleserverHQ simpleclient simpleclientHQ simpleclientserver roomserver roomclient presenceserver presenceclient garageserver garageclient fridgeserver fridgeclient threadingsample devicediscoveryserver devicediscoveryclient groupserver groupclient lightserver + +all: all.PHONY + +apps: apps.PHONY + +buildScript_all: buildScript_all.PHONY + +prep_dirs: + -mkdir -p $(OUT_DIR) + +oc_cpp_sdk: + cd ../ && $(MAKE) cpp_sdk "BUILD=$(BUILD)" + +simpleserver: simpleserver.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ simpleserver.cpp $(CXX_INC) $(CXX_LIBS) + +simpleserverHQ: simpleserverHQ.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ simpleserverHQ.cpp $(CXX_INC) $(CXX_LIBS) + +simpleclientHQ: simpleclientHQ.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ simpleclientHQ.cpp $(CXX_INC) $(CXX_LIBS) + +simpleclient: simpleclient.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ simpleclient.cpp $(CXX_INC) $(CXX_LIBS) + +fridgeserver: fridgeserver.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ fridgeserver.cpp $(CXX_INC) $(CXX_LIBS) + +fridgeclient: fridgeclient.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ fridgeclient.cpp $(CXX_INC) $(CXX_LIBS) + +presenceserver: presenceserver.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ presenceserver.cpp $(CXX_INC) $(CXX_LIBS) + +presenceclient: presenceclient.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ presenceclient.cpp $(CXX_INC) $(CXX_LIBS) + +simpleclientserver: simpleclientserver.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ simpleclientserver.cpp $(CXX_INC) $(CXX_LIBS) + +roomserver: roomserver.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ roomserver.cpp $(CXX_INC) $(CXX_LIBS) + +roomclient: roomclient.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ roomclient.cpp $(CXX_INC) $(CXX_LIBS) + +garageserver: garageserver.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ garageserver.cpp $(CXX_INC) $(CXX_LIBS) + +garageclient: garageclient.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ garageclient.cpp $(CXX_INC) $(CXX_LIBS) + +threadingsample: threadingsample.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ threadingsample.cpp $(CXX_INC) $(CXX_LIBS) + +groupserver: groupserver.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ groupserver.cpp $(CXX_INC) $(CXX_LIBS) + +groupclient: groupclient.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ groupclient.cpp $(CXX_INC) $(CXX_LIBS) + +lightserver: lightserver.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ lightserver.cpp $(CXX_INC) $(CXX_LIBS) + +devicediscoveryserver: devicediscoveryserver.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ devicediscoveryserver.cpp $(CXX_INC) $(CXX_LIBS) + +devicediscoveryclient: devicediscoveryclient.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OUT_DIR)/$@ devicediscoveryclient.cpp $(CXX_INC) $(CXX_LIBS) + + + +ocicuc_target: + cd ocicuc && $(MAKE) apps + +clean: + rm -rf debug + rm -rf release + cd ../ && $(MAKE) clean_cpp_sdk + cd ocicuc && $(MAKE) clean + cd ocicuc && $(MAKE) clean_apps + +clean_apps: + rm -rf debug + rm -rf release + cd ocicuc && $(MAKE) clean + cd ocicuc && $(MAKE) clean_apps diff --git a/resource/examples/ocicuc/.gitignore b/resource/examples/ocicuc/.gitignore new file mode 100644 index 000000000..3f5d7129e --- /dev/null +++ b/resource/examples/ocicuc/.gitignore @@ -0,0 +1,4 @@ +# Ignore our example executables +client +monoprocess +server diff --git a/resource/examples/ocicuc/Makefile b/resource/examples/ocicuc/Makefile new file mode 100644 index 000000000..17556f8db --- /dev/null +++ b/resource/examples/ocicuc/Makefile @@ -0,0 +1,84 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +BUILD:=release +PLATFORM:=linux + +OCLIB=../.. +OCLIB_LIB=../../$(BUILD)/obj/liboc.a + +BOOST_BASE=/usr/local/boost +BOOST_INC=$(BOOST_BASE)/include +BOOST_LIB=$(BOOST_BASE)/lib + +CXX_FLAGS.debug := -g3 -O0 +CXX_FLAGS.release := -O3 + +CXX_FLAGS:=-Werror -Wall -std=c++0x -ggdb $(CXX_FLAGS.$(BUILD)) -pthread + +# There's probably nicer Makefile magic for this, but hopefully it will suffice: +CXX_INC=-I$(OCLIB)/include \ + -I$(BOOST_INC) \ + -I../../include/ \ + -I../../oc_logger/include/ \ + -I../../csdk/stack/include \ + -I../../csdk/ocsocket/include \ + -I../../csdk/ocrandom/include \ + -I../../csdk/logger/include \ + +BOOST_LIBS=-lboost_program_options +#BOOST_LIBS=-L/usr/local/boost/lib/ -lboost_program_options # for boost libraries at the specified path + +LIB_OC_LOGGER:=../../oc_logger/lib/oc_logger.a + +CXX_LIBS=$(OCLIB_LIB) ../../csdk/$(PLATFORM)/$(BUILD)/liboctbstack.a $(LIB_OC_LOGGER) $(BOOST_LIBS) + +APPS += client +APPS += server +APPS += monoprocess +APPS += small_example + +.PHONY: client server + +all: apps + @echo Remember to \"export LD_LIBRARY_PATH=$(BOOST_LIB)\:\$$LD_LIBRARY_PATH\" + +apps: $(APPS) + +%.o: %.cpp + $(CXX) $(CXXFLAGS) $(CXX_FLAGS) $(CXX_INC) -c -o $@ $< + +client: client.o driver.o utility.o + $(CXX) $(CXX_FLAGS) -o $@ $^ $(CXX_LIBS) + +server: server.o driver.o utility.o light_resource.o + $(CXX) $(CXX_FLAGS) -o $@ $^ $(CXX_LIBS) + +monoprocess: monoprocess.o driver.o utility.o light_resource.o + $(CXX) $(CXX_FLAGS) -o $@ $^ $(CXX_LIBS) + +small_example: small_example.o driver.o utility.o + $(CXX) $(CXX_FLAGS) -o $@ $^ $(CXX_LIBS) + +clean: + rm -f *.o $(APPS) + +clean_apps: + rm -f *.o $(APPS) diff --git a/resource/examples/ocicuc/README b/resource/examples/ocicuc/README new file mode 100644 index 000000000..d0d99b75a --- /dev/null +++ b/resource/examples/ocicuc/README @@ -0,0 +1,49 @@ + +OCICUC is a light framework for rapidly building OIC test/demo/example applications. It provides pre-built +entry points and handling for things like command line parameters and modularlizes resources, so that +adding new features or building a new test application is a lightweight undertaking. + +. +├── client.cpp - a multi-resource client, similar to simpleclient +├── demo_client.hpp - client code, shared between client and multiprocess programs +├── driver.cpp - ocicuc base driver program +├── exec.hpp - header for binding with the driver +├── light_resource.cpp - example resource +├── light_resource.hpp - example resource +├── monoprocess.cpp - client and server in a single process +├── server.cpp - a multi-resource server, similar to simpleserver +├── small_example.cpp - a near-minimal example program +├── utility.cpp - utility functions for the demo programs +└── utility.hpp - utility functions + +You can extend the existing programs to add new resource types, etc.. Refer to the help screen for each program +for further details. For instance, to start a server with 5 resources and then test it with a separate client, +you could run: + + ./server --nres=5 + +...and, in another shell: + + ./client --nres=5 + +To build a new program that hooks into the ocicuc driver program, you just need to define the functions in "exec.hpp", +for example: + +namespace Intel { namespace OCDemo { + +int exec(const boost::program_options::variables_map& vm); + +auto make_description() + -> boost::program_options::options_description; + +}} // namespace Intel::OCDemo + +You can see an example of a skeleton program in small_example.cpp. + +To run a program with default parameters, use "--", for example: + +./monoprocess -- + +Have fun! + + diff --git a/resource/examples/ocicuc/SConscript b/resource/examples/ocicuc/SConscript new file mode 100644 index 000000000..434efd776 --- /dev/null +++ b/resource/examples/ocicuc/SConscript @@ -0,0 +1,48 @@ +## +# Examples build script +## +Import('env') +# Add third party libraries +lib_env = env.Clone() +SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env') + +ocicuc_env = lib_env.Clone() +###################################################################### +# Build flags +###################################################################### +ocicuc_env.AppendUnique(CPPPATH = [ + '../../include/', + '../../csdk/stack/include', + '../../csdk/ocsocket/include', + '../../csdk/ocrandom/include', + '../../csdk/logger/include', + '../../oc_logger/include' + ]) + +ocicuc_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')]) +ocicuc_env.PrependUnique(LIBS = ['oc', 'octbstack', 'coap', 'oc_logger']) + +target_os = env.get('TARGET_OS') +if target_os not in ['windows', 'winrt']: + ocicuc_env.AppendUnique(CXXFLAGS = ['-std=c++0x']) + +if target_os == 'android': + ocicuc_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions']) + ocicuc_env.AppendUnique(LIBS = ['boost_program_options', 'boost_thread', 'gnustl_static']) + + if not env.get('RELEASE'): + ocicuc_env.AppendUnique(LIBS = ['log']) + +if target_os == 'darwin': + ocicuc_env.AppendUnique(LIBS = ['boost_program_options']) + +###################################################################### +# Source files and Targets +###################################################################### +client = ocicuc_env.Program('client', ['client.cpp', 'driver.cpp', 'utility.cpp']) +server = ocicuc_env.Program('server', ['server.cpp', 'driver.cpp', 'utility.cpp', 'light_resource.cpp']) +monoprocess = ocicuc_env.Program('monoprocess', ['monoprocess.cpp', 'driver.cpp', 'utility.cpp', 'light_resource.cpp']) +small_example = ocicuc_env.Program('small_example', ['small_example.cpp', 'driver.cpp', 'utility.cpp']) + +Alias("examples_ocicuc", [client, server, monoprocess, small_example]) +env.AppendTarget('examples_ocicuc') diff --git a/resource/examples/ocicuc/client.cpp b/resource/examples/ocicuc/client.cpp new file mode 100644 index 000000000..c3771bb97 --- /dev/null +++ b/resource/examples/ocicuc/client.cpp @@ -0,0 +1,126 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// This contains the Boost MPL defines required for the boost_variant +// serialization, so it must go before the boost/program_options +#include "OCApi.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "OCResource.h" +#include "OCPlatform.h" + +#include "exec.hpp" +#include "utility.hpp" + +#include "demo_client.hpp" + +namespace Intel { namespace OCDemo { + +auto make_description() + -> boost::program_options::options_description +{ + using std::string; + using std::vector; + + namespace po = boost::program_options; + + po::options_description desc("Client options"); + + desc.add_options() + ("nres", po::value()->default_value(1), "number of resources to use for testing") + ("host_ip", po::value()->default_value("0.0.0.0"), "IP of host") + ("host_port", po::value()->default_value(0), "port of host") + ("interface", po::value()->default_value("eth0"), "network interface name") + ("uri", po::value>(), "remote resource URI") + ; + + return desc; +} + +int exec(const boost::program_options::variables_map& vm) +{ + using namespace std; + + OC::OCPlatform::Configure({ + OC::ServiceType::InProc, // in-process server + OC::ModeType::Client, // client mode + vm["host_ip"].as(), // host + vm["host_port"].as(), // port + OC::QualityOfService::LowQos + }); + + vector resource_URIs; + + if(0 == vm.count("uri")) + { + std::cout << "No URI specified, looking for everything in \"core\".\n"; + + // Find all resources: + resource_URIs.push_back("coap://224.0.1.187/oc/core"); + + /* Example of finding specific resources: + const auto& nprops = vm["nres"].as(); + + for(unsigned long instance_number = 1; + instance_number <= nprops; + instance_number++) + { + ostringstream uri; + + + uri << "coap://" << vm["host_ip"].as() << "/oc/core?rt=core.light" << '_' << instance_number; + resource_URIs.push_back(uri.str()); // ie. "coap://224.0.1.187/oc/core?rt=core.light_1"); + } + */ + } + else + { + const vector& input_URIs = vm["uri"].as< vector >(); + copy(begin(input_URIs), end(input_URIs), back_inserter(resource_URIs)); + } + + std::cout << "Requesting " << resource_URIs.size() << " URIs:\n"; + + for(const auto& resource_URI : resource_URIs) + cout << resource_URI << '\n'; + + Intel::OCDemo::client::resource_handler resources(resource_URIs); + + // Register callbacks and wait for resources: + resources.find_resources(); + + // Allow the client to receive events from the server: + for(;;) + ; + + return 0; +} + +}} // namespace Intel::OCDemo + diff --git a/resource/examples/ocicuc/demo_client.hpp b/resource/examples/ocicuc/demo_client.hpp new file mode 100644 index 000000000..d5ce57874 --- /dev/null +++ b/resource/examples/ocicuc/demo_client.hpp @@ -0,0 +1,234 @@ + +/* Example client program (this is not a library header, don't include it in random programs): */ + +namespace Intel { namespace OCDemo { namespace client { + +// Although not "done" here, this could be expanded into an interface to handle any sort of +// resource: +class resource_handle +{ + friend class resource_handler; + + private: + const std::string URI; + std::shared_ptr resource; + + public: + resource_handle(const std::string& URI_, std::shared_ptr resource_) + : URI(URI_), + resource(resource_) + {} + + resource_handle(const std::string& URI_) + : URI(URI_) + {} + + // Callbacks (note that the signature after binding will match exactly: + private: + void onFoundResource(std::shared_ptr in_resource); + void onResourceGet(const OC::HeaderOptions& headerOptions, + OC::OCRepresentation rep, const int error_code); + void onResourcePut(const OC::HeaderOptions& headerOptions, const OC::OCRepresentation rep, + const int error_code); + void onObserve(const OC::HeaderOptions& headerOptions, const OC::OCRepresentation rep, + const int error_code, const int& sequence_number); +}; + +class resource_handler +{ + + static std::vector> resources; // URI -> Maybe resource + + public: + resource_handler(const std::vector& resource_URIs_); + resource_handler(); + + public: + bool has(const std::string& URI) + { + for(const auto& r : resources) + { + if(URI == r->URI) + return true; + } + + return false; + } + + void add(const std::string& URI) + { + if(!has(URI)) + resources.emplace_back(std::make_shared(URI)); + } + + void find_resources() + { + for(const auto& resource : resources) + { + std::cout << "* Finding resources \"" << resource->URI << "\".\n"; + + call_timer.mark("find_resources"); + + OC::OCPlatform::findResource("", resource->URI, + std::bind(&resource_handle::onFoundResource, resource, std::placeholders::_1)); + } + } +}; + +std::vector> resource_handler::resources; + +resource_handler::resource_handler(const std::vector& resource_URIs) +{ + for(const auto& URI : resource_URIs) + add(URI); +} + +void resource_handle::onFoundResource(std::shared_ptr in_resource) +{ + using std::cout; + + cout << "* onFoundResource():\n"; + + try + { + if(nullptr == in_resource) + throw OC::OCException("invalid resource passed to client callback"); + + call_timer.report_and_reset("find_resources"); + + // Now, fixup our own representation ptr: + resource = in_resource; + + /* Note: You can combine the host and URI to get a unique identifier, for + example to filter out events you aren't interested in. Here, we just report the + data: */ + cout << "resource URI: " << resource->uri() << "; " + << "host address: " << resource->host() << '\n'; + + call_timer.mark("get_resource"); + + OC::QueryParamsMap qpm; + + resource->get(qpm, std::bind(&resource_handle::onResourceGet, this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + } + catch(OC::OCException& e) + { + std::cerr << "onFoundResource(): exception " << e.reason() << ": " << e.what() << '\n'; + } + catch(std::exception& e) + { + std::cerr << "onFoundResource(): exception: " << e.what() << '\n'; + } +} + +void resource_handle::onResourceGet(const OC::HeaderOptions& headerOptions, + const OC::OCRepresentation rep, const int error_code) +{ + using std::cout; + + cout << "onResourceGet():\n"; + + call_timer.report_and_reset("get_resource"); + + if(error_code) + { + std::cerr << "onResourceGet(): error: " << error_code << '\n'; + return; + } + + if(nullptr == resource) + { + std::cerr << "onResourceGet(): empty resource pointer.\n"; + return; + } + + std::cout << "input attributes:\n"; + std::cout << "Attribute \"" << "state" << "\": "<< rep.getValue("state")<<"; "; + std::cout << "Attribute \"" << "power" << "\": "<< rep.getValue("power")<<"; \n"; + + // Now, make a change to the light representation (replacing, rather than parsing): + bool state = true; + int power = 10; + + std::cout << "output attributes:\n"; + std::cout << "Attribute \"" << "state" << "\": "<< state<<"; "; + std::cout << "Attribute \"" << "power" << "\": "<< power<<"; \n"; + + call_timer.mark("put_resource"); + + OC::OCRepresentation out_rep; + out_rep.setValue("state", state); + out_rep.setValue("power", power); + + resource->put(out_rep, OC::QueryParamsMap(), + std::bind(&resource_handle::onResourcePut, this, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3)); +} + +void resource_handle::onResourcePut(const OC::HeaderOptions& headerOptions, + const OC::OCRepresentation rep, const int error_code) +{ + std::cout << "onResourcePut():\n"; + + call_timer.report_and_reset("put_resource"); + + if(0 != error_code) + { + std::ostringstream os; + + os << "onResourcePut(): error code " << error_code << " from server response."; + + throw OC::OCException(os.str()); + } + + std::cout << "input attributes:\n"; + std::cout << "Attribute \"" << "state" << "\": "<< rep.getValue("state")<<"; "; + std::cout << "Attribute \"" << "power" << "\": "<< rep.getValue("power")<<"; \n"; + + call_timer.mark("observe_resource"); + + // Start an observer: + resource->observe(OC::ObserveType::Observe, OC::QueryParamsMap(), + std::bind(&resource_handle::onObserve, this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, + std::placeholders::_4)); +} + +void resource_handle::onObserve(const OC::HeaderOptions& headerOptions, + const OC::OCRepresentation rep, const int error_code, const int& sequence_number) +{ + if(0 != error_code) + { + std::ostringstream os; + os << "onObserve(): error " << error_code << " from callback.\n"; + throw OC::OCException(os.str()); + } + + std::cout << "onObserve(): sequence number: " << sequence_number << ":\n"; + + call_timer.report_and_reset("observe_resource"); + + std::cout << "Attribute \"" << "state" << "\": "<< rep.getValue("state")<<"; "; + std::cout << "Attribute \"" << "power" << "\": "<< rep.getValue("power")<<"; \n"; + + const auto oc = observe_count(); + + std::cout << "onObserve(): observation count is: " << oc << '\n'; + + // We don't want to be observed forever for purposes of this demo: + if(10 <= oc) + { + std::cout << "onObserve(): cancelling observation.\n"; + + const auto result = resource->cancelObserve(); + + std::cout << "onObserve(): result of cancellation: " << result << ".\n"; + + this_thread::sleep_for(chrono::seconds(10)); + } +} + +}}} // namespace Intel::OCDemo::client + + diff --git a/resource/examples/ocicuc/driver.cpp b/resource/examples/ocicuc/driver.cpp new file mode 100644 index 000000000..9d7edb545 --- /dev/null +++ b/resource/examples/ocicuc/driver.cpp @@ -0,0 +1,58 @@ + +#include + +#include +#include + +#include + +#include "exec.hpp" + +namespace Intel { namespace OCDemo { + +auto parse_options(boost::program_options::options_description& desc, int argc, char *argv[]) + -> boost::program_options::variables_map +{ + namespace po = boost::program_options; + + po::positional_options_description popts; + popts.add("uri", -1); + + po::variables_map vm; + + po::store(po::command_line_parser(argc,argv).options(desc).positional(popts).run(), + vm); + + po::notify(vm); + + return vm; +} + +}} // namespace Intel::OCDemo + +int main(int argc, char *argv[]) +try +{ + using namespace std; + + auto desc = Intel::OCDemo::make_description(); + auto vm = Intel::OCDemo::parse_options(desc, argc, argv); + + if(1 == argc || vm.count("help")) + { + std::cerr << desc << '\n'; + return 1; + } + + return Intel::OCDemo::exec(vm); +} +catch(std::exception& e) +{ + std::cerr << "Unhandled exception: " << e.what() << '\n'; + return 1; +} +catch(...) +{ + std::cerr << "Unhandled exception.\n"; + return 1; +} diff --git a/resource/examples/ocicuc/exec.hpp b/resource/examples/ocicuc/exec.hpp new file mode 100644 index 000000000..f1ff62acc --- /dev/null +++ b/resource/examples/ocicuc/exec.hpp @@ -0,0 +1,37 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef __EXEC_HPP + #define __EXEC_HPP 1 + +#include + +/* Interface point for the driver code. Your program needs to implement these +functions: */ +namespace Intel { namespace OCDemo { + +int exec(const boost::program_options::variables_map& vm); + +auto make_description() + -> boost::program_options::options_description; + +}} // namespace Intel::OCDemo + +#endif diff --git a/resource/examples/ocicuc/light_resource.cpp b/resource/examples/ocicuc/light_resource.cpp new file mode 100644 index 000000000..6586ac6f7 --- /dev/null +++ b/resource/examples/ocicuc/light_resource.cpp @@ -0,0 +1,211 @@ +#include "light_resource.hpp" + +namespace Intel { namespace OCDemo { + +std::atomic LightResource::shutdown_flag(false); +std::thread LightResource::observe_thread; + +void LightResource::setRepresentation(const OCRepresentation& rep) +{ + cout << "\t\t\t" << "Received representation: " << endl; + + rep.getValue("state", m_state); + rep.getValue("power", m_power); + + cout << "\t\t\t\t" << "power: " << m_power << endl; + cout << "\t\t\t\t" << "state: " << m_state << endl; +} + +OCRepresentation LightResource::getRepresentation(void) +{ + m_rep.setValue("state", m_state); + m_rep.setValue("power", m_power); + return m_rep; +} + +void LightResource::addType(const std::string& type) const +{ + OCStackResult result = OC::OCPlatform::bindTypeToResource(m_resourceHandle, type); + + if(OC_STACK_OK != result) + cout << "Binding TypeName to Resource was unsuccessful, result was " << result << '\n'; +} + +void LightResource::addInterface(const std::string& interface) const +{ + OCStackResult result = OC::OCPlatform::bindInterfaceToResource(m_resourceHandle, interface); + + if(OC_STACK_OK != result) + cout << "Binding TypeName to Resource was unsuccessful, result was " << result << '\n'; +} + +void LightResource::createResource(const unsigned int resource_number) +{ + string resourceURI { make_URI(resource_number) }; + string resourceTypeName { "core.light" }; + + cout << "registering resource: " << resourceURI << '\n'; + cout << "registering type name \"" << resourceTypeName << "\".\n"; + // This will internally create and register the resource, binding the current instance's method as a callback: + OCStackResult result = OC::OCPlatform::registerResource( + m_resourceHandle, resourceURI, resourceTypeName, + DEFAULT_INTERFACE, + std::bind(&LightResource::entityHandler, this, std::placeholders::_1), + OC_DISCOVERABLE | OC_OBSERVABLE); + if (OC_STACK_OK != result) + std::cout << "Resource creation failed.\n"; +} + +void LightResource::observe_function() +{ + cerr << "Observation thread is spinning up.\n"; + + while(!shutdown_flag) + { + std::this_thread::sleep_for(std::chrono::seconds(2)); + + if(!m_observation) + continue; + + m_power += 10; + + const auto result = OC::OCPlatform::notifyAllObservers(getHandle()); + + // Stop notifications when there are no more observers: + if(OC_STACK_NO_OBSERVERS == result) + { + m_observation = 0; + } + } + + cerr << "Observation thread is shutting down.\n"; +} + +void LightResource::unregisterResource() +{ + std::cout << "Unregistering light resource"< request) +{ + if(!request) + { + cerr << "entityHandler(): Received invalid request object.\n"; + return OC_EH_ERROR; + } + + switch(request->getRequestHandlerFlag()) + { + default: + cerr << "entityHandler(): invalid request flag\n"; + break; + + case RequestHandlerFlag::InitFlag: + cerr << "entityHandler(): Initialization requested.\n"; + break; + + case RequestHandlerFlag::RequestFlag: + dispatch_request(request->getRequestType(), request); + break; + + case RequestHandlerFlag::ObserverFlag: + handle_observe_event(request); + break; + } + + return OC_EH_OK; +} + +void LightResource::dispatch_request(const std::string& request_type, std::shared_ptr request) +{ + std::cout << "dispatch_request(): " << request_type << '\n'; + + if("GET" == request_type) + return handle_get_request(request); + + if("PUT" == request_type) + return handle_put_request(request); + + if("POST" == request_type) + return handle_post_request(request); + + if("DELETE" == request_type) + return handle_delete_request(request); + + cerr << "entityHandler(): Invalid request type \"" << request_type << "\".\n"; +} + +void LightResource::handle_get_request(std::shared_ptr request) +{ + cout << "handle_get_request():\n"; + + const auto query_params_map = request->getQueryParameters(); + + // ...do any processing of the query here... + + // Get a representation of the resource and send it back as a response: + auto pResponse = std::make_shared(); + pResponse->setRequestHandle(request->getRequestHandle()); + pResponse->setResourceHandle(request->getResourceHandle()); + pResponse->setErrorCode(200); + pResponse->setResponseResult(OC_EH_OK); + pResponse->setResourceRepresentation(getRepresentation()); + OCPlatform::sendResponse(pResponse); +} + +void LightResource::handle_put_request(std::shared_ptr request) +{ + // Here's how you would get any query parameters: + const auto query_params_map = request->getQueryParameters(); + // ...do something with the query parameters (if there were any)... + + auto rep = request->getResourceRepresentation(); + + setRepresentation(rep); + + auto pResponse = std::make_shared(); + pResponse->setRequestHandle(request->getRequestHandle()); + pResponse->setResourceHandle(request->getResourceHandle()); + pResponse->setErrorCode(200); + pResponse->setResponseResult(OC_EH_OK); + pResponse->setResourceRepresentation(getRepresentation()); + OCPlatform::sendResponse(pResponse); +} + +void LightResource::handle_post_request(std::shared_ptr request) +{ + // ...demo-code... +} + +void LightResource::handle_delete_request(std::shared_ptr request) +{ + // ...demo-code... +} + +// Set up observation in a separate thread: +void LightResource::handle_observe_event(std::shared_ptr request) +{ + if(observe_thread.joinable()) + return; + + observe_thread = thread(bind(&LightResource::observe_function, this)); + observe_thread.detach(); +} + + + +}} // namespace Intel::OCDemo + diff --git a/resource/examples/ocicuc/light_resource.hpp b/resource/examples/ocicuc/light_resource.hpp new file mode 100644 index 000000000..494b366a9 --- /dev/null +++ b/resource/examples/ocicuc/light_resource.hpp @@ -0,0 +1,95 @@ +#ifndef __LIGHT_RESOURCE_HPP + #define __LIGHT_RESOURCE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "OCApi.h" +#include "OCResource.h" +#include "OCPlatform.h" + +/* An example of a server-side resource: */ +namespace Intel { namespace OCDemo { + +using namespace OC; +using namespace std; + +/// This class represents a single resource named 'lightResource'. This resource has +/// two simple properties named 'state' and 'power' +class LightResource +{ + public: + bool m_state; // off or on? + int m_power; // power level + OCRepresentation m_rep; + + private: + atomic m_observation; // are we under observation? + + private: + static atomic shutdown_flag; + static thread observe_thread; + + private: + OCResourceHandle m_resourceHandle; + + public: + LightResource() + : m_state(false), + m_power(0), + m_observation(false) + {} + + ~LightResource() + { + shutdown_flag = true; + + if(observe_thread.joinable()) + observe_thread.join(); + } + + private: + inline std::string make_URI(const unsigned int resource_number) + { + std::string uri = std::string("/a/light") + "_" + std::to_string(resource_number); + m_rep.setUri(uri); + return uri; + } + + public: + // This function internally calls registerResource API. + void createResource(const unsigned int resource_number); + void unregisterResource(); + OCResourceHandle getHandle() const { return m_resourceHandle; } + + void setRepresentation(const OCRepresentation& rep); + OCRepresentation getRepresentation(void); + + void addType(const std::string& type) const; + void addInterface(const std::string& interface) const; + + private: + OCEntityHandlerResult entityHandler(std::shared_ptr request); + + private: + void observe_function(); + + // Request handlers: + private: + void dispatch_request(const std::string& request_type, std::shared_ptr request); + void handle_get_request(std::shared_ptr request); + void handle_put_request(std::shared_ptr request); + void handle_post_request(std::shared_ptr request); + void handle_delete_request(std::shared_ptr request); + void handle_observe_event(std::shared_ptr request); +}; + +}} // namespace Intel::OCDemo + +#endif diff --git a/resource/examples/ocicuc/monoprocess.cpp b/resource/examples/ocicuc/monoprocess.cpp new file mode 100644 index 000000000..14566ea3c --- /dev/null +++ b/resource/examples/ocicuc/monoprocess.cpp @@ -0,0 +1,222 @@ +//****************************************************************** +// +// Copyright 2014 Intel Corporation All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "OCApi.h" +#include "OCResource.h" +#include "OCPlatform.h" + +#include "exec.hpp" +#include "utility.hpp" + +#include "demo_client.hpp" +#include "light_resource.hpp" + +namespace Intel { namespace OCDemo { + +auto make_description() + -> boost::program_options::options_description +{ + using std::string; + + namespace po = boost::program_options; + + po::options_description desc("Monoprocess Client/Server options"); + + desc.add_options() + ("nres", po::value()->default_value(1), "number of resources to use for testing") + ("host_ip", po::value()->default_value("0.0.0.0"), "IP of host") + ("host_port", po::value()->default_value(0), "port of host") + ("interface", po::value()->default_value("eth0"), "network interface name") + ("uri", po::value>(), "resource URI") + ; + + return desc; +} + +/* Unfortunately, our target compiler may not support std::async correctly, so this +leverages RAII to save us from having to use the double-join-check pattern: */ +struct simple_join_guard +{ + thread t; + + template + simple_join_guard(FnT&& fn) + : t(fn) + {} + + ~simple_join_guard() + { + if(t.joinable()) + t.join(); + } +}; + +struct client_t +{ + const boost::program_options::variables_map m_vm; + + atomic& quit_flag; + + vector resource_URIs; + + public: + client_t(const boost::program_options::variables_map vm, + atomic& quit_flag_) + : m_vm(vm), + quit_flag(quit_flag_) + {} + + public: + void init() + { + if(0 != m_vm.count("uri")) + { + const vector& input_URIs = m_vm["uri"].as< vector >(); + copy(begin(input_URIs), end(input_URIs), back_inserter(resource_URIs)); + } + else + resource_URIs.push_back("coap://224.0.1.187/oc/core"); + } + + void operator()() + { + std::cout << "Requesting " << resource_URIs.size() << " URIs:\n"; + + for(const auto& resource_URI : resource_URIs) + cout << resource_URI << '\n'; + + Intel::OCDemo::client::resource_handler resources(resource_URIs); + + // Register callbacks and wait for resources: + resources.find_resources(); + + // Allow the client to receive events from the server: + while(!quit_flag) + { + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + } +}; + +struct server_t +{ + const boost::program_options::variables_map m_vm; + + atomic& quit_flag; + + unsigned long m_nresources; + + vector resource_URIs; + + vector> lights; + + public: + server_t(const boost::program_options::variables_map& vm, + atomic& quit_flag_) + : m_vm(vm), + quit_flag(quit_flag_) + { + m_nresources = vm["nres"].as(); + } + + public: + void init(); + + void operator()() + { + while(!quit_flag) + { + std::this_thread::sleep_for(std::chrono::seconds(5)); + } + } +}; + +void server_t::init() +{ + lights.resize(m_nresources); + + for(unsigned int resource_number = 1; m_nresources >= resource_number; resource_number++) + { + cout << "Registering resource " << resource_number << ": " << std::flush; + + auto lr = make_shared(); + + lr->createResource(resource_number); + lr->addType("core.brightlight"); + lr->addInterface("oc.mi.ll"); + + lights.push_back(lr); + + cout << "Ok." << std::endl; + } +} + +int exec(const boost::program_options::variables_map& vm) +{ + using namespace std; + + std::cout << "Starting platform: " << std::flush; + + OC::OCPlatform::Configure(OC::PlatformConfig { + OC::ServiceType::InProc, + OC::ModeType::Both, // run in client/server mode + vm["host_ip"].as(), // host + vm["host_port"].as(), // port + OC::QualityOfService::LowQos + }); + std::cout << "Ok." << std::endl; + + std::atomic quit_flag; + + server_t server(vm, quit_flag); + client_t client(vm, quit_flag); + +std::cout << "JFW: TODO: don't need to separate these any more\n"; + server.init(); + client.init(); + + // Run the server and client: + { + simple_join_guard server_guard(server); + simple_join_guard client_guard(client); + + // Note that at present nothing makes this true: + while(!quit_flag) + { + // Perform app tasks + std::this_thread::sleep_for(std::chrono::seconds(2)); + } + } + + return 1; +} + +}} // namespace Intel::OCDemo + diff --git a/resource/examples/ocicuc/server.cpp b/resource/examples/ocicuc/server.cpp new file mode 100644 index 000000000..65fca0e4a --- /dev/null +++ b/resource/examples/ocicuc/server.cpp @@ -0,0 +1,99 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "utility.hpp" + +#include "exec.hpp" +#include "light_resource.hpp" + +namespace Intel { namespace OCDemo { + +auto make_description() + -> boost::program_options::options_description +{ + using std::string; + + namespace po = boost::program_options; + + po::options_description desc("Server options"); + + desc.add_options() + ("nres", po::value()->default_value(1), "number of resources to use for testing") + ("host_ip", po::value()->default_value("0.0.0.0"), "IP of host") + ("host_port", po::value()->default_value(0), "port of host") + ("interface", po::value()->default_value("eth0"), "network interface name") + ("uri", po::value>(), "resource URI") + ("runtime", po::value()->default_value(3600), "time in seconds to keep the server alive") + ; + + return desc; +} + +int exec(const boost::program_options::variables_map& vm) +{ + using namespace std; + + std::cout << "Starting platform: " << std::flush; + + OC::OCPlatform::Configure({ + OC::ServiceType::InProc, // in-process server + OC::ModeType::Server, // run in server mode + vm["host_ip"].as(), // host + vm["host_port"].as(), // port + OC::QualityOfService::LowQos + }); + + std::cout << "Ok." << std::endl; + + vector resource_URIs; + + vector> lights; + + const unsigned long& nresources = vm["nres"].as(); + + for(unsigned int resource_number = 1; nresources >= resource_number; resource_number++) + { + cout << "Registering resource " << resource_number << ": " << std::flush; + + auto lr = make_shared(); + + lr->createResource(resource_number); + lr->addType(std::string("core.brightlight")); + lr->addInterface(std::string("oc.mi.ll")); + + lights.push_back(lr); + + cout << "Ok." << std::endl; + } + + // Perform app tasks + cout << "Sleeping for "<< vm["runtime"].as()<<" seconds."<())); + + for(auto light: lights) + { + light->unregisterResource(); + } + + return 1; +} + +}} // namespace Intel::OCDemo + diff --git a/resource/examples/ocicuc/small_example.cpp b/resource/examples/ocicuc/small_example.cpp new file mode 100644 index 000000000..e641cffdc --- /dev/null +++ b/resource/examples/ocicuc/small_example.cpp @@ -0,0 +1,44 @@ +/* Example program illustrating how to work with the ocicuc driver program: */ + +#include "exec.hpp" + +#include + +namespace Intel { namespace OCDemo { + +/* exec() is essentially main(), and is where the driver will start your +program after command-line options have been parsed: */ +int exec(const boost::program_options::variables_map& vm) +{ + using std::cout; + + cout << "This is the start of my wonderful program!\n"; + + cout << "My command-line options are:\n"; + + for(const auto& o : vm) + cout << o.first << " => " << o.second.as() << '\n'; + + return 0; +} + +/* make_description() is your opportunity to describe your program's help screen and command +line parameter types. Refer to the boost::program_options library for details on how to +add different kinds of command-line options: */ +auto make_description() + -> boost::program_options::options_description +{ + namespace po = boost::program_options; // because boost::program_options is a lot to type! + + po::options_description desc("My wonderful program's options! Run with \"--\" to simply use the defaults."); + + desc.add_options() + ("param", po::value()->default_value("Hello, World!"), "description of param") + ; + + return desc; +} + +}} // namespace Intel::OCDemo + + diff --git a/resource/examples/ocicuc/utility.cpp b/resource/examples/ocicuc/utility.cpp new file mode 100644 index 000000000..823e57f0e --- /dev/null +++ b/resource/examples/ocicuc/utility.cpp @@ -0,0 +1,81 @@ +#include +#include +#include +#include + +#include "utility.hpp" + +namespace Intel { namespace OCDemo { + +int observe_count() +{ + static unsigned long long oc = 0; + return ++oc; +} + +}} // namespace Intel::OCDemo + +// Helper for measuring call times: +namespace Intel { namespace OCDemo { + +using std::cout; +using namespace std::chrono; + +call_times call_timer; + +void call_times::reset(const std::string& entry) +{ + timings[entry] = make_pair(high_resolution_clock::now(), std::chrono::high_resolution_clock::time_point()); +} + +void call_times::mark(const std::string& name) +{ + auto e = timings.find(name); + + if(timings.end() == e) + { + reset(name); + return; + } + + auto& tp = (*e).second; + + if(tp.first > tp.second) + timings[name].second = high_resolution_clock::now(); + } + +void call_times::report() +{ + cout << "Time marks:\n"; + + for_each(begin(timings), end(timings), + [](const std::pair& tm) -> void + { + const std::string& name { tm.first }; + + const time_point& request_time { tm.second.first }; + const time_point& response_time { tm.second.second }; + + cout << '\t' << name << ": "; + + if(request_time > response_time) + { + cout << "\n"; + return; + } + + auto elapsed_ms = duration_cast(response_time - request_time).count(); + cout << elapsed_ms << "ms ("; + + auto elapsed_us = duration_cast(response_time - request_time).count(); + cout << elapsed_us << "us)\n"; + }); +} + +void call_times::report_and_reset(const std::string& name) +{ + mark(name), report(), reset(name); +} + + +}} // namespace Intel::OCDemo diff --git a/resource/examples/ocicuc/utility.hpp b/resource/examples/ocicuc/utility.hpp new file mode 100644 index 000000000..bc734d748 --- /dev/null +++ b/resource/examples/ocicuc/utility.hpp @@ -0,0 +1,71 @@ +//****************************************************************** +// +// Copyright 2014 Intel Corporation All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef __OC_OCDEMO_UTILITY_H + #define __OC_OCDEMO_UTILITY_H + +#include +#include +#include +#include + +#include "OCApi.h" + +namespace Intel { namespace OCDemo { + +/* A static observation counter: */ +int observe_count(); + +/* Helpers for measuring request times: */ +typedef std::pair< + std::chrono::time_point, + std::chrono::time_point + > clock_interval; + +struct call_times +{ + public: + bool display_reports; + + public: + std::map timings; + + public: + call_times() + : display_reports(true) + {} + + call_times(const bool& display_reports_) + : display_reports(display_reports_) + {} + + public: + void reset(const std::string& entry); + void mark(const std::string& name); + + void report(); + void report_and_reset(const std::string& name); +}; + +extern call_times call_timer; + +}} // namespace Intel::OCDemo + +#endif diff --git a/resource/examples/old_tests/MyMultiResourceHandler.cpp b/resource/examples/old_tests/MyMultiResourceHandler.cpp new file mode 100644 index 000000000..76b5f4e51 --- /dev/null +++ b/resource/examples/old_tests/MyMultiResourceHandler.cpp @@ -0,0 +1,158 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include + +#include "ocapi.h" +#include "OCReflect.h" +#include "OCObserver.h" +#include "OCException.h" +#include "MyMultiResourceHandler.h" + +namespace { + +void log(const std::string& msg) +{ + std::cerr << msg << '\n'; +} + +} // namespace + +void OC::MyMultiResourceHandler::onFoundResource(OCResourceResult *update, void *params){ + + //Step1: Find a specific resource that also contains OCReflect byte stream of methods and properties + for( auto &resource : update->resources ) + { + if(resource.getURI() == "/garage/dimmer/a") + { + performDimmerOperations(resource, update); + } + else if(resource.getURI() == "/garage/door/a") + { + performDoorOperations(resource, update); + } + } +} + +void OC::MyMultiResourceHandler::performDimmerOperations(OC::OCResource myResource, OC::OCResourceResult *update) +{ + using OC::OCReflect::entity; + using OC::OCReflect::method; + using OC::OCReflect::remote_resource; + + using OC::bind_observer; + using OC::unbind_observer; + + try + { + // Perform resource operation + // Note that this resource dimmer has + // 'manufacturer' as a property + // 'powerState' as a observable property + // 'setPowered' as a method + // 'getPowered' as a method + + //Step1: Find a specific method and invoke it. or Find a specific property and use it. + + // Canonical one-step approach to get a callable function object: + // OCReflect::method throw OC::OCReflect::reflect_exception if there is no setLevel method in the myResource + auto setPowered = OCReflect::method(myResource, "setPowered"); + + // invoke the remote method, + // invalid arguments return as an OC::OCReflect::reflect_exception + setPowered(true); + + // Canonical one-step approach to get a callable function object: + // OCReflect::method throw OC::OCReflect::reflect_exception if there is no setLevel method in the myResource + auto getPowered = OCReflect::method(myResource, "getPowered"); + + // invoke the remote method, + // invalid arguments return as an OC::OCReflect::reflect_exception + // bool power = getPowered(); // Use power variable to do other operations + + // Canonical one-step approach to access a property: + std::string manufacturer = update->property("manufacturer"); + + //Example to observe a property + bind_observer(&myObserverHandler, myResource, "powerState"); + + //Example to unobserve a property + unbind_observer(&myObserverHandler, myResource, "powerState"); + } + catch(OC::reflection_exception& e) + { + log(e.what()); + } + catch(std::exception& e) + { + log(e.what()); + } +} + +void OC::MyMultiResourceHandler::performDoorOperations(OC::OCResource myResource, OC::OCResourceResult *update) +{ + // Perform resource operation + // Note that this resource door has + // 'manufacturer' as a property + // 'setLockState' as a method + // 'getLockState' as a method + + try + { + // Step1: Find a specific method and invoke it or find a specific property and use it. + + // Canonical one-step approach to get a callable function object: + // OCReflect::method throw OC::OCReflect::reflect_exception if there is no setLevel method in the myResource + auto setLockState = OCReflect::method(myResource, "setLockState"); + + // invoke the remote method, + // invalid arguments return as an OC::OCReflect::reflect_exception + setLockState(true); + + // Canonical one-step approach to get a callable function object: + // OCReflect::method throw OC::OCReflect::reflect_exception if there is no setLevel method in the myResource + auto getLockState = OCReflect::method(myResource, "getLockState"); + + // invoke the remote method, + // invalid arguments return as an OC::OCReflect::reflect_exception + // bool lockState = getLockState(); // use lockState variable for any other operations + + // Canonical one-step approach to access a property + std::string manufacturer = update->property("manufacturer"); + } + catch(OC::reflection_exception& e) + { + log(e.what()); + } + catch(std::exception& e) + { + log(e.what()); + } +} + +void OC::MyMultiResourceHandler::MyMultiResourceHandler::onCompleted() +{ + +} + +void OC::MyMultiResourceHandler::MyMultiResourceHandler::onFailed() +{ + +} diff --git a/resource/examples/old_tests/MyMultiResourceHandler.h b/resource/examples/old_tests/MyMultiResourceHandler.h new file mode 100644 index 000000000..c0695b791 --- /dev/null +++ b/resource/examples/old_tests/MyMultiResourceHandler.h @@ -0,0 +1,45 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "ocapi.h" +#include "OCResourceHandler.h" +#include "MyObserverHandler.h" + +namespace OC { + +class MyMultiResourceHandler : + public OCResourceHandler +{ +public: + void onFoundResource(OCResourceResult *update, void *params); + void onCompleted(); + void onFailed(); + +private: + MyObserverHandler myObserverHandler; + + /// This is a private function to perform operations related to dimmer resource + void performDimmerOperations(OCResource myResource, OCResourceResult *update); + + /// This is a private function to perform operations related to door resource + void performDoorOperations(OCResource myResource, OCResourceResult *update); +}; + +} // namespace OC diff --git a/resource/examples/old_tests/MyObserverHandler.cpp b/resource/examples/old_tests/MyObserverHandler.cpp new file mode 100644 index 000000000..ee090cef6 --- /dev/null +++ b/resource/examples/old_tests/MyObserverHandler.cpp @@ -0,0 +1,26 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "MyObserverHandler.h" + +void OC::MyObserverHandler::onObserverUpdate(std::string propertyName, void *value) +{ + +} diff --git a/resource/examples/old_tests/MyObserverHandler.h b/resource/examples/old_tests/MyObserverHandler.h new file mode 100644 index 000000000..25d699157 --- /dev/null +++ b/resource/examples/old_tests/MyObserverHandler.h @@ -0,0 +1,33 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "OCApi.h" +#include "OCObserverHandler.h" + +namespace OC { + +class MyObserverHandler : + public OC::OCObserverHandler +{ +public: + void onObserverUpdate(std::string propertyName, void *value); +}; + +} // namespace OC diff --git a/resource/examples/old_tests/MyResourceHandler.cpp b/resource/examples/old_tests/MyResourceHandler.cpp new file mode 100644 index 000000000..cd6a5110a --- /dev/null +++ b/resource/examples/old_tests/MyResourceHandler.cpp @@ -0,0 +1,107 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +#include + +#include "ocapi.h" +#include "OCReflect.h" +#include "OCObserver.h" +#include "OCException.h" +#include "MyResourceHandler.h" + +void log(const std::string& msg) +{ + std::cerr << msg << '\n'; +} + +MyResourceHandler::MyResourceHandler(void) +{ +} + + +MyResourceHandler::~MyResourceHandler(void) +{ +} + +void MyResourceHandler::onFoundResource(OCResourceResult *update, void *params){ + using OC::OCReflect::entity; + using OC::OCReflect::method; + using OC::OCReflect::remote_resource; + + using OC::bind_observer; + using OC::unbind_observer; + + try + { + //Step1: Find a specific resource that also contains OCReflect byte stream of methods and properties + OCResource myResource; + for ( auto &resource : update->resources ) { + if(resource.getURI() == "/light/a"){ + myResource = resource; + break; + } + } + + //Step2: Find a specific method and invoke it. or Find a specific property and use it. + + // Canonical one-step approach to get a callable function object: + // OCReflect::method throw OC::OCReflect::reflect_exception if there is no setLevel method in the myResource + auto setLevel = OC::OCReflect::method(myResource, "setLevel"); + + setLevel(75, 255); + + // Individual steps-- each may throw on failure: + remote_resource myLight(myResource, "lights/a"); // JFW: this may be subsumed by type OCResource + + entity e_setPowered = myLight("setPowered"); + + method setPowered = OC::OCReflect::narrow(e_setPowered); + + setPowered(true); + + // Canonical one-step approach to access a property: + std::string manufacturer = update->property("manufacturer"); + + // Individual steps: + entity e_manufacturer = myResource.property("manufacturer"); + std::string manufacturer_2 = OC::OCReflect::narrow(e_manufacturer); + + //Example to observe a property + bind_observer(&myObserverHandler, myResource, "PowerState"); + + //Example to unobserve a property + unbind_observer(&myObserverHandler, myResource, "PowerState"); + } + catch(OC::reflection_exception& e) + { + log(e.what()); + } + catch(std::exception& e) + { + log(e.what()); + } +} + +void MyResourceHandler::onCompleted(){ +} + +void MyResourceHandler::onFailed(){ +} diff --git a/resource/examples/old_tests/MyResourceHandler.h b/resource/examples/old_tests/MyResourceHandler.h new file mode 100644 index 000000000..28b9e8823 --- /dev/null +++ b/resource/examples/old_tests/MyResourceHandler.h @@ -0,0 +1,41 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "ocapi.h" +#include "OCResourceHandler.h" +#include "MyObserverHandler.h" + +using namespace OC; + +class MyResourceHandler : + public OCResourceHandler +{ +public: + MyResourceHandler(void); + virtual ~MyResourceHandler(void); + void onFoundResource(OCResourceResult *update, void *params); + void onCompleted(); + void onFailed(); + +private: + MyObserverHandler myObserverHandler; + +}; + diff --git a/resource/examples/old_tests/OCWrapper/makefile b/resource/examples/old_tests/OCWrapper/makefile new file mode 100644 index 000000000..e0b44e4f2 --- /dev/null +++ b/resource/examples/old_tests/OCWrapper/makefile @@ -0,0 +1,64 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +CXX=g++ +CXX_FLAGS=-std=c++0x -Wall -pthread + +final: server client serverApp + +serverApp: InProcServerWrapper.o testServerApp.o ocstack_stub.o OCResource.o InProcClientWrapper.o OCReflect.o OCPlatform.o + $(CXX) $(CXX_FLAGS) -o serverApp InProcServerWrapper.o testServerApp.o ocstack_stub.o OCResource.o InProcClientWrapper.o OCReflect.o OCPlatform.o + +server: InProcServerWrapper.o testServer.o ocstack_stub.o OCResource.o InProcClientWrapper.o OCReflect.o + $(CXX) $(CXX_FLAGS) -o server InProcServerWrapper.o testServer.o ocstack_stub.o OCResource.o InProcClientWrapper.o OCReflect.o + +client: InProcServerWrapper.o testClient.o ocstack_stub.o OCResource.o InProcClientWrapper.o OCReflect.o + $(CXX) $(CXX_FLAGS) -o client InProcServerWrapper.o testClient.o ocstack_stub.o OCResource.o InProcClientWrapper.o OCReflect.o + +OCReflect.o: ../../../OCLib/OCReflect.cpp + $(CXX) $(CXX_FLAGS) -c ../../../OCLib/OCReflect.cpp -I../../../csdk/ -I../../../include -I../ + +OCPlatform.o: ../../../OCLib/OCPlatform.cpp + $(CXX) $(CXX_FLAGS) -c ../../../OCLib/OCPlatform.cpp -I../../../csdk/ -I../../../include/ -I../ -I../client/ -I../server/ + +OCResource.o: ../../../OCLib/OCResource.cpp + $(CXX) $(CXX_FLAGS) -c ../../../OCLib/OCResource.cpp -I../../../csdk/ -I../../../include/ -I../ -I../client/ -I../server/ + +ocstack_stub.o : ../../../csdk/ocstack_stub.c + gcc -c ../../../csdk/ocstack_stub.c -I../../../csdk/ + +InProcServerWrapper.o: ../server/InProcServerWrapper.cpp + $(CXX) $(CXX_FLAGS) -c ../server/InProcServerWrapper.cpp -I../../../csdk/ -I../../../include -I../ + +InProcClientWrapper.o: ../client/InProcClientWrapper.cpp + $(CXX) $(CXX_FLAGS) -c ../client/InProcClientWrapper.cpp -I../../../csdk/ -I../../../include -I../ + +testServer.o : testServer.cpp + $(CXX) $(CXX_FLAGS) -c testServer.cpp -I../../../csdk/ -I../../../include -I../ -I../client/ -I../server/ + +testServerApp.o : testServerApp.cpp + $(CXX) $(CXX_FLAGS) -c testServerApp.cpp -I../../../csdk/ -I../../../include -I../ -I../client/ -I../server/ + +testClient.o : testClient.cpp + $(CXX) $(CXX_FLAGS) -c testClient.cpp -I../../../csdk/ -I../../../include -I../ -I../client/ -I../server/ + +clean: + rm *.o server client serverApp + diff --git a/resource/examples/old_tests/OCWrapper/parsetest.cpp b/resource/examples/old_tests/OCWrapper/parsetest.cpp new file mode 100644 index 000000000..9eb71dacc --- /dev/null +++ b/resource/examples/old_tests/OCWrapper/parsetest.cpp @@ -0,0 +1,120 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include + +using namespace std; +using namespace boost::property_tree; + +void parseResource(ptree resource) +{ + cout<<"\t\tParsing Resource with "<< resource.size() <<" facts:"<("href", "") <("obs",0)==1)<() < +#include +#include +#include + +using namespace OC; + +void testClient() +{ + PlatformConfig cfg; + cfg.ipAddress = "192.168.1.5"; + cfg.port = 8080; + cfg.mode = ModeType::Client; + cfg.serviceType = ServiceType::InProc; + + IWrapperFactory::Ptr pFactory = std::make_shared(); + IClientWrapper::Ptr pWrapper = pFactory->CreateClientWrapper(cfg); +} + +int main() +{ + testClient(); +} diff --git a/resource/examples/old_tests/OCWrapper/testServer.cpp b/resource/examples/old_tests/OCWrapper/testServer.cpp new file mode 100644 index 000000000..986c3a47f --- /dev/null +++ b/resource/examples/old_tests/OCWrapper/testServer.cpp @@ -0,0 +1,97 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace OC; +using namespace OC::OCReflect; + +// Demo of how to generate OCStack stuff: +void rep_test() +{ + using OC::OCReflect::property_type; + using OC::OCReflect::named_property_binding; + + named_property_binding_vector sigs { + named_property_binding("state", property_type::boolean), + named_property_binding("power", property_type::integer), + }; + + using namespace OC::OCReflect::OCStack; + + std::vector reps { convert(sigs) }; + + for(const auto& r : reps) + std::cout << r << '\n'; + + char **LEDrep = convert(reps); + + std::for_each(LEDrep, LEDrep + length(LEDrep), [](const char *s) { std::cout << s << '\n'; }); + + + + + OCEntityHandler entityHandler; + OCResourceHandle resourceHandle; + + OCCreateResource( &resourceHandle, // OCResourceHandle *handl + "core.led", // const char * resourceTypeName + "state:oc.bt.b;power:oc.bt.i", //const char * resourceTypeRepresentation + "core.rw", //const char * resourceInterfaceName + OC_REST_GET | OC_REST_PUT, // uint8_t allowedMethods + "/a/led", // const char * uri + entityHandler, // OCEntityHandler entityHandler + OC_DISCOVERABLE | OC_OBSERVABLE // uint8_t resourceProperties + ); + + + + release(LEDrep); +} + +void testServer() +{ + PlatformConfig cfg; + cfg.ipAddress = "192.168.1.5"; + cfg.port = 8080; + cfg.mode = ModeType::Server; + cfg.serviceType = ServiceType::InProc; + + IWrapperFactory::Ptr pFactory= std::make_shared(); + + IServerWrapper::Ptr pServer = pFactory->CreateServerWrapper(cfg); + + //pServer->bindTo +} + +int main() +{ + rep_test(); + testServer(); +} diff --git a/resource/examples/old_tests/OCWrapper/testServerApp.cpp b/resource/examples/old_tests/OCWrapper/testServerApp.cpp new file mode 100644 index 000000000..3db9871a6 --- /dev/null +++ b/resource/examples/old_tests/OCWrapper/testServerApp.cpp @@ -0,0 +1,131 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// +/// This sample provides steps to define an interface for a resource +/// (properties and methods) and host this resource on the server. +/// + +#include + +#include +#include +#include +#include +#include + +using namespace std; + +using namespace OC; +using namespace OC::OCReflect; + +/// This class represents a single resource named 'light'. This resource has +/// two simple properties named 'state' and 'power' and they have respective setter +/// and getter methods. + +class light +{ +private: + /// Access this property from a TB client + bool m_state; + int m_power; + +public: + light() + : m_power(0), + m_state(false) + {} + +public: + /// Setter method for the setting the power of this light resource + void setPower(int powerValue) + { + m_power = powerValue; + } + + /// Getter method for the getting the power of this light resource + int getPower() const + { + return m_power; + } + + /// Setter method for the setting the state of this light resource + void setState(bool state) + { + m_state = state; + } + + /// Getter method for the getting the state of this light resource + bool getState() const + { + return m_state; + } + +public: + /* Note that this does not need to be a member function: for classes you do not have + access to, you can accomplish this with a free function: */ + + /// This function binds the properties and methods to the server. + void bindTo(OC::OCPlatform& platform) + { + using OC::OCReflect::property_type; + using OC::OCReflect::property_binding; + + property_binding_vector properties { + property_binding("state", property_type::boolean), + property_binding("power", property_type::integer) + }; + + std::string resourceURI = "/a/light"; + std::string resourceTypeName = "light"; + platform.registerResource(resourceURI, resourceTypeName, properties); + } +}; + +int main() +{ + // Step1: Create a OCPlatform instance. + // Step1.1: The constructor of OCPlatform class takes PlatformConfig object. + // Note: Platform creation is synchronous call. + + PlatformConfig cfg; + cfg.ipAddress = "192.168.1.5"; + cfg.port = 8080; + cfg.mode = ModeType::Server; + cfg.serviceType = ServiceType::InProc; + + cout << "Creating OCPlatform .. \n"; + + OCPlatform platform(cfg); + + // Step2: Create the instance of the resource class (in this case instance of class 'light'). + // Step2.1: Invoke bindTo function of class light. + + light myLight; + myLight.bindTo(platform); + + while(true) + { + //some tasks + } + + // No explicit call to stop the platform. + // When OCPlatform destructor is invoked, internally we do platform cleanup +} diff --git a/resource/examples/old_tests/multiple_resources.cpp b/resource/examples/old_tests/multiple_resources.cpp new file mode 100644 index 000000000..f0fc98609 --- /dev/null +++ b/resource/examples/old_tests/multiple_resources.cpp @@ -0,0 +1,264 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// +/// This sample provides steps to define an interface for multiple resources +/// (properties and methods) and host these resources on the server. +/// +#include + +#include "OCServer.h" +#include "OCReflect.h" + +using namespace OC::OCReflect; + +class dimmer +{ +private: + int m_level; + int m_color; + +public: + bool m_powered; // This is an observable property + std::string manufacturer; // This is a non-observable property + +public: + dimmer() + : m_level(0), + m_color(0), + m_powered(false), + manufacturer("Integrated Electronics") + {} + +public: + /// Setter method for the setting the power state of this dimmer resource + void setPowered(const bool newState) + { + m_powered = newState; + } + + /// Getter method for the setting the power state of this dimmer resource + bool getPowered() const + { + return m_powered; + } + + /// Setter method for the setting the intensity level of this dimmer resource + /// Along with above basic method, this method takes two arguments + /// with first argument as intensity level and second level as color. + void setLevel(const int newLevel, int color) + { + m_level = newLevel; + m_color = color; + } + + /// Getter method for getting the intensity level of the dimmer resoruce + int getLevel() const + { + return m_level; + } + + /// Note that this does not need to be a member function: for classes you do not have + /// access to, you can accomplish this with a free function: +public: + void bindTo(OC::OCServer& server, const std::string& base_URI) + { + /*using OC::OCReflect::method_signature; + using OC::OCReflect::method_binding; + using OC::OCReflect::property_signature; + using OC::OCReflect::property_binding; + using OC::OCReflect::bind_service; + using OC::OCReflect::bind_property; + + using OC::OCReflect::property_type;*/ + + // Register the URI with the server + server.registerResource(this, base_URI); + + // Steps to map the property + + // The canonical way to bind a property to a server in one step: + bind_property( + server, // server to bind to + this->manufacturer, // pointer to property + "manufacturer", // property binding name + OC::OCReflect::property_type::string, // property + OC::OCReflect::property_attribute::r // type decoration + ); + + // The canonical way to bind a property to a server in one step: + bind_property( + server, // server to bind to + this->m_powered, // pointer to property + "powerState", // property binding name + OC::OCReflect::property_type::boolean, // property + OC::OCReflect::property_attribute::r // type decoration + ); + + // Steps to map the methods + + // Example to map getPowered method using the canonical way in one step: + bind_service(server, // server to bind to + this, // instance (ourself) to bind + &dimmer::getPowered, // address of the method to bind + "getPowered", // name to bind with service URL + property_type::boolean); // return type of the method + + // Example to map setPowered method using the canonical way in one step: + bind_service(server, // server to bind to + this, // instance (ourself) to bind + &dimmer::setPowered, // address of the method to bind + "setPowered", // name to bind with service URL + property_type::nil, // return type of the method + property_type::boolean); // parameter type for setPowered method + + // Example to map setLevel method using the canonical way in one step: + bind_service( + server, // server to bind with + this, // instance to bind + &dimmer::setLevel, // method to bind + "setLevel", // service name + property_type::nil, // input type + property_type::integer, // parameter list starts (parameter type for level) + property_type::integer); // parameter list (parameter type for color) + + // Example to map getLevel method using the canonical way in one step: + bind_service(server, this, &dimmer::getLevel, "getLevel", property_type::integer); + } +}; + +class door +{ + bool m_locked; + +public: + std::string manufacturer; + +public: + door() + : m_locked(true), + manufacturer("Integrated Electronics") + {} + +public: + /// Setter method for the setting the lock state of this door resource + void setLockState(const bool lockState) + { + m_locked = lockState; + } + + /// Getter method for the setting the lock state of this door resource + bool getLockState() const + { + return m_locked; + } + + /* Note that this does not need to be a member function: for classes you do not have + access to, you can accomplish this with a free function: */ +public: + void bindTo(OC::OCServer& server, const std::string& base_URI) + { + /*using OC::OCReflect::method_signature; + using OC::OCReflect::method_binding; + using OC::OCReflect::property_signature; + using OC::OCReflect::property_binding; + using OC::OCReflect::bind_service; + using OC::OCReflect::bind_property; + + using OC::OCReflect::property_type;*/ + + // Register the URI with the server + server.registerResource(this, base_URI); + + // Steps to map the property + + // The canonical way to bind a property to a server in one step: + bind_property( + server, // server to bind to + this->manufacturer, // pointer to property + "manufacturer", // property binding name + OC::OCReflect::property_type::string, // property + OC::OCReflect::property_attribute::r // type decoration + ); + + // Steps to map the methods + + // Example to map getPowered method using the canonical way in one step: + bind_service(server, // server to bind to + this, // instance (ourself) to bind + &door::getLockState, // address of the method to bind + "getLockState", // name to bind with service URL + property_type::boolean); // return type of the method + + // Example to map setPowered method using the canonical way in one step: + bind_service(server, // server to bind to + this, // instance (ourself) to bind + &door::setLockState, // address of the method to bind + "setLockState", // name to bind with service URL + property_type::nil, // return type of the method + property_type::boolean); // parameter type for setPowered method + } +}; + +class garage +{ +private: + dimmer myDimmer; + door myDoor; + +public: + void bindTo(OC::OCServer& server, const std::string& base_URI) + { + // Register the URI with the server + server.registerResource(this, base_URI); + + // Bind child resource 'dimmer' to the server + myDimmer.bindTo(server, base_URI + "/dimmer/a"); + + // Bind child resource 'door' to the server + myDoor.bindTo(server, base_URI + "/door/a"); + } +}; + +int main() +{ + //Step1: create a server + OC::OCSecurityModel securityModel; + OC::OCServer server; + server.setSecurityModel(securityModel); + + //Step2: Create a Garage resource + garage myGarage; + + //Step3: Bind garage resource to the server + //Note: Garage resource has child resources -- dimmer and door. + myGarage.bindTo(server, "/garage/"); + + //Step4: Start the server + server.start(); + + while(true) + { + //do something here + } + + //Step4: Stop the server + server.stop(); +} diff --git a/resource/examples/presenceclient.cpp b/resource/examples/presenceclient.cpp new file mode 100644 index 000000000..857d0f4b1 --- /dev/null +++ b/resource/examples/presenceclient.cpp @@ -0,0 +1,316 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// PresenceClient.cpp : A client example for presence notification +// +#include +#include +#include +#include +#include + +#include "OCPlatform.h" +#include "OCApi.h" + +using namespace OC; + +std::shared_ptr curResource; + +static int TEST_CASE = 0; + +/** + * List of methods that can be inititated from the client + */ +typedef enum { + TEST_UNICAST_PRESENCE_NORMAL = 1, + TEST_UNICAST_PRESENCE_WITH_FILTER, + TEST_UNICAST_PRESENCE_WITH_FILTERS, + TEST_MULTICAST_PRESENCE_NORMAL, + TEST_MULTICAST_PRESENCE_WITH_FILTER, + TEST_MULTICAST_PRESENCE_WITH_FILTERS, + MAX_TESTS +} CLIENT_TEST; + +void printUsage() +{ + std::cout << "Usage : presenceclient -t <1|2>" << std::endl; + std::cout << "-t 1 : Discover Resources and Initiate Unicast Presence" << std::endl; + std::cout << "-t 2 : Discover Resources and Initiate Unicast Presence with Filter" + << std::endl; + std::cout << "-t 3 : Discover Resources and Initiate Unicast Presence with Two Filters" + << std::endl; + std::cout << "-t 4 : Discover Resources and Initiate Multicast Presence" << std::endl; + std::cout << "-t 5 : Discover Resources and Initiate Multicast Presence with Filter" + << std::endl; + std::cout << "-t 6 : Discover Resources and Initiate Multicast Presence with two Filters" + << std::endl; +} + +// Callback to presence +void presenceHandler(OCStackResult result, const unsigned int nonce, const std::string& hostAddress) +{ + std::cout << "Received presence notification from : " << hostAddress << std::endl; + std::cout << "In presenceHandler: "; + + switch(result) + { + case OC_STACK_OK: + std::cout << "Nonce# " << nonce << std::endl; + break; + case OC_STACK_PRESENCE_STOPPED: + std::cout << "Presence Stopped\n"; + break; + case OC_STACK_PRESENCE_TIMEOUT: + std::cout << "Presence Timeout\n"; + break; + case OC_STACK_VIRTUAL_DO_NOT_HANDLE: + std::cout << "Virtual do not handle\n"; + break; + default: + std::cout << "Error\n"; + break; + } +} + +// Callback to found resources +void foundResource(std::shared_ptr resource) +{ + if(curResource) + { + std::cout << "Found another resource, ignoring"<uri(); + std::cout << "\tURI of the resource: " << resourceURI << std::endl; + + // Get the resource host address + hostAddress = resource->host(); + std::cout << "\tHost address of the resource: " << hostAddress << std::endl; + + // Get the resource types + std::cout << "\tList of resource types: " << std::endl; + for(auto &resourceTypes : resource->getResourceTypes()) + { + std::cout << "\t\t" << resourceTypes << std::endl; + } + + // Get the resource interfaces + std::cout << "\tList of resource interfaces: " << std::endl; + for(auto &resourceInterfaces : resource->getResourceInterfaces()) + { + std::cout << "\t\t" << resourceInterfaces << std::endl; + } + + if(resourceURI == "/a/light") + { + OCStackResult result = OC_STACK_OK; + curResource = resource; + OCPlatform::OCPresenceHandle presenceHandle = nullptr; + + if(TEST_CASE == TEST_UNICAST_PRESENCE_NORMAL) + { + result = OCPlatform::subscribePresence(presenceHandle, hostAddress, + &presenceHandler); + if(result == OC_STACK_OK) + { + std::cout<< "Subscribed to unicast address: " << hostAddress << std::endl; + } + else + { + std::cout<< "Failed to subscribe to unicast address:" << hostAddress + << std::endl; + } + } + if(TEST_CASE == TEST_UNICAST_PRESENCE_WITH_FILTER || + TEST_CASE == TEST_UNICAST_PRESENCE_WITH_FILTERS) + { + result = OCPlatform::subscribePresence(presenceHandle, hostAddress, + "core.light", &presenceHandler); + if(result == OC_STACK_OK) + { + std::cout<< "Subscribed to unicast address: " << hostAddress; + } + else + { + std::cout<< "Failed to subscribe to unicast address: " << hostAddress; + } + std::cout << " with resource type \"core.light\"." << std::endl; + } + if(TEST_CASE == TEST_UNICAST_PRESENCE_WITH_FILTERS) + { + result = OCPlatform::subscribePresence(presenceHandle, hostAddress, "core.fan", + &presenceHandler); + if(result == OC_STACK_OK) + { + std::cout<< "Subscribed to unicast address: " << hostAddress; + } + else + { + std::cout<< "Failed to subscribe to unicast address: " << hostAddress; + } + std::cout << " with resource type \"core.fan\"." << std::endl; + } + } + } + else + { + // Resource is invalid + std::cout << "Resource is invalid" << std::endl; + } + + } + catch(std::exception& e) + { + //log(e.what()); + } +} + +int main(int argc, char* argv[]) { + int opt; + + while ((opt = getopt(argc, argv, "t:")) != -1) + { + switch(opt) + { + case 't': + TEST_CASE = atoi(optarg); + break; + default: + printUsage(); + return -1; + } + } + if(TEST_CASE >= MAX_TESTS || TEST_CASE <= 0) + { + printUsage(); + return -1; + } + + // Create PlatformConfig object + PlatformConfig cfg { + OC::ServiceType::InProc, + OC::ModeType::Client, + "0.0.0.0", + 0, + OC::QualityOfService::LowQos + }; + + OCPlatform::Configure(cfg); + + try + { + std::cout << "Created Platform..."< lock(blocker); + cv.wait(lock); + + }catch(OCException& e) + { + //log(e.what()); + } + + return 0; +} + diff --git a/resource/examples/presenceserver.cpp b/resource/examples/presenceserver.cpp new file mode 100644 index 000000000..18e0d7ec2 --- /dev/null +++ b/resource/examples/presenceserver.cpp @@ -0,0 +1,257 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// +/// This sample provides steps to define an interface for a resource +/// (properties and methods) and host this resource on the server. +/// + +#include + +#include +#include +#include +#include + +#include "OCPlatform.h" +#include "OCApi.h" + +using namespace OC; +using namespace std; + +#define numPresenceResources (2) + +// Forward declaring the entityHandler +OCEntityHandlerResult entityHandler(std::shared_ptr request); + +/// This class represents a single resource named 'lightResource'. This resource has +/// two simple properties named 'state' and 'power' + +class LightResource +{ +public: + /// Access this property from a TB client + bool m_state; + int m_power; + std::string m_lightUri; + std::string m_lightUri2; + std::string m_lightUri3; + OCResourceHandle m_resourceHandle; + OCResourceHandle m_resourceHandle2; + OCResourceHandle m_resourceHandle3; + +public: + /// Constructor + LightResource(): m_state(false), m_power(0), m_lightUri("/a/light"), + m_lightUri2("/a/light2"),m_lightUri3("/a/light3") {} + + /* Note that this does not need to be a member function: for classes you do not have + access to, you can accomplish this with a free function: */ + + /// This function internally calls registerResource API. + void createResource() + { + std::string resourceURI = m_lightUri; // URI of the resource + std::string resourceTypeName = "core.light"; // resource type name. + std::string resourceInterface = DEFAULT_INTERFACE; // resource interface. + + // OCResourceProperty is defined ocstack.h + uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE; + + // This will internally create and register the resource. + OCStackResult result = OCPlatform::registerResource( + m_resourceHandle, resourceURI, resourceTypeName, + resourceInterface, &entityHandler, resourceProperty); + + if (OC_STACK_OK != result) + { + cout << "Resource creation was unsuccessful\n"; + } + } + + /// This function internally calls registerResource API. + void createResource2() + { + std::string resourceURI = m_lightUri2; // URI of the resource + std::string resourceTypeName = "core.light"; // resource type name. In this case, it is light + std::string resourceInterface = DEFAULT_INTERFACE; // resource interface. + + // OCResourceProperty is defined ocstack.h + uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE; + + // This will internally create and register the resource. + OCStackResult result = OCPlatform::registerResource( + m_resourceHandle2, resourceURI, resourceTypeName, + resourceInterface, &entityHandler, resourceProperty); + + if (OC_STACK_OK != result) + { + cout << "Resource creation was unsuccessful\n"; + } + } + + void createResource3() + { + std::string resourceURI = m_lightUri3; // URI of the resource + std::string resourceTypeName = "core.light"; + std::string resourceInterface = DEFAULT_INTERFACE; // resource interface. + + // OCResourceProperty is defined ocstack.h + uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE; + + // This will internally create and register the resource. + OCStackResult result = OCPlatform::registerResource( + m_resourceHandle3, resourceURI, resourceTypeName, + resourceInterface, &entityHandler, resourceProperty); + + if (OC_STACK_OK != result) + { + cout << "Resource creation was unsuccessful\n"; + } + } + + OCResourceHandle getHandle() + { + return m_resourceHandle; + } + + void addType(const std::string& type) const + { + OCStackResult result = OC::OCPlatform::bindTypeToResource(m_resourceHandle, type); + if (OC_STACK_OK != result) + { + cout << "Binding TypeName to Resource was unsuccessful\n"; + } + } + + void addInterface(const std::string& interface) const + { + OCStackResult result = OC::OCPlatform::bindInterfaceToResource(m_resourceHandle, interface); + if (OC_STACK_OK != result) + { + cout << "Binding TypeName to Resource was unsuccessful\n"; + } + } + +}; + +void createPresenceResources() +{ + std::array resourceURI { { + "/a/fan", + "/a/led" } }; + std::array resourceTypeName { { + "core.fan", + "core.led" } }; + + std::string resourceInterface = DEFAULT_INTERFACE; // resource interface. + OCResourceHandle handle; + // OCResourceProperty is defined ocstack.h + uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE; + + // This will internally create and register the resource. + OCStackResult result = OC_STACK_OK; + for(int i=0; i request) +{ + cout << "\tIn Server CPP entity handler:\n"; + return OC_EH_OK; +} + +int main() +{ + // Create PlatformConfig object + PlatformConfig cfg { + OC::ServiceType::InProc, + OC::ModeType::Server, + "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces + 0, // Uses randomly available port + OC::QualityOfService::LowQos + }; + + OCPlatform::Configure(cfg); + try + { + using namespace OC::OCPlatform; + // Time to Live is 30 seconds + startPresence(30); + + // Invoke createResource function of class light. + myLightResource.createResource(); + printf("Created first resource of type \"core.light\""); + + printf("\nEnter a key to create the second resource of type \"core.light\"\n"); + getchar(); + + myLightResource.createResource2(); + + printf("\nEnter a key to stop the presence\n"); + getchar(); + stopPresence(); + + printf("\nEnter a key to restart the presence\n"); + getchar(); + + startPresence(30); + + printf("\nEnter a key to create the third resource of type \"core.light\"\n"); + getchar(); + + myLightResource.createResource3(); + + printf("\nEnter a key to create two non-operational resources.\"\n"); + getchar(); + + createPresenceResources(); + + // A condition variable will free the mutex it is given, then do a non- + // intensive block until 'notify' is called on it. In this case, since we + // don't ever call cv.notify, this should be a non-processor intensive version + // of while(true); + std::mutex blocker; + std::condition_variable cv; + std::unique_lock lock(blocker); + cv.wait(lock); + } + catch(OCException e) + { + //log(e.what()); + } + + // No explicit call to stop the platform. + // When OCPlatform destructor is invoked, internally we do platform cleanup + + return 0; +} diff --git a/resource/examples/roomclient.cpp b/resource/examples/roomclient.cpp new file mode 100644 index 000000000..7e73597a7 --- /dev/null +++ b/resource/examples/roomclient.cpp @@ -0,0 +1,255 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// OCClient.cpp : Defines the entry point for the console application. +// +#include +#include +#include +#include +#include + +#include "OCPlatform.h" +#include "OCApi.h" + +using namespace OC; + +const int SUCCESS_RESPONSE = 0; +std::shared_ptr curResource; + +int observe_count() +{ + static int oc = 0; + return ++oc; +} + +// Forward declaration +void putRoomRepresentation(std::shared_ptr resource); +void onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode); + +void printRoomRepresentation(const OCRepresentation& rep) +{ + std::cout << "\tResource URI: " << rep.getUri() << std::endl; + + if(rep.hasAttribute("name")) + { + std::cout << "\tRoom name: " << rep.getValue("name") << std::endl; + } + + std::vector children = rep.getChildren(); + + for(auto oit = children.begin(); oit != children.end(); ++oit) + { + std::cout << "\t\tChild Resource URI: " << oit->getUri() << std::endl; + if(oit->getUri().find("light") != std::string::npos) + { + if(oit->hasAttribute("state") && oit->hasAttribute("color")) + { + std::cout << "\t\tstate:" << oit->getValue("state") << std::endl; + std::cout << "\t\tcolor:" << oit->getValue("color") << std::endl; + } + } + else if(oit->getUri().find("fan") != std::string::npos) + { + if(oit->hasAttribute("state") && oit->hasAttribute("speed")) + { + std::cout << "\t\tstate:" << oit->getValue("state") << std::endl; + std::cout << "\t\tspeed:" << oit->getValue("speed") << std::endl; + } + } + } +} + +// callback handler on GET request +void onGet(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode) +{ + if(eCode == SUCCESS_RESPONSE) + { + std::cout << "GET request was successful" << std::endl; + + printRoomRepresentation(rep); + + putRoomRepresentation(curResource); + } + else + { + std::cout << "onGET Response error: " << eCode << std::endl; + std::exit(-1); + } +} + +void onGet1(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode) +{ + if(eCode == SUCCESS_RESPONSE) + { + std::cout << "GET request was successful" << std::endl; + + printRoomRepresentation(rep); + } + else + { + std::cout << "onGET Response error: " << eCode << std::endl; + std::exit(-1); + } +} + +// Local function to get representation of room resource +void getRoomRepresentation(std::shared_ptr resource, + std::string interface, GetCallback getCallback) +{ + if(resource) + { + std::cout << "Getting room representation on: "<< interface << std::endl; + + resource->get("core.room", interface, QueryParamsMap(), getCallback); + } +} + +// Local function to put a different state for this resource +void putRoomRepresentation(std::shared_ptr resource) +{ + if(resource) + { + OCRepresentation rep; + std::cout << "Putting room representation on: " << BATCH_INTERFACE << std::endl; + + bool state = true; + int speed = 10; + rep.setValue("state", state); + rep.setValue("speed", speed); + + // Invoke resource's pit API with attribute map, query map and the callback parameter + resource->put("core.room", BATCH_INTERFACE, rep, QueryParamsMap(), &onPut); + } +} + +// callback handler on PUT request +void onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode) +{ + if(eCode == SUCCESS_RESPONSE) + { + std::cout << "PUT request was successful" << std::endl; + + printRoomRepresentation(rep); + + getRoomRepresentation(curResource, DEFAULT_INTERFACE, onGet1); + } + else + { + std::cout << "onPut Response error: " << eCode << std::endl; + std::exit(-1); + } +} + +// Callback to found resources +void foundResource(std::shared_ptr resource) +{ + if(curResource) + { + std::cout << "Found another resource, ignoring"<uri(); + std::cout << "\tURI of the resource: " << resourceURI << std::endl; + + // Get the resource host address + hostAddress = resource->host(); + std::cout << "\tHost address of the resource: " << hostAddress << std::endl; + + // Get the resource types + std::cout << "\tList of resource types: " << std::endl; + for(auto &resourceTypes : resource->getResourceTypes()) + { + std::cout << "\t\t" << resourceTypes << std::endl; + } + + // Get the resource interfaces + std::cout << "\tList of resource interfaces: " << std::endl; + for(auto &resourceInterfaces : resource->getResourceInterfaces()) + { + std::cout << "\t\t" << resourceInterfaces << std::endl; + } + + if(resourceURI == "/a/room") + { + curResource = resource; + // Call a local function which will internally invoke get API on the resource pointer + getRoomRepresentation(resource, BATCH_INTERFACE, onGet); + } + } + else + { + // Resource is invalid + std::cout << "Resource is invalid" << std::endl; + } + + } + catch(std::exception& e) + { + //log(e.what()); + } +} + +int main(int argc, char* argv[]) { + + // Create PlatformConfig object + PlatformConfig cfg { + OC::ServiceType::InProc, + OC::ModeType::Client, + "0.0.0.0", + 0, + OC::QualityOfService::LowQos + }; + + OCPlatform::Configure(cfg); + + try + { + // Find all resources + OCPlatform::findResource("", "coap://224.0.1.187/oc/core", &foundResource); + std::cout<< "Finding Resource... " < lock(blocker); + cv.wait(lock); + + }catch(OCException& e) + { + //log(e.what()); + } + + return 0; +} + diff --git a/resource/examples/roomserver.cpp b/resource/examples/roomserver.cpp new file mode 100644 index 000000000..25c7ee9e8 --- /dev/null +++ b/resource/examples/roomserver.cpp @@ -0,0 +1,604 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// +/// This sample shows how one could create a resource (collection) with children. +/// + +#include + +#include +#include + +#include "OCPlatform.h" +#include "OCApi.h" + +using namespace OC; +using namespace std; + + +// Forward declaring the entityHandler (room) +OCEntityHandlerResult entityHandlerRoom(std::shared_ptr request); +OCEntityHandlerResult entityHandlerLight(std::shared_ptr request); +OCEntityHandlerResult entityHandlerFan(std::shared_ptr request); + +/// Specifies whether default collection entity handler is used or not +bool useDefaultCollectionEH = false; + +class RoomResource +{ +public: + + // Room members + std::string m_roomUri; + std::string m_roomName; + std::vector m_roomTypes; + std::vector m_roomInterfaces; + OCResourceHandle m_roomHandle; + OCRepresentation m_roomRep; + + // light members + bool m_lightState; + int m_lightColor; + std::string m_lightUri; + std::vector m_lightTypes; + std::vector m_lightInterfaces; + OCResourceHandle m_lightHandle; + OCRepresentation m_lightRep; + + // fan members + bool m_fanState; + int m_fanSpeed; + std::string m_fanUri; + std::vector m_fanTypes; + std::vector m_fanInterfaces; + OCResourceHandle m_fanHandle; + OCRepresentation m_fanRep; + +public: + /// Constructor + RoomResource(): m_roomName("John's Room"), m_lightState(false), + m_lightColor(0), m_fanState(false), m_fanSpeed(0) + { + m_lightUri = "/a/light"; // URI of the resource + m_lightTypes.push_back("core.light"); // resource type name. In this case, it is light + m_lightInterfaces.push_back(DEFAULT_INTERFACE); // resource interface. + + m_lightRep.setUri(m_lightUri); + m_lightRep.setResourceTypes(m_lightTypes); + m_lightRep.setResourceInterfaces(m_lightInterfaces); + m_lightRep.setValue("state", m_lightState); + m_lightRep.setValue("color", m_lightColor); + + m_fanUri = "/a/fan"; // URI of the resource + m_fanTypes.push_back("core.fan"); // resource type name. In this case, it is light + m_fanInterfaces.push_back(DEFAULT_INTERFACE); // resource interface. + + m_fanRep.setUri(m_fanUri); + m_fanRep.setResourceTypes(m_fanTypes); + m_fanRep.setResourceInterfaces(m_fanInterfaces); + m_fanRep.setValue("state", m_fanState); + m_fanRep.setValue("speed", m_fanSpeed); + + m_roomUri = "/a/room"; // URI of the resource + m_roomTypes.push_back("core.room"); // resource type name. In this case, it is light + m_roomInterfaces.push_back(DEFAULT_INTERFACE); // resource interface. + m_roomInterfaces.push_back(BATCH_INTERFACE); // resource interface. + m_roomInterfaces.push_back(LINK_INTERFACE); // resource interface. + m_roomRep.setValue("name", m_roomName); + m_roomRep.setUri(m_roomUri); + m_roomRep.setResourceTypes(m_roomTypes); + m_roomRep.setResourceInterfaces(m_roomInterfaces); + } + + /// This function internally calls registerResource API. + void createResources() + { + // This function internally creates and registers the resource. + using namespace OC::OCPlatform; + OCStackResult result = OC_STACK_ERROR; + + // Based on the case, we will use default collection EH (by passing NULL in entity handler + // parameter) or use application entity handler. + if(useDefaultCollectionEH) + { + result = registerResource( + m_roomHandle, m_roomUri, m_roomTypes[0], + m_roomInterfaces[0], NULL, + OC_DISCOVERABLE | OC_OBSERVABLE); + } + else + { + result = registerResource( + m_roomHandle, m_roomUri, m_roomTypes[0], + m_roomInterfaces[0], entityHandlerRoom, + OC_DISCOVERABLE | OC_OBSERVABLE); + } + + if (OC_STACK_OK != result) + { + cout << "Resource creation (room) was unsuccessful\n"; + } + + result = bindInterfaceToResource(m_roomHandle, m_roomInterfaces[1]); + if (OC_STACK_OK != result) + { + cout << "Binding TypeName to Resource was unsuccessful\n"; + } + + result = bindInterfaceToResource(m_roomHandle, m_roomInterfaces[2]); + if (OC_STACK_OK != result) + { + cout << "Binding TypeName to Resource was unsuccessful\n"; + } + + result = registerResource(m_lightHandle, m_lightUri, m_lightTypes[0], + m_lightInterfaces[0], entityHandlerLight, + OC_DISCOVERABLE | OC_OBSERVABLE); + + if (OC_STACK_OK != result) + { + cout << "Resource creation (light) was unsuccessful\n"; + } + + result = registerResource(m_fanHandle, m_fanUri, m_fanTypes[0], + m_fanInterfaces[0], entityHandlerFan, + OC_DISCOVERABLE | OC_OBSERVABLE); + + if (OC_STACK_OK != result) + { + cout << "Resource creation (fan) was unsuccessful\n"; + } + + result = bindResource(m_roomHandle, m_lightHandle); + if (OC_STACK_OK != result) + { + cout << "Binding fan resource to room was unsuccessful\n"; + } + + result = bindResource(m_roomHandle, m_fanHandle); + if (OC_STACK_OK != result) + { + cout << "Binding light resource to room was unsuccessful\n"; + } + + } + + void setLightRepresentation(OCRepresentation& rep) + { + bool tempState = false; + int tempColor = 0; + + // If both entries exist + if(rep.getValue("state", tempState) && rep.getValue("color", tempColor)) + { + m_lightState = tempState; + m_lightColor= tempColor; + + cout << "\t\t\t\t" << "state: " << m_lightState << endl; + cout << "\t\t\t\t" << "color: " << m_lightColor << endl; + } + } + + void setFanRepresentation(OCRepresentation& rep) + { + bool tempState = false; + int tempSpeed = 0; + + // If both entries exist + if(rep.getValue("state", tempState) && rep.getValue("speed", tempSpeed)) + { + m_fanState = tempState; + m_fanSpeed = tempSpeed; + + cout << "\t\t\t\t" << "state: " << m_fanState << endl; + cout << "\t\t\t\t" << "speed: " << m_fanSpeed << endl; + } + } + + + OCRepresentation getLightRepresentation() + { + m_lightRep.setValue("state", m_lightState); + m_lightRep.setValue("color", m_lightColor); + + return m_lightRep; + } + + OCRepresentation getFanRepresentation() + { + m_fanRep.setValue("state", m_fanState); + m_fanRep.setValue("speed", m_fanSpeed); + return m_fanRep; + } + + OCRepresentation getRoomRepresentation(void) + { + m_roomRep.clearChildren(); + + m_roomRep.addChild(getLightRepresentation()); + m_roomRep.addChild(getFanRepresentation()); + return m_roomRep; + } + +}; + +// Create the instance of the resource class (in this case instance of class 'RoomResource'). +RoomResource myRoomResource; + +OCStackResult sendRoomResponse(std::shared_ptr pRequest) +{ + auto pResponse = std::make_shared(); + pResponse->setRequestHandle(pRequest->getRequestHandle()); + pResponse->setResourceHandle(pRequest->getResourceHandle()); + + // Check for query params (if any) + QueryParamsMap queryParamsMap = pRequest->getQueryParameters(); + + cout << "\t\t\tquery params: \n"; + for(auto it = queryParamsMap.begin(); it != queryParamsMap.end(); it++) + { + cout << "\t\t\t\t" << it->first << ":" << it->second << endl; + } + + OCRepresentation rep; + rep = myRoomResource.getRoomRepresentation(); + + auto findRes = queryParamsMap.find("if"); + + if(findRes != queryParamsMap.end()) + { + pResponse->setResourceRepresentation(rep, findRes->second); + } + else + { + pResponse->setResourceRepresentation(rep, DEFAULT_INTERFACE); + } + + pResponse->setErrorCode(200); + pResponse->setResponseResult(OC_EH_OK); + + return OCPlatform::sendResponse(pResponse); +} + +// This function prepares a response for any incoming request to Light resource. +bool prepareLightResponse(std::shared_ptr request) +{ + cout << "\tIn Server CPP (Light) prepareLightResponse:\n"; + bool result = false; + if(request) + { + // Get the request type and request flag + std::string requestType = request->getRequestType(); + int requestFlag = request->getRequestHandlerFlag(); + + if(requestFlag == RequestHandlerFlag::InitFlag) + { + cout << "\t\trequestFlag : Init\n"; + + // entity handler to perform resource initialization operations + } + else if(requestFlag == RequestHandlerFlag::RequestFlag) + { + cout << "\t\trequestFlag : Request\n"; + + // If the request type is GET + if(requestType == "GET") + { + cout << "\t\t\trequestType : GET\n"; + // GET operations are directly handled while sending the response + // in the sendLightResponse function + result = true; + } + else if(requestType == "PUT") + { + cout << "\t\t\trequestType : PUT\n"; + OCRepresentation rep = request->getResourceRepresentation(); + + // Do related operations related to PUT request + myRoomResource.setLightRepresentation(rep); + result= true; + } + else if(requestType == "POST") + { + // POST request operations + } + else if(requestType == "DELETE") + { + // DELETE request operations + } + } + else if(requestFlag == RequestHandlerFlag::ObserverFlag) + { + cout << "\t\trequestFlag : Observer\n"; + } + } + else + { + std::cout << "Request invalid" << std::endl; + } + + return result; +} + +// This function prepares a response for any incoming request to Fan resource. +bool prepareFanResponse(std::shared_ptr request) +{ + cout << "\tIn Server CPP (Fan) prepareFanResponse:\n"; + bool result = false; + + if(request) + { + // Get the request type and request flag + std::string requestType = request->getRequestType(); + int requestFlag = request->getRequestHandlerFlag(); + + if(requestFlag == RequestHandlerFlag::InitFlag) + { + cout << "\t\trequestFlag : Init\n"; + + // entity handler to perform resource initialization operations + } + else if(requestFlag == RequestHandlerFlag::RequestFlag) + { + cout << "\t\trequestFlag : Request\n"; + + // If the request type is GET + if(requestType == "GET") + { + cout << "\t\t\trequestType : GET\n"; + // GET operations are directly handled while sending the response + // in the sendLightResponse function + result = true; + } + else if(requestType == "PUT") + { + cout << "\t\t\trequestType : PUT\n"; + + OCRepresentation rep = request->getResourceRepresentation(); + + // Do related operations related to PUT request + myRoomResource.setFanRepresentation(rep); + result = true; + } + else if(requestType == "POST") + { + // POST request operations + } + else if(requestType == "DELETE") + { + // DELETE request operations + } + } + else if(requestFlag == RequestHandlerFlag::ObserverFlag) + { + cout << "\t\trequestFlag : Observer\n"; + } + } + else + { + std::cout << "Request invalid" << std::endl; + } + + return result; +} + +OCEntityHandlerResult entityHandlerRoom(std::shared_ptr request) +{ + cout << "\tIn Server CPP entity handler:\n"; + OCEntityHandlerResult ehResult = OC_EH_ERROR; + + if(request) + { + // Get the request type and request flag + std::string requestType = request->getRequestType(); + int requestFlag = request->getRequestHandlerFlag(); + + if(requestFlag == RequestHandlerFlag::InitFlag) + { + cout << "\t\trequestFlag : Init\n"; + + // entity handler to perform resource initialization operations + } + else if(requestFlag == RequestHandlerFlag::RequestFlag) + { + cout << "\t\trequestFlag : Request\n"; + + // If the request type is GET + if(requestType == "GET") + { + cout << "\t\t\trequestType : GET\n"; + if(OC_STACK_OK == sendRoomResponse(request)) + { + ehResult = OC_EH_OK; + } + } + else if(requestType == "PUT") + { + cout << "\t\t\trequestType : PUT\n"; + // Call these functions to prepare the response for child resources and + // then send the final response using sendRoomResponse function + prepareLightResponse(request); + prepareFanResponse(request); + if(OC_STACK_OK == sendRoomResponse(request)) + { + ehResult = OC_EH_OK; + } + } + else if(requestType == "POST") + { + // POST request operations + } + else if(requestType == "DELETE") + { + // DELETE request operations + } + } + else if(requestFlag == RequestHandlerFlag::ObserverFlag) + { + cout << "\t\trequestFlag : Observer\n"; + } + } + else + { + std::cout << "Request invalid" << std::endl; + } + + return ehResult; +} + +OCStackResult sendLightResponse(std::shared_ptr pRequest) +{ + auto pResponse = std::make_shared(); + pResponse->setRequestHandle(pRequest->getRequestHandle()); + pResponse->setResourceHandle(pRequest->getResourceHandle()); + pResponse->setResourceRepresentation(myRoomResource.getLightRepresentation()); + pResponse->setErrorCode(200); + pResponse->setResponseResult(OC_EH_OK); + + return OCPlatform::sendResponse(pResponse); +} + + + +OCEntityHandlerResult entityHandlerLight(std::shared_ptr request) +{ + cout << "\tIn Server CPP (Light) entity handler:\n"; + OCEntityHandlerResult ehResult = OC_EH_ERROR; + + if(prepareLightResponse(request)) + { + if(OC_STACK_OK == sendLightResponse(request)) + { + ehResult = OC_EH_OK; + } + else + { + std::cout << "sendLightResponse failed." << std::endl; + } + } + else + { + std::cout << "PrepareLightResponse failed." << std::endl; + } + return ehResult; +} + +OCStackResult sendFanResponse(std::shared_ptr pRequest) +{ + auto pResponse = std::make_shared(); + pResponse->setRequestHandle(pRequest->getRequestHandle()); + pResponse->setResourceHandle(pRequest->getResourceHandle()); + pResponse->setResourceRepresentation(myRoomResource.getFanRepresentation()); + pResponse->setErrorCode(200); + pResponse->setResponseResult(OC_EH_OK); + + return OCPlatform::sendResponse(pResponse); +} + + +OCEntityHandlerResult entityHandlerFan(std::shared_ptr request) +{ + cout << "\tIn Server CPP (Fan) entity handler:\n"; + OCEntityHandlerResult ehResult = OC_EH_ERROR; + if(prepareFanResponse(request)) + { + if(OC_STACK_OK == sendFanResponse(request)) + { + ehResult = OC_EH_OK; + } + else + { + std::cout << "sendFanResponse failed." << std::endl; + } + } + else + { + std::cout << "PrepareFanResponse failed." << std::endl; + } + + return ehResult; +} + +void printUsage() +{ + std::cout << std::endl; + std::cout << "Usage : roomserver \n"; + std::cout << "1 : Create room resource with default collection entity handler.\n"; + std::cout << "2 : Create room resource with application collection entity handler.\n"; +} + +int main(int argc, char* argv[]) +{ + printUsage(); + + if(argc == 2) + { + int value = atoi(argv[1]); + switch (value) + { + case 1: + useDefaultCollectionEH = true; + break; + case 2: + default: + break; + } + } + else + { + return -1; + } + + // Create PlatformConfig object + PlatformConfig cfg { + OC::ServiceType::InProc, + OC::ModeType::Server, + "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces + 0, // Uses randomly available port + OC::QualityOfService::LowQos + }; + + OCPlatform::Configure(cfg); + try + { + + myRoomResource.createResources(); + + // A condition variable will free the mutex it is given, then do a non- + // intensive block until 'notify' is called on it. In this case, since we + // don't ever call cv.notify, this should be a non-processor intensive version + // of while(true); + std::mutex blocker; + std::condition_variable cv; + std::unique_lock lock(blocker); + cv.wait(lock); + + } + catch(OCException e) + { + std::cout << "Exception in main: " << e.what(); + } + + // No explicit call to stop the platform. + // When OCPlatform destructor is invoked, internally we do platform cleanup + + return 0; +} diff --git a/resource/examples/simpleclient.cpp b/resource/examples/simpleclient.cpp new file mode 100644 index 000000000..85c0dc16e --- /dev/null +++ b/resource/examples/simpleclient.cpp @@ -0,0 +1,393 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// OCClient.cpp : Defines the entry point for the console application. +// +#include +#include +#include +#include +#include + +#include "OCPlatform.h" +#include "OCApi.h" + +using namespace OC; + +std::shared_ptr curResource; +static ObserveType OBSERVE_TYPE_TO_USE = ObserveType::Observe; + +class Light +{ +public: + + bool m_state; + int m_power; + std::string m_name; + + Light() : m_state(false), m_power(0), m_name("") + { + } +}; + +Light mylight; + +int observe_count() +{ + static int oc = 0; + return ++oc; +} + +void onObserve(const HeaderOptions headerOptions, const OCRepresentation& rep, + const int& eCode, const int& sequenceNumber) +{ + if(eCode == OC_STACK_OK) + { + std::cout << "OBSERVE RESULT:"< 30) + { + std::cout<<"Cancelling Observe..."<cancelObserve(); + + std::cout << "Cancel result: "<< result <("createduri") << std::endl; + } + else + { + rep.getValue("state", mylight.m_state); + rep.getValue("power", mylight.m_power); + rep.getValue("name", mylight.m_name); + + std::cout << "\tstate: " << mylight.m_state << std::endl; + std::cout << "\tpower: " << mylight.m_power << std::endl; + std::cout << "\tname: " << mylight.m_name << std::endl; + } + + if (OBSERVE_TYPE_TO_USE == ObserveType::Observe) + std::cout << endl << "Observe is used." << endl << endl; + else if (OBSERVE_TYPE_TO_USE == ObserveType::ObserveAll) + std::cout << endl << "ObserveAll is used." << endl << endl; + + curResource->observe(OBSERVE_TYPE_TO_USE, QueryParamsMap(), &onObserve); + + } + else + { + std::cout << "onPost2 Response error: " << eCode << std::endl; + std::exit(-1); + } +} + +void onPost(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode) +{ + if(eCode == OC_STACK_OK || eCode == OC_STACK_RESOURCE_CREATED) + { + std::cout << "POST request was successful" << std::endl; + + if(rep.hasAttribute("createduri")) + { + std::cout << "\tUri of the created resource: " + << rep.getValue("createduri") << std::endl; + } + else + { + rep.getValue("state", mylight.m_state); + rep.getValue("power", mylight.m_power); + rep.getValue("name", mylight.m_name); + + std::cout << "\tstate: " << mylight.m_state << std::endl; + std::cout << "\tpower: " << mylight.m_power << std::endl; + std::cout << "\tname: " << mylight.m_name << std::endl; + } + + OCRepresentation rep2; + + std::cout << "Posting light representation..."<post(rep2, QueryParamsMap(), &onPost2); + } + else + { + std::cout << "onPost Response error: " << eCode << std::endl; + std::exit(-1); + } +} + +// Local function to put a different state for this resource +void postLightRepresentation(std::shared_ptr resource) +{ + if(resource) + { + OCRepresentation rep; + + std::cout << "Posting light representation..."<post(rep, QueryParamsMap(), &onPost); + } +} + +// callback handler on PUT request +void onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode) +{ + if(eCode == OC_STACK_OK) + { + std::cout << "PUT request was successful" << std::endl; + + rep.getValue("state", mylight.m_state); + rep.getValue("power", mylight.m_power); + rep.getValue("name", mylight.m_name); + + std::cout << "\tstate: " << mylight.m_state << std::endl; + std::cout << "\tpower: " << mylight.m_power << std::endl; + std::cout << "\tname: " << mylight.m_name << std::endl; + + postLightRepresentation(curResource); + } + else + { + std::cout << "onPut Response error: " << eCode << std::endl; + std::exit(-1); + } +} + +// Local function to put a different state for this resource +void putLightRepresentation(std::shared_ptr resource) +{ + if(resource) + { + OCRepresentation rep; + + std::cout << "Putting light representation..."<put(rep, QueryParamsMap(), &onPut); + } +} + +// Callback handler on GET request +void onGet(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode) +{ + if(eCode == OC_STACK_OK) + { + std::cout << "GET request was successful" << std::endl; + std::cout << "Resource URI: " << rep.getUri() << std::endl; + + rep.getValue("state", mylight.m_state); + rep.getValue("power", mylight.m_power); + rep.getValue("name", mylight.m_name); + + std::cout << "\tstate: " << mylight.m_state << std::endl; + std::cout << "\tpower: " << mylight.m_power << std::endl; + std::cout << "\tname: " << mylight.m_name << std::endl; + + putLightRepresentation(curResource); + } + else + { + std::cout << "onGET Response error: " << eCode << std::endl; + std::exit(-1); + } +} + +// Local function to get representation of light resource +void getLightRepresentation(std::shared_ptr resource) +{ + if(resource) + { + std::cout << "Getting Light Representation..."<get(test, &onGet); + } +} + +// Callback to found resources +void foundResource(std::shared_ptr resource) +{ + if(curResource) + { + std::cout << "Found another resource, ignoring"<uri(); + std::cout << "\tURI of the resource: " << resourceURI << std::endl; + + // Get the resource host address + hostAddress = resource->host(); + std::cout << "\tHost address of the resource: " << hostAddress << std::endl; + + // Get the resource types + std::cout << "\tList of resource types: " << std::endl; + for(auto &resourceTypes : resource->getResourceTypes()) + { + std::cout << "\t\t" << resourceTypes << std::endl; + } + + // Get the resource interfaces + std::cout << "\tList of resource interfaces: " << std::endl; + for(auto &resourceInterfaces : resource->getResourceInterfaces()) + { + std::cout << "\t\t" << resourceInterfaces << std::endl; + } + + if(resourceURI == "/a/light") + { + curResource = resource; + // Call a local function which will internally invoke get API on the resource pointer + getLightRepresentation(resource); + } + } + else + { + // Resource is invalid + std::cout << "Resource is invalid" << std::endl; + } + + } + catch(std::exception& e) + { + //log(e.what()); + } +} + +void PrintUsage() +{ + std::cout << std::endl; + std::cout << "Usage : simpleclient " << std::endl; + std::cout << " ObserveType : 1 - Observe" << std::endl; + std::cout << " ObserveType : 2 - ObserveAll" << std::endl; +} + +int main(int argc, char* argv[]) { + if (argc == 1) + { + OBSERVE_TYPE_TO_USE = ObserveType::Observe; + } + else if (argc == 2) + { + int value = atoi(argv[1]); + if (value == 1) + OBSERVE_TYPE_TO_USE = ObserveType::Observe; + else if (value == 2) + OBSERVE_TYPE_TO_USE = ObserveType::ObserveAll; + else + OBSERVE_TYPE_TO_USE = ObserveType::Observe; + } + else + { + PrintUsage(); + return -1; + } + + // Create PlatformConfig object + PlatformConfig cfg { + OC::ServiceType::InProc, + OC::ModeType::Client, + "0.0.0.0", + 0, + OC::QualityOfService::LowQos + }; + + OCPlatform::Configure(cfg); + try + { + // makes it so that all boolean values are printed as 'true/false' in this stream + std::cout.setf(std::ios::boolalpha); + // Find all resources + OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.light", &foundResource); + std::cout<< "Finding Resource... " < lock(blocker); + cv.wait(lock); + + }catch(OCException& e) + { + //log(e.what()); + } + + return 0; +} + diff --git a/resource/examples/simpleclientHQ.cpp b/resource/examples/simpleclientHQ.cpp new file mode 100644 index 000000000..e3a6f2cdb --- /dev/null +++ b/resource/examples/simpleclientHQ.cpp @@ -0,0 +1,407 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// OCClient.cpp : Defines the entry point for the console application. +// +#include +#include +#include +#include +#include + +#include "OCPlatform.h" +#include "OCApi.h" + +using namespace OC; + +const int SUCCESS_RESPONSE = 0; +std::shared_ptr curResource; +static ObserveType OBSERVE_TYPE_TO_USE = ObserveType::Observe; + +class Light +{ +public: + + bool m_state; + int m_power; + std::string m_name; + + Light() : m_state(false), m_power(0), m_name("") + { + } +}; + +Light mylight; + +int observe_count() +{ + static int oc = 0; + return ++oc; +} + +void onObserve(const HeaderOptions headerOptions, const OCRepresentation& rep, + const int& eCode, const int& sequenceNumber) +{ + if(eCode == SUCCESS_RESPONSE) + { + std::cout << "OBSERVE RESULT:"< 30) + { + std::cout<<"Cancelling Observe..."<cancelObserve(OC::QualityOfService::HighQos); + + std::cout << "Cancel result: "<< result << " waiting for confirmation ..." <("createduri") << std::endl; + } + else + { + rep.getValue("state", mylight.m_state); + rep.getValue("power", mylight.m_power); + rep.getValue("name", mylight.m_name); + + std::cout << "\tstate: " << mylight.m_state << std::endl; + std::cout << "\tpower: " << mylight.m_power << std::endl; + std::cout << "\tname: " << mylight.m_name << std::endl; + } + + if (OBSERVE_TYPE_TO_USE == ObserveType::Observe) + std::cout << endl << "Observe is used." << endl << endl; + else if (OBSERVE_TYPE_TO_USE == ObserveType::ObserveAll) + std::cout << endl << "ObserveAll is used." << endl << endl; + sleep(1); + curResource->observe(OBSERVE_TYPE_TO_USE, QueryParamsMap(), &onObserve, + OC::QualityOfService::HighQos); + + } + else + { + std::cout << "onPost2 Response error: " << eCode << std::endl; + std::exit(-1); + } +} + +void onPost(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode) +{ + if(eCode == SUCCESS_RESPONSE) + { + std::cout << "POST request was successful" << std::endl; + + if(rep.hasAttribute("createduri")) + { + std::cout << "\tUri of the created resource: " + << rep.getValue("createduri") << std::endl; + } + else + { + rep.getValue("state", mylight.m_state); + rep.getValue("power", mylight.m_power); + rep.getValue("name", mylight.m_name); + + std::cout << "\tstate: " << mylight.m_state << std::endl; + std::cout << "\tpower: " << mylight.m_power << std::endl; + std::cout << "\tname: " << mylight.m_name << std::endl; + } + + OCRepresentation rep2; + + std::cout << "Posting light representation..."<post(rep2, QueryParamsMap(), &onPost2, OC::QualityOfService::HighQos); + } + else + { + std::cout << "onPost Response error: " << eCode << std::endl; + std::exit(-1); + } +} + +// Local function to put a different state for this resource +void postLightRepresentation(std::shared_ptr resource) +{ + if(resource) + { + OCRepresentation rep; + + std::cout << "Posting light representation..."<post(rep, QueryParamsMap(), &onPost, OC::QualityOfService::HighQos); + } +} + +// callback handler on PUT request +void onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode) +{ + if(eCode == SUCCESS_RESPONSE) + { + std::cout << "PUT request was successful" << std::endl; + + rep.getValue("state", mylight.m_state); + rep.getValue("power", mylight.m_power); + rep.getValue("name", mylight.m_name); + + std::cout << "\tstate: " << mylight.m_state << std::endl; + std::cout << "\tpower: " << mylight.m_power << std::endl; + std::cout << "\tname: " << mylight.m_name << std::endl; + sleep(1); + postLightRepresentation(curResource); + } + else + { + std::cout << "onPut Response error: " << eCode << std::endl; + std::exit(-1); + } +} + +// Local function to put a different state for this resource +void putLightRepresentation(std::shared_ptr resource) +{ + if(resource) + { + OCRepresentation rep; + + std::cout << "Putting light representation..."<put(rep, QueryParamsMap(), &onPut, OC::QualityOfService::HighQos); + } +} + +// Callback handler on GET request +void onGet(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode) +{ + if(eCode == SUCCESS_RESPONSE) + { + std::cout << "GET request was successful" << std::endl; + std::cout << "Resource URI: " << rep.getUri() << std::endl; + + rep.getValue("state", mylight.m_state); + rep.getValue("power", mylight.m_power); + rep.getValue("name", mylight.m_name); + + std::cout << "\tstate: " << mylight.m_state << std::endl; + std::cout << "\tpower: " << mylight.m_power << std::endl; + std::cout << "\tname: " << mylight.m_name << std::endl; + sleep(1); + putLightRepresentation(curResource); + } + else + { + std::cout << "onGET Response error: " << eCode << std::endl; + std::exit(-1); + } +} + +// Local function to get representation of light resource +void getLightRepresentation(std::shared_ptr resource) +{ + if(resource) + { + std::cout << "Getting Light Representation..."<get(test, &onGet,OC::QualityOfService::HighQos); + } +} + +// Callback to found resources +void foundResource(std::shared_ptr resource) +{ + if(curResource) + { + std::cout << "Found another resource, ignoring"<uri(); + std::cout << "\tURI of the resource: " << resourceURI << std::endl; + + // Get the resource host address + hostAddress = resource->host(); + std::cout << "\tHost address of the resource: " << hostAddress << std::endl; + + // Get the resource types + std::cout << "\tList of resource types: " << std::endl; + for(auto &resourceTypes : resource->getResourceTypes()) + { + std::cout << "\t\t" << resourceTypes << std::endl; + } + + // Get the resource interfaces + std::cout << "\tList of resource interfaces: " << std::endl; + for(auto &resourceInterfaces : resource->getResourceInterfaces()) + { + std::cout << "\t\t" << resourceInterfaces << std::endl; + } + + if(resourceURI == "/a/light") + { + curResource = resource; + sleep(1); + // Call a local function which will internally invoke get API on the resource pointer + getLightRepresentation(resource); + } + } + else + { + // Resource is invalid + std::cout << "Resource is invalid" << std::endl; + } + + } + catch(std::exception& e) + { + //log(e.what()); + } +} + +void PrintUsage() +{ + std::cout << std::endl; + std::cout << "Usage : simpleclient " << std::endl; + std::cout << " ObserveType : 1 - Observe" << std::endl; + std::cout << " ObserveType : 2 - ObserveAll" << std::endl; +} + +int main(int argc, char* argv[]) { + if (argc == 1) + { + OBSERVE_TYPE_TO_USE = ObserveType::Observe; + } + else if (argc == 2) + { + int value = atoi(argv[1]); + if (value == 1) + OBSERVE_TYPE_TO_USE = ObserveType::Observe; + else if (value == 2) + OBSERVE_TYPE_TO_USE = ObserveType::ObserveAll; + else + OBSERVE_TYPE_TO_USE = ObserveType::Observe; + } + else + { + PrintUsage(); + return -1; + } + + // Create PlatformConfig object + PlatformConfig cfg { + OC::ServiceType::InProc, + OC::ModeType::Client, + "0.0.0.0", + 0, + OC::QualityOfService::LowQos + }; + + OCPlatform::Configure(cfg); + + try + { + // Find all resources + OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.light", &foundResource, + OC::QualityOfService::LowQos); + std::cout<< "Finding Resource... " < lock(blocker); + cv.wait(lock); + + }catch(OCException& e) + { + //log(e.what()); + } + + return 0; +} + diff --git a/resource/examples/simpleclientserver.cpp b/resource/examples/simpleclientserver.cpp new file mode 100644 index 000000000..d3ee18ba6 --- /dev/null +++ b/resource/examples/simpleclientserver.cpp @@ -0,0 +1,322 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// +/// This sample provides steps to define an interface for a resource +/// (properties and methods) and host this resource on the server. +/// Additionally, it'll have a client example to discover it as well. +/// +#include +#include +#include +#include +#include +#include +#include "OCPlatform.h" +#include "OCApi.h" +using namespace OC; + +class ClientWorker +{ +private: + bool m_isFoo; + int m_barCount; + void putResourceInfo(const HeaderOptions& headerOptions, + const OCRepresentation rep, const OCRepresentation rep2, const int eCode) + { + std::cout << "In PutResourceInfo" << std::endl; + + std::cout <<"Clientside Put response to get was: "<put(rep2, QueryParamsMap(), + PutCallback(std::bind(&ClientWorker::putResourceInfo, this, std::placeholders::_1, + rep2, std::placeholders::_2, std::placeholders::_3))); + } + } + + void foundResource(std::shared_ptr resource) + { + std::cout << "In foundResource" << std::endl; + if(resource && resource->uri() == "/q/foo") + { + { + std::lock_guard lock(m_resourceLock); + if(m_resource) + { + return; + } + + m_resource = resource; + } + + std::cout << "Found Resource: "<host()<uri()<getResourceTypes()) + { + std::cout << "\t\t" << resourceTypes << std::endl; + } + + // Get the resource interfaces + std::cout << "\tList of resource interfaces: " << std::endl; + for(auto &resourceInterfaces : resource->getResourceInterfaces()) + { + std::cout << "\t\t" << resourceInterfaces << std::endl; + } + + std::cout<<"Doing a get on q/foo."<get(QueryParamsMap(), + GetCallback(std::bind(&ClientWorker::getResourceInfo, this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3))); + } + } + +public: + void start() + { + std::cout<<"Starting Client find:"< lk(m_mutex); + m_cv.wait(lk); + } + } +private: + std::mutex m_mutex; + std::mutex m_resourceLock; + std::condition_variable m_cv; + std::shared_ptr m_resource; +}; + +struct FooResource +{ + bool m_isFoo; + int m_barCount; + OCResourceHandle m_resourceHandle; + OCRepresentation m_rep; + + FooResource(): m_isFoo(true), m_barCount (0) + { + m_rep.setUri("/q/foo"); + m_rep.setValue("isFoo", m_isFoo); + m_rep.setValue("barCount", m_barCount); + } + + bool createResource() + { + std::string resourceURI = "/q/foo"; + std::string resourceTypeName = "core.foo"; + std::string resourceInterface = DEFAULT_INTERFACE; + + uint8_t resourceProperty = OC_DISCOVERABLE; + + EntityHandler eh(std::bind(&FooResource::entityHandler, + this, std::placeholders::_1)); + OCStackResult result = OCPlatform::registerResource(m_resourceHandle, + resourceURI, resourceTypeName, + resourceInterface, + eh, resourceProperty); + if(OC_STACK_OK != result) + { + std::cout<<"Resource creation unsuccessful"< pRequest) + { + auto pResponse = std::make_shared(); + pResponse->setRequestHandle(pRequest->getRequestHandle()); + pResponse->setResourceHandle(pRequest->getResourceHandle()); + pResponse->setResourceRepresentation(get(), ""); + pResponse->setErrorCode(200); + pResponse->setResponseResult(OC_EH_OK); + + return OCPlatform::sendResponse(pResponse); + } + + OCEntityHandlerResult entityHandler(std::shared_ptr request) + { + std::cout<<"\tConsumer Entity Handler:"<getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag) + { + std::cout << "\t\trequestFlag : Request"<getRequestType() == "GET") + { + std::cout<<"\t\t\trequestType : GET"<getRequestType() == "PUT") + { + std::cout<<"\t\t\trequestType : PUT"<getResourceRepresentation(); + put(rep); + if(OC_STACK_OK == sendResponse(request)) + { + ehResult = OC_EH_OK; + } + } + else + { + std::cout<<"\t\t\trequestType : UNSUPPORTED: "<< + request->getRequestType()<getRequestHandlerFlag()==RequestHandlerFlag::InitFlag) + { + std::cout<<"InitFlag"<getRequestHandlerFlag()== RequestHandlerFlag::ObserverFlag) + { + std::cout<<"ObserverFlag"< + +#include +#include +#include + +#include "OCPlatform.h" +#include "OCApi.h" + +using namespace OC; +using namespace std; +namespace PH = std::placeholders; + +int gObservation = 0; +void * ChangeLightRepresentation (void *param); +void * handleSlowResponse (void *param, std::shared_ptr pRequest); + +// Specifies where to notify all observers or list of observers +// false: notifies all observers +// true: notifies list of observers +bool isListOfObservers = false; + +// Specifies secure or non-secure +// false: non-secure resource +// true: secure resource +bool isSecure = false; + +/// Specifies whether Entity handler is going to do slow response or not +bool isSlowResponse = false; + +// Forward declaring the entityHandler + +/// This class represents a single resource named 'lightResource'. This resource has +/// two simple properties named 'state' and 'power' + +class LightResource +{ + +public: + /// Access this property from a TB client + std::string m_name; + bool m_state; + int m_power; + std::string m_lightUri; + OCResourceHandle m_resourceHandle; + OCRepresentation m_lightRep; + ObservationIds m_interestedObservers; + +public: + /// Constructor + LightResource() + :m_name("John's light"), m_state(false), m_power(0), m_lightUri("/a/light") { + // Initialize representation + m_lightRep.setUri(m_lightUri); + + m_lightRep.setValue("state", m_state); + m_lightRep.setValue("power", m_power); + m_lightRep.setValue("name", m_name); + } + + /* Note that this does not need to be a member function: for classes you do not have + access to, you can accomplish this with a free function: */ + + /// This function internally calls registerResource API. + void createResource() + { + std::string resourceURI = m_lightUri; //URI of the resource + std::string resourceTypeName = "core.light"; //resource type name. In this case, it is light + std::string resourceInterface = DEFAULT_INTERFACE; // resource interface. + + // OCResourceProperty is defined ocstack.h + uint8_t resourceProperty; + if(isSecure) + { + resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE | OC_SECURE; + } + else + { + resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE; + } + EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1); + + // This will internally create and register the resource. + OCStackResult result = OCPlatform::registerResource( + m_resourceHandle, resourceURI, resourceTypeName, + resourceInterface, cb, resourceProperty); + + if (OC_STACK_OK != result) + { + cout << "Resource creation was unsuccessful\n"; + } + } + + OCStackResult createResource1() + { + std::string resourceURI = "/a/light1"; // URI of the resource + std::string resourceTypeName = "core.light"; // resource type name. In this case, it is light + std::string resourceInterface = DEFAULT_INTERFACE; // resource interface. + + // OCResourceProperty is defined ocstack.h + uint8_t resourceProperty; + if(isSecure) + { + resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE | OC_SECURE; + } + else + { + resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE; + } + EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1); + + OCResourceHandle resHandle; + + // This will internally create and register the resource. + OCStackResult result = OCPlatform::registerResource( + resHandle, resourceURI, resourceTypeName, + resourceInterface, cb, resourceProperty); + + if (OC_STACK_OK != result) + { + cout << "Resource creation was unsuccessful\n"; + } + + return result; + } + + OCResourceHandle getHandle() + { + return m_resourceHandle; + } + + // Puts representation. + // Gets values from the representation and + // updates the internal state + void put(OCRepresentation& rep) + { + try { + if (rep.getValue("state", m_state)) + { + cout << "\t\t\t\t" << "state: " << m_state << endl; + } + else + { + cout << "\t\t\t\t" << "state not found in the representation" << endl; + } + + if (rep.getValue("power", m_power)) + { + cout << "\t\t\t\t" << "power: " << m_power << endl; + } + else + { + cout << "\t\t\t\t" << "power not found in the representation" << endl; + } + } + catch (exception& e) + { + cout << e.what() << endl; + } + + } + + // Post representation. + // Post can create new resource or simply act like put. + // Gets values from the representation and + // updates the internal state + OCRepresentation post(OCRepresentation& rep) + { + static int first = 1; + + // for the first time it tries to create a resource + if(first) + { + first = 0; + + if(OC_STACK_OK == createResource1()) + { + OCRepresentation rep1; + rep1.setValue("createduri", std::string("/a/light1")); + + return rep1; + } + } + + // from second time onwards it just puts + put(rep); + return get(); + } + + + // gets the updated representation. + // Updates the representation with latest internal state before + // sending out. + OCRepresentation get() + { + m_lightRep.setValue("state", m_state); + m_lightRep.setValue("power", m_power); + + return m_lightRep; + } + + void addType(const std::string& type) const + { + OCStackResult result = OCPlatform::bindTypeToResource(m_resourceHandle, type); + if (OC_STACK_OK != result) + { + cout << "Binding TypeName to Resource was unsuccessful\n"; + } + } + + void addInterface(const std::string& interface) const + { + OCStackResult result = OCPlatform::bindInterfaceToResource(m_resourceHandle, interface); + if (OC_STACK_OK != result) + { + cout << "Binding TypeName to Resource was unsuccessful\n"; + } + } + +private: +// This is just a sample implementation of entity handler. +// Entity handler can be implemented in several ways by the manufacturer +OCEntityHandlerResult entityHandler(std::shared_ptr request) +{ + cout << "\tIn Server CPP entity handler:\n"; + OCEntityHandlerResult ehResult = OC_EH_ERROR; + if(request) + { + // Get the request type and request flag + std::string requestType = request->getRequestType(); + int requestFlag = request->getRequestHandlerFlag(); + + if(requestFlag & RequestHandlerFlag::InitFlag) + { + cout << "\t\trequestFlag : Init\n"; + + // entity handler to perform resource initialization operations + } + if(requestFlag & RequestHandlerFlag::RequestFlag) + { + cout << "\t\trequestFlag : Request\n"; + auto pResponse = std::make_shared(); + pResponse->setRequestHandle(request->getRequestHandle()); + pResponse->setResourceHandle(request->getResourceHandle()); + + // If the request type is GET + if(requestType == "GET") + { + cout << "\t\t\trequestType : GET\n"; + if(isSlowResponse) // Slow response case + { + static int startedThread = 0; + if(!startedThread) + { + std::thread t(handleSlowResponse, (void *)this, request); + startedThread = 1; + t.detach(); + } + ehResult = OC_EH_SLOW; + } + else // normal response case. + { + pResponse->setErrorCode(200); + pResponse->setResponseResult(OC_EH_OK); + pResponse->setResourceRepresentation(get()); + if(OC_STACK_OK == OCPlatform::sendResponse(pResponse)) + { + ehResult = OC_EH_OK; + } + } + } + else if(requestType == "PUT") + { + cout << "\t\t\trequestType : PUT\n"; + OCRepresentation rep = request->getResourceRepresentation(); + + // Do related operations related to PUT request + // Update the lightResource + put(rep); + pResponse->setErrorCode(200); + pResponse->setResponseResult(OC_EH_OK); + pResponse->setResourceRepresentation(get()); + if(OC_STACK_OK == OCPlatform::sendResponse(pResponse)) + { + ehResult = OC_EH_OK; + } + } + else if(requestType == "POST") + { + cout << "\t\t\trequestType : POST\n"; + + OCRepresentation rep = request->getResourceRepresentation(); + + // Do related operations related to POST request + OCRepresentation rep_post = post(rep); + pResponse->setResourceRepresentation(rep_post); + pResponse->setErrorCode(200); + if(rep_post.hasAttribute("createduri")) + { + pResponse->setResponseResult(OC_EH_RESOURCE_CREATED); + pResponse->setNewResourceUri(rep_post.getValue("createduri")); + } + + if(OC_STACK_OK == OCPlatform::sendResponse(pResponse)) + { + ehResult = OC_EH_OK; + } + } + else if(requestType == "DELETE") + { + // DELETE request operations + } + } + + if(requestFlag & RequestHandlerFlag::ObserverFlag) + { + ObservationInfo observationInfo = request->getObservationInfo(); + if(ObserveAction::ObserveRegister == observationInfo.action) + { + m_interestedObservers.push_back(observationInfo.obsId); + } + else if(ObserveAction::ObserveUnregister == observationInfo.action) + { + m_interestedObservers.erase(std::remove( + m_interestedObservers.begin(), + m_interestedObservers.end(), + observationInfo.obsId), + m_interestedObservers.end()); + } + + pthread_t threadId; + + cout << "\t\trequestFlag : Observer\n"; + gObservation = 1; + static int startedThread = 0; + + // Observation happens on a different thread in ChangeLightRepresentation function. + // If we have not created the thread already, we will create one here. + if(!startedThread) + { + pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)this); + startedThread = 1; + } + ehResult = OC_EH_OK; + } + } + else + { + std::cout << "Request invalid" << std::endl; + } + + return ehResult; +} + +}; + +// ChangeLightRepresentaion is an observation function, +// which notifies any changes to the resource to stack +// via notifyObservers +void * ChangeLightRepresentation (void *param) +{ + LightResource* lightPtr = (LightResource*) param; + + // This function continuously monitors for the changes + while (1) + { + sleep (5); + + if (gObservation) + { + // If under observation if there are any changes to the light resource + // we call notifyObservors + // + // For demostration we are changing the power value and notifying. + lightPtr->m_power += 10; + + cout << "\nPower updated to : " << lightPtr->m_power << endl; + cout << "Notifying observers with resource handle: " << lightPtr->getHandle() << endl; + + OCStackResult result = OC_STACK_OK; + + if(isListOfObservers) + { + std::shared_ptr resourceResponse(new OCResourceResponse()); + + resourceResponse->setErrorCode(200); + resourceResponse->setResourceRepresentation(lightPtr->get(), DEFAULT_INTERFACE); + + result = OCPlatform::notifyListOfObservers( lightPtr->getHandle(), + lightPtr->m_interestedObservers, + resourceResponse); + } + else + { + result = OCPlatform::notifyAllObservers(lightPtr->getHandle()); + } + + if(OC_STACK_NO_OBSERVERS == result) + { + cout << "No More observers, stopping notifications" << endl; + gObservation = 0; + } + } + } + + return NULL; +} + +void * handleSlowResponse (void *param, std::shared_ptr pRequest) +{ + // This function handles slow response case + LightResource* lightPtr = (LightResource*) param; + // Induce a case for slow response by using sleep + std::cout << "SLOW response" << std::endl; + sleep (10); + + auto pResponse = std::make_shared(); + pResponse->setRequestHandle(pRequest->getRequestHandle()); + pResponse->setResourceHandle(pRequest->getResourceHandle()); + pResponse->setResourceRepresentation(lightPtr->get()); + pResponse->setErrorCode(200); + pResponse->setResponseResult(OC_EH_OK); + + // Set the slow response flag back to false + isSlowResponse = false; + OCPlatform::sendResponse(pResponse); + return NULL; +} + +void PrintUsage() +{ + std::cout << std::endl; + std::cout << "Usage : simpleserver \n"; + std::cout << " Default - Non-secure resource and notify all observers\n"; + std::cout << " 1 - Non-secure resource and notify list of observers\n\n"; + std::cout << " 2 - Secure resource and notify all observers\n"; + std::cout << " 3 - Secure resource and notify list of observers\n\n"; + std::cout << " 4 - Non-secure resource, GET slow response, notify all observers\n"; +} + + +int main(int argc, char* argv[]) +{ + PrintUsage(); + + if (argc == 1) + { + isListOfObservers = false; + isSecure = false; + } + else if (argc == 2) + { + int value = atoi(argv[1]); + switch (value) + { + case 1: + isListOfObservers = true; + isSecure = false; + break; + case 2: + isListOfObservers = false; + isSecure = true; + break; + case 3: + isListOfObservers = true; + isSecure = true; + break; + case 4: + isSlowResponse = true; + default: + break; + } + } + else + { + return -1; + } + + // Create PlatformConfig object + PlatformConfig cfg { + OC::ServiceType::InProc, + OC::ModeType::Server, + "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces + 0, // Uses randomly available port + OC::QualityOfService::LowQos + }; + + OCPlatform::Configure(cfg); + try + { + // Create the instance of the resource class + // (in this case instance of class 'LightResource'). + LightResource myLight; + + // Invoke createResource function of class light. + myLight.createResource(); + + myLight.addType(std::string("core.brightlight")); + myLight.addInterface(std::string("oc.mi.ll")); + + // A condition variable will free the mutex it is given, then do a non- + // intensive block until 'notify' is called on it. In this case, since we + // don't ever call cv.notify, this should be a non-processor intensive version + // of while(true); + std::mutex blocker; + std::condition_variable cv; + std::unique_lock lock(blocker); + cv.wait(lock); + } + catch(OCException e) + { + //log(e.what()); + } + + // No explicit call to stop the platform. + // When OCPlatform::destructor is invoked, internally we do platform cleanup + + return 0; +} diff --git a/resource/examples/simpleserverHQ.cpp b/resource/examples/simpleserverHQ.cpp new file mode 100644 index 000000000..cf0d09a87 --- /dev/null +++ b/resource/examples/simpleserverHQ.cpp @@ -0,0 +1,480 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// +/// This sample provides steps to define an interface for a resource +/// (properties and methods) and host this resource on the server. +/// + +#include + +#include +#include +#include + +#include "OCPlatform.h" +#include "OCApi.h" + +using namespace OC; +using namespace std; +namespace PH = std::placeholders; + +int gObservation = 0; +void * ChangeLightRepresentation (void *param); + +// Specifies where to notify all observers or list of observers +// 0 - notifies all observers +// 1 - notifies list of observers +int isListOfObservers = 0; + +/// This class represents a single resource named 'lightResource'. This resource has +/// two simple properties named 'state' and 'power' + +class LightResource +{ + +public: + /// Access this property from a TB client + std::string m_name; + bool m_state; + int m_power; + std::string m_lightUri; + OCResourceHandle m_resourceHandle; + OCRepresentation m_lightRep; + ObservationIds m_interestedObservers; + +public: + /// Constructor + LightResource(PlatformConfig& cfg) + :m_name("John's light"), m_state(false), m_power(0), m_lightUri("/a/light") { + // Initialize representation + m_lightRep.setUri(m_lightUri); + + m_lightRep.setValue("state", m_state); + m_lightRep.setValue("power", m_power); + m_lightRep.setValue("name", m_name); + } + + /* Note that this does not need to be a member function: for classes you do not have + access to, you can accomplish this with a free function: */ + + /// This function internally calls registerResource API. + void createResource() + { + std::string resourceURI = m_lightUri; // URI of the resource + std::string resourceTypeName = "core.light"; // resource type name. In this case, it is light + std::string resourceInterface = DEFAULT_INTERFACE; // resource interface. + + // OCResourceProperty is defined ocstack.h + uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE; + + EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1); + + // This will internally create and register the resource. + OCStackResult result = OCPlatform::registerResource( + m_resourceHandle, resourceURI, resourceTypeName, + resourceInterface, cb, resourceProperty); + + if (OC_STACK_OK != result) + { + cout << "Resource creation was unsuccessful\n"; + } + } + + OCStackResult createResource1() + { + std::string resourceURI = "/a/light1"; // URI of the resource + std::string resourceTypeName = "core.light"; // resource type name. In this case, it is light + std::string resourceInterface = DEFAULT_INTERFACE; // resource interface. + + // OCResourceProperty is defined ocstack.h + uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE; + + EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1); + + OCResourceHandle resHandle; + + // This will internally create and register the resource. + OCStackResult result = OCPlatform::registerResource( + resHandle, resourceURI, resourceTypeName, + resourceInterface, cb, resourceProperty); + + if (OC_STACK_OK != result) + { + cout << "Resource creation was unsuccessful\n"; + } + + return result; + } + + OCResourceHandle getHandle() + { + return m_resourceHandle; + } + + // Puts representation. + // Gets values from the representation and + // updates the internal state + void put(OCRepresentation& rep) + { + try { + if (rep.getValue("state", m_state)) + { + cout << "\t\t\t\t" << "state: " << m_state << endl; + } + else + { + cout << "\t\t\t\t" << "state not found in the representation" << endl; + } + + if (rep.getValue("power", m_power)) + { + cout << "\t\t\t\t" << "power: " << m_power << endl; + } + else + { + cout << "\t\t\t\t" << "power not found in the representation" << endl; + } + } + catch (exception& e) + { + cout << e.what() << endl; + } + + } + + // Post representation. + // Post can create new resource or simply act like put. + // Gets values from the representation and + // updates the internal state + OCRepresentation post(OCRepresentation& rep) + { + static int first = 1; + + std::cout << "In POST\n"; + + // for the first time it tries to create a resource + if(first) + { + std::cout << "In POST/First\n"; + + first = 0; + + if(OC_STACK_OK == createResource1()) + { + std::cout << "Created a new resource\n"; + OCRepresentation rep1; + rep1.setValue("createduri", std::string("/a/light1")); + + return rep1; + } + } + + // from second time onwards it just puts + put(rep); + return get(); + } + + + // gets the updated representation. + // Updates the representation with latest internal state before + // sending out. + OCRepresentation get() + { + m_lightRep.setValue("state", m_state); + m_lightRep.setValue("power", m_power); + + return m_lightRep; + } + + void addType(const std::string& type) const + { + OCStackResult result = OCPlatform::bindTypeToResource(m_resourceHandle, type); + if (OC_STACK_OK != result) + { + cout << "Binding TypeName to Resource was unsuccessful\n"; + } + } + + void addInterface(const std::string& interface) const + { + OCStackResult result = OCPlatform::bindInterfaceToResource(m_resourceHandle, interface); + if (OC_STACK_OK != result) + { + cout << "Binding TypeName to Resource was unsuccessful\n"; + } + } + +private: + +OCStackResult sendResponse(std::shared_ptr pRequest) +{ + auto pResponse = std::make_shared(); + pResponse->setRequestHandle(pRequest->getRequestHandle()); + pResponse->setResourceHandle(pRequest->getResourceHandle()); + pResponse->setResourceRepresentation(get()); + pResponse->setErrorCode(200); + pResponse->setResponseResult(OC_EH_OK); + + return OCPlatform::sendResponse(pResponse); +} + +OCStackResult sendPostResponse(std::shared_ptr pRequest) +{ + auto pResponse = std::make_shared(); + pResponse->setRequestHandle(pRequest->getRequestHandle()); + pResponse->setResourceHandle(pRequest->getResourceHandle()); + + OCRepresentation rep = pRequest->getResourceRepresentation(); + OCRepresentation rep_post = post(rep); + + pResponse->setResourceRepresentation(rep_post); + pResponse->setErrorCode(200); + pResponse->setResponseResult(OC_EH_OK); + + return OCPlatform::sendResponse(pResponse); +} + +// This is just a sample implementation of entity handler. +// Entity handler can be implemented in several ways by the manufacturer +OCEntityHandlerResult entityHandler(std::shared_ptr request) +{ + cout << "\tIn Server CPP entity handler:\n"; + OCEntityHandlerResult ehResult = OC_EH_ERROR; + + if(request) + { + // Get the request type and request flag + std::string requestType = request->getRequestType(); + int requestFlag = request->getRequestHandlerFlag(); + + if(requestFlag & RequestHandlerFlag::InitFlag) + { + cout << "\t\trequestFlag : Init\n"; + // entity handler to perform resource initialization operations + } + if(requestFlag & RequestHandlerFlag::RequestFlag) + { + cout << "\t\trequestFlag : Request\n"; + + // If the request type is GET + if(requestType == "GET") + { + cout << "\t\t\trequestType : GET\n"; + if(OC_STACK_OK == sendResponse(request)) + { + ehResult = OC_EH_OK; + } + } + else if(requestType == "PUT") + { + cout << "\t\t\trequestType : PUT\n"; + + OCRepresentation rep = request->getResourceRepresentation(); + // Do related operations related to PUT request + // Update the lightResource + put(rep); + if(OC_STACK_OK == sendResponse(request)) + { + ehResult = OC_EH_OK; + } + } + else if(requestType == "POST") + { + cout << "\t\t\trequestType : POST\n"; + if(OC_STACK_OK == sendPostResponse(request)) + { + ehResult = OC_EH_OK; + } + } + else if(requestType == "DELETE") + { + // DELETE request operations + } + } + + if(requestFlag & RequestHandlerFlag::ObserverFlag) + { + ObservationInfo observationInfo = request->getObservationInfo(); + if(ObserveAction::ObserveRegister == observationInfo.action) + { + m_interestedObservers.push_back(observationInfo.obsId); + } + else if(ObserveAction::ObserveUnregister == observationInfo.action) + { + m_interestedObservers.erase(std::remove( + m_interestedObservers.begin(), + m_interestedObservers.end(), + observationInfo.obsId), + m_interestedObservers.end()); + } + + pthread_t threadId; + + cout << "\t\trequestFlag : Observer\n"; + gObservation = 1; + static int startedThread = 0; + + // Observation happens on a different thread in ChangeLightRepresentation function. + // If we have not created the thread already, we will create one here. + if(!startedThread) + { + pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)this); + startedThread = 1; + } + ehResult = OC_EH_OK; + } + } + else + { + std::cout << "Request invalid" << std::endl; + } + + return ehResult; +} + +}; + +// ChangeLightRepresentaion is an observation function, +// which notifies any changes to the resource to stack +// via notifyObservers +void * ChangeLightRepresentation (void *param) +{ + LightResource* lightPtr = (LightResource*) param; + + // This function continuously monitors for the changes + while (1) + { + sleep (5); + + if (gObservation) + { + // If under observation if there are any changes to the light resource + // we call notifyObservors + // + // For demostration we are changing the power value and notifying. + lightPtr->m_power += 10; + + cout << "\nPower updated to : " << lightPtr->m_power << endl; + cout << "Notifying observers with resource handle: " << lightPtr->getHandle() << endl; + + OCStackResult result = OC_STACK_OK; + + if(isListOfObservers) + { + std::shared_ptr resourceResponse(new OCResourceResponse()); + + resourceResponse->setErrorCode(200); + resourceResponse->setResourceRepresentation(lightPtr->get(), DEFAULT_INTERFACE); + + result = OCPlatform::notifyListOfObservers( + lightPtr->getHandle(), + lightPtr->m_interestedObservers, + resourceResponse, + OC::QualityOfService::HighQos); + } + else + { + result = OCPlatform::notifyAllObservers(lightPtr->getHandle(), + OC::QualityOfService::HighQos); + } + + if(OC_STACK_NO_OBSERVERS == result) + { + cout << "No More observers, stopping notifications" << endl; + gObservation = 0; + } + } + } + + return NULL; +} + +void PrintUsage() +{ + std::cout << std::endl; + std::cout << "Usage : simplserver \n"; + std::cout << " ObserveType : 0 - Observe All\n"; + std::cout << " ObserveType : 1 - Observe List of observers\n\n"; +} + + +int main(int argc, char* argv[]) +{ + PrintUsage(); + + if (argc == 1) + { + isListOfObservers = 0; + } + else if (argc == 2) + { + int value = atoi(argv[1]); + if (value == 1) + isListOfObservers = 1; + else + isListOfObservers = 0; + } + else + { + return -1; + } + + // Create PlatformConfig object + PlatformConfig cfg { + OC::ServiceType::InProc, + OC::ModeType::Server, + "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces + 0, // Uses randomly available port + OC::QualityOfService::LowQos + }; + + OCPlatform::Configure(cfg); + + try + { + // Create the instance of the resource class (in this case instance of class 'LightResource'). + LightResource myLight(cfg); + + // Invoke createResource function of class light. + myLight.createResource(); + + myLight.addType(std::string("core.brightlight")); + myLight.addInterface(std::string("oc.mi.ll")); + + // A condition variable will free the mutex it is given, then do a non- + // intensive block until 'notify' is called on it. In this case, since we + // don't ever call cv.notify, this should be a non-processor intensive version + // of while(true); + std::mutex blocker; + std::condition_variable cv; + std::unique_lock lock(blocker); + cv.wait(lock); + } + catch(OCException e) + { + //log(e.what()); + } + + // No explicit call to stop the platform. + // When OCPlatform destructor is invoked, internally we do platform cleanup + + return 0; +} diff --git a/resource/examples/threadingsample.cpp b/resource/examples/threadingsample.cpp new file mode 100644 index 000000000..ff556e285 --- /dev/null +++ b/resource/examples/threadingsample.cpp @@ -0,0 +1,384 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// +/// This sample demonstrates : running one server in main thread, another +/// server in a separate thread, and running 2 clients in each thread. +/// + + +#include +#include +#include +#include +#include +#include +#include "OCPlatform.h" +#include "OCApi.h" +using namespace OC; + + +struct FooResource +{ + bool m_isFoo; + int m_barCount; + std::string m_uri; + std::string m_resourceType; + OCResourceHandle m_resourceHandle; + OCRepresentation m_rep; + + FooResource(std::string uri): m_isFoo(true), m_barCount (0), + m_uri(uri), m_resourceType("core.foo") + { + m_rep.setUri(m_uri); + m_rep.setValue("isFoo", m_isFoo); + m_rep.setValue("barCount", m_barCount); + } + + bool createResource() + { + std::string resourceInterface = DEFAULT_INTERFACE; + + uint8_t resourceProperty = OC_DISCOVERABLE; + + EntityHandler eh(std::bind(&FooResource::entityHandler, this, + std::placeholders::_1)); + OCStackResult result = OCPlatform::registerResource(m_resourceHandle, m_uri, + m_resourceType, resourceInterface, eh, resourceProperty); + if(OC_STACK_OK != result) + { + std::cout<<"Resource creation unsuccessful"< pRequest) + { + auto pResponse = std::make_shared(); + pResponse->setRequestHandle(pRequest->getRequestHandle()); + pResponse->setResourceHandle(pRequest->getResourceHandle()); + pResponse->setResourceRepresentation(get(), ""); + pResponse->setErrorCode(200); + pResponse->setResponseResult(OC_EH_OK); + + return OCPlatform::sendResponse(pResponse); + } + + OCEntityHandlerResult entityHandler(std::shared_ptr request) + { + std::cout<<"\tConsumer Entity Handler:"<getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag) + { + std::cout << "\t\trequestFlag : Request"<getRequestType() == "GET") + { + std::cout<<"\t\t\trequestType : GET"<getRequestType() == "PUT") + { + std::cout<<"\t\t\trequestType : PUT"<getResourceRepresentation(); + put(rep); + if(OC_STACK_OK == sendResponse(request)) + { + ehResult = OC_EH_OK; + } + } + else + { + std::cout<<"\t\t\trequestType : UNSUPPORTED: " << + request->getRequestType()<getRequestHandlerFlag()==RequestHandlerFlag::InitFlag) + { + std::cout<<"InitFlag"<getRequestHandlerFlag()== RequestHandlerFlag::ObserverFlag) + { + std::cout<<"ObserverFlag"< resource, const HeaderOptions& headerOptions, + const OCRepresentation rep, + const int eCode) +{ + bool m_isFoo = false; + int m_barCount = 0; + std::cout << "In getResourceInfo" << std::endl; + + std::cout<<"Clientside response to get was: "<put(rep2, QueryParamsMap(), + PutCallback(std::bind(putResourceInfo, std::placeholders::_1, + rep2, std::placeholders::_2, std::placeholders::_3))); + } +} + +void printResourceInfo(std::shared_ptr resource) +{ + std::cout << "Found Resource: "<host()<uri()<getResourceTypes()) + { + std::cout << "\t\t" << resourceTypes << std::endl; + } + + // Get the resource interfaces + std::cout << "\tList of resource interfaces: " << std::endl; + for(auto &resourceInterfaces : resource->getResourceInterfaces()) + { + std::cout << "\t\t" << resourceInterfaces << std::endl; + } +} + +void foundResource2(std::shared_ptr resource) +{ + std::cout << "In foundResource2:" << std::endl; + + if(resource && resource->uri() == "/q/foo2") + { + printResourceInfo(resource); + + std::cout<<"Doing a get on q/foo."<get(QueryParamsMap(), + GetCallback(std::bind(getResourceInfo, resource, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3))); + } + else + { + std::cout << "foundResource2: Ignoring the resource which doesn't have uri /q/foo2\n"; + } +} + +void foundResource1(std::shared_ptr resource) +{ + std::cout << "In foundResource1:" << std::endl; + if(resource && resource->uri() == "/q/foo1") + { + printResourceInfo(resource); + } + else + { + std::cout << "foundResource1: Ignoring the resource which doesn't have uri /q/foo1\n"; + } +} + +void client1() +{ + std::cout << "in client1\n"; + + std::cout<<"result1:" << OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.foo", + foundResource1)<< std::endl; + + // A condition variable will free the mutex it is given, then do a non- + // intensive block until 'notify' is called on it. In this case, since we + // don't ever call cv.notify, this should be a non-processor intensive version + // of while(true); + std::mutex blocker; + std::condition_variable cv; + std::unique_lock lock(blocker); + cv.wait(lock); +} + +void client2() +{ + std::cout << "in client2\n"; + + std::cout<<"result2:" << OCPlatform::findResource("", + "coap://224.0.1.187/oc/core?rt=core.foo", + foundResource2)<< std::endl; + + // A condition variable will free the mutex it is given, then do a non- + // intensive block until 'notify' is called on it. In this case, since we + // don't ever call cv.notify, this should be a non-processor intensive version + // of while(true); + std::mutex blocker; + std::condition_variable cv; + std::unique_lock lock(blocker); + cv.wait(lock); +} + +void server() +{ + FooResource fooRes("/q/foo2"); + + if(!fooRes.createResource()) + { + return; + } + + // A condition variable will free the mutex it is given, then do a non- + // intensive block until 'notify' is called on it. In this case, since we + // don't ever call cv.notify, this should be a non-processor intensive version + // of while(true); + std::mutex blocker; + std::condition_variable cv; + std::unique_lock lock(blocker); + cv.wait(lock); +} + +int main() +{ + PlatformConfig cfg { + OC::ServiceType::InProc, + OC::ModeType::Both, + "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces + 0, // Uses randomly available port + OC::QualityOfService::LowQos + }; + + OCPlatform::Configure(cfg); + + try + { + // main thread running as server + FooResource fooRes("/q/foo1"); + if(!fooRes.createResource()) + { + return -1; + } + + // Start a server in a seperate thread + std::thread t(server); + t.detach(); + + sleep(10); + + // Start each client in a seperate thread + std::thread t1(client1); + t1.detach(); + + // Start each client in a seperate thread + std::thread t2(client2); + t2.detach(); + + // A condition variable will free the mutex it is given, then do a non- + // intensive block until 'notify' is called on it. In this case, since we + // don't ever call cv.notify, this should be a non-processor intensive version + // of while(true); + std::mutex blocker; + std::condition_variable cv; + std::unique_lock lock(blocker); + cv.wait(lock); + } + catch(OCException& e) + { + std::cout<< "Exception in main: "< + +namespace OC +{ + class OCRepresentation; + + struct NullType{}; + // Since null needs to be encoded in a special fashion in JSON, the encoder + // needs to know the index of the NullType Sentinel Any time the code does a special + // case for the NullType, we use the AttributeValueNullIndex. This MUST be kept up to date + // with the variant's which() for NullType. + static const int AttributeValueNullIndex = 0; + typedef boost::variant< + + // Base values: + NullType, // Note: this handles the null-type and must match the above static const + int, + double, + bool, + std::string, + OC::OCRepresentation, + + // Sequences: + std::vector, + std::vector, + std::vector, + std::vector, + std::vector, + + // Nested sequences: + std::vector>, + std::vector>>, + + std::vector>, + std::vector>>, + + std::vector>, + std::vector>>, + + std::vector>, + std::vector>>, + + std::vector>, + std::vector>> + > AttributeValue; + +} +#endif // __ATTRIBUTEVALUE_H diff --git a/resource/include/IClientWrapper.h b/resource/include/IClientWrapper.h new file mode 100644 index 000000000..1e40e2311 --- /dev/null +++ b/resource/include/IClientWrapper.h @@ -0,0 +1,89 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef _I_CLIENT_WRAPPER_H_ +#define _I_CLIENT_WRAPPER_H_ + +#include +#include + +#include + +namespace OC +{ + class OCPlatform_impl; + + class IClientWrapper : public std::enable_shared_from_this + { + protected: + + public: + typedef std::shared_ptr Ptr; + + IClientWrapper() + {} + + virtual OCStackResult ListenForResource(const std::string& serviceUrl, + const std::string& resourceType, FindCallback& callback, + QualityOfService QoS) = 0; + + virtual OCStackResult ListenForDevice(const std::string& serviceUrl, + const std::string& deviceURI, FindDeviceCallback& callback, + QualityOfService QoS) = 0; + + virtual OCStackResult GetResourceRepresentation(const std::string& host, + const std::string& uri, const QueryParamsMap& queryParams, + const HeaderOptions& headerOptions, + GetCallback& callback, QualityOfService QoS)=0; + + virtual OCStackResult PutResourceRepresentation(const std::string& host, + const std::string& uri, const OCRepresentation& rep, + const QueryParamsMap& queryParams, const HeaderOptions& headerOptions, + PutCallback& callback, QualityOfService QoS) = 0; + + virtual OCStackResult PostResourceRepresentation(const std::string& host, + const std::string& uri, const OCRepresentation& rep, + const QueryParamsMap& queryParams, const HeaderOptions& headerOptions, + PostCallback& callback, QualityOfService QoS) = 0; + + virtual OCStackResult DeleteResource(const std::string& host, const std::string& uri, + const HeaderOptions& headerOptions, DeleteCallback& callback, + QualityOfService QoS) = 0; + + virtual OCStackResult ObserveResource(ObserveType observeType, OCDoHandle* handle, + const std::string& host, const std::string& uri, + const QueryParamsMap& queryParams, const HeaderOptions& headerOptions, + ObserveCallback& callback, QualityOfService QoS)=0; + + virtual OCStackResult CancelObserveResource(OCDoHandle handle, const std::string& host, + const std::string& uri, const HeaderOptions& headerOptions, QualityOfService QoS)=0; + + virtual OCStackResult SubscribePresence(OCDoHandle* handle, const std::string& host, + const std::string& resourceType, SubscribeCallback& presenceHandler)=0; + + virtual OCStackResult UnsubscribePresence(OCDoHandle handle) =0; + + virtual OCStackResult GetDefaultQos(QualityOfService& qos) = 0; + + virtual ~IClientWrapper(){} + }; +} + +#endif diff --git a/resource/include/IServerWrapper.h b/resource/include/IServerWrapper.h new file mode 100644 index 000000000..c6c0b2d72 --- /dev/null +++ b/resource/include/IServerWrapper.h @@ -0,0 +1,86 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef _I_SERVER_WRAPPER_H_ +#define _I_SERVER_WRAPPER_H_ + +#include +#include + +#include +#include +#include +#include + +namespace OC +{ + class IServerWrapper + { + protected: + + public: + typedef std::shared_ptr Ptr; + + IServerWrapper() + {} + + virtual ~IServerWrapper(){}; + + virtual OCStackResult registerResource( + OCResourceHandle& resourceHandle, + std::string& resourceURI, + const std::string& resourceTypeName, + const std::string& resourceInterface, + EntityHandler& entityHandler, + uint8_t resourceProperty) = 0; + + virtual OCStackResult registerDeviceInfo( + const OCDeviceInfo deviceInfo) = 0; + + virtual OCStackResult registerResourceWithHost( + OCResourceHandle& resourceHandle, + std::string& resourceHOST, + std::string& resourceURI, + const std::string& resourceTypeName, + const std::string& resourceInterface, + EntityHandler& entityHandler, + uint8_t resourceProperty) = 0; + + virtual OCStackResult unregisterResource( + const OCResourceHandle& resourceHandle) = 0; + virtual OCStackResult bindTypeToResource( + const OCResourceHandle& resourceHandle, + const std::string& resourceTypeName) = 0; + + virtual OCStackResult bindInterfaceToResource( + const OCResourceHandle& resourceHandle, + const std::string& resourceInterfaceName) = 0; + + virtual OCStackResult startPresence(const unsigned int seconds) = 0; + + virtual OCStackResult stopPresence() = 0; + + virtual OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler) = 0; + + virtual OCStackResult sendResponse(const std::shared_ptr pResponse) = 0; + }; +} + +#endif diff --git a/resource/include/InProcClientWrapper.h b/resource/include/InProcClientWrapper.h new file mode 100644 index 000000000..ced111d44 --- /dev/null +++ b/resource/include/InProcClientWrapper.h @@ -0,0 +1,139 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef _IN_PROC_CLIENT_WRAPPER_H_ +#define _IN_PROC_CLIENT_WRAPPER_H_ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace OC +{ + namespace ClientCallbackContext + { + struct GetContext + { + GetCallback callback; + }; + + struct SetContext + { + PutCallback callback; + }; + + struct ListenContext + { + FindCallback callback; + std::weak_ptr clientWrapper; + }; + + struct DeviceListenContext + { + FindDeviceCallback callback; + IClientWrapper::Ptr clientWrapper; + }; + + struct SubscribePresenceContext + { + SubscribeCallback callback; + }; + + struct DeleteContext + { + DeleteCallback callback; + }; + + struct ObserveContext + { + ObserveCallback callback; + }; + } + + class InProcClientWrapper : public IClientWrapper + { + + public: + + InProcClientWrapper(std::weak_ptr csdkLock, + PlatformConfig cfg); + virtual ~InProcClientWrapper(); + + virtual OCStackResult ListenForResource(const std::string& serviceUrl, + const std::string& resourceType, FindCallback& callback, + QualityOfService QoS); + + virtual OCStackResult ListenForDevice(const std::string& serviceUrl, + const std::string& deviceURI, FindDeviceCallback& callback, + QualityOfService QoS); + + virtual OCStackResult GetResourceRepresentation(const std::string& host, + const std::string& uri, const QueryParamsMap& queryParams, + const HeaderOptions& headerOptions, + GetCallback& callback, QualityOfService QoS); + + virtual OCStackResult PutResourceRepresentation(const std::string& host, + const std::string& uri, const OCRepresentation& attributes, + const QueryParamsMap& queryParams, const HeaderOptions& headerOptions, + PutCallback& callback, QualityOfService QoS); + + virtual OCStackResult PostResourceRepresentation(const std::string& host, + const std::string& uri, const OCRepresentation& attributes, + const QueryParamsMap& queryParams, const HeaderOptions& headerOptions, + PostCallback& callback, QualityOfService QoS); + + virtual OCStackResult DeleteResource(const std::string& host, const std::string& uri, + const HeaderOptions& headerOptions, DeleteCallback& callback, QualityOfService QoS); + + virtual OCStackResult ObserveResource(ObserveType observeType, OCDoHandle* handle, + const std::string& host, const std::string& uri, const QueryParamsMap& queryParams, + const HeaderOptions& headerOptions, ObserveCallback& callback, QualityOfService QoS); + + virtual OCStackResult CancelObserveResource(OCDoHandle handle, const std::string& host, + const std::string& uri, const HeaderOptions& headerOptions, QualityOfService QoS); + + virtual OCStackResult SubscribePresence(OCDoHandle* handle, const std::string& host, + const std::string& resourceType, SubscribeCallback& presenceHandler); + + virtual OCStackResult UnsubscribePresence(OCDoHandle handle); + OCStackResult GetDefaultQos(QualityOfService& QoS); + private: + void listeningFunc(); + std::string assembleSetResourceUri(std::string uri, const QueryParamsMap& queryParams); + std::string assembleSetResourcePayload(const OCRepresentation& attributes); + void assembleHeaderOptions(OCHeaderOption options[], + const HeaderOptions& headerOptions); + std::thread m_listeningThread; + bool m_threadRun; + std::weak_ptr m_csdkLock; + + private: + PlatformConfig m_cfg; + }; +} + +#endif diff --git a/resource/include/InProcServerWrapper.h b/resource/include/InProcServerWrapper.h new file mode 100644 index 000000000..b68f599bc --- /dev/null +++ b/resource/include/InProcServerWrapper.h @@ -0,0 +1,86 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef _IN_PROC_SERVER_WRAPPER_H_ +#define _IN_PROC_SERVER_WRAPPER_H_ + +#include +#include +#include + +#include + +namespace OC +{ + class InProcServerWrapper : public IServerWrapper + { + public: + InProcServerWrapper( + std::weak_ptr csdkLock, + PlatformConfig cfg); + virtual ~InProcServerWrapper(); + + virtual OCStackResult registerResource( + OCResourceHandle& resourceHandle, + std::string& resourceURI, + const std::string& resourceTypeName, + const std::string& resourceInterface, + EntityHandler& entityHandler, + uint8_t resourceProperty); + + virtual OCStackResult registerDeviceInfo( + const OCDeviceInfo deviceInfo); + + virtual OCStackResult registerResourceWithHost( + OCResourceHandle& resourceHandle, + std::string& resourceHOST, + std::string& resourceURI, + const std::string& resourceTypeName, + const std::string& resourceInterface, + EntityHandler& entityHandler, + uint8_t resourceProperty); + + virtual OCStackResult unregisterResource( + const OCResourceHandle& resourceHandle); + + virtual OCStackResult bindTypeToResource( + const OCResourceHandle& resourceHandle, + const std::string& resourceTypeName); + + virtual OCStackResult bindInterfaceToResource( + const OCResourceHandle& resourceHandle, + const std::string& resourceInterface); + + virtual OCStackResult startPresence(const unsigned int seconds); + + virtual OCStackResult stopPresence(); + + virtual OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler); + + virtual OCStackResult sendResponse(const std::shared_ptr pResponse); + private: + void processFunc(); + std::thread m_processThread; + bool m_threadRun; + std::weak_ptr m_csdkLock; + }; +} + +#endif diff --git a/resource/include/InitializeException.h b/resource/include/InitializeException.h new file mode 100644 index 000000000..c6eed56ee --- /dev/null +++ b/resource/include/InitializeException.h @@ -0,0 +1,76 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef _INITIALIZE_EXCEPTION_H_ +#define _INITIALIZE_EXCEPTION_H_ + +#include +#include +#include "StringConstants.h" + +namespace OC +{ + class InitializeException : public std::exception + { + public: + InitializeException(const std::string& msg, OCStackResult reasonCode): m_errorMessage(msg), m_reason(reasonCode) + { + } + + OCStackResult ReasonCode() + { + return m_reason; + } + + std::string Message() + { + return m_errorMessage; + } + + std::string Reason() + { + switch(m_reason) + { + case OC_STACK_OK: + return OC::InitException::NO_ERROR; + case OC_STACK_INVALID_URI: + return OC::InitException::INVALID_URI; + case OC_STACK_INVALID_IP: + return OC::InitException::INVALID_IP; + case OC_STACK_INVALID_PORT: + return OC::InitException::INVALID_PORT; + case OC_STACK_INVALID_CALLBACK: + return OC::InitException::INVALID_CB; + case OC_STACK_INVALID_METHOD: + return OC::InitException::INVALID_METHOD; + case OC_STACK_ERROR: + return OC::InitException::GENERAL_FAULT; + default: + return OC::InitException::UNKNOWN_ERROR; + } + } + + private: + const std::string& m_errorMessage; + OCStackResult m_reason; + }; +} + +#endif diff --git a/resource/include/OCAndroid.h b/resource/include/OCAndroid.h new file mode 100644 index 000000000..ec015ee76 --- /dev/null +++ b/resource/include/OCAndroid.h @@ -0,0 +1,44 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef _OCANDROID_H_ +#define _OCANDROID_H_ + +#ifdef __ANDROID__ +#include + +// FIXME : ugly hack +// Android missing functions +namespace std { + int stoi(const std::string& s); + double stod(const std::string& s); + long long stoll(const std::string& s); + unsigned long long stoull(const std::string& s); + long double stold(const string& s); + + std::string to_string(int i); + std::string to_string(uint32_t i); + std::string to_string(double d); +} + +#endif + + +#endif diff --git a/resource/include/OCApi.h b/resource/include/OCApi.h new file mode 100644 index 000000000..b523da538 --- /dev/null +++ b/resource/include/OCApi.h @@ -0,0 +1,226 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef __INTEL_OCAPI_H_2014_07_10 +#define __INTEL_OCAPI_H_2014_07_10 + +#include +#include +#include +#include +#include +#include + +#include "ocstack.h" +#include "OCHeaderOption.h" +#include +#include "StringConstants.h" +#include "oc_logger.hpp" + +#include + +namespace OC +{ + class OCResource; + class OCResourceRequest; + class OCResourceResponse; +} // namespace OC + +namespace OC +{ + typedef boost::iostreams::stream log_target_t; + + namespace detail + { + /* We'll want to provide some sort of explicit hook for custom logging at some + point; until then, this should do nicely (note that since these are lambdas, + later a special target could be captured, allowing much flexibility): */ + auto oclog_target = []() -> log_target_t& + { + static OC::oc_log_stream ols(oc_make_ostream_logger); + static log_target_t os(ols); + + return os; + }; + } // namespace OC::detail + + auto oclog = []() -> boost::iostreams::stream& + { + return detail::oclog_target(); + }; + +} // namespace OC + +namespace OC +{ + + enum class OCPlatformStatus + { + PlatformUp, + PlatformDown + }; + + enum class OCAdvertisementStatus + { + None + }; + + typedef std::string URI; + + enum class ServiceType + { + InProc, + OutOfProc + }; + + enum class ModeType + { + Server, + Client, + Both + }; + + enum class QualityOfService : uint8_t + { + LowQos = OC_LOW_QOS, + MidQos = OC_MEDIUM_QOS, + HighQos = OC_HIGH_QOS, + NaQos = OC_NA_QOS // No Quality is defined, let the stack decide + }; + + /** + * Data structure to provide the configuration. + * ServiceType: indicate InProc or OutOfProc + * ModeType : indicate whether we want to do server, client or both + * ipAddress : ip address of server. + * if you speecifiy 0.0.0.0 : it listens on any interface. + * port : port of server. + * : if you specifiy 0 : next available random port is used. + * : if you specify 5683 : client discovery can work even if they don't specify port. + * QoS : Quality of Service : CONFIRMABLE or NON CONFIRMABLE. + */ + struct PlatformConfig + { + ServiceType serviceType; + ModeType mode; + std::string ipAddress; + uint16_t port; + + QualityOfService QoS; + + public: + PlatformConfig() + : serviceType(ServiceType::InProc), + mode(ModeType::Both), + ipAddress("0.0.0.0"), + port(0), + QoS(QualityOfService::NaQos) + {} + PlatformConfig(const ServiceType serviceType_, + const ModeType mode_, + const std::string& ipAddress_, + const uint16_t port_, + const QualityOfService QoS_) + : serviceType(serviceType_), + mode(mode_), + ipAddress(ipAddress_), + port(port_), + QoS(QoS_) + {} + }; + + enum RequestHandlerFlag + { + InitFlag = 1 << 0, + RequestFlag = 1 << 1, + ObserverFlag = 1 << 2 + }; + + enum class ObserveType + { + Observe, + ObserveAll + }; + // + // Typedef for header option vector + // OCHeaderOption class is in HeaderOption namespace + typedef std::vector HeaderOptions; + + // Typedef for query parameter map + typedef std::map QueryParamsMap; + + // Typedef for list of observation IDs + typedef std::vector ObservationIds; + + enum class ObserveAction + { + ObserveRegister, + ObserveUnregister + }; + + typedef struct + { + // Action associated with observation request + ObserveAction action; + // Identifier for observation being registered/unregistered + OCObservationId obsId; + } ObservationInfo; + + // const strings for different interfaces + + // Default interface + const std::string DEFAULT_INTERFACE = "oc.mi.def"; + + // Used in discovering (GET) links to other resources of a collection. + const std::string LINK_INTERFACE = "oc.mi.ll"; + + // Used in GET, PUT, POST, DELETE methods on links to other resources of a collection. + const std::string BATCH_INTERFACE = "oc.mi.b"; + + // Used in GET, PUT, POST methods on links to other remote resources of a group. + const std::string GROUP_INTERFACE = "oc.mi.c"; + + + typedef std::function)> FindCallback; + + typedef std::function FindDeviceCallback; + + typedef std::function)> EntityHandler; + + typedef std::function SubscribeCallback; + + typedef std::function GetCallback; + + typedef std::function PostCallback; + + typedef std::function PutCallback; + + typedef std::function DeleteCallback; + + typedef std::function ObserveCallback; +} // namespace OC + +#endif diff --git a/resource/include/OCException.h b/resource/include/OCException.h new file mode 100644 index 000000000..b297a0c92 --- /dev/null +++ b/resource/include/OCException.h @@ -0,0 +1,56 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef __INTEL_OCEXCEPTION_H_2014_07_10 + #define __INTEL_OCEXCEPTION_H_2014_07_10 + +#include +#include +#include + +namespace OC { + +class OCException : public std::runtime_error +{ + public: + OCException(const std::string& msg, OCStackResult reason = OC_STACK_ERROR) + : std::runtime_error(msg), + m_reason(reason) + {} + + static std::string reason(const OCStackResult sr); + + std::string reason() const + { + return reason(m_reason); + } + + std::string reason(const OC::OCException& e) const + { + return e.reason(); + } + + private: + OCStackResult m_reason; +}; + +} // namespace OC + +#endif diff --git a/resource/include/OCHeaderOption.h b/resource/include/OCHeaderOption.h new file mode 100644 index 000000000..31517c5de --- /dev/null +++ b/resource/include/OCHeaderOption.h @@ -0,0 +1,88 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// @file OCHeaderOption.h + +/// @brief This file contains the declaration of classes and its members related to +/// OCHeaderOption. + +#ifndef __OCHEADEROPTION_H +#define __OCHEADEROPTION_H + +#include +#include +namespace OC +{ + namespace HeaderOption + { + /** + * @brief OCHeaderOption class allows to create instances which comprises optionID + * and optionData as members. These are used in setting Header options. + * After creating instances of OCHeaderOptions, use setHeaderOptions API + * (in OCResource.h) to set header Options. + * NOTE: HeaderOptionID is an unsigned integer value which MUST be within + * range of 2048 to 3000 inclusive of lower and upper bound. + * HeaderOptions instance creation fails if above condition is not satisfied. + */ + const uint16_t MIN_HEADER_OPTIONID = 2048; + const uint16_t MAX_HEADER_OPTIONID = 3000; + + class OCHeaderOption + { + private: + uint16_t m_optionID; + std::string m_optionData; + + public: + /** + * OCHeaderOption constructor + */ + OCHeaderOption(uint16_t optionID, std::string optionData): + m_optionID(optionID), + m_optionData(optionData) + { + if(!(optionID >= MIN_HEADER_OPTIONID && optionID <= MAX_HEADER_OPTIONID)) + { + throw OCException(OC::Exception::OPTION_ID_RANGE_INVALID); + } + } + + /** + * API to get Option ID + * @return unsigned integer option ID + */ + uint16_t getOptionID() const + { + return m_optionID; + } + + /* + * API to get Option data + * @return std::string of option data + */ + std::string getOptionData() const + { + return m_optionData; + } + }; + } // namespace HeaderOption +} // namespace OC + +#endif //__OCHEADEROPTION_H diff --git a/resource/include/OCPlatform.h b/resource/include/OCPlatform.h new file mode 100644 index 000000000..1cad3399f --- /dev/null +++ b/resource/include/OCPlatform.h @@ -0,0 +1,443 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// @file OCPlatform.h + +/// @brief This file contains the declaration of classes and its members related to +/// OCPlatform. + +#ifndef __OCPLATFORM_H +#define __OCPLATFORM_H +#include +#include +namespace OC +{ + /** + * @brief: This namespace contains the main entrance/functionality of the product. + * It may be used with OC::OCPlatform::functionName. To set a custom configuration, + * the implementer must make a call to OCPlatform::Configure before the first usage + * of a function in this namespace. + */ + namespace OCPlatform + { + /** + * API for overwriting the default configuration of the OCPlatform object. + * Note: Any calls made to this AFTER the first call to OCPlatform::Instance + * will have no affect + */ + void Configure(const PlatformConfig& config); + + // typedef for handle to cancel presence info with + typedef OCDoHandle OCPresenceHandle; + + /** + * API for notifying base that resource's attributes have changed. + * + * @param OCResourceHandle resource handle of the resource + * @param QualityOfService the quality of communication + * + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. + * NOTE: This API is for server side only. + * NOTE: OCResourceHandle is defined in ocstack.h. + * NOTE: OCStackResult is defined in ocstack.h. + */ + OCStackResult notifyAllObservers(OCResourceHandle resourceHandle); + OCStackResult notifyAllObservers(OCResourceHandle resourceHandle, QualityOfService QoS); + + /** + * API for notifying only specific clients that resource's attributes have changed. + * + * @param OCResourceHandle resource handle of the resource + * @param observationIds std vector of observationIds. These set of ids are ones which + * which will be notified upon resource change. + * @param responsePtr OCResourceResponse pointer used by app to fill the response for this + * resource change. + * @param QualityOfService the quality of communication + * + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. + * + * NOTE: This API is for server side only. + * NOTE: OCResourceHandle is defined in ocstack.h. + * NOTE: OCStackResult is defined in ocstack.h. + */ + OCStackResult notifyListOfObservers( + OCResourceHandle resourceHandle, + ObservationIds& observationIds, + const std::shared_ptr responsePtr); + OCStackResult notifyListOfObservers( + OCResourceHandle resourceHandle, + ObservationIds& observationIds, + const std::shared_ptr responsePtr, + QualityOfService QoS); + + /** + * API for Service and Resource Discovery. + * NOTE: This API applies to client side only. + * + * @param host - Host IP Address of a service to direct resource discovery query. If null or + * empty, performs multicast resource discovery query + * @param resourceURI - name of the resource. If null or empty, performs search for all + * resource names + * @param handler - Handles callbacks, success states and failure states. + * + * Four modes of discovery defined as follows: + * (NULL/Empty, NULL/Empty) - Performs ALL service discovery AND ALL resource + * discovery. + * (NULL/Empty, Not Empty) - Performs query for a filtered/scoped/particular + * resource(s) from ALL services. + * (Not Empty, NULL/Empty) - Performs ALL resource discovery on a particular service. + * (Not Empty, Not Empty) - Performs query for a filtered/scoped/particular + * resource(s) + * from a particular service. + * @param QualityOfService the quality of communication + * + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. + * NOTE: First parameter 'host' currently represents an IP address. This will change in + * future and will refer to endpoint interface so that we can refer to other transports such + * as BTH etc. + * NOTE: OCStackResult is defined in ocstack.h. + */ + OCStackResult findResource(const std::string& host, const std::string& resourceURI, + FindCallback resourceHandler); + OCStackResult findResource(const std::string& host, const std::string& resourceURI, + FindCallback resourceHandler, QualityOfService QoS); + + /** + * API for Device Discovery + * + * + * @param host - Host IP Address. If null or empty, Multicast is performed. + * @param resourceURI - Uri containing address to the virtual device in C Stack + ("/oc/core/d") + * @param QualityOfService the quality of communication + * + */ + OCStackResult getDeviceInfo(const std::string& host, const std::string& deviceURI, + FindDeviceCallback deviceInfoHandler); + OCStackResult getDeviceInfo(const std::string& host, const std::string& deviceURI, + FindDeviceCallback deviceInfoHandler, QualityOfService QoS); + + /** + * This API registers a resource with the server + * NOTE: This API applies to server side only. + * + * @param resourceHandle - Upon successful registration, resourceHandle will be filled + * @param resourceURI - The URI of the resource. Example: "a/light". See NOTE below + * @param resourceTypeName - The resource type. Example: "light" + * @param resourceInterface - The resource interface (whether it is collection etc). + * @param entityHandler - entity handler callback. + * @param resourceProperty - indicates the property of the resource. Defined in ocstack.h. + * setting resourceProperty as OC_DISCOVERABLE will allow Discovery of this resource + * setting resourceProperty as OC_OBSERVABLE will allow observation + * settings resourceProperty as OC_DISCOVERABLE | OC_OBSERVABLE will allow both discovery and + * observation + * + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. + * NOTE: "a/light" is a relative URI. + * Above relative URI will be prepended (by core) with a host IP + namespace "oc" + * Therefore, fully qualified URI format would be //HostIP-Address/namespace/relativeURI" + * Example, a relative URI: 'a/light' will result in a fully qualified URI: + * //192.168.1.1/oc/a/light" + * First parameter can take a relative URI and core will take care of preparing the fully + * qualified URI OR + * first paramter can take fully qualified URI and core will take that as is for further + * operations + * NOTE: OCStackResult is defined in ocstack.h. + */ + OCStackResult registerResource(OCResourceHandle& resourceHandle, + std::string& resourceURI, + const std::string& resourceTypeName, + const std::string& resourceInterface, + EntityHandler entityHandler, + uint8_t resourceProperty); + + /** + * This API registers a resource with the server + * NOTE: This API applies to server & client side. + + * @param resourceHandle - Upon successful registration, resourceHandle will be filled + * @param OCResource - The instance of OCResource that all data filled. + * + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. + */ + + OCStackResult registerResource(OCResourceHandle& resourceHandle, + const std::shared_ptr< OCResource > resource); + + /** + * Register Device Info + * + * @param deviceInfo - structure containing all the device specific information + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ + + OCStackResult registerDeviceInfo(const OCDeviceInfo deviceInfo); + + /** + * Set default device entity handler + * + * @param entityHandler - entity handler to handle requests for + * any undefined resources or default actions. + * if NULL is passed it removes the device default entity handler. + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ + OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler); + + /** + * This API unregisters a resource with the server + * NOTE: This API applies to server side only. + * + * @param resourceHandle - This is the resource handle which we which to unregister from the + * server + * + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. + * NOTE: OCStackResult is defined in ocstack.h. + */ + OCStackResult unregisterResource(const OCResourceHandle& resourceHandle); + + /** + * Add a resource to a collection resource. + * + * @param collectionHandle - handle to the collection resource + * @param addedResourceHandle - handle to resource to be added to the collection resource + * + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * NOTE: OCStackResult is defined in ocstack.h.
+ * NOTE: bindResource must be used only after the both collection resource and + * resource to add under a collections are created and respective handles obtained
+ * Example:
+ * Step 1: registerResource(homeResourceHandle, "a/home", "home", Link_Interface, + * entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * Step 2: registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface, + * entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * Step 3: bindResource(homeResourceHandle, kitchenResourceHandle);
+ * At the end of Step 3, resource "a/home" will contain a reference to "a/kitchen".
+ */ + OCStackResult bindResource(const OCResourceHandle collectionHandle, + const OCResourceHandle resourceHandle); + + /** + * Add multiple resources to a collection resource. + * + * @param collectionHandle - handle to the collection resource + * @param addedResourceHandleList reference to list of resource handles to be added to the + * collection resource + * + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * NOTE: OCStackResult is defined in ocstack.h.
+ * NOTE: bindResources must be used only after the both collection resource and + * list of resources to add under a collection are created and respective handles + * obtained
+ * Example:
+ * Step 1: registerResource(homeResourceHandle, "a/home", "home", Link_Interface, + * homeEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * Step 2: registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface, + * kitchenEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * Step 3: registerResource(roomResourceHandle, "a/room", "room", Link_Interface, + * roomEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * Step 4: std::vector rList; rList.push_back(kitchenResourceHandle); + * rList.push_back(roomResourceHandle);
+ * Step 5: bindResource(homeResourceHandle, rList);
+ * At the end of Step 5, resource "a/home" will contain a references to "a/kitchen" and + * "a/room"
+ */ + OCStackResult bindResources(const OCResourceHandle collectionHandle, + const std::vector& addedResourceHandleList); + + /** + * Unbind a resource from a collection resource. + * + * @param collectionHandle - handle to the collection resource + * @param resourceHandle resource handle to be unbound from the collection resource + * + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * NOTE: OCStackResult is defined in ocstack.h.
+ * NOTE: unbindResource must be used only after the both collection resource and + * resource to unbind from a collection are created and respective handles obtained
+ * Example
+ * Step 1: registerResource(homeResourceHandle, "a/home", "home", Link_Interface, + * entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * Step 2: registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface, + * entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * Step 3: bindResource(homeResourceHandle, kitchenResourceHandle);
+ * Step 4: unbindResource(homeResourceHandle, kitchenResourceHandle);
+ * At the end of Step 4, resource "a/home" will no longer reference "a/kitchen".
+ */ + OCStackResult unbindResource(const OCResourceHandle collectionHandle, + const OCResourceHandle resourceHandle); + + /** + * Unbind resources from a collection resource. + * + * @param collectionHandle - handle to the collection resource + * @param resourceHandleList List of resource handles to be unbound from the collection + * resource + * + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * + * NOTE: OCStackResult is defined in ocstack.h.
+ * NOTE: unbindResources must be used only after the both collection resource and + * list of resources resource to unbind from a collection are created and respective handles + * obtained.
+ * Example
+ * Step 1: registerResource(homeResourceHandle, "a/home", "home", Link_Interface, + * homeEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * Step 2: registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface, + * kitchenEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * Step 3: registerResource(roomResourceHandle, "a/room", "room", Link_Interface, + * roomEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * Step 4: std::vector rList; rList.push_back(kitchenResourceHandle); + * rList.push_back(roomResourceHandle);
+ * Step 5: bindResource(homeResourceHandle, rList);
+ * Step 6: unbindResources(homeResourceHandle, rList);
+ * At the end of Step 6, resource "a/home" will no longer reference to "a/kitchen" and + * "a/room"
+ */ + OCStackResult unbindResources(const OCResourceHandle collectionHandle, + const std::vector& resourceHandleList); + + /** + * Binds a type to a particular resource + * @param resourceHandle - handle to the resource + * @param resourceTypeName - new typename to bind to the resource + + * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success
+ */ + OCStackResult bindTypeToResource(const OCResourceHandle& resourceHandle, + const std::string& resourceTypeName); + + /** + * Binds an interface to a particular resource + * @param resourceHandle - handle to the resource + * @param resourceTypeName - new interface to bind to the resource + + * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success
+ */ + OCStackResult bindInterfaceToResource(const OCResourceHandle& resourceHandle, + const std::string& resourceInterfaceName); + + + /** + * Start Presence announcements. + * + * @param ttl - time to live + * @return OCStackResult - Returns OCSTACK_OK if success
+ * + * Server can call this function when it comes online for the + * first time, or when it comes back online from offline mode, + * or when it re enters network. + * + */ + + OCStackResult startPresence(const unsigned int ttl); + + /** + * Stop Presence announcements. + * + * @return OCStackResult - Returns OCSTACK_OK if success
+ * + * Server can call this function when it is terminating, + * going offline, or when going away from network. + * + */ + + OCStackResult stopPresence(); + + /** + * subscribes to a server's presence change events. By making this subscription, + * every time a server adds/removes/alters a resource, starts or is intentionally + * stopped (potentially more to be added later). + * + * @param presenceHandle - a handle object that can be used to identify this subscription + * request. It can be used to unsubscribe from these events in the future. + * It will be set upon successful return of this method. + * @param host - The IP address/addressable name of the server to subscribe to. + * @param resourceType - a resource type specified as a filter for subscription callbacks. + * @param presenceHandler - callback function that will receive notifications/subscription + * events + * + * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success
+ */ + OCStackResult subscribePresence(OCPresenceHandle& presenceHandle, const std::string& host, + SubscribeCallback presenceHandler); + OCStackResult subscribePresence(OCPresenceHandle& presenceHandle, const std::string& host, + const std::string& resourceType, SubscribeCallback presenceHandler); + + /** + * unsubscribes from a previously subscribed server's presence events. Note that + * you may for a short time still receive events from the server since it may take time + * for the unsubscribe to take effect. + * + * @param presenceHandle - the handle object provided by the subscribePresence call that + * identifies this subscription. + * + * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success
+ */ + OCStackResult unsubscribePresence(OCPresenceHandle presenceHandle); + + /** + * Creates a resource proxy object so that get/put/observe functionality + * can be used without discovering the object in advance. Note that the + * consumer of this method needs to provide all of the details required to + * correctly contact and observe the object. If the consumer lacks any of + * this information, they should discover the resource object normally. + * Additionally, you can only create this object if OCPlatform was initialized + * to be a Client or Client/Server. Otherwise, this will return an empty + * shared ptr. + * + * @param host - a string containing a resolvable host address of the server + * holding the resource. Currently this should be in the format + * coap://address:port, though in the future, we expect this to + * change to //address:port + * + * @param uri - the rest of the resource's URI that will permit messages to be + * properly routed. Example: /a/light + * + * @param isObservable - a boolean containing whether the resource supports observation + * + * @param resourceTypes - a collection of resource types implemented by the resource + * + * @param interfaces - a collection of interfaces that the resource supports/implements + * @return OCResource::Ptr - a shared pointer to the new resource object + */ + OCResource::Ptr constructResourceObject(const std::string& host, const std::string& uri, + bool isObservable, const std::vector& resourceTypes, + const std::vector& interfaces); + + /** + * Allows application entity handler to send response to an incoming request. + * + * @param pResponse - OCResourceResponse pointer that will permit to set values related + * to resource response.
+ * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success
+ */ + OCStackResult sendResponse(const std::shared_ptr pResponse); + } +} + +#endif //__OCPLATFORM_H + + diff --git a/resource/include/OCPlatform_impl.h b/resource/include/OCPlatform_impl.h new file mode 100644 index 000000000..f25ce2e18 --- /dev/null +++ b/resource/include/OCPlatform_impl.h @@ -0,0 +1,496 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// @file OCPlatform_impl.h + +/// @brief Implementation of the OCPlatform functionality. It contains +/// a singleton interface that is used only by the OCPlatform namespace and is the +/// central entrance to the stack. + +#ifndef __OCPLATFORM_IMPL_H +#define __OCPLATFORM_IMPL_H + +#include + +#include "OCApi.h" +#include "OCResource.h" +#include "WrapperFactory.h" +#include "OCResourceRequest.h" +#include "OCResourceResponse.h" +#include "OCRepresentation.h" + +#include "oc_logger.hpp" + +namespace OC +{ + /** + * @brief Both server and client must initialize the core platform by instantiating OCPlatform. + * On successful initialization, an instance of the OCPlatform is returned. + * APIs in OCPlatform provide mechanism to register a resource and host the resource + * on the server, find resources on the network etc. + */ + class OCPlatform_impl + { + private: + static PlatformConfig& globalConfig(); + public: + /** + * API for overwriting the default configuration of the OCPlatform object. + * Note: Any calls made to this AFTER the first call to OCPlatform::Instance + * will have no affect + */ + static void Configure(const PlatformConfig& config); + + /** + * API for retrieving the current OCPlatform object. This will use the + * default platform config, unless the default is over-written using the + * Configure method before the first call to instance. + */ + static OCPlatform_impl& Instance(); + + public: + // typedef for handle to cancel presence info with + typedef OCDoHandle OCPresenceHandle; + + /** + * Virtual destructor + */ + virtual ~OCPlatform_impl(void); + + /** + * API for notifying base that resource's attributes have changed. + * + * @param OCResourceHandle resource handle of the resource + * @param QualityOfService the quality of communication + * + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. + * NOTE: This API is for server side only. + * NOTE: OCResourceHandle is defined in ocstack.h. + * NOTE: OCStackResult is defined in ocstack.h. + */ + OCStackResult notifyAllObservers(OCResourceHandle resourceHandle); + OCStackResult notifyAllObservers(OCResourceHandle resourceHandle, QualityOfService QoS); + + /** + * API for notifying only specific clients that resource's attributes have changed. + * + * @param OCResourceHandle resource handle of the resource + * @param observationIds std vector of observationIds. These set of ids are ones which + * which will be notified upon resource change. + * @param responsePtr OCResourceResponse pointer used by app to fill the response for this + * resource change. + * @param QualityOfService the quality of communication + * + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. + * + * NOTE: This API is for server side only. + * NOTE: OCResourceHandle is defined in ocstack.h. + * NOTE: OCStackResult is defined in ocstack.h. + */ + OCStackResult notifyListOfObservers( + OCResourceHandle resourceHandle, + ObservationIds& observationIds, + const std::shared_ptr responsePtr); + OCStackResult notifyListOfObservers( + OCResourceHandle resourceHandle, + ObservationIds& observationIds, + const std::shared_ptr responsePtr, + QualityOfService QoS); + + /** + * API for Service and Resource Discovery. + * NOTE: This API applies to client side only. + * + * @param host - Host IP Address of a service to direct resource discovery query. If null or + * empty, performs multicast resource discovery query + * @param resourceURI - name of the resource. If null or empty, performs search for all + * resource names + * @param handler - Handles callbacks, success states and failure states. + * + * Four modes of discovery defined as follows: + * (NULL/Empty, NULL/Empty) - Performs ALL service discovery AND ALL resource + * discovery. + * (NULL/Empty, Not Empty) - Performs query for a filtered/scoped/particular + * resource(s) from ALL services. + * (Not Empty, NULL/Empty) - Performs ALL resource discovery on a particular service. + * (Not Empty, Not Empty) - Performs query for a filtered/scoped/particular + * resource(s) from a particular service. + * @param QualityOfService the quality of communication + * + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. + * NOTE: First parameter 'host' currently represents an IP address. This will change in + * future and will refer to endpoint interface so that we can refer to other transports such + * as BTH etc. + * NOTE: OCStackResult is defined in ocstack.h. + */ + OCStackResult findResource(const std::string& host, const std::string& resourceURI, + FindCallback resourceHandler); + OCStackResult findResource(const std::string& host, const std::string& resourceURI, + FindCallback resourceHandler, QualityOfService QoS); + + /** + * API for Device Discovery + * + * @param host - Host IP Address. If null or empty, Multicast is performed. + * @param resourceURI - Uri containing address to the virtual device in C Stack + * ("/oc/core/d") + * + * @param QualityOfService the quality of communication + * + */ + OCStackResult getDeviceInfo(const std::string& host, const std::string& deviceURI, + FindDeviceCallback deviceInfoHandler); + OCStackResult getDeviceInfo(const std::string& host, const std::string& deviceURI, + FindDeviceCallback deviceInfoHandler, QualityOfService QoS); + + /** + * This API registers a resource with the server + * NOTE: This API applies to server side only. + * + * @param resourceHandle - Upon successful registration, resourceHandle will be filled + * @param resourceURI - The URI of the resource. Example: "a/light". See NOTE below + * @param resourceTypeName - The resource type. Example: "light" + * @param resourceInterface - The resource interface (whether it is collection etc). + * @param entityHandler - entity handler callback. + * @param resourceProperty - indicates the property of the resource. Defined in ocstack.h. + * setting resourceProperty as OC_DISCOVERABLE will allow Discovery of this resource + * setting resourceProperty as OC_OBSERVABLE will allow observation + * settings resourceProperty as OC_DISCOVERABLE | OC_OBSERVABLE will allow both discovery + * and observation + * + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. + * NOTE: "a/light" is a relative URI. + * Above relative URI will be prepended (by core) with a host IP + namespace "oc" + * Therefore, fully qualified URI format would be //HostIP-Address/namespace/relativeURI" + * Example, a relative URI: 'a/light' will result in a fully qualified URI: + * //192.168.1.1/oc/a/light" + * First parameter can take a relative URI and core will take care of preparing the fully + * qualified URI OR + * first paramter can take fully qualified URI and core will take that as is for further + * operations + * NOTE: OCStackResult is defined in ocstack.h. + */ + OCStackResult registerResource(OCResourceHandle& resourceHandle, + std::string& resourceURI, + const std::string& resourceTypeName, + const std::string& resourceInterface, + EntityHandler entityHandler, + uint8_t resourceProperty); + + /** + * This API registers a resource with the server + * NOTE: This API applies to server & client side. + + * @param resourceHandle - Upon successful registration, resourceHandle will be filled + * @param OCResource - The instance of OCResource that all data filled. + * + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. + */ + + OCStackResult registerResource(OCResourceHandle& resourceHandle, + const std::shared_ptr resource); + + /** + * This API registers all the device specific information + * + * @param OCDeviceInfo - Structure containing all the device related information + * + * @return OCStackResult return value of the API. Returns OC_STACK_OK if success + * + * Note: OCDeviceInfo is defined in OCStack.h + */ + OCStackResult registerDeviceInfo(const OCDeviceInfo deviceInfo); + + /** + * Set default device entity handler + * + * @param entityHandler - entity handler to handle requests for + * any undefined resources or default actions. + * if NULL is passed it removes the device default entity handler. + * + * @return + * OC_STACK_OK - no errors + * OC_STACK_ERROR - stack process error + */ + OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler); + + /** + * This API unregisters a resource with the server + * NOTE: This API applies to server side only. + * + * @param resourceHandle - This is the resource handle which we which to unregister from the + * server + * + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. + * NOTE: OCStackResult is defined in ocstack.h. + */ + OCStackResult unregisterResource(const OCResourceHandle& resourceHandle) const; + + /** + * Add a resource to a collection resource. + * + * @param collectionHandle - handle to the collection resource + * @param addedResourceHandle - handle to resource to be added to the collection resource + * + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * NOTE: OCStackResult is defined in ocstack.h.
+ * NOTE: bindResource must be used only after the both collection resource and + * resource to add under a collections are created and respective handles obtained
+ * Example:
+ * Step 1: registerResource(homeResourceHandle, "a/home", "home", Link_Interface, + * entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * Step 2: registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface, + * entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * Step 3: bindResource(homeResourceHandle, kitchenResourceHandle);
+ * At the end of Step 3, resource "a/home" will contain a reference to "a/kitchen".
+ */ + OCStackResult bindResource(const OCResourceHandle collectionHandle, + const OCResourceHandle resourceHandle); + + /** + * Add multiple resources to a collection resource. + * + * @param collectionHandle - handle to the collection resource + * @param addedResourceHandleList reference to list of resource handles to be added to + * the collection resource + * + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * NOTE: OCStackResult is defined in ocstack.h.
+ * NOTE: bindResources must be used only after the both collection resource and + * list of resources to add under a collection are created and respective handles + * obtained
+ * Example:
+ * Step 1: registerResource(homeResourceHandle, "a/home", "home", Link_Interface, + * homeEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * Step 2: registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface, + * kitchenEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * Step 3: registerResource(roomResourceHandle, "a/room", "room", Link_Interface, + * roomEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * Step 4: std::vector rList; rList.push_back(kitchenResourceHandle); + * rList.push_back(roomResourceHandle);
+ * Step 5: bindResource(homeResourceHandle, rList);
+ * At the end of Step 5, resource "a/home" will contain a references to "a/kitchen" + * and "a/room"
+ */ + OCStackResult bindResources(const OCResourceHandle collectionHandle, + const std::vector& addedResourceHandleList); + + /** + * Unbind a resource from a collection resource. + * + * @param collectionHandle - handle to the collection resource + * @param resourceHandle resource handle to be unbound from the collection resource + * + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * NOTE: OCStackResult is defined in ocstack.h.
+ * NOTE: unbindResource must be used only after the both collection resource and + * resource to unbind from a collection are created and respective handles obtained
+ * Example
+ * Step 1: registerResource(homeResourceHandle, "a/home", "home", Link_Interface, + * entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * Step 2: registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface, + * entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * Step 3: bindResource(homeResourceHandle, kitchenResourceHandle);
+ * Step 4: unbindResource(homeResourceHandle, kitchenResourceHandle);
+ * At the end of Step 4, resource "a/home" will no longer reference "a/kitchen".
+ */ + OCStackResult unbindResource(const OCResourceHandle collectionHandle, + const OCResourceHandle resourceHandle); + + /** + * Unbind resources from a collection resource. + * + * @param collectionHandle - handle to the collection resource + * @param resourceHandleList List of resource handles to be unbound from the collection + * resource + * + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * + * NOTE: OCStackResult is defined in ocstack.h.
+ * NOTE: unbindResources must be used only after the both collection resource and + * list of resources resource to unbind from a collection are created and respective handles + * obtained.
+ * Example
+ * Step 1: registerResource(homeResourceHandle, "a/home", "home", Link_Interface, + * homeEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * Step 2: registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface, + * kitchenEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * Step 3: registerResource(roomResourceHandle, "a/room", "room", Link_Interface, + * roomEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * Step 4: std::vector rList; rList.push_back(kitchenResourceHandle); + * rList.push_back(roomResourceHandle);
+ * Step 5: bindResource(homeResourceHandle, rList);
+ * Step 6: unbindResources(homeResourceHandle, rList);
+ * At the end of Step 6, resource "a/home" will no longer reference to "a/kitchen" + * and "a/room"
+ */ + OCStackResult unbindResources(const OCResourceHandle collectionHandle, + const std::vector& resourceHandleList); + + /** + * Binds a type to a particular resource + * @param resourceHandle - handle to the resource + * @param resourceTypeName - new typename to bind to the resource + + * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success
+ */ + OCStackResult bindTypeToResource(const OCResourceHandle& resourceHandle, + const std::string& resourceTypeName) const; + + /** + * Binds an interface to a particular resource + * @param resourceHandle - handle to the resource + * @param resourceTypeName - new interface to bind to the resource + + * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success
+ */ + OCStackResult bindInterfaceToResource(const OCResourceHandle& resourceHandle, + const std::string& resourceInterfaceName) const; + + /** + * Start Presence announcements. + * + * @param ttl - time to live + * @return OCStackResult - Returns OCSTACK_OK if success
+ * + * Server can call this function when it comes online for the + * first time, or when it comes back online from offline mode, + * or when it re enters network. + * + */ + OCStackResult startPresence(const unsigned int ttl); + + /** + * Stop Presence announcements. + * + * @return OCStackResult - Returns OCSTACK_OK if success
+ * + * Server can call this function when it is terminating, + * going offline, or when going away from network. + * + */ + OCStackResult stopPresence(); + + /** + * subscribes to a server's presence change events. By making this subscription, + * every time a server adds/removes/alters a resource, starts or is intentionally + * stopped (potentially more to be added later). + * + * @param presenceHandle - a handle object that can be used to identify this subscription + * request. It can be used to unsubscribe from these events in the future. + * It will be set upon successful return of this method. + * @param host - The IP address/addressable name of the server to subscribe to. + * @param resourceType - a resource type specified as a filter for subscription callbacks. + * @param presenceHandler - callback function that will receive notifications/subscription + * events + * + * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success
+ */ + OCStackResult subscribePresence(OCPresenceHandle& presenceHandle, const std::string& host, + SubscribeCallback presenceHandler); + OCStackResult subscribePresence(OCPresenceHandle& presenceHandle, const std::string& host, + const std::string& resourceType, SubscribeCallback presenceHandler); + + /** + * unsubscribes from a previously subscribed server's presence events. Note that + * you may for a short time still receive events from the server since it may take time + * for the unsubscribe to take effect. + * + * @param presenceHandle - the handle object provided by the subscribePresence call that + * identifies this subscription. + * + * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success
+ */ + OCStackResult unsubscribePresence(OCPresenceHandle presenceHandle); + + /** + * Creates a resource proxy object so that get/put/observe functionality + * can be used without discovering the object in advance. Note that the + * consumer of this method needs to provide all of the details required to + * correctly contact and observe the object. If the consumer lacks any of + * this information, they should discover the resource object normally. + * Additionally, you can only create this object if OCPlatform was initialized + * to be a Client or Client/Server. Otherwise, this will return an empty + * shared ptr. + * + * @param host - a string containing a resolvable host address of the server + * holding the resource. Currently this should be in the format + * coap://address:port, though in the future, we expect this to + * change to //address:port + * + * @param uri - the rest of the resource's URI that will permit messages to be + * properly routed. Example: /a/light + * + * @param isObservable - a boolean containing whether the resource supports observation + * + * @param resourceTypes - a collection of resource types implemented by the resource + * + * @param interfaces - a collection of interfaces that the resource supports/implements + * @return OCResource::Ptr - a shared pointer to the new resource object + */ + OCResource::Ptr constructResourceObject(const std::string& host, const std::string& uri, + bool isObservable, const std::vector& resourceTypes, + const std::vector& interfaces); + + /** + * Allows application entity handler to send response to an incoming request. + * + * @param pResponse - OCResourceResponse pointer that will permit to set values related + * to resource response.
+ * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success
+ */ + OCStackResult sendResponse(const std::shared_ptr pResponse); + + private: + PlatformConfig m_cfg; + + private: + std::unique_ptr m_WrapperInstance; + IServerWrapper::Ptr m_server; + IClientWrapper::Ptr m_client; + std::shared_ptr m_csdkLock; + + private: + /** + * Constructor for OCPlatform. Constructs a new OCPlatform from a given PlatformConfig with + * appropriate fields + * @param config PlatformConfig struct which has details such as modeType + * (server/client/both), in-proc/out-of-proc etc. + */ + OCPlatform_impl(const PlatformConfig& config); + + /** + * Private function to initalize the platfrom + */ + void init(const PlatformConfig& config); + + /** + * Private constructor/operators to prevent copying + * of this object + */ + OCPlatform_impl(const OCPlatform_impl& other)= delete; + OCPlatform_impl& operator=(const OCPlatform_impl&) = delete; + OCPlatform_impl& operator=(const OCPlatform_impl&&) = delete; + }; +} + +#endif //__OCPLATFORM_IMPL_H + + diff --git a/resource/include/OCRepresentation.h b/resource/include/OCRepresentation.h new file mode 100644 index 000000000..2e64fcdae --- /dev/null +++ b/resource/include/OCRepresentation.h @@ -0,0 +1,229 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// @file OCRepresentation.h + +/// @brief This file contains the declaration of classes and its members +/// related to OCRepresentation + +#ifndef __OCREPRESENTATION_H +#define __OCREPRESENTATION_H + + +#include +#include +#include +#include + +#include +#include + +#ifdef __ANDROID__ +#include "OCAndroid.h" +#endif + +#include + +namespace cereal +{ + class access; +} + +namespace OC +{ + + enum class InterfaceType + { + None, + LinkParent, + BatchParent, + DefaultParent, + LinkChild, + BatchChild, + DefaultChild + }; + + // The consumer requires resource info to be printed in 2 different ways, both with the "oc":[] + // and without. This enum is used to differentiate between the two situations. When the + // serialize is called with Include OC, we encode OC, otherwise we skip it and return just the + // contents of the array. + enum class OCInfoFormat + { + IncludeOC, + ExcludeOC + }; + + class MessageContainer + { + public: + void setJSONRepresentation(const std::string& payload); + + void setJSONRepresentation(const unsigned char* payload); + + std::string getJSONRepresentation(OCInfoFormat f) const; + + const std::vector& representations() const; + + void addRepresentation(const OCRepresentation& rep); + + const OCRepresentation& operator[](int index) const + { + return m_reps[index]; + } + + const OCRepresentation& back() const + { + return m_reps.back(); + } + private: + std::vector m_reps; + }; + class OCRepresentation + { + public: + OCRepresentation(); + std::string getJSONRepresentation() const; + + void addChild(const OCRepresentation&); + + void clearChildren(); + + const std::vector& getChildren() const; + + void setChildren(const std::vector& children); + + void setUri(const std::string& uri); + + std::string getUri() const; + + const std::vector& getResourceTypes() const; + + void setResourceTypes(const std::vector& resourceTypes); + + const std::vector& getResourceInterfaces() const; + + void setResourceInterfaces(const std::vector& resourceInterfaces); + + bool empty() const; + + int numberOfAttributes() const; + + bool erase(const std::string& str); + + template + void setValue(const std::string& str, const T& val) + { + m_values[str] = val; + } + + template + bool getValue(const std::string& str, T& val) const + { + auto x = m_values.find(str); + + if(x!= m_values.end()) + { + val = boost::get(x->second); + return true; + } + else + { + val = T(); + return false; + } + } + + template + T getValue(const std::string& str) const + { + T val = T(); + auto x = m_values.find(str); + if(x != m_values.end()) + { + val = boost::get(x->second); + } + return val; + } + + bool hasAttribute(const std::string& str) const; + + void setNULL(const std::string& str); + + bool isNULL(const std::string& str) const; + private: + friend class OCResourceResponse; + friend class cereal::access; + + // the root node has a slightly different JSON version + // based on the interface type configured in ResourceResponse. + // This allows ResourceResponse to set it, so that the save function + // doesn't serialize things that it isn't supposed to serialize. + void setInterfaceType(InterfaceType ift) + { + m_interfaceType = ift; + } + + // class used to wrap the 'prop' feature of the save/load + class Prop + { + public: + Prop(std::vector& resourceTypes, + std::vector& interfaces) + : m_types(resourceTypes), m_interfaces(interfaces) + {} + + /* Prop(const std::vector& resourceTypes, + const std::vector& interfaces) + :m_types(resourceTypes), + m_interfaces(interfaces) + {}*/ + private: + friend class cereal::access; + template + void save(Archive& ar) const; + + template + void load(Archive& ar); + + std::vector& m_types; + std::vector& m_interfaces; + }; + template + static void optional_load(Archive& ar, Val&& v); + + template + void save(Archive& ar) const; + + template + void load(Archive& ar); + + private: + std::string m_uri; + std::vector m_children; + std::map m_values; + std::vector m_resourceTypes; + std::vector m_interfaces; + + InterfaceType m_interfaceType; + }; +} // namespace OC + + +#endif //__OCREPRESENTATION_H diff --git a/resource/include/OCResource.h b/resource/include/OCResource.h new file mode 100644 index 000000000..63c4253ab --- /dev/null +++ b/resource/include/OCResource.h @@ -0,0 +1,322 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// @file OCResource.h + +/// @brief This file contains the declaration of classes and its members related to +/// Resource. + +#ifndef __OCRESOURCE_H +#define __OCRESOURCE_H + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace OC +{ + /** + * @brief OCResource represents an OC resource. A resource could be a light controller, + * temperature sensor, smoke detector, etc. A resource comes with a well-defined + * contract or interface onto which you can perform different operations, such as + * turning on the light, getting the current temperature or subscribing for event + * notifications from the smoke detector. A resource can be composed of one or + * more resources. + */ + class OCResource + { + friend class OCPlatform_impl; + friend class ListenOCContainer; + public: + typedef std::shared_ptr Ptr; + /** + * Virtual destructor + */ + virtual ~OCResource(void); + + /** + * Function to get the attributes of a resource. + * @param queryParametersMap map which can have the query parameter name and value + * @param attributeHandler handles callback + * The callback function will be invoked with a map of attribute name and values. + * The callback function will also have the result from this Get operation + * This will have error codes + * @param QualityOfService the quality of communication + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. + * NOTE: OCStackResult is defined in ocstack.h. + */ + OCStackResult get(const QueryParamsMap& queryParametersMap, GetCallback attributeHandler); + OCStackResult get(const QueryParamsMap& queryParametersMap, GetCallback attributeHandler, + QualityOfService QoS); + + /** + * Function to get the attributes of a resource. + * + * @param resourceType resourceType of the resource operate on + * @param resourceInterface interface type of the resource to operate on + * @param queryParametersMap map which can have the query parameter name and value + * @param attributeHandler handles callback + * The callback function will be invoked with a map of attribute name and values. + * The callback function will be invoked with a list of URIs if 'get' is invoked on a + * resource container (list will be empty if not a container) + * The callback function will also have the result from this Get operation. This will + * have error codes + * @param QualityOfService the quality of communication + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * NOTE: OCStackResult is defined in ocstack.h.
+ * Example:
+ * Consider resource "a/home" (with link interface and resource type as home) contains links + * to "a/kitchen" and "a/room". + * Step 1: get("home", Link_Interface, &onGet)
+ * Callback onGet will receive a) Empty attribute map because there are no attributes for + * a/home b) list with + * full URI of "a/kitchen" and "a/room" resources and their properties c) error code for GET + * operation
+ * NOTE: A resource may contain single or multiple resource types. Also, a resource may + * contain single or multiple interfaces.
+ * Currently, single GET request is allowed to do operate on single resource type or resource + * interface. In future, a single GET
+ * can operate on multiple resource types and interfaces.
+ * NOTE: A client can traverse a tree or graph by doing successive GETs on the returned + * resources at a node.
+ */ + OCStackResult get(const std::string& resourceType, const std::string& resourceInterface, + const QueryParamsMap& queryParametersMap, GetCallback attributeHandler); + OCStackResult get(const std::string& resourceType, const std::string& resourceInterface, + const QueryParamsMap& queryParametersMap, GetCallback attributeHandler, + QualityOfService QoS); + + /** + * Function to set the representation of a resource (via PUT) + * @param representation which can either have all the attribute names and values + (which will represent entire state of the resource) or a + * set of attribute names and values which needs to be modified + * The callback function will be invoked with a map of attribute name and values. + * The callback function will also have the result from this Put operation + * This will have error codes + * @param queryParametersMap map which can have the query parameter name and value + * @param attributeHandler attribute handler + * @param QualityOfService the quality of communication + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. + * NOTE: OCStackResult is defined in ocstack.h. + */ + OCStackResult put(const OCRepresentation& representation, + const QueryParamsMap& queryParametersMap, PutCallback attributeHandler); + OCStackResult put(const OCRepresentation& representation, + const QueryParamsMap& queryParametersMap, PutCallback attributeHandler, + QualityOfService QoS); + + /** + * Function to set the attributes of a resource (via PUT) + * @param resourceType resource type of the resource to operate on + * @param resourceInterface interface type of the resource to operate on + * @param representation representation of the resource + * @param queryParametersMap Map which can have the query parameter name and value + * @param attributeHandler attribute handler + * The callback function will be invoked with a map of attribute name and values. + * The callback function will also have the result from this Put operation + * This will have error codes. + * The Representation parameter maps which can either have all the attribute names + * and values + * (which will represent entire state of the resource) or a + * set of attribute names and values which needs to be modified + * @param QualityOfService the quality of communication + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * NOTE: OCStackResult is defined in ocstack.h.
+ */ + OCStackResult put(const std::string& resourceType, const std::string& resourceInterface, + const OCRepresentation& representation, const QueryParamsMap& queryParametersMap, + PutCallback attributeHandler); + OCStackResult put(const std::string& resourceType, const std::string& resourceInterface, + const OCRepresentation& representation, const QueryParamsMap& queryParametersMap, + PutCallback attributeHandler, QualityOfService QoS); + + /** + * Function to post on a resource + * @param representation which can either have all the attribute names and values + (which will represent entire state of the resource) or a + * set of attribute names and values which needs to be modified + * The callback function will be invoked with a map of attribute name and values. + * The callback function will also have the result from this Put operation + * This will have error codes + * @param queryParametersMap map which can have the query parameter name and value + * @param attributeHandler attribute handler + * @param QualityOfService the quality of communication + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. + * NOTE: OCStackResult is defined in ocstack.h. + */ + OCStackResult post(const OCRepresentation& representation, + const QueryParamsMap& queryParametersMap, PostCallback attributeHandler); + OCStackResult post(const OCRepresentation& representation, + const QueryParamsMap& queryParametersMap, PostCallback attributeHandler, + QualityOfService QoS); + + /** + * Function to post on a resource + * @param resourceType resource type of the resource to operate on + * @param resourceInterface interface type of the resource to operate on + * @param representation representation of the resource + * @param queryParametersMap Map which can have the query parameter name and value + * @param attributeHandler attribute handler + * The callback function will be invoked with a map of attribute name and values. + * The callback function will also have the result from this Put operation + * This will have error codes. + * The Representation parameter maps which can either have all the attribute names + * and values + * (which will represent entire state of the resource) or a + * set of attribute names and values which needs to be modified + * @param QualityOfService the quality of communication + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * NOTE: OCStackResult is defined in ocstack.h.
+ */ + OCStackResult post(const std::string& resourceType, const std::string& resourceInterface, + const OCRepresentation& representation, const QueryParamsMap& queryParametersMap, + PostCallback attributeHandler); + OCStackResult post(const std::string& resourceType, const std::string& resourceInterface, + const OCRepresentation& representation, const QueryParamsMap& queryParametersMap, + PostCallback attributeHandler, QualityOfService QoS); + + /** + * Function to perform DELETE operation + * @param observeHandler handles callback + * The callback function will have headerOptions and result from this Delete + * operation. This will have error codes + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. + * NOTE: OCStackResult is defined in ocstack.h. + */ + OCStackResult deleteResource(DeleteCallback deleteHandler); + OCStackResult deleteResource(DeleteCallback deleteHandler, QualityOfService QoS); + + /** + * Function to set observation on the resource + * @param observeType allows the client to specify how it wants to observe. + * @param queryParametersMap map which can have the query parameter name and value + * @param observeHandler handles callback + * The callback function will be invoked with a map of attribute name and values. + * The callback function will also have the result from this observe operation + * This will have error codes + * @param QualityOfService the quality of communication + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. + * NOTE: OCStackResult is defined in ocstack.h. + */ + OCStackResult observe(ObserveType observeType, const QueryParamsMap& queryParametersMap, + ObserveCallback observeHandler); + OCStackResult observe(ObserveType observeType, const QueryParamsMap& queryParametersMap, + ObserveCallback observeHandler, QualityOfService qos); + + /** + * Function to cancel the observation on the resource + * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. + * NOTE: OCStackResult is defined in ocstack.h. + */ + OCStackResult cancelObserve(); + OCStackResult cancelObserve(QualityOfService qos); + + /** + * Function to set header information. + * @param headerOptions std::vector where header information(header optionID and optionData + * is passed + * + * NOTE: Once the headers information is set, it will be applicable to GET, PUT and observe + * request.
+ * setHeaderOptions can be used multiple times if headers need to be modifed by the client. + * Latest headers will be used to send in the request.
+ * NOTE: Initial support is only for two headers. If headerMap consists of more than two + * header options, they will be ignored.
+ * Use unsetHeaderOptions API to clear the header information. + */ + void setHeaderOptions(const HeaderOptions& headerOptions) + { + m_headerOptions = headerOptions; + } + + /** + * Function to unset header options. + */ + void unsetHeaderOptions() + { + m_headerOptions.clear(); + } + + /** + * Function to get the host address of this resource + * @return std::string host address + * NOTE: This might or might not be exposed in future due to security concerns + */ + std::string host() const; + + /** + * Function to get the URI for this resource + * @return std::string resource URI + */ + std::string uri() const; + + /** + * Function to provide ability to check if this resource is observable or not + * @return bool true indicates resource is observable; false indicates resource is + * not observable. + */ + bool isObservable() const; + + /** + * Function to get the list of resource types + * @return vector of resource types + */ + std::vector getResourceTypes() const + { + return m_resourceTypes; + } + + /** + * Function to get the list of resource interfaces + * @return vector of resource interface + */ + std::vector getResourceInterfaces(void) const + { + return m_interfaces; + } + + private: + std::weak_ptr m_clientWrapper; + std::string m_uri; + std::string m_host; + bool m_isObservable; + bool m_isCollection; + std::vector m_resourceTypes; + std::vector m_interfaces; + std::vector m_children; + OCDoHandle m_observeHandle; + HeaderOptions m_headerOptions; + + private: + OCResource(std::weak_ptr clientWrapper, const std::string& host, + const std::string& uri, bool observable, const std::vector& resourceTypes, + const std::vector& interfaces); + }; + +} // namespace OC + +#endif //__OCRESOURCE_H diff --git a/resource/include/OCResourceRequest.h b/resource/include/OCResourceRequest.h new file mode 100644 index 000000000..101f6fb85 --- /dev/null +++ b/resource/include/OCResourceRequest.h @@ -0,0 +1,232 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// @file OCResourceRequest.h + +/// @brief This file contains the declaration of classes and its members related to +/// ResourceRequest. + +#ifndef __OCRESOURCEREQUEST_H +#define __OCRESOURCEREQUEST_H + +#include "OCApi.h" +#include "OCRepresentation.h" + +void formResourceRequest(OCEntityHandlerFlag, + OCEntityHandlerRequest*, + std::shared_ptr); + + +namespace OC +{ + /** + * @brief OCResourceRequest provides APIs to extract details from a request URI + */ + class OCResourceRequest + { + public: + typedef std::shared_ptr Ptr; + + /** + * Virtual destructor + */ + virtual ~OCResourceRequest(void) + { + } + + /** + * Retrieves the type of request string for the entity handler function to operate + * @return std::string request type. This could be 'GET'/'PUT'/'POST'/'DELETE' + */ + std::string getRequestType() const {return m_requestType;} + + /** + * Retrieves the query parameters from the request + * @return std::string query parameters in the request + */ + const QueryParamsMap& getQueryParameters() const {return m_queryParameters;} + + /** + * Retrieves the request handler flag type. This can be either INIT flag or + * REQUEST flag or OBSERVE flag. + * NOTE: + * INIT indicates that the vendor's entity handler should go and perform + * initialization operations + * REQUEST indicates that it is a request of certain type (GET/PUT/POST/DELETE) + * and entity handler needs to perform corresponding operations + * OBSERVE indicates that the request is of type Observe and entity handler + * needs to perform corresponding operations + * @return int type of request flag + */ + int getRequestHandlerFlag() const {return m_requestHandlerFlag;} + + /** + * Provides the entire resource attribute representation + * @return OCRepresentation reference containing the name value pairs + * representing the resource's attributes + */ + const OCRepresentation& getResourceRepresentation() const {return m_representation;} + + /** + * @return ObservationInfo reference provides observation information + */ + const ObservationInfo& getObservationInfo() const {return m_observationInfo;} + + /** + * sets resource uri + * @param resourceUri specifies the resource uri + */ + void setResourceUri(const std::string resourceUri) + { + m_resourceUri = resourceUri; + } + + /** + * gets resource uri + * @return std::string resource uri + */ + std::string getResourceUri(void) + { + return m_resourceUri; + } + + /** + * This API retrieves headerOptions which was sent from a client + * + * @return std::map HeaderOptions with the header options + */ + const HeaderOptions& getHeaderOptions() const + { + return m_headerOptions; + } + + /** + * This API retrieves the request handle + * + * @return OCRequestHandle + */ + const OCRequestHandle& getRequestHandle() const + { + return m_requestHandle; + } + + /** + * This API retrieves the resource handle + * + * return OCResourceHandle + */ + const OCResourceHandle& getResourceHandle() const + { + return m_resourceHandle; + } + + private: + std::string m_requestType; + std::string m_resourceUri; + QueryParamsMap m_queryParameters; + int m_requestHandlerFlag; + OCRepresentation m_representation; + ObservationInfo m_observationInfo; + HeaderOptions m_headerOptions; + OCRequestHandle m_requestHandle; + OCResourceHandle m_resourceHandle; + + + private: + friend void (::formResourceRequest)(OCEntityHandlerFlag, OCEntityHandlerRequest*, + std::shared_ptr); + void setRequestType(const std::string& requestType) + { + m_requestType = requestType; + } + + void setPayload(const std::string& requestPayload) + { + if(requestPayload.empty()) + { + return; + } + + MessageContainer info; + info.setJSONRepresentation(requestPayload); + + const std::vector& reps = info.representations(); + if(reps.size() >0) + { + std::vector::const_iterator itr = reps.begin(); + std::vector::const_iterator back = reps.end(); + m_representation = *itr; + ++itr; + + for(;itr != back; ++itr) + { + m_representation.addChild(*itr); + } + } + else + { + throw OCException(OC::Exception::INVALID_REPRESENTATION); + } + } + + void setQueryParams(QueryParamsMap& queryParams) + { + m_queryParameters = queryParams; + } + + void setRequestHandlerFlag(int requestHandlerFlag) + { + m_requestHandlerFlag = requestHandlerFlag; + } + + void setObservationInfo(const ObservationInfo& observationInfo) + { + m_observationInfo = observationInfo; + } + + void setHeaderOptions(const HeaderOptions& headerOptions) + { + m_headerOptions = headerOptions; + } + + /** + * This API allows to set request handle + * @param requestHandle - OCRequestHandle type used to set the + * request handle + */ + void setRequestHandle(const OCRequestHandle& requestHandle) + { + m_requestHandle = requestHandle; + } + + /** + * This API allows to set the resource handle + * @param resourceHandle - OCResourceHandle type used to set the + * resource handle + */ + void setResourceHandle(const OCResourceHandle& resourceHandle) + { + m_resourceHandle = resourceHandle; + } + + }; + }// namespace OC + +#endif //__OCRESOURCEREQUEST_H diff --git a/resource/include/OCResourceResponse.h b/resource/include/OCResourceResponse.h new file mode 100644 index 000000000..1c8e3fa16 --- /dev/null +++ b/resource/include/OCResourceResponse.h @@ -0,0 +1,268 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// @file OCResourceResponse.h + +/// @brief This file contains the declaration of classes and its members related to +/// ResourceResponse. + +#ifndef __OCRESOURCERESPONSE_H +#define __OCRESOURCERESPONSE_H + +#include "OCApi.h" +#include +#include +#include + +using namespace std; + +namespace OC +{ + class InProcServerWrapper; + + /** + * @brief OCResourceResponse provides APIs to set the response details + */ + class OCResourceResponse + { + public: + typedef std::shared_ptr Ptr; + + OCResourceResponse() + {} + + virtual ~OCResourceResponse(void) {} + + /** + * This API sets the error code for this response + * @param eCode error code to set + */ + void setErrorCode(const int eCode) { m_errorCode = eCode; } + + /** + * gets new resource uri + * @return std::string new resource uri + */ + std::string getNewResourceUri(void) + { + return m_newResourceUri; + } + + /** + * sets new resource uri + * @param newResourceUri specifies the resource uri of the resource created + */ + void setNewResourceUri(const std::string newResourceUri) + { + m_newResourceUri = newResourceUri; + } + + /** + * This API allows to set headerOptions in the response + * @param headerOptions HeaderOptions vector consisting of OCHeaderOption objects + */ + void setHeaderOptions(const HeaderOptions& headerOptions) + { + m_headerOptions = headerOptions; + } + + /** + * This API allows to set request handle + * + * @param requestHandle - OCRequestHandle type used to set the request handle + */ + void setRequestHandle(const OCRequestHandle& requestHandle) + { + m_requestHandle = requestHandle; + } + + /** + * This API allows to set the resource handle + * + * @param resourceHandle - OCResourceHandle type used to set the resource handle + */ + void setResourceHandle(const OCResourceHandle& resourceHandle) + { + m_resourceHandle = resourceHandle; + } + + /** + * This API allows to set the EntityHandler response result + * + * @param responseResult - OCEntityHandlerResult type to set the result value + */ + void setResponseResult(const OCEntityHandlerResult& responseResult) + { + m_responseResult = responseResult; + } + + /** + * API to set the entire resource attribute representation + * @param attributeMap reference containing the name value pairs representing + * the resource's attributes + * @param interface specifies the interface + */ + void setResourceRepresentation(OCRepresentation& rep, std::string interface) { + m_interface = interface; + m_representation = rep; + } + + /** + * API to set the entire resource attribute representation + * @param attributeMap rvalue reference containing the name value pairs representing + * the resource's attributes + * @param interface specifies the interface + */ + void setResourceRepresentation(OCRepresentation&& rep, std::string interface) { + setResourceRepresentation(rep, interface); + } + + /** + * API to set the entire resource attribute representation + * @param attributeMap reference containing the name value pairs representing the resource's + * attributes + */ + void setResourceRepresentation(OCRepresentation& rep) { + // Call the default + m_interface = DEFAULT_INTERFACE; + m_representation = rep; + } + + /** + * API to set the entire resource attribute representation + * @param attributeMap rvalue reference containing the name value pairs representing the + * resource's attributes + */ + void setResourceRepresentation(OCRepresentation&& rep) { + // Call the above function + setResourceRepresentation(rep); + } + private: + std::string m_newResourceUri; + int m_errorCode; + HeaderOptions m_headerOptions; + std::string m_interface; + OCRepresentation m_representation; + OCRequestHandle m_requestHandle; + OCResourceHandle m_resourceHandle; + OCEntityHandlerResult m_responseResult; + + private: + friend class InProcServerWrapper; + + std::string getPayload() const + { + MessageContainer inf; + OCRepresentation first(m_representation); + + if(m_interface==LINK_INTERFACE) + { + first.setInterfaceType(InterfaceType::LinkParent); + } + else if(m_interface==BATCH_INTERFACE) + { + first.setInterfaceType(InterfaceType::BatchParent); + } + else + { + first.setInterfaceType(InterfaceType::DefaultParent); + } + + inf.addRepresentation(first); + + for(const OCRepresentation& rep : m_representation.getChildren()) + { + OCRepresentation cur(rep); + + if(m_interface==LINK_INTERFACE) + { + cur.setInterfaceType(InterfaceType::LinkChild); + } + else if(m_interface==BATCH_INTERFACE) + { + cur.setInterfaceType(InterfaceType::BatchChild); + } + else + { + cur.setInterfaceType(InterfaceType::DefaultChild); + } + + inf.addRepresentation(cur); + + } + + return inf.getJSONRepresentation(OCInfoFormat::ExcludeOC); + } + public: + + /** + * Get error code + */ + int getErrorCode() const; + + /** + * Get the Response Representation + */ + const OCRepresentation& getResourceRepresentation() const + { + return m_representation; + } + /** + * This API allows to retrieve headerOptions from a response + */ + const HeaderOptions& getHeaderOptions() const + { + return m_headerOptions; + } + + /** + * This API retrieves the request handle + * + * @return OCRequestHandle value + */ + const OCRequestHandle& getRequestHandle() const + { + return m_requestHandle; + } + + /** + * This API retrieves the resource handle + * + * @return OCResourceHandle value + */ + const OCResourceHandle& getResourceHandle() const + { + return m_resourceHandle; + } + + /** + * This API retrieves the entity handle response result + * + * @return OCEntityHandler result value + */ + const OCEntityHandlerResult getResponseResult() const + { + return m_responseResult; + } + }; + +} // namespace OC + +#endif //__OCRESOURCERESPONSE_H diff --git a/resource/include/OCSecurityModel.h b/resource/include/OCSecurityModel.h new file mode 100644 index 000000000..9c447aa35 --- /dev/null +++ b/resource/include/OCSecurityModel.h @@ -0,0 +1,56 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// @file OCSecurityModel.h + +/// @brief This file contains the declaration of classes and its members required to provide +/// security model support. + +#ifndef __OCSECURITYMODEL_H +#define __OCSECURITYMODEL_H + +#include "OCApi.h" + +namespace OC +{ + /** + * @brief This class provides the required security model to + * access a service or a particular resource. + */ + class OCSecurityModel + { + public: + OCSecurityModel(void); + + virtual ~OCSecurityModel(void); + + /** + * @fn checks the security access + * + * @param sourceURI - source URI + * @param destinationURI - destination URI of the resoruce to access + * @param encryptionLevel - Encryption level + * @param remoteIdentity - remote identity + */ + void checkAccess(URI sourceURI, URI destinationURI, int encryptionLevel, int remoteIdentity); + }; +} + +#endif //__OCSECURITYMODEL_H diff --git a/resource/include/OCSerialization.h b/resource/include/OCSerialization.h new file mode 100644 index 000000000..f611407f3 --- /dev/null +++ b/resource/include/OCSerialization.h @@ -0,0 +1,280 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include +#include + +#include + +namespace OC +{ + class ListenOCContainer + { + private: + enum class OCSecureType + { + IPv4Secure, + IPv4 + }; + + class ListenResourceContainer + { + class ListenResourcePropertiesContainer + { + friend class cereal::access; + friend class ListenResourceContainer; + + template + void serialize(Archive& ar) + { + try + { + m_observable=false; + int obsTemp; + ar(cereal::make_nvp(OC::Key::OBSERVABLEKEY, obsTemp)); + m_observable = obsTemp != 0; + } + catch(cereal::Exception&) + { + // we swallow this exception, since it means the key + // doesn't exist, allowing these to be optional + ar.setNextName(nullptr); + } + + try + { + m_secure = false; + int secureTemp; + ar(cereal::make_nvp(OC::Key::SECUREKEY, secureTemp)); + m_secure = secureTemp != 0; + + m_port = -1; + ar(cereal::make_nvp(OC::Key::PORTKEY, m_port)); + } + catch(cereal::Exception&) + { + ar.setNextName(nullptr); + } + + try + { + ar(cereal::make_nvp(OC::Key::RESOURCETYPESKEY,m_resourceTypes)); + } + catch(cereal::Exception&) + { + ar.setNextName(nullptr); + } + try + { + ar(cereal::make_nvp(OC::Key::INTERFACESKEY, m_interfaces)); + } + catch(cereal::Exception&) + { + ar.setNextName(nullptr); + } + } + + bool m_observable; + std::vector m_resourceTypes; + std::vector m_interfaces; + bool m_secure; + int m_port; + }; + + public: + ListenResourceContainer() : m_loaded(false) + {} + + private: + friend class cereal::access; + friend class ListenOCContainer; + + template + void serialize(Archive& ar) + { + try + { + ar(cereal::make_nvp(OC::Key::URIKEY, m_uri)); + m_loaded=true; + } + catch(cereal::Exception&) + { + ar.setNextName(nullptr); + } + try + { + ar(cereal::make_nvp(OC::Key::PROPERTYKEY, m_props)); + m_loaded=true; + } + catch(cereal::Exception&) + { + ar.setNextName(nullptr); + } + } + + + std::string m_uri; + bool m_loaded; + ListenResourcePropertiesContainer m_props; + + bool loaded() const + { + return m_loaded; + } + + bool observable() const + { + return m_props.m_observable; + } + + OCSecureType secureType() const + { + return m_props.m_secure?OCSecureType::IPv4Secure :OCSecureType::IPv4; + } + + int port() const + { + return m_props.m_port; + } + + std::vector resourceTypes() const + { + return m_props.m_resourceTypes; + } + + std::vector interfaces() const + { + return m_props.m_interfaces; + } + }; + + private: + friend class cereal::access; + template + void serialize(Archive& ar) + { + std::vector resources; + ar(resources); + } + public: + ListenOCContainer(std::weak_ptr cw, const OCDevAddr& address, + std::stringstream& json): + m_clientWrapper(cw), m_address(address) + { + LoadFromJson(json); + } + + const std::vector>& Resources() const + { + return m_resources; + } + + private: + std::string ConvertOCAddrToString(OCSecureType sec, int secureport) + { + char stringAddress[DEV_ADDR_SIZE_MAX]; + uint16_t port; + + ostringstream os; + + if(sec== OCSecureType::IPv4) + { + os<<"coap://"; + } + else if(sec == OCSecureType::IPv4Secure) + { + os<<"coaps://"; + } + else + { + oclog() << "ConvertOCAddrToString(): invalid SecureType"<0 && secureport<=65535) + { + port = static_cast(secureport); + } + else if(sec == OCSecureType::IPv4 && 0==OCDevAddrToPort(&m_address, &port)) + { + // nothing to do, this is a successful case + } + else + { + oclog() << "ConvertOCAddrToString() : Invalid Port" + <(port); + + return os.str(); + } + + void LoadFromJson(std::stringstream& json) + { + cereal::JSONInputArchive archive(json); + + std::vector resources; + archive(cereal::make_nvp(OC::Key::OCKEY, resources)); + + m_resources.clear(); + + for(const auto& res : resources) + { + try + { + if(res.loaded()) + { + m_resources.push_back(std::shared_ptr( + new OCResource(m_clientWrapper, + ConvertOCAddrToString(res.secureType(),res.port()), + res.m_uri, res.observable(), res.resourceTypes(), + res.interfaces()))); + } + + } + catch(ResourceInitException& e) + { + oclog() << "listenCallback(): failed to create resource: " << e.what() + << std::flush; + } + } + } + std::vector> m_resources; + std::weak_ptr m_clientWrapper; + OCDevAddr m_address; + }; +} diff --git a/resource/include/OCUtilities.h b/resource/include/OCUtilities.h new file mode 100644 index 000000000..a7368207d --- /dev/null +++ b/resource/include/OCUtilities.h @@ -0,0 +1,101 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef _INTEL_OCUTILITIES_H_ +#define _INTEL_OCUTILITIES_H_ + +#include +#include +#include +#include +#include + +#include "OCException.h" + +namespace OC { + namespace Utilities { + + typedef std::map QueryParamsKeyVal; + /* + * @brief Helper function to get query parameter from a URI + * @remarks Its okay to return a copy of the container.\ + * The size is not expected to be huge. + * @remarks Temporary: The URI must strictly have\ + * coap as the protocol in the fully qualified URI\ + * e.g., coap://1.2.3.4:5657/foo?bar=0) + * @remarks If a separate class for URI parser is needed,\ + * please talk to Erich Keane. + * @todo If more URI elements need to be parsed,\ + * please move the common parsing logic to a + * different function + */ + QueryParamsKeyVal getQueryParams(const std::string& uri); + + } +} + +/* The C++11 standard unfortunately forgot to provide make_unique<>! However, if we're +using C++14 or later, we want to take the standard library's implementation: */ +#if defined(__cplusplus) && __cplusplus < 201300 +namespace OC { + + template + std::unique_ptr make_unique(XS&& ...xs) + { + return std::unique_ptr(new T(std::forward(xs)...)); + } + +} // namespace OC +#else + using std::make_unique; +#endif + +namespace OC { + + using OC::make_unique; + + /* Examine an OCStackResult, and either forward its value or raise an exception: */ + OCStackResult result_guard(const OCStackResult r); + + /* Check for a nullptr, and throw an exception if we see one; otherwise, return the + result of the function call: */ + template + auto nil_guard(PtrT&& p, FnT&& fn, ParamTs&& ...params) -> OCStackResult + { + if(nullptr == p) + { + throw OCException(OC::Exception::NIL_GUARD_NULL, OC_STACK_INVALID_PARAM); + } + + // Note that although parameters are being forwarded, std::bind() will make a single copy: + return std::bind(fn, p, std::forward(params)...)(); + } + + /* Check for nullptr and forward the result of an OC function call on success; raise + an exception on failure or exceptional result: */ + template + auto checked_guard(PtrT&& p, FnT&& fn, ParamTs&& ...params) -> OCStackResult + { + return result_guard(nil_guard(p, fn, std::forward(params)...)); + } + +} // namespace OC + +#endif diff --git a/resource/include/OicJsonSerializer.hpp b/resource/include/OicJsonSerializer.hpp new file mode 100644 index 000000000..d7eb98e02 --- /dev/null +++ b/resource/include/OicJsonSerializer.hpp @@ -0,0 +1,847 @@ +/*! \file OicJsonSerializer.hpp + \brief JSON input and output archives. +Note: this has been customized by Intel(R) for usage in the OIC project. +Nearly the entire file is from Cereal (see copyright notice below) other than specified +below +Added: +#include of AttributeValue Type +JSONOutputArchive::saveValue() to add JSON null value +loadAttributeValues to get attribute values out of a map (implemented in OCRepresentation) + +*/ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef CEREAL_ARCHIVES_JSON_HPP_ +#define CEREAL_ARCHIVES_JSON_HPP_ + +#include +#include +#include +namespace cereal +{ + //! An exception thrown when rapidjson fails an internal assertion + /*! @ingroup Utility */ + struct RapidJSONException : Exception + { RapidJSONException( const char * what_ ) : Exception( what_ ) {} }; +} + +// Override rapidjson assertions to throw exceptions by default +#ifndef RAPIDJSON_ASSERT +#define RAPIDJSON_ASSERT(x) if(!(x)){ \ + throw ::cereal::RapidJSONException("rapidjson internal assertion failure: " #x); } +#endif // RAPIDJSON_ASSERT + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace cereal +{ + // ###################################################################### + //! An output archive designed to save data to JSON + /*! This archive uses RapidJSON to build serialie data to JSON. + + JSON archives provides a human readable output but at decreased + performance (both in time and space) compared to binary archives. + + JSON benefits greatly from name-value pairs, which if present, will + name the nodes in the output. If these are not present, each level + of the output will be given an automatically generated delimited name. + + The precision of the output archive controls the number of decimals output + for floating point numbers and should be sufficiently large (i.e. at least 20) + if there is a desire to have binary equality between the numbers output and + those read in. In general you should expect a loss of precision when going + from floating point to text and back. + + JSON archives do not output the size information for any dynamically sized structure + and instead infer it from the number of children for a node. This means that data + can be hand edited for dynamic sized structures and will still be readable. This + is accomplished through the cereal::SizeTag object, which will cause the archive + to output the data as a JSON array (e.g. marked by [] instead of {}), which indicates + that the container is variable sized and may be edited. + + \ingroup Archives */ + class JSONOutputArchive : public OutputArchive + { + enum class NodeType { StartObject, InObject, StartArray, InArray }; + + typedef rapidjson::GenericWriteStream WriteStream; + typedef rapidjson::Writer JSONWriter; + + public: + /*! @name Common Functionality + Common use cases for directly interacting with an JSONOutputArchive */ + //! @{ + + //! A class containing various advanced options for the JSON archive + class Options + { + public: + //! Default options + static Options Default(){ return Options(); } + + //! Specify specific options for the JSONOutputArchive + /*! @param precision The precision used for floating point numbers*/ + explicit Options( int precision = std::numeric_limits::max_digits10) : + itsPrecision( precision ) { } + + private: + friend class JSONOutputArchive; + int itsPrecision; + }; + + //! Construct, outputting to the provided stream + /*! @param stream The stream to output to. + @param options The JSON specific options to use. See the Options struct + for the values of default parameters */ + JSONOutputArchive(std::ostream & stream, Options const & options = Options::Default() ) : + OutputArchive(this), + itsWriteStream(stream), + itsWriter(itsWriteStream, options.itsPrecision), + itsNextName(nullptr) + { + itsNameCounter.push(0); + itsNodeStack.push(NodeType::StartObject); + } + + //! Destructor, flushes the JSON + ~JSONOutputArchive() + { + itsWriter.EndObject(); + } + + //! Saves some binary data, encoded as a base64 string, with an optional name + /*! This will create a new node, optionally named, and insert a value that consists of + the data encoded as a base64 string */ + void saveBinaryValue( const void * data, size_t size, const char * name = nullptr ) + { + setNextName( name ); + writeName(); + + auto base64string = base64::encode( reinterpret_cast( data ), size ); + saveValue( base64string ); + }; + + //! @} + /*! @name Internal Functionality + Functionality designed for use by those requiring control over the inner mechanisms of + the JSONOutputArchive */ + //! @{ + + //! Starts a new node in the JSON output + /*! The node can optionally be given a name by calling setNextName prior + to creating the node + + Nodes only need to be started for types that are themselves objects or arrays */ + void startNode() + { + writeName(); + itsNodeStack.push(NodeType::StartObject); + itsNameCounter.push(0); + } + + //! Designates the most recently added node as finished + void finishNode() + { + // if we ended up serializing an empty object or array, writeName + // will never have been called - so start and then immediately end + // the object/array. + // + // We'll also end any object/arrays we happen to be in + switch(itsNodeStack.top()) + { + case NodeType::StartArray: + itsWriter.StartArray(); + case NodeType::InArray: + itsWriter.EndArray(); + break; + case NodeType::StartObject: + itsWriter.StartObject(); + case NodeType::InObject: + itsWriter.EndObject(); + break; + } + + itsNodeStack.pop(); + itsNameCounter.pop(); + } + + //! Sets the name for the next node created with startNode + void setNextName( const char * name ) + { + itsNextName = name; + } + + //! Saves a null to the current node, added by Intel + void saveValue() { itsWriter.Null_(); } + //! Saves a bool to the current node + void saveValue(bool b) { itsWriter.Bool_(b); } + //! Saves an int to the current node + void saveValue(int i) { itsWriter.Int(i); } + //! Saves a uint to the current node + void saveValue(unsigned u) { itsWriter.Uint(u); } + //! Saves an int64 to the current node + void saveValue(int64_t i64) { itsWriter.Int64(i64); } + //! Saves a uint64 to the current node + void saveValue(uint64_t u64) { itsWriter.Uint64(u64); } + //! Saves a double to the current node + void saveValue(double d) { itsWriter.Double(d); } + //! Saves a string to the current node + void saveValue(std::string const & s) { itsWriter.String(s.c_str(), static_cast( s.size() )); } + //! Saves a const char * to the current node + void saveValue(char const * s) { itsWriter.String(s); } + + public: +#ifdef _MSC_VER + //! MSVC only long overload to current node + void saveValue( unsigned long lu ){ saveLong( lu ); }; +#else // _MSC_VER + //! Serialize a long if it would not be caught otherwise + template inline + typename std::enable_if::value && + !std::is_same::value && + !std::is_same::value, void>::type + saveValue( T t ) + { + saveLong( t ); + return t; + } + + //! Serialize an unsigned long if it would not be caught otherwise + template inline + typename std::enable_if::value && + !std::is_same::value && + !std::is_same::value, void>::type + saveValue( T t ) + { + saveLong( t ); + return t; + } +#endif // _MSC_VER + + //! Save exotic arithmetic as strings to current node + /*! Handles long long (if distinct from other types), unsigned long (if distinct), and long double */ + template inline + typename std::enable_if::value && + !std::is_same::value && + !std::is_same::value && + !std::is_same::value && + !std::is_same::value && + (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long)), void>::type + saveValue(T const & t) + { + std::stringstream ss; ss.precision( std::numeric_limits::max_digits10 ); + ss << t; + saveValue( ss.str() ); + return t; + } + + //! Write the name of the upcoming node and prepare object/array state + /*! Since writeName is called for every value that is output, regardless of + whether it has a name or not, it is the place where we will do a deferred + check of our node state and decide whether we are in an array or an object. + + The general workflow of saving to the JSON archive is: + + 1. (optional) Set the name for the next node to be created, usually done by an NVP + 2. Start the node + 3. (if there is data to save) Write the name of the node (this function) + 4. (if there is data to save) Save the data (with saveValue) + 5. Finish the node + */ + void writeName() + { + NodeType const & nodeType = itsNodeStack.top(); + + // Start up either an object or an array, depending on state + if(nodeType == NodeType::StartArray) + { + itsWriter.StartArray(); + itsNodeStack.top() = NodeType::InArray; + } + else if(nodeType == NodeType::StartObject) + { + itsNodeStack.top() = NodeType::InObject; + itsWriter.StartObject(); + } + + // Array types do not output names + if(nodeType == NodeType::InArray) return; + + if(itsNextName == nullptr) + { + std::string name = "value" + std::to_string( itsNameCounter.top()++ ) + "\0"; + saveValue(name); + } + else + { + saveValue(itsNextName); + itsNextName = nullptr; + } + } + + //! Designates that the current node should be output as an array, not an object + void makeArray() + { + itsNodeStack.top() = NodeType::StartArray; + } + + //! @} + + private: + WriteStream itsWriteStream; //!< Rapidjson write stream + JSONWriter itsWriter; //!< Rapidjson writer + char const * itsNextName; //!< The next name + std::stack itsNameCounter; //!< Counter for creating unique names for unnamed nodes + std::stack itsNodeStack; + }; // JSONOutputArchive + + // ###################################################################### + //! An input archive designed to load data from JSON + /*! This archive uses RapidJSON to read in a JSON archive. + + Input JSON should have been produced by the JSONOutputArchive. Data can + only be added to dynamically sized containers (marked by JSON arrays) - + the input archive will determine their size by looking at the number of child nodes. + Only JSON originating from a JSONOutputArchive is officially supported, but data + from other sources may work if properly formatted. + + The JSONInputArchive does not require that nodes are loaded in the same + order they were saved by JSONOutputArchive. Using name value pairs (NVPs), + it is possible to load in an out of order fashion or otherwise skip/select + specific nodes to load. + + The default behavior of the input archive is to read sequentially starting + with the first node and exploring its children. When a given NVP does + not match the read in name for a node, the archive will search for that + node at the current level and load it if it exists. After loading an out of + order node, the archive will then proceed back to loading sequentially from + its new position. + + Consider this simple example where loading of some data is skipped: + + @code{cpp} + // imagine the input file has someData(1-9) saved in order at the top level node + ar( someData1, someData2, someData3 ); // XML loads in the order it sees in the file + ar( cereal::make_nvp( "hello", someData6 ) ); // NVP given does not + // match expected NVP name, so we search + // for the given NVP and load that value + ar( someData7, someData8, someData9 ); // with no NVP given, loading resumes at its + // current location, proceeding sequentially + @endcode + + \ingroup Archives */ + class JSONInputArchive : public InputArchive + { + private: + typedef rapidjson::GenericReadStream ReadStream; + typedef rapidjson::GenericValue> JSONValue; + typedef JSONValue::ConstMemberIterator MemberIterator; + typedef JSONValue::ConstValueIterator ValueIterator; + typedef rapidjson::Document::GenericValue GenericValue; + + public: + /*! @name Common Functionality + Common use cases for directly interacting with an JSONInputArchive */ + //! @{ + + //! Construct, reading from the provided stream + /*! @param stream The stream to read from */ + JSONInputArchive(std::istream & stream) : + InputArchive(this), + itsNextName( nullptr ), + itsReadStream(stream) + { + itsDocument.ParseStream<0>(itsReadStream); + itsIteratorStack.emplace_back(itsDocument.MemberBegin(), itsDocument.MemberEnd()); + } + + //! Loads some binary data, encoded as a base64 string + /*! This will automatically start and finish a node to load the data, and can be called directly by + users. + + Note that this follows the same ordering rules specified in the class description in regards + to loading in/out of order */ + void loadBinaryValue( void * data, size_t size, const char * name = nullptr ) + { + itsNextName = name; + + std::string encoded; + loadValue( encoded ); + auto decoded = base64::decode( encoded ); + + if( size != decoded.size() ) + throw Exception("Decoded binary data size does not match specified size"); + + std::memcpy( data, decoded.data(), decoded.size() ); + itsNextName = nullptr; + }; + + // Intel Added this as a custom parsing hook for the AttributeValue map + void loadAttributeValues(std::map& map); + + private: + //! @} + /*! @name Internal Functionality + Functionality designed for use by those requiring control over the inner mechanisms of + the JSONInputArchive */ + //! @{ + + //! An internal iterator that handles both array and object types + /*! This class is a variant and holds both types of iterators that + rapidJSON supports - one for arrays and one for objects. */ + class Iterator + { + public: + friend class cereal::JSONInputArchive; + Iterator() : itsIndex( 0 ), itsType(Null_) {} + + Iterator(MemberIterator begin, MemberIterator end) : + itsMemberItBegin(begin), itsMemberItEnd(end), itsIndex(0), itsType(Member) + { } + + Iterator(ValueIterator begin, ValueIterator end) : + itsValueItBegin(begin), itsValueItEnd(end), itsIndex(0), itsType(Value) + { } + + //! Advance to the next node + Iterator & operator++() + { + ++itsIndex; + return *this; + } + + //! Get the value of the current node + GenericValue const & value() + { + switch(itsType) + { + case Value : return itsValueItBegin[itsIndex]; + case Member: return itsMemberItBegin[itsIndex].value; + default: throw cereal::Exception("Invalid Iterator Type!"); + } + } + + //! Get the name of the current node, or nullptr if it has no name + const char * name() const + { + if( itsType == Member && (itsMemberItBegin + itsIndex) != itsMemberItEnd ) + return itsMemberItBegin[itsIndex].name.GetString(); + else + return nullptr; + } + + //! Adjust our position such that we are at the node with the given name + /*! @throws Exception if no such named node exists */ + inline void search( const char * searchName ) + { + const auto len = std::strlen( searchName ); + size_t index = 0; + for( auto it = itsMemberItBegin; it != itsMemberItEnd; ++it, ++index ) + if( std::strncmp( searchName, it->name.GetString(), len ) == 0 ) + { + itsIndex = index; + return; + } + + throw Exception("JSON Parsing failed - provided NVP not found"); + } + + private: + MemberIterator itsMemberItBegin, itsMemberItEnd; //!< The member iterator (object) + ValueIterator itsValueItBegin, itsValueItEnd; //!< The value iterator (array) + size_t itsIndex; //!< The current index of this iterator + enum Type {Value, Member, Null_} itsType; //!< Whether this holds values (array) or members (objects) or nothing + }; + + //! Searches for the expectedName node if it doesn't match the actualName + /*! This needs to be called before every load or node start occurs. This function will + check to see if an NVP has been provided (with setNextName) and if so, see if that name matches the actual + next name given. If the names do not match, it will search in the current level of the JSON for that name. + If the name is not found, an exception will be thrown. + + Resets the NVP name after called. + + @throws Exception if an expectedName is given and not found */ + inline void search() + { + // The name an NVP provided with setNextName() + if( itsNextName ) + { + // The actual name of the current node + auto const actualName = itsIteratorStack.back().name(); + + // Do a search if we don't see a name coming up, or if the names don't match + if( !actualName || std::strcmp( itsNextName, actualName ) != 0 ) + itsIteratorStack.back().search( itsNextName ); + } + + itsNextName = nullptr; + } + + public: + //! Starts a new node, going into its proper iterator + /*! This places an iterator for the next node to be parsed onto the iterator stack. If the next + node is an array, this will be a value iterator, otherwise it will be a member iterator. + + By default our strategy is to start with the document root node and then recursively iterate through + all children in the order they show up in the document. + We don't need to know NVPs to do this; we'll just blindly load in the order things appear in. + + If we were given an NVP, we will search for it if it does not match our the name of the next node + that would normally be loaded. This functionality is provided by search(). */ + void startNode() + { + search(); + + if(itsIteratorStack.back().value().IsArray()) + itsIteratorStack.emplace_back(itsIteratorStack.back().value().Begin(), itsIteratorStack.back().value().End()); + else + itsIteratorStack.emplace_back(itsIteratorStack.back().value().MemberBegin(), itsIteratorStack.back().value().MemberEnd()); + } + + //! Finishes the most recently started node + void finishNode() + { + itsIteratorStack.pop_back(); + ++itsIteratorStack.back(); + } + + //! Sets the name for the next node created with startNode + void setNextName( const char * name ) + { + itsNextName = name; + } + + //! Loads a value from the current node - small signed overload + template inline + typename std::enable_if::value && sizeof(T) < sizeof(int64_t), void>::type + loadValue(T & val) + { + search(); + + val = itsIteratorStack.back().value().GetInt(); + ++itsIteratorStack.back(); + } + + //! Loads a value from the current node - small unsigned overload + template inline + typename std::enable_if<(std::is_unsigned::value && sizeof(T) < sizeof(uint64_t)) && + !std::is_same::value, void>::type + loadValue(T & val) + { + search(); + + val = itsIteratorStack.back().value().GetUint(); + ++itsIteratorStack.back(); + } + + //! Loads a value from the current node - bool overload + void loadValue(bool & val) { search(); val = itsIteratorStack.back().value().GetBool_(); ++itsIteratorStack.back(); } + //! Loads a value from the current node - int64 overload + void loadValue(int64_t & val) { search(); val = itsIteratorStack.back().value().GetInt64(); ++itsIteratorStack.back(); } + //! Loads a value from the current node - uint64 overload + void loadValue(uint64_t & val) { search(); val = itsIteratorStack.back().value().GetUint64(); ++itsIteratorStack.back(); } + //! Loads a value from the current node - float overload + void loadValue(float & val) { search(); val = static_cast(itsIteratorStack.back().value().GetDouble()); ++itsIteratorStack.back(); } + //! Loads a value from the current node - double overload + void loadValue(double & val) { search(); val = itsIteratorStack.back().value().GetDouble(); ++itsIteratorStack.back(); } + //! Loads a value from the current node - string overload + void loadValue(std::string & val) { search(); val = itsIteratorStack.back().value().GetString(); ++itsIteratorStack.back(); } + + private: + //! Convert a string to a long long + void stringToNumber( std::string const & str, long long & val ) { val = std::stoll( str ); } + //! Convert a string to an unsigned long long + void stringToNumber( std::string const & str, unsigned long long & val ) { val = std::stoull( str ); } + //! Convert a string to a long double + void stringToNumber( std::string const & str, long double & val ) { val = std::stold( str ); } + + public: + //! Loads a value from the current node - long double and long long overloads + template inline + typename std::enable_if::value && + !std::is_same::value && + !std::is_same::value && + !std::is_same::value && + !std::is_same::value && + (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long)), void>::type + loadValue(T & val) + { + std::string encoded; + loadValue( encoded ); + stringToNumber( encoded, val ); + } + + //! Loads the size for a SizeTag + void loadSize(size_type & size) + { + size = (itsIteratorStack.rbegin() + 1)->value().Size(); + } + + //! @} + + private: + const char * itsNextName; //!< Next name set by NVP + ReadStream itsReadStream; //!< Rapidjson write stream + std::vector itsIteratorStack; //!< 'Stack' of rapidJSON iterators + rapidjson::Document itsDocument; //!< Rapidjson document + }; + + // ###################################################################### + // JSONArchive prologue and epilogue functions + // ###################################################################### + + // ###################################################################### + //! Prologue for NVPs for JSON archives + /*! NVPs do not start or finish nodes - they just set up the names */ + template inline + void prologue( JSONOutputArchive &, NameValuePair const & ) + { } + + //! Prologue for NVPs for JSON archives + template inline + void prologue( JSONInputArchive &, NameValuePair const & ) + { } + + // ###################################################################### + //! Epilogue for NVPs for JSON archives + /*! NVPs do not start or finish nodes - they just set up the names */ + template inline + void epilogue( JSONOutputArchive &, NameValuePair const & ) + { } + + //! Epilogue for NVPs for JSON archives + /*! NVPs do not start or finish nodes - they just set up the names */ + template inline + void epilogue( JSONInputArchive &, NameValuePair const & ) + { } + + // ###################################################################### + //! Prologue for SizeTags for JSON archives + /*! SizeTags are strictly ignored for JSON, they just indicate + that the current node should be made into an array */ + template inline + void prologue( JSONOutputArchive & ar, SizeTag const & ) + { + ar.makeArray(); + } + + //! Prologue for SizeTags for JSON archives + template inline + void prologue( JSONInputArchive &, SizeTag const & ) + { } + + // ###################################################################### + //! Epilogue for SizeTags for JSON archives + /*! SizeTags are strictly ignored for JSON */ + template inline + void epilogue( JSONOutputArchive &, SizeTag const & ) + { } + + //! Epilogue for SizeTags for JSON archives + template inline + void epilogue( JSONInputArchive &, SizeTag const & ) + { } + + // ###################################################################### + //! Prologue for all other types for JSON archives (except minimal types) + /*! Starts a new node, named either automatically or by some NVP, + that may be given data by the type about to be archived + + Minimal types do not start or finish nodes */ + template inline + typename std::enable_if::value && + !traits::has_minimal_output_serialization::value, void>::type + prologue( JSONOutputArchive & ar, T const & ) + { + ar.startNode(); + } + + //! Prologue for all other types for JSON archives + template inline + typename std::enable_if::value && + !traits::has_minimal_input_serialization::value, void>::type + prologue( JSONInputArchive & ar, T const & ) + { + ar.startNode(); + } + + // ###################################################################### + //! Epilogue for all other types other for JSON archives (except minimal types + /*! Finishes the node created in the prologue + + Minimal types do not start or finish nodes */ + template inline + typename std::enable_if::value && + !traits::has_minimal_output_serialization::value, void>::type + epilogue( JSONOutputArchive & ar, T const & ) + { + ar.finishNode(); + } + + //! Epilogue for all other types other for JSON archives + template inline + typename std::enable_if::value && + !traits::has_minimal_input_serialization::value, void>::type + epilogue( JSONInputArchive & ar, T const & ) + { + ar.finishNode(); + } + + // ###################################################################### + //! Prologue for arithmetic types for JSON archives + template inline + typename std::enable_if::value, void>::type + prologue( JSONOutputArchive & ar, T const & ) + { + ar.writeName(); + } + + //! Prologue for arithmetic types for JSON archives + template inline + typename std::enable_if::value, void>::type + prologue( JSONInputArchive &, T const & ) + { } + + // ###################################################################### + //! Epilogue for arithmetic types for JSON archives + template inline + typename std::enable_if::value, void>::type + epilogue( JSONOutputArchive &, T const & ) + { } + + //! Epilogue for arithmetic types for JSON archives + template inline + typename std::enable_if::value, void>::type + epilogue( JSONInputArchive &, T const & ) + { } + + // ###################################################################### + //! Prologue for strings for JSON archives + template inline + void prologue(JSONOutputArchive & ar, std::basic_string const &) + { + ar.writeName(); + } + + //! Prologue for strings for JSON archives + template inline + void prologue(JSONInputArchive &, std::basic_string const &) + { } + + // ###################################################################### + //! Epilogue for strings for JSON archives + template inline + void epilogue(JSONOutputArchive &, std::basic_string const &) + { } + + //! Epilogue for strings for JSON archives + template inline + void epilogue(JSONInputArchive &, std::basic_string const &) + { } + + // ###################################################################### + // Common JSONArchive serialization functions + // ###################################################################### + + //! Serializing NVP types to JSON + template inline + void save( JSONOutputArchive & ar, NameValuePair const & t ) + { + ar.setNextName( t.name ); + ar( t.value ); + } + + template inline + void load( JSONInputArchive & ar, NameValuePair & t ) + { + ar.setNextName( t.name ); + ar( t.value ); + } + + //! Saving for arithmetic to JSON + template inline + typename std::enable_if::value, void>::type + save(JSONOutputArchive & ar, T const & t) + { + ar.saveValue( t ); + } + + //! Loading arithmetic from JSON + template inline + typename std::enable_if::value, void>::type + load(JSONInputArchive & ar, T & t) + { + ar.loadValue( t ); + } + + //! saving string to JSON + template inline + void save(JSONOutputArchive & ar, std::basic_string const & str) + { + ar.saveValue( str ); + } + + //! loading string from JSON + template inline + void load(JSONInputArchive & ar, std::basic_string & str) + { + ar.loadValue( str ); + } + + // ###################################################################### + //! Saving SizeTags to JSON + template inline + void save( JSONOutputArchive &, SizeTag const & ) + { + // nothing to do here, we don't explicitly save the size + } + + //! Loading SizeTags from JSON + template inline + void load( JSONInputArchive & ar, SizeTag & st ) + { + ar.loadSize( st.size ); + } +} // namespace cereal + +// register archives for polymorphic support +CEREAL_REGISTER_ARCHIVE(cereal::JSONInputArchive) +CEREAL_REGISTER_ARCHIVE(cereal::JSONOutputArchive) + +#endif // CEREAL_ARCHIVES_JSON_HPP_ diff --git a/resource/include/OutOfProcClientWrapper.h b/resource/include/OutOfProcClientWrapper.h new file mode 100644 index 000000000..049c445a5 --- /dev/null +++ b/resource/include/OutOfProcClientWrapper.h @@ -0,0 +1,86 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef _OUT_OF_PROC_CLIENT_WRAPPER_H_ +#define _OUT_OF_PROC_CLIENT_WRAPPER_H_ + +#include + +namespace OC +{ + class OutOfProcClientWrapper : public IClientWrapper + { + public: + OutOfProcClientWrapper(std::weak_ptr csdkLock, + PlatformConfig cfg) + {} + + virtual OCStackResult ListenForResource(const std::string& serviceUrl, + const std::string& resourceType, FindCallback& callback, QualityOfService QoS) + {return OC_STACK_NOTIMPL;} + + virtual OCStackResult ListenForDevice(const std::string& serviceUrl, + const std::string& deviceURI, FindDeviceCallback& callback, + QualityOfService QoS) + {return OC_STACK_NOTIMPL;} + + virtual OCStackResult GetResourceRepresentation(const std::string& host, + const std::string& uri, const QueryParamsMap& queryParams, + const HeaderOptions& headerOptions, GetCallback& callback, + QualityOfService QoS) + {return OC_STACK_NOTIMPL;} + + virtual OCStackResult PutResourceRepresentation(const std::string& host, + const std::string& uri, const OCRepresentation& attributes, + const QueryParamsMap& queryParams, + const HeaderOptions& headerOptions, PutCallback& callback, + QualityOfService QoS) + {return OC_STACK_NOTIMPL;} + + virtual OCStackResult PostResourceRepresentation(const std::string& host, + const std::string& uri, const OCRepresentation& attributes, + const QueryParamsMap& queryParams, const HeaderOptions& headerOptions, + PostCallback& callback, QualityOfService QoS) + {return OC_STACK_NOTIMPL;} + + virtual OCStackResult DeleteResource(const std::string& host, const std::string& uri, + const HeaderOptions& headerOptions, DeleteCallback& callback, + QualityOfService QoS) {return OC_STACK_NOTIMPL;} + + virtual OCStackResult ObserveResource(ObserveType observeType, OCDoHandle* handle, + const std::string& host, const std::string& uri, const QueryParamsMap& queryParams, + const HeaderOptions& headerOptions, + ObserveCallback& callback, QualityOfService QoS){return OC_STACK_NOTIMPL;} + + virtual OCStackResult CancelObserveResource(OCDoHandle handle, const std::string& host, + const std::string& uri, + const HeaderOptions& headerOptions, QualityOfService QoS){return OC_STACK_NOTIMPL;} + + virtual OCStackResult SubscribePresence(OCDoHandle* handle, const std::string& host, + const std::string& resourceType, SubscribeCallback& presenceHandler) + {return OC_STACK_NOTIMPL;} + + virtual OCStackResult UnsubscribePresence(OCDoHandle handle){return OC_STACK_NOTIMPL;} + + virtual OCStackResult GetDefaultQos(QualityOfService& QoS){return OC_STACK_NOTIMPL;} + }; +} + +#endif diff --git a/resource/include/OutOfProcServerWrapper.h b/resource/include/OutOfProcServerWrapper.h new file mode 100644 index 000000000..91c6f15ee --- /dev/null +++ b/resource/include/OutOfProcServerWrapper.h @@ -0,0 +1,116 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef _OUT_OF_PROC_SERVER_WRAPPER_H_ +#define _OUT_OF_PROC_SERVER_WRAPPER_H_ + +#include + +namespace OC +{ + class OutOfProcServerWrapper : public IServerWrapper + { + public: + OutOfProcServerWrapper(PlatformConfig cfg) + {} + + virtual OCStackResult registerResource( + OCResourceHandle& resourceHandle, + std::string& resourceURI, + const std::string& resourceTypeName, + const std::string& resourceInterface, + EntityHandler& entityHandler, + uint8_t resourceProperty) + + { + // Not implemented + return OC_STACK_NOTIMPL; + } + + virtual OCStackResult registerDeviceInfo( + const OCDeviceInfo deviceInfo) + { + // Not implemented + return OC_STACK_NOTIMPL; + } + + virtual OCStackResult registerResourceWithHost( + OCResourceHandle& resourceHandle, + std::string& resourceHOST, + std::string& resourceURI, + const std::string& resourceTypeName, + const std::string& resourceInterface, + EntityHandler& entityHandler, + uint8_t resourceProperty) + { + // Not implemented + return OC_STACK_NOTIMPL; + } + + virtual OCStackResult unregisterResource( + const OCResourceHandle& resourceHandle) + { + //Not implemented yet + return OC_STACK_ERROR; + } + + virtual OCStackResult bindTypeToResource( + const OCResourceHandle& resourceHandle, + const std::string& resourceTypeName) + { + //Not implemented yet + return OC_STACK_NOTIMPL; + } + + virtual OCStackResult bindInterfaceToResource( + const OCResourceHandle& resourceHandle, + const std::string& resourceInterfaceName) + { + //Not implemented yet + return OC_STACK_NOTIMPL; + } + + virtual OCStackResult startPresence(const unsigned int seconds) + { + //Not implemented yet + return OC_STACK_NOTIMPL; + } + + virtual OCStackResult stopPresence() + { + //Not implemented yet + return OC_STACK_NOTIMPL; + } + + virtual OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler) + { + //Not implemented yet + return OC_STACK_NOTIMPL; + } + + virtual OCStackResult sendResponse(const std::shared_ptr pResponse) + { + //Not implemented yet + return OC_STACK_NOTIMPL; + } + }; +} + +#endif diff --git a/resource/include/ResourceInitException.h b/resource/include/ResourceInitException.h new file mode 100644 index 000000000..c045b6c9e --- /dev/null +++ b/resource/include/ResourceInitException.h @@ -0,0 +1,127 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef _RESOURCE_INIT_EXCEPTION_H_ +#define _RESOURCE_INIT_EXCEPTION_H_ + +#include +#include +#include "StringConstants.h" + +namespace OC +{ + class ResourceInitException : public std::exception + { + public: + ResourceInitException( + bool missingUri, + bool missingType, + bool missingInterface, + bool missingClientWrapper, + bool invalidPort, + bool invalidIp) + : m_missingUri(missingUri), + m_missingType(missingType), + m_missingInterface(missingInterface), + m_missingClientWrapper(missingClientWrapper), + m_invalidPort(invalidPort), + m_invalidIp(invalidIp) + { + } + + bool isInvalidPort() const + { + return m_invalidPort; + } + + bool isInvalidIp() const + { + return m_invalidIp; + } + + bool isClientWrapperMissing() const + { + return m_missingClientWrapper; + } + + bool isUriMissing() const + { + return m_missingUri; + } + + bool isTypeMissing() const + { + return m_missingType; + } + + bool isInterfaceMissing() const + { + return m_missingInterface; + } + + virtual const char* what() const noexcept + { + std::string ret; + + if(isUriMissing()) + { + ret += OC::InitException::MISSING_URI; + } + + if(isTypeMissing()) + { + ret += OC::InitException::MISSING_TYPE; + } + + if(isInterfaceMissing()) + { + ret += OC::InitException::MISSING_INTERFACE; + } + + if(isClientWrapperMissing()) + { + ret += OC::InitException::MISSING_CLIENT_WRAPPER; + } + + if(isInvalidPort()) + { + ret += OC::InitException::INVALID_PORT; + } + + if(isInvalidIp()) + { + ret += OC::InitException::INVALID_IP; + } + + return ret.c_str(); + } + + private: + + bool m_missingUri; + bool m_missingType; + bool m_missingInterface; + bool m_missingClientWrapper; + bool m_invalidPort; + bool m_invalidIp; + }; +} + +#endif diff --git a/resource/include/StringConstants.h b/resource/include/StringConstants.h new file mode 100644 index 000000000..048a47660 --- /dev/null +++ b/resource/include/StringConstants.h @@ -0,0 +1,136 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef _STRING_CONSTANTS_H_ +#define _STRING_CONSTANTS_H_ + +#include + +using namespace std; + +namespace OC +{ + namespace InitException + { + static const std::string NO_ERROR = "No Error"; + static const std::string INVALID_URI = "Invalid URI"; + static const std::string INVALID_PORT = "Invalid Port"; + static const std::string INVALID_IP = "Invalid IP"; + static const std::string INVALID_CB = "Invalid Callback"; + static const std::string INVALID_METHOD = "Invalid Method"; + static const std::string GENERAL_FAULT = "General Fault"; + static const std::string UNKNOWN_ERROR = "Unknown Error"; + + static const std::string STACK_INIT_ERROR = "Error Initializing Stack"; + static const std::string NOT_CONFIGURED_AS_SERVER = + "Cannot static construct a Server when configured as a client"; + static const std::string INVALID_PARAM = "Invalid Param"; + static const std::string MISSING_URI = "Missing URI;"; + static const std::string MISSING_TYPE = "Missing Resource Type;"; + static const std::string MISSING_INTERFACE = "Missing Interface;"; + static const std::string MISSING_CLIENT_WRAPPER = "Missing ClientWrapper;"; + } + + namespace Exception // Not To Be Confused With 'InitException' + { + static const std::string SVCTYPE_OUTOFPROC = "ServiceType::OutOfProc"; + static const std::string BIND_TYPE_FAILED = "Bind Type to resource failed"; + static const std::string BIND_INTERFACE_FAILED = "Bind Interface to resource failed"; + static const std::string START_PRESENCE_FAILED = "startPresence failed"; + static const std::string END_PRESENCE_FAILED = "stopPresence failed"; + static const std::string INVALID_ARRAY = "Array type should have at least []"; + static const std::string STR_NULL_RESPONSE = "Response is NULL"; + static const std::string STR_PAYLOAD_OVERFLOW = "Payload overflow"; + static const std::string NIL_GUARD_NULL = "nullptr at nil_guard()"; + static const std::string GENERAL_JSON_PARSE_FAILED = "JSON Parser Error"; + static const std::string RESOURCE_UNREG_FAILED = "Unregistering resource failed"; + static const std::string OPTION_ID_RANGE_INVALID = + "Error: OptionID valid only from 2048 to 3000 inclusive."; + + static const std::string NO_ERROR = "No Error"; + static const std::string RESOURCE_CREATED = "Resource Created"; + static const std::string RESOURCE_DELETED = "Resource Deleted"; + static const std::string INVALID_URI = "Invalid URI"; + static const std::string INVALID_IP = "Invalid IP"; + static const std::string INVALID_PORT = "Invalid Port"; + static const std::string INVALID_CB = "Invalid Callback"; + static const std::string INVALID_METHOD = "Invalid Method"; + static const std::string INVALID_QUERY = "Invalid Query"; + static const std::string INVALID_PARAM = "Invalid Param"; + static const std::string INVALID_OBESERVE = "Invalid Observe Param"; + static const std::string NO_MEMORY = "No Memory"; + static const std::string COMM_ERROR = "Communication Error"; + static const std::string NOT_IMPL = "Not Implemented"; + static const std::string NOT_FOUND = "Resource Not Found"; + static const std::string RESOURCE_ERROR = "Resource Error"; + static const std::string SLOW_RESOURCE = "Slow Resource"; + static const std::string NO_OBSERVERS = "No Observers"; + static const std::string OBSV_NO_FOUND = "Stack observer not found"; + static const std::string OBSV_NOT_ADDED = "Stack observer not added"; + static const std::string OBSV_NOT_REMOVED = "Stack observer not removed"; + static const std::string STACK_RESOURCE_DELETED = "The specified resource has been deleted"; + static const std::string PRESENCE_STOPPED = "Stack presence stopped"; + static const std::string PRESENCE_TIMEOUT = "Stack presence timed out"; + static const std::string PRESENCE_NOT_HANDLED = "Stack presence should not be handled"; + static const std::string INVALID_OPTION = "Invalid option"; + static const std::string GENERAL_FAULT = "General Fault"; + static const std::string MALFORMED_STACK_RESPONSE = "Response from OC_STACK is malformed"; + static const std::string VIRTUAL_DO_NOT_HANDLE = "Virtual Do Not Handle"; + static const std::string PERSISTENT_BUFFER_REQUIRED = "Persistent response buffer required"; + static const std::string STACK_CONTINUE = "Stack continue"; + static const std::string INVALID_REQUEST_HANDLE = "Invalid request handle"; + static const std::string UNKNOWN_ERROR = "Unknown Error"; + static const std::string INVALID_REPRESENTATION = "Invalid Payload JSON"; + static const std::string INVALID_JSON_TYPE = "Unrecognized JSON Type "; + static const std::string INVALID_JSON_NUMERIC = "Unrecognized JSON Numeric "; + static const std::string INVALID_JSON_ARRAY_DEPTH = "Max JSON Array Depth exceeded"; + static const std::string INVALID_JSON_TYPE_TAG = "Invalid JSON Type Tag"; + static const std::string INVALID_ATTRIBUTE = "Invalid Attribute: "; + } + + namespace Error + { + static const std::string INVALID_IP = "Invalid IP"; + } + + namespace PlatformCommands + { + static const std::string GET = "GET"; + static const std::string PUT = "PUT"; + static const std::string POST = "POST"; + static const std::string DELETE = "DELETE"; + } + + namespace Key + { + static const std::string OCKEY = "oc"; + static const std::string URIKEY = "href"; + static const std::string OBSERVABLEKEY = "obs"; + static const std::string RESOURCETYPESKEY = "rt"; + static const std::string INTERFACESKEY = "if"; + static const std::string PROPERTYKEY = "prop"; + static const std::string REPKEY = "rep"; + static const std::string SECUREKEY = "sec"; + static const std::string PORTKEY = "port"; + } + +} + +#endif // _STRING_CONSTANTS_H_ diff --git a/resource/include/WrapperFactory.h b/resource/include/WrapperFactory.h new file mode 100644 index 000000000..2f15b8077 --- /dev/null +++ b/resource/include/WrapperFactory.h @@ -0,0 +1,89 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef _WRAPPER_FACTORY_H_ +#define _WRAPPER_FACTORY_H_ + +#include +#include +#include "IClientWrapper.h" +#include "IServerWrapper.h" +#include +#include +#include +#include +#include "StringConstants.h" + +namespace OC +{ + // Interface to permit easier mocking/unit testing later + class IWrapperFactory + { + public: + typedef std::shared_ptr Ptr; + + virtual IClientWrapper::Ptr CreateClientWrapper( + std::weak_ptr csdkLock, PlatformConfig cfg) =0; + virtual IServerWrapper::Ptr CreateServerWrapper( + std::weak_ptr csdkLock, PlatformConfig cfg) =0; + virtual ~IWrapperFactory(){} + }; + + // Class to create the client/server object! + class WrapperFactory : public IWrapperFactory + { + public: + WrapperFactory(){} + + virtual IClientWrapper::Ptr CreateClientWrapper( + std::weak_ptr csdkLock, PlatformConfig cfg) + { + switch(cfg.serviceType) + { + case ServiceType::InProc: + return std::make_shared(csdkLock, cfg); + break; + case ServiceType::OutOfProc: + return std::make_shared(csdkLock, cfg); + break; + } + return nullptr; + } + + virtual IServerWrapper::Ptr CreateServerWrapper( + std::weak_ptr csdkLock, PlatformConfig cfg) + { + switch(cfg.serviceType) + { + case ServiceType::InProc: + return std::make_shared(csdkLock, cfg); + break; + case ServiceType::OutOfProc: + throw OC::OCException(OC::Exception::SVCTYPE_OUTOFPROC, OC_STACK_NOTIMPL); + break; + } + return nullptr; + } + + virtual ~WrapperFactory(){} + }; +} + +#endif diff --git a/resource/makefile b/resource/makefile new file mode 100644 index 000000000..a710781f2 --- /dev/null +++ b/resource/makefile @@ -0,0 +1,129 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +# override with `make BUILD=debug` +# default to release build +BUILD := release +CXX := g++ +#CXX := clang + +ifeq ($(ROOT_DIR), ) + ROOT_DIR := $(PWD) +endif +ifeq ($(PLATFORM), ) + PLATFORM := "linux" +endif + +DEPEND_DIR:= $(ROOT_DIR)/dependencies +CEREAL_DIR:= $(DEPEND_DIR)/cereal + +OUT_DIR := $(ROOT_DIR)/$(BUILD) +OBJ_DIR := $(OUT_DIR)/obj + +CXX_FLAGS.debug := -g3 -std=c++0x -Wall -pthread -O0 +CXX_FLAGS.release := -std=c++0x -Wall -pthread -O3 + +CXX_INC := -I./include/ +CXX_INC += -I./oc_logger/include + +CXX_INC += -I./csdk/stack/include +CXX_INC += -I./csdk/ocsocket/include +CXX_INC += -I./csdk/ocrandom/include +CXX_INC += -I./csdk/logger/include +CXX_INC += -I./csdk/libcoap +CXX_INC += -I$(CEREAL_DIR)/include +# Force metatargets to build: +all.PHONY: applyDepPatches prep_dirs c_sdk oc_logger_target liboc.a examples + +buildScript_all.PHONY: applyDepPatches prep_dirs oc_logger_target liboc.a + +all: all.PHONY + +buildScript_all: buildScript_all.PHONY + +prep_dirs: deps + -mkdir -p $(OUT_DIR) + -mkdir -p $(OBJ_DIR) + +# used to fetch all dependencies +deps: + -mkdir -p $(DEPEND_DIR) +#cereal fetch + if [ ! -d "$(CEREAL_DIR)" ]; then\ + cd $(DEPEND_DIR) && git clone https://github.com/USCiLab/cereal.git;\ + cd $(CEREAL_DIR) && git checkout 7121e91e6ab8c3e6a6516d9d9c3e6804e6f65245;\ + fi + +applyDepPatches: deps +#reset git to the 'base version', so we can apply our patch without issues + cd $(CEREAL_DIR) && git reset --hard 7121e91e6ab8c3e6a6516d9d9c3e6804e6f65245; + cd $(CEREAL_DIR) && git apply $(ROOT_DIR)/patches/cereal_gcc46.patch + +c_sdk: + cd csdk && $(MAKE) "BUILD=$(BUILD)" "PLATFORM=$(PLATFORM)" + +oc_logger_target: + cd oc_logger && $(MAKE) "BUILD=$(BUILD)" + +cpp_sdk: prep_dirs c_sdk liboc.a + +examples: liboc.a + cd examples && $(MAKE) apps "BUILD=$(BUILD)" + +liboc.a: OCPlatform_impl.o OCPlatform.o OCResource.o OCException.o OCUtilities.o InProcServerWrapper.o InProcClientWrapper.o OCRepresentation.o + ar -cvq $(OBJ_DIR)/liboc.a $(OBJ_DIR)/OCPlatform_impl.o $(OBJ_DIR)/OCPlatform.o $(OBJ_DIR)/OCResource.o $(OBJ_DIR)/OCException.o $(OBJ_DIR)/OCUtilities.o $(OBJ_DIR)/InProcServerWrapper.o $(OBJ_DIR)/InProcClientWrapper.o $(OBJ_DIR)/OCRepresentation.o + +OCPlatform_impl.o: src/OCPlatform_impl.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCPlatform_impl.cpp $(CXX_INC) + +OCPlatform.o: src/OCPlatform.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCPlatform.cpp $(CXX_INC) + +OCRepresentation.o: src/OCRepresentation.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCRepresentation.cpp $(CXX_INC) + +OCResource.o: src/OCResource.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCResource.cpp $(CXX_INC) + +OCException.o: src/OCException.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCException.cpp $(CXX_INC) + +OCUtilities.o: src/OCUtilities.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCUtilities.cpp $(CXX_INC) + +InProcServerWrapper.o: src/InProcServerWrapper.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/InProcServerWrapper.cpp $(CXX_INC) + +InProcClientWrapper.o: src/InProcClientWrapper.cpp + $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/InProcClientWrapper.cpp $(CXX_INC) + +clean: clean_legacy + -rm -rf release + -rm -rf debug + cd oc_logger && $(MAKE) clean + +clean_cpp_sdk: clean_legacy + -rm -rf release + -rm -rf debug + +clean_legacy: + -rm -f -v $(OBJ_DIR)/liboc.a $(OBJ_DIR)/*.o + cd csdk && $(MAKE) clean + cd csdk && $(MAKE) deepclean diff --git a/resource/oc_logger/Makefile b/resource/oc_logger/Makefile new file mode 100644 index 000000000..5637e5ef0 --- /dev/null +++ b/resource/oc_logger/Makefile @@ -0,0 +1,56 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +# override with `make BUILD=debug` +# default to release build +BUILD := release + +LIB_DIR=./lib/ +BIN_DIR=./bin/ + +.PHONY: c_lib cpp_lib static_libs examples samples + +all: dirs c_lib cpp_lib static_libs examples samples + +dirs: + -mkdir -p $(LIB_DIR) $(BIN_DIR) + +c_lib: + cd c && $(MAKE) "BUILD=$(BUILD)" + +cpp_lib: + cd cpp && $(MAKE) "BUILD=$(BUILD)" + +static_libs: + ar -cvq $(LIB_DIR)/oc_logger_core.a $(BIN_DIR)/oc_logger.o + ar -cvq $(LIB_DIR)/oc_logger.a $(BIN_DIR)/oc_logger.o $(BIN_DIR)/targets/*.o + +examples: + cd examples && $(MAKE) "BUILD=$(BUILD)" + +samples: + cd samples/linux && $(MAKE) "BUILD=$(BUILD)" + +clean: + cd examples && $(MAKE) "clean" + cd samples/linux && $(MAKE) "clean" + rm -rf $(BIN_DIR)/targets/*.o + cd cpp && $(MAKE) clean + cd c && $(MAKE) clean diff --git a/resource/oc_logger/SConscript b/resource/oc_logger/SConscript new file mode 100644 index 000000000..5cb21cbae --- /dev/null +++ b/resource/oc_logger/SConscript @@ -0,0 +1,35 @@ +## +# liboc_logger (share library) build script +## + +Import('env') + +lib_env = env.Clone() +SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env') + +liboc_logger_env = lib_env.Clone() +###################################################################### +# Build flags +###################################################################### +liboc_logger_env.PrependUnique(CPPPATH = ['include']) + +target_os = env.get('TARGET_OS') +if target_os == 'android': + liboc_logger_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions']) + liboc_logger_env.AppendUnique(LIBS = ['gnustl_static', 'log']) + +if target_os not in ['arduino', 'windows', 'winrt']: + liboc_logger_env.AppendUnique(CFLAGS = ['-Wall', '-std=c99', '-fPIC']) + liboc_logger_env.AppendUnique(CXXFLAGS = ['-Wall', '-std=c++0x', '-fPIC']) + +###################################################################### +# Source files and Targets +###################################################################### +shared_liboc_logger_core = liboc_logger_env.SharedLibrary('oc_logger_core', 'c/oc_logger.c', OBJPREFIX='core_') +shared_liboc_logger = liboc_logger_env.SharedLibrary('oc_logger', ['c/oc_logger.c', 'c/oc_console_logger.c', 'cpp/oc_ostream_logger.cpp']) +static_liboc_logger = liboc_logger_env.StaticLibrary('oc_logger', ['c/oc_logger.c', 'c/oc_console_logger.c', 'cpp/oc_ostream_logger.cpp']) + +liboc_logger_env.InstallTarget([shared_liboc_logger_core, shared_liboc_logger, static_liboc_logger ], 'liboc_logger') + +if target_os not in ['ios']: + SConscript('examples/SConscript') diff --git a/resource/oc_logger/c/Makefile b/resource/oc_logger/c/Makefile new file mode 100644 index 000000000..5d553181d --- /dev/null +++ b/resource/oc_logger/c/Makefile @@ -0,0 +1,52 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# + +BUILD := release + +CC_FLAGS.debug=-Wall -std=c99 -Werror -O0 -g +CC_FLAGS.release=-Wall -std=c99 -Werror -O2 + +INC=-I../include/ +CC:=gcc + +BIN_DIR=../bin +LIB_DIR=../lib +TEST_DIR=../test + +LIB=$(LIB_DIR)/oc_logger.a + +CCX=$(CC) $(CC_FLAGS.$(BUILD)) + +all: setup c_lib c_targets + +setup: + mkdir -p $(BIN_DIR) $(LIB_DIR) + mkdir -p $(BIN_DIR)/targets + mkdir -p $(TEST_DIR) + +c_lib: + $(CCX) $(INC) -c -o $(BIN_DIR)/oc_logger.o oc_logger.c + +c_targets: + $(CCX) $(INC) -c -o $(BIN_DIR)/targets/oc_console_logger.o oc_console_logger.c + +clean: + rm -rf -v \*\.o test_logging $(BIN_DIR)/* $(LIB_DIR)/* diff --git a/resource/oc_logger/c/oc_console_logger.c b/resource/oc_logger/c/oc_console_logger.c new file mode 100644 index 000000000..a84de53b2 --- /dev/null +++ b/resource/oc_logger/c/oc_console_logger.c @@ -0,0 +1,100 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "oc_logger.h" +#include "targets/oc_console_logger.h" + +#include +#include + +typedef struct +{ + FILE *out; +} oc_console_logger_ctx; + +oc_log_ctx_t *oc_make_console_logger() +{ + return oc_log_make_ctx( + NULL, + OC_LOG_ALL, + oc_console_logger_init, + oc_console_logger_destroy, + oc_console_logger_flush, + oc_console_logger_set_level, + oc_console_logger_write, + oc_console_logger_set_module + ); +} + +int oc_console_logger_init(oc_log_ctx_t *ctx, void *world) +{ + oc_console_logger_ctx *my_ctx; + + my_ctx = (oc_console_logger_ctx *)malloc(sizeof(oc_console_logger_ctx)); + + if(0 == my_ctx) + return 0; + + my_ctx->out = stderr; + + ctx->ctx = (void *)my_ctx; + + return 1; +} + +void oc_console_logger_destroy(oc_log_ctx_t *ctx) +{ + oc_console_logger_ctx *lctx = (oc_console_logger_ctx *)ctx->ctx; + + fflush(lctx->out); + + free(lctx); +} + +void oc_console_logger_flush(oc_log_ctx_t *ctx) +{ + oc_console_logger_ctx *lctx = (oc_console_logger_ctx *)ctx->ctx; + + fflush(lctx->out); +} + +void oc_console_logger_set_level(oc_log_ctx_t *ctx, const int level) +{ + /* We don't have any special thing we need to do when a log level changes. */ + return; +} + +size_t oc_console_logger_write(oc_log_ctx_t *ctx, const int level, const char *msg) +{ + oc_console_logger_ctx *lctx = (oc_console_logger_ctx *)ctx->ctx; + + /* A "real" implementation might want to replace the loglevel with a mnemonic: */ + + if(0 == ctx->module_name) + return 1 + fprintf(lctx->out, "%d: %s\n", level, msg); + + return 1 + fprintf(lctx->out, "%d: [%s]: %s\n", level, ctx->module_name, msg); +} + +int oc_console_logger_set_module(oc_log_ctx_t *ctx, const char *module_name) +{ + /* We don't do anything special when the module name changes: */ + return 1; +} diff --git a/resource/oc_logger/c/oc_logger.c b/resource/oc_logger/c/oc_logger.c new file mode 100644 index 000000000..4c3db1adb --- /dev/null +++ b/resource/oc_logger/c/oc_logger.c @@ -0,0 +1,159 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "oc_logger.h" + +#include +#include + +oc_log_ctx_t *oc_log_make_ctx( + void* world, + const oc_log_level level, + oc_log_init_t init, + oc_log_destroy_t destroy, + oc_log_flush_t flush, + oc_log_set_level_t set_level, + oc_log_write_level_t write_level, + oc_log_set_module_t set_module + ) +{ + oc_log_ctx_t *log_ctx; + + if(0 == init || + 0 == destroy || + 0 == flush || + 0 == set_level || + 0 == write_level || + 0 == set_module) + return 0; + + if(__OC_LOG_MIN__ > level || __OC_LOG_MAX__ < level) + return 0; + + log_ctx = (oc_log_ctx_t *)malloc(sizeof(oc_log_ctx_t)); + + if(0 == log_ctx) + return 0; + + log_ctx->ctx = 0; /* we'll get to this in a sec... */ + log_ctx->log_level = level; + log_ctx->module_name = 0; + log_ctx->init = init; + log_ctx->destroy = destroy; + log_ctx->flush = flush; + log_ctx->set_level = set_level; + log_ctx->set_module = set_module; + + log_ctx->write_level = write_level; + + if(0 == log_ctx->init(log_ctx, world)) + { + free(log_ctx); + return 0; + } + + return log_ctx; +} + +void oc_log_destroy(oc_log_ctx_t *ctx) +{ + if(0 == ctx) + return; + + ctx->destroy(ctx); + + if(0 != ctx->module_name) + free(ctx->module_name); + + free(ctx); +} + +int oc_log_init(oc_log_ctx_t *ctx, void *world) +{ + if(0 == ctx) + return 0; + + return ctx->init(ctx, world); +} + +void oc_log_flush(oc_log_ctx_t *ctx) +{ + if(0 == ctx) + { + return; + } + ctx->flush(ctx); +} + +void oc_log_set_level(oc_log_ctx_t *ctx, const oc_log_level ll) +{ + if(0 == ctx) + { + return; + } + ctx->set_level(ctx, ll); +} + +size_t oc_log_write(oc_log_ctx_t *ctx, const char *msg) +{ + if(0 == ctx) + return 0; + + return oc_log_write_level(ctx, ctx->log_level, msg); +} + +size_t oc_log_write_level(oc_log_ctx_t *ctx, const oc_log_level ll, const char *msg) +{ + if(0 == ctx) + return 0; + + ctx->log_level = ll; + + /* Notify: */ + return ctx->write_level(ctx, ll, msg); +} + +int oc_log_set_module(oc_log_ctx_t *ctx, const char *module_name) +{ + char *mn; + size_t l; + + if(0 == ctx) + return 0; + + /* Swap pointers so that module data's not erased in the event of failure: */ + l = strlen(module_name); + + mn = (char *)malloc(1 + l); + + if(0 == mn) + return 0; + + memcpy(mn, module_name, 1 + l); + + if(0 != ctx->module_name) + free(ctx->module_name); + + ctx->module_name = mn; + + /* Notify: */ + return ctx->set_module(ctx, ctx->module_name); +} + diff --git a/resource/oc_logger/cpp/Makefile b/resource/oc_logger/cpp/Makefile new file mode 100644 index 000000000..0b2c41e77 --- /dev/null +++ b/resource/oc_logger/cpp/Makefile @@ -0,0 +1,47 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# + +BIN_DIR=../bin +LIB_DIR=../lib + +INC=-I../include/ + +LIB=$(LIB_DIR)/oc_logger.a + +BUILD := release + +CXX_FLAGS.debug=-Wall -std=c++0x -O0 -g +CXX_FLAGS.release=-Wall -std=c++0x -O2 + +CXX := g++ + +CXX_X=$(CXX) $(CXX_FLAGS.$(BUILD)) $(INC) + +all: dirs targets + +dirs: + -mkdir -p $(BIN_DIR)/targets + +targets: + $(CXX_X) -c -o $(BIN_DIR)/targets/oc_ostream_logger.o oc_ostream_logger.cpp + +clean: + rm -f ./test_logging ./*.o diff --git a/resource/oc_logger/cpp/oc_ostream_logger.cpp b/resource/oc_logger/cpp/oc_ostream_logger.cpp new file mode 100644 index 000000000..cadf87106 --- /dev/null +++ b/resource/oc_logger/cpp/oc_ostream_logger.cpp @@ -0,0 +1,199 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "oc_logger.hpp" +#include "targets/oc_ostream_logger.h" + +#include +#include + +#include +#include +#include +#include + +namespace { + +struct oc_ostream_logger_ctx +{ + std::ostream* os_ptr; + std::ostream& os; + + std::mutex mutex; + + oc_ostream_logger_ctx(std::ostream *here) + : os_ptr(here), + os(*os_ptr) + {} +}; + +} // namespace + +/* Courtesy-function: */ +oc_log_ctx_t *oc_make_ostream_logger() +{ + return oc_log_make_ctx( + nullptr, + OC_LOG_ALL, + oc_ostream_log_init, + oc_ostream_log_destroy, + oc_ostream_log_flush, + oc_ostream_log_set_level, + oc_ostream_log_write, + oc_ostream_log_set_module + ); +} + +int oc_ostream_log_init(oc_log_ctx_t *ctx, void *world) +try +{ + auto *target = reinterpret_cast(world); + + if(nullptr == world) + target = &std::cout; + + oc_ostream_logger_ctx *my_ctx = new oc_ostream_logger_ctx(target); + + ctx->ctx = static_cast(my_ctx); + + return 1; +} +catch(...) +{ + return 0; +} + +void oc_ostream_log_destroy(oc_log_ctx_t *ctx) +try +{ + static std::mutex dtor_mtx; + + oc_ostream_logger_ctx *lctx = static_cast(ctx->ctx); + + { + std::unique_lock ul(dtor_mtx); + + lctx->os << std::flush; + + delete lctx; + } +} +catch(...) +{ +} + +void oc_ostream_log_flush(oc_log_ctx_t *ctx) +try +{ + oc_ostream_logger_ctx *lctx = static_cast(ctx->ctx); + + std::lock_guard lg(lctx->mutex); + + lctx->os << std::flush; +} +catch(...) +{ +} + +void oc_ostream_log_set_level(oc_log_ctx_t *ctx, const int level) +try +{ + /* We don't have any special thing we need to do when a log level changes. */ + return; +} +catch(...) +{ +} + +size_t oc_ostream_log_write(oc_log_ctx_t *ctx, const int level, const char *msg) +try +{ + oc_ostream_logger_ctx *lctx = static_cast(ctx->ctx); + + std::lock_guard lg(lctx->mutex); + + std::ostringstream os; + + os << level << ": "; + + if(nullptr != ctx->module_name) + os << '[' << ctx->module_name << "] "; + + os << msg << '\n'; + + lctx->os << os.str().c_str(); + + return 1 + os.str().length(); +} +catch(...) +{ + return 0; +} + +int oc_ostream_log_set_module(oc_log_ctx_t *ctx, const char *module_name) +try +{ + // Nothing special needs to happen for a module name change: + return 1; +} +catch(...) +{ + return 0; +} + +int oc_ostream_log_lock(oc_log_ctx_t *ctx) +try +{ + oc_ostream_logger_ctx *lctx = static_cast(ctx->ctx); + + lctx->mutex.lock(); + + return 1; +} +catch(...) +{ + return 0; +} + +int oc_ostream_log_unlock(oc_log_ctx_t *ctx) +try +{ + oc_ostream_logger_ctx *lctx = static_cast(ctx->ctx); + + lctx->mutex.unlock(); + + return 1; +} +catch(...) +{ + return 0; +} + +int oc_ostream_log_try_lock(oc_log_ctx_t *ctx) +try +{ + oc_ostream_logger_ctx *lctx = static_cast(ctx->ctx); + + return lctx->mutex.try_lock(); +} +catch(...) +{ + return 0; +} diff --git a/resource/oc_logger/examples/Makefile b/resource/oc_logger/examples/Makefile new file mode 100644 index 000000000..7cf10732a --- /dev/null +++ b/resource/oc_logger/examples/Makefile @@ -0,0 +1,56 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# + +BUILD := release + +CC_FLAGS.debug=-Wall -std=c99 -Werror -O0 -g +CC_FLAGS.release=-Wall -std=c99 -Werror -O2 + +CXX_FLAGS.debug=-Wall -std=c++0x -O0 -g +CXX_FLAGS.release=-Wall -std=c++0x -O2 + +CXX_STDLIB=-lstdc++ + +CC:=gcc +CXX:=g++ +CXX_X=$(CXX) $(CXX_FLAGS.$(BUILD)) $(INC) + +INC=-I../include/ + +BIN_DIR=../bin +LIB_DIR=../lib + +CC_LIB=$(LIB_DIR)/oc_logger.a $(CXX_STDLIB) +CXX_LIB=$(LIB_DIR)/oc_logger.a $(CXX_STDLIB) + +CCX=$(CC) $(CC_FLAGS.$(BUILD)) + +all: examples_c examples_cpp + +examples_c: + $(CCX) $(INC) -o $(BIN_DIR)/test_logging test_logging.c $(CC_LIB) + +examples_cpp: + $(CXX_X) -o $(BIN_DIR)/test_logging_cpp test_logging.cpp $(CXX_LIB) + +clean: + rm -f $(BIN_DIR)/test_logging $(BIN_DIR)/test_logging_cpp + diff --git a/resource/oc_logger/examples/SConscript b/resource/oc_logger/examples/SConscript new file mode 100644 index 000000000..de1ab4a58 --- /dev/null +++ b/resource/oc_logger/examples/SConscript @@ -0,0 +1,34 @@ +## +# liboc_logger examples build script +## + +Import('env') + +lib_env = env.Clone() +SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env') + +examples_env = lib_env.Clone() +###################################################################### +# Build flags +###################################################################### +examples_env.PrependUnique(CPPPATH = ['../include']) +examples_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')]) +examples_env.AppendUnique(LIBS = ['oc_logger', 'stdc++']) + +target_os = env.get('TARGET_OS') +if target_os == 'android': + examples_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions']) + examples_env.AppendUnique(LIBS = ['gnustl_static']) + +if target_os not in ['arduino', 'windows', 'winrt']: + examples_env.AppendUnique(CFLAGS = Split('-Wall -std=c99 -Werror')) + examples_env.AppendUnique(CXXFLAGS = Split('-Wall -std=c++0x')) + +###################################################################### +# Source files and Targets +###################################################################### +examples_c = examples_env.Program('examples_c', 'test_logging.c', OBJPREFIX='c_') +examples_cpp = examples_env.Program('examples_cpp', 'test_logging.cpp') + +Alias('liboc_logger_examples', [examples_c, examples_cpp]) +examples_env.AppendTarget('liboc_logger_examples') diff --git a/resource/oc_logger/examples/test_logging.c b/resource/oc_logger/examples/test_logging.c new file mode 100644 index 000000000..7db0443bd --- /dev/null +++ b/resource/oc_logger/examples/test_logging.c @@ -0,0 +1,82 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "oc_logger.h" +#include "targets/oc_console_logger.h" +#include "targets/oc_ostream_logger.h" + +#include + +/* Example of basic usage of the C library: */ +void basic_demo(void) +{ + oc_log_ctx_t *log; + + log = oc_make_console_logger(); + + if(0 == log) + { + fprintf(stderr, "Unable to initialize logging subsystem.\n"); + return; + } + + oc_log_write(log, "Hello, World!"); + + oc_log_set_module(log, "FabulousModule"); + + oc_log_set_level(log, 50); + + oc_log_write(log, "Hello again, World!"); + + oc_log_destroy(log); +} + +/* Example of calling a C++ log implementation from C: */ +void cpp_demo() +{ + oc_log_ctx_t *log; + + log = oc_make_ostream_logger(); + + if(0 == log) + { + fprintf(stderr, "Unable to initialize logging subsystem.\n"); + return; + } + + oc_log_write(log, "Hello from C++, World!"); + + oc_log_set_module(log, "BestModuleEver"); + + oc_log_set_level(log, 50); + + oc_log_write(log, "Hello again from C++, World!"); + oc_log_write(log, "Hello once more from C++, World!"); + + oc_log_destroy(log); +} + +int main() +{ + basic_demo(); + cpp_demo(); + + return 0; +} diff --git a/resource/oc_logger/examples/test_logging.cpp b/resource/oc_logger/examples/test_logging.cpp new file mode 100644 index 000000000..61a6a58cc --- /dev/null +++ b/resource/oc_logger/examples/test_logging.cpp @@ -0,0 +1,97 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "oc_logger.hpp" + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +void basic_demo() +{ + using OC::oc_log_stream; + + oc_log_stream ols(oc_make_ostream_logger); + + boost::iostreams::stream os(ols); + + os << "Greetings from the nifty world of logging!" << std::flush; + + ols.set_level(OC_LOG_ALL); + ols.set_module("TheHappyModule"); + ols.set_module("TheModule"); + os << "Whee!" << std::flush; + + // Setting the module name by getting the device from the stream itself: + (*os).set_module("TheHappiestModuleEver"); + os << "Whee! Again!" << std::flush; +} + +/* Show that we can use a C logger from C++: */ +void c_demo() +{ + using OC::oc_log_stream; + + oc_log_stream ols(oc_make_console_logger); + + boost::iostreams::stream os(ols); + + os << "Greetings from the nifty world of logging!" << std::flush; + + ols.set_level(OC_LOG_ALL); + ols.set_module("TheHappyModule"); + os << "Whee!" << std::flush; + + (*os).set_module("TheHappiestModuleEver"); + os << "Whee!" << std::flush; +} + +void alternative_demo() +{ + /* Annother way to create a context: */ + auto logger = []() -> boost::iostreams::stream& + { + static OC::oc_log_stream ols(oc_make_ostream_logger); + static boost::iostreams::stream os(ols); + + return os; + }; + + logger()->set_module("FantasticModule"); + logger() << "Hello, logging world!" << std::flush; +} + +int main() +{ + basic_demo(); + c_demo(); + alternative_demo(); + return 0; +} + diff --git a/resource/oc_logger/include/oc_console_logger.h b/resource/oc_logger/include/oc_console_logger.h new file mode 100644 index 000000000..02adb4f68 --- /dev/null +++ b/resource/oc_logger/include/oc_console_logger.h @@ -0,0 +1,43 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef __OC_CONSOLE_LOGGER_H_2014_09_5 + #define __OC_CONSOLE_LOGGER_H_2014_09_5 + +#include "oc_logger_types.h" + +#ifdef __cplusplus + extern "C" { +#endif + +oc_log_ctx_t *oc_make_console_logger(); + +int oc_console_logger_init(oc_log_ctx_t *ctx, void *world); +void oc_console_logger_destroy(oc_log_ctx_t *ctx); +void oc_console_logger_flush(oc_log_ctx_t *ctx); +void oc_console_logger_set_level(oc_log_ctx_t *ctx, const int level); +size_t oc_console_logger_write(oc_log_ctx_t *ctx, const int level, const char *msg); +int oc_console_logger_set_module(oc_log_ctx_t *ctx, const char *module_name); + +#ifdef __cplusplus + } // extern "C" +#endif + +#endif diff --git a/resource/oc_logger/include/oc_log.hpp b/resource/oc_logger/include/oc_log.hpp new file mode 100644 index 000000000..dd145dd77 --- /dev/null +++ b/resource/oc_logger/include/oc_log.hpp @@ -0,0 +1,27 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef __OC_LOG_HPP_20140910 + #define __OC_LOG_HPP_20140910 + +#include "oc_ostream_logger.hpp" +#include "oc_log_stream.hpp" + +#endif diff --git a/resource/oc_logger/include/oc_log_stream.hpp b/resource/oc_logger/include/oc_log_stream.hpp new file mode 100644 index 000000000..bafa1419e --- /dev/null +++ b/resource/oc_logger/include/oc_log_stream.hpp @@ -0,0 +1,80 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef __OC_LOG_STREAM_HPP_20140910 + #define __OC_LOG_STREAM_HPP_20140910 + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "oc_logger.h" + +namespace OC { + +class oc_log_stream : boost::iostreams::sink +{ + std::shared_ptr m_log; + + public: + typedef char char_type; + typedef boost::iostreams::sink_tag category; + + public: + template + oc_log_stream(ContextCtor& c) + : m_log { c(), oc_log_destroy } + {} + + template + oc_log_stream(ContextCtor& c, void *world) + : m_log { c(world), oc_log_destroy } + {} + + public: + inline void flush() noexcept { return oc_log_flush(m_log.get()); } + inline void set_level(const oc_log_level new_level) noexcept { return oc_log_set_level(m_log.get(), new_level); } + inline int set_module(const std::string& module_name) noexcept { return oc_log_set_module(m_log.get(), module_name.c_str()); } + + public: + std::streamsize write(const char_type *s, std::streamsize n) + { + /* It may seem strange to do this here, but it's a consequence of the + underlying library not supporting ptr+len style buffers at this time: */ + std::string s2(s, n + s); + + oc_log_write(m_log.get(), s2.c_str()); + + return n; + } + + private: + oc_log_stream operator=(const oc_log_stream&) = delete; +}; + +} // namespace OC + +#endif diff --git a/resource/oc_logger/include/oc_logger.h b/resource/oc_logger/include/oc_logger.h new file mode 100644 index 000000000..8368db002 --- /dev/null +++ b/resource/oc_logger/include/oc_logger.h @@ -0,0 +1,54 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef __OC_LOGGER_H_2014_09_5 + #define __OC_LOGGER_H_2014_09_5 + +#include "oc_logger_types.h" + +#ifdef __cplusplus + extern "C" { +#endif + +/* Basic interface: */ +oc_log_ctx_t *oc_log_make_ctx( + void* world, + const oc_log_level level, + oc_log_init_t init, + oc_log_destroy_t destroy, + oc_log_flush_t flush, + oc_log_set_level_t set_level, + oc_log_write_level_t write_level, + oc_log_set_module_t set_module + ); + +void oc_log_destroy(oc_log_ctx_t *ctx); + +void oc_log_flush(oc_log_ctx_t *ctx); +void oc_log_set_level(oc_log_ctx_t *ctx, const oc_log_level ll); +size_t oc_log_write(oc_log_ctx_t *ctx, const char *msg); +size_t oc_log_write_level(oc_log_ctx_t *ctx, const oc_log_level ll, const char *msg); +int oc_log_set_module(oc_log_ctx_t *ctx, const char *module_name); + +#ifdef __cplusplus + } // extern "C" +#endif + +#endif diff --git a/resource/oc_logger/include/oc_logger.hpp b/resource/oc_logger/include/oc_logger.hpp new file mode 100644 index 000000000..2d0df2144 --- /dev/null +++ b/resource/oc_logger/include/oc_logger.hpp @@ -0,0 +1,31 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef __OC_LOG_HPP_20140910 + #define __OC_LOG_HPP_20140910 + +#include "oc_logger.h" + +#include "oc_log_stream.hpp" + +#include "targets/oc_console_logger.h" +#include "targets/oc_ostream_logger.h" + +#endif diff --git a/resource/oc_logger/include/oc_logger_types.h b/resource/oc_logger/include/oc_logger_types.h new file mode 100644 index 000000000..4789711ea --- /dev/null +++ b/resource/oc_logger/include/oc_logger_types.h @@ -0,0 +1,84 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef __OC_LOGGER_TYPES_H_2024_09_5 + #define __OC_LOGGER_TYPES_H_2024_09_5 + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + typedef enum { + __OC_LOG_MIN__ = -1, + OC_LOG_ALL = 0, + OC_LOG_FATAL, + OC_LOG_ERROR, + OC_LOG_WARNING, + OC_LOG_INFO, + OC_LOG_DEBUG, + OC_LOG_DISABLED, + __OC_LOG_MAX__ + } oc_log_level; + +typedef struct _oc_log_ctx +{ + void* ctx; + + oc_log_level log_level; + + char* module_name; + + /* Required interface: */ + int (*init) (struct _oc_log_ctx *, void *); + void (*destroy) (struct _oc_log_ctx *); + void (*flush) (struct _oc_log_ctx *); + void (*set_level) (struct _oc_log_ctx *, const int); + size_t (*write_level) (struct _oc_log_ctx *, const int, const char *); + int (*set_module) (struct _oc_log_ctx *, const char *); + + /* Optional interface (if one is implemented, all must be implemented): */ + int (*lock) (struct _oc_log_ctx *); + int (*unlock) (struct _oc_log_ctx *); + int (*try_lock) (struct _oc_log_ctx *); + int (*locked_destroy) (struct _oc_log_ctx *); + +} oc_log_ctx_t; + +/* Notice that these are all passed the /top level/ ctx-- it's "public" with respect to +these functions, they have full access to fiddle with the structure all they want (but, +generally should avoid doing that); I could certainly be convinced to go the other direction, +and have most functions only take the inner context: */ +typedef int (*oc_log_init_t) (oc_log_ctx_t *, void *); +typedef void (*oc_log_destroy_t) (oc_log_ctx_t *); +typedef void (*oc_log_flush_t) (oc_log_ctx_t *); +typedef void (*oc_log_set_level_t) (oc_log_ctx_t *, const int); +typedef size_t (*oc_log_write_level_t) (oc_log_ctx_t *, const int, const char *); +typedef int (*oc_log_set_module_t) (oc_log_ctx_t *, const char *); +typedef int (*oc_log_lock_t) (oc_log_ctx_t *); +typedef int (*oc_log_unlock_t) (oc_log_ctx_t *); +typedef int (*oc_log_try_lock_t) (oc_log_ctx_t *); + +#ifdef __cplusplus + } // extern "C" +#endif + +#endif diff --git a/resource/oc_logger/include/targets/oc_console_logger.h b/resource/oc_logger/include/targets/oc_console_logger.h new file mode 100644 index 000000000..02adb4f68 --- /dev/null +++ b/resource/oc_logger/include/targets/oc_console_logger.h @@ -0,0 +1,43 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef __OC_CONSOLE_LOGGER_H_2014_09_5 + #define __OC_CONSOLE_LOGGER_H_2014_09_5 + +#include "oc_logger_types.h" + +#ifdef __cplusplus + extern "C" { +#endif + +oc_log_ctx_t *oc_make_console_logger(); + +int oc_console_logger_init(oc_log_ctx_t *ctx, void *world); +void oc_console_logger_destroy(oc_log_ctx_t *ctx); +void oc_console_logger_flush(oc_log_ctx_t *ctx); +void oc_console_logger_set_level(oc_log_ctx_t *ctx, const int level); +size_t oc_console_logger_write(oc_log_ctx_t *ctx, const int level, const char *msg); +int oc_console_logger_set_module(oc_log_ctx_t *ctx, const char *module_name); + +#ifdef __cplusplus + } // extern "C" +#endif + +#endif diff --git a/resource/oc_logger/include/targets/oc_ostream_logger.h b/resource/oc_logger/include/targets/oc_ostream_logger.h new file mode 100644 index 000000000..0431469e9 --- /dev/null +++ b/resource/oc_logger/include/targets/oc_ostream_logger.h @@ -0,0 +1,49 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef __OC_OSTREAM_LOGGER_H_2014_09_5 + #define __OC_OSTREAM_LOGGER_H_2014_09_5 + +#include "oc_logger_types.h" + +/* Example of a C-callable C++ logger: */ +#ifdef __cplusplus + extern "C" { +#endif + +oc_log_ctx_t *oc_make_ostream_logger(); + +int oc_ostream_log_init(oc_log_ctx_t *ctx, void *world); +void oc_ostream_log_destroy(oc_log_ctx_t *ctx); +void oc_ostream_log_flush(oc_log_ctx_t *ctx); +void oc_ostream_log_set_level(oc_log_ctx_t *ctx, const int level); +size_t oc_ostream_log_write(oc_log_ctx_t *ctx, const int level, const char *msg); +int oc_ostream_log_set_module(oc_log_ctx_t *ctx, const char *module_name); + +int oc_ostream_log_lock(oc_log_ctx_t *ctx); +int oc_ostream_log_unlock(oc_log_ctx_t *ctx); +int oc_ostream_log_try_lock(oc_log_ctx_t *ctx); // non-blocking +int oc_ostream_log_locked_destroy(oc_log_ctx_t *ctx); + +#ifdef __cplusplus + } // extern "C" +#endif + +#endif diff --git a/resource/oc_logger/samples/linux/README b/resource/oc_logger/samples/linux/README new file mode 100644 index 000000000..25a4cd364 --- /dev/null +++ b/resource/oc_logger/samples/linux/README @@ -0,0 +1,44 @@ +------------------------------------------------------------------------------- + NOTICE - Transition to SCONS +------------------------------------------------------------------------------- + +The IoTivity build system is transitioning to SCONS. Although the +makefiles are still available (until v1.0) and some developers are +still using them, they are currently no longer supported. To learn more +about building using SCONS see Readme.scons.txt in the repository root +directory. The build steps used in continuous integration can be found +in auto_build.sh which is also in the the repository root directory. + +------------------------------------------------------------------------------- + +To run the oc_logger C sample app, first build liboctbstack.a + +cd /csdk + +To enable logging +make BUILD=debug +else +make BUILD=release + +Next, build the oc_logger C sample app + +cd /oc_logger/samples/linux + +To enable logging +make BUILD=debug +else +make BUILD=release + +The logger sample has two options, default logging or +a custom logger that can be supplied by the user application + +To run the application with the default logger, run + +./debug/test_logging -c 0 + +To run the application using a built in custom console logger, run + +./debug/test_logging -c 1 + + + diff --git a/resource/oc_logger/samples/linux/makefile b/resource/oc_logger/samples/linux/makefile new file mode 100644 index 000000000..6c3bb8794 --- /dev/null +++ b/resource/oc_logger/samples/linux/makefile @@ -0,0 +1,94 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +# override with `make BUILD=debug` +# default to release build +BUILD := release +PLATFORM := linux +CC := g++ +OUT_DIR := $(BUILD) +OBJ_DIR := $(OUT_DIR)/obj + +ifeq ($(ROOT_DIR), ) +ROOT_DIR = ../../../csdk +endif + +OUT_DIR = ./ + +OCLOGGER_DIR = $(ROOT_DIR)/logger +OC_LOG_DIR = $(ROOT_DIR)/../oc_logger +OCRANDOM_DIR = $(ROOT_DIR)/ocrandom +OCSOCKET_DIR = $(ROOT_DIR)/ocsocket +LCOAP_DIR = $(ROOT_DIR)/libcoap-4.1.1 +OCCOAP_DIR = $(ROOT_DIR)/occoap +OCTBSTACK_DIR = $(ROOT_DIR)/stack + +OC_LOG_INC = $(OC_LOG_DIR)/include +OC_LOG_LIB = $(OC_LOG_DIR)/lib/oc_logger.a + +OCLOGGER_INC = $(OCLOGGER_DIR)/include +OCRANDOM_INC = $(OCRANDOM_DIR)/include +OCSOCKET_INC = $(OCSOCKET_DIR)/include +LCOAP_INC = $(LCOAP_DIR) +OCCOAP_INC = $(OCCOAP_DIR)/include +OCTBSTACK_INC = $(OCTBSTACK_DIR)/include + +INC_DIRS := -I$(OCLOGGER_INC) +INC_DIRS += -I$(OC_LOG_INC) +INC_DIRS += -I$(OCRANDOM_INC) +INC_DIRS += -I$(OCSOCKET_INC) +INC_DIRS += -I$(LCOAP_INC) +INC_DIRS += -I$(OCCOAP_INC) +INC_DIRS += -I$(OCTBSTACK_INC) + +CC_FLAGS.debug := -O0 -g3 -Wall -ffunction-sections -fdata-sections \ + -std=c99 $(INC_DIRS) -L$(ROOT_DIR)/$(PLATFORM)/$(BUILD) -DTB_LOG +CC_FLAGS.release := -Os -Wall -fdata-sections -Wl,--gc-sections -Wl,-s \ + -std=c99 $(INC_DIRS) -L$(ROOT_DIR)/$(PLATFORM)/$(BUILD) + +LDLIBS += $(OC_LOG_LIB) -loctbstack -lpthread +CPPFLAGS += $(CC_FLAGS.$(BUILD)) $(LDLIBS) + +SOURCES := test_logging.c + +OBJECTS:= $(patsubst %.c, $(OBJ_DIR)/%.o, $(SOURCES)) + +PROGRAMS += test_logging + +all: prep_dirs $(OBJECTS) $(PROGRAMS) + +prep_dirs: + -mkdir -p $(OUT_DIR) + -mkdir -p $(OBJ_DIR) + +$(OBJ_DIR)/%.o: %.c + $(CC) -c $(CPPFLAGS) $< -o $@ + +test_logging: $(OBJ_DIR)/test_logging.o + $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@ + +.PHONY: clean + +clean: legacy_clean + -rm -rf release + -rm -rf debug + +legacy_clean: + rm -f *.o $(PROGRAMS) diff --git a/resource/oc_logger/samples/linux/test_logging.c b/resource/oc_logger/samples/linux/test_logging.c new file mode 100644 index 000000000..2ddd9ffdc --- /dev/null +++ b/resource/oc_logger/samples/linux/test_logging.c @@ -0,0 +1,80 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "logger.h" +#include +#include +#include +#include + +#define TAG PCF("MAIN") + +static int customLogger = 0; + +static void PrintUsage() +{ + OC_LOG(INFO, TAG, "Usage : test_logging -c <0|1>"); + OC_LOG(INFO, TAG, "-u <0|1> : 0 - default logging, 1 - custom console logging"); +} + +int main(int argc, char* argv[]) +{ + int opt; + + while ((opt = getopt(argc, argv, "c:")) != -1) + { + switch(opt) + { + case 'c': + customLogger = atoi(optarg); + break; + default: + PrintUsage(); + return -1; + } + } + + if (customLogger == 0) + { + // Default logger + OC_LOG(DEBUG, TAG, "This is a DEBUG"); + OC_LOG(INFO, TAG, "This is a INFO"); + OC_LOG(WARNING, TAG, "This is a WARNING"); + OC_LOG(ERROR, TAG, "This is a ERROR"); + OC_LOG(FATAL, TAG, "This is a FATAL"); + } + else + { + // Custom logger, in this case, the console logger + oc_log_ctx_t *log = oc_make_console_logger(); + + OC_LOG_CONFIG(log); + + OC_LOG(DEBUG, TAG, "This is a DEBUG"); + OC_LOG(INFO, TAG, "This is a INFO"); + OC_LOG(WARNING, TAG, "This is a WARNING"); + OC_LOG(ERROR, TAG, "This is a ERROR"); + OC_LOG(FATAL, TAG, "This is a FATAL"); + OC_LOG_SHUTDOWN(); + } + + + return 0; +} diff --git a/resource/oc_logger/test/test_logging.cpp b/resource/oc_logger/test/test_logging.cpp new file mode 100644 index 000000000..7b242688f --- /dev/null +++ b/resource/oc_logger/test/test_logging.cpp @@ -0,0 +1,54 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "oc_log.hpp" +#include "oc_console_logger.h" +#include "oc_ostream_logger.hpp" + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +int main() +{ + using OC::oc_log_stream; + + oc_log_stream ols(oc_make_console_logger); + + boost::iostreams::stream os(ols); + + os << "Greetings from the nifty world of loggin'!" << std::flush; + + (*os).set_module("TheHappiestModuleEver"); + + os << "Whee!" << std::flush; + + return 0; +} + diff --git a/resource/patches/boost/arm-linux-androideabi/user-config.jam b/resource/patches/boost/arm-linux-androideabi/user-config.jam new file mode 100644 index 000000000..bea3cee07 --- /dev/null +++ b/resource/patches/boost/arm-linux-androideabi/user-config.jam @@ -0,0 +1,137 @@ +# Copyright 2003, 2005 Douglas Gregor +# Copyright 2004 John Maddock +# Copyright 2002, 2003, 2004, 2007 Vladimir Prus +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +# This file is used to configure your Boost.Build installation. You can modify +# this file in place, or you can place it in a permanent location so that it +# does not get overwritten should you get a new version of Boost.Build. See: +# +# http://www.boost.org/boost-build2/doc/html/bbv2/overview/configuration.html +# +# for documentation about possible permanent locations. + +# This file specifies which toolsets (C++ compilers), libraries, and other +# tools are available. Often, you should be able to just uncomment existing +# example lines and adjust them to taste. The complete list of supported tools, +# and configuration instructions can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/reference/tools.html +# + +# This file uses Jam language syntax to describe available tools. Mostly, +# there are 'using' lines, that contain the name of the used tools, and +# parameters to pass to those tools -- where paremeters are separated by +# semicolons. Important syntax notes: +# +# - Both ':' and ';' must be separated from other tokens by whitespace +# - The '\' symbol is a quote character, so when specifying Windows paths you +# should use '/' or '\\' instead. +# +# More details about the syntax can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/advanced.html#bbv2.advanced.jam_language +# + +# ------------------ +# GCC configuration. +# ------------------ + +# Configure gcc (default version). +# using gcc ; + +# Configure specific gcc version, giving alternative name to use. +# using gcc : 3.2 : g++-3.2 ; + +import os ; + +local androidNDK = [ os.environ ANDROID_NDK ] ; +local platform = [ os.environ PLATFORM ] ; +local version = [ os.environ VERSION ] ; + +using gcc : : arm-linux-androideabi-g++ : + arm-linux-androideabi-ar + arm-linux-androideabi-ranlib + -fexceptions + -frtti + -fpic + -ffunction-sections + -funwind-tables + -D__ARM_ARCH_5__ + -D__ARM_ARCH_5T__ + -D__ARM_ARCH_5E__ + -D__ARM_ARCH_5TE__ + -Wno-psabi + -march=armv5te + -mtune=xscale + -msoft-float + -mthumb + -Os + -fomit-frame-pointer + -fno-strict-aliasing + -finline-limit=64 + -I$(androidNDK)/platforms/$(platform)/arch-arm/usr/include + -Wa,--noexecstack + -DANDROID + -D__ANDROID__ + -DNDEBUG + -O2 + -g + -I$(androidNDK)/sources/cxx-stl/gnu-libstdc++/$(version)/include + -I$(androidNDK)/sources/cxx-stl/gnu-libstdc++/$(version)/libs/armeabi/include + # @Moss - Above are the 'oficial' android flags + arm + -fvisibility=hidden + -fvisibility-inlines-hidden + -fdata-sections + -D__arm__ + -D_REENTRANT + -D_GLIBCXX__PTHREADS + ; + +# ------------------- +# MSVC configuration. +# ------------------- + +# Configure msvc (default version, searched for in standard locations and PATH). +# using msvc ; + +# Configure specific msvc version (searched for in standard locations and PATH). +# using msvc : 8.0 ; + + +# ---------------------- +# Borland configuration. +# ---------------------- +# using borland ; + + +# ---------------------- +# STLPort configuration. +# ---------------------- + +# Configure specifying location of STLPort headers. Libraries must be either +# not needed or available to the compiler by default. +# using stlport : : /usr/include/stlport ; + +# Configure specifying location of both headers and libraries explicitly. +# using stlport : : /usr/include/stlport /usr/lib ; + + +# ----------------- +# QT configuration. +# ----------------- + +# Configure assuming QTDIR gives the installation prefix. +# using qt ; + +# Configure with an explicit installation prefix. +# using qt : /usr/opt/qt ; + +# --------------------- +# Python configuration. +# --------------------- + +# Configure specific Python version. +# using python : 3.1 : /usr/bin/python3 : /usr/include/python3.1 : /usr/lib ; diff --git a/resource/patches/boost/x86/user-config.jam b/resource/patches/boost/x86/user-config.jam new file mode 100644 index 000000000..bb0a2e3b6 --- /dev/null +++ b/resource/patches/boost/x86/user-config.jam @@ -0,0 +1,137 @@ +# Copyright 2003, 2005 Douglas Gregor +# Copyright 2004 John Maddock +# Copyright 2002, 2003, 2004, 2007 Vladimir Prus +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +# This file is used to configure your Boost.Build installation. You can modify +# this file in place, or you can place it in a permanent location so that it +# does not get overwritten should you get a new version of Boost.Build. See: +# +# http://www.boost.org/boost-build2/doc/html/bbv2/overview/configuration.html +# +# for documentation about possible permanent locations. + +# This file specifies which toolsets (C++ compilers), libraries, and other +# tools are available. Often, you should be able to just uncomment existing +# example lines and adjust them to taste. The complete list of supported tools, +# and configuration instructions can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/reference/tools.html +# + +# This file uses Jam language syntax to describe available tools. Mostly, +# there are 'using' lines, that contain the name of the used tools, and +# parameters to pass to those tools -- where paremeters are separated by +# semicolons. Important syntax notes: +# +# - Both ':' and ';' must be separated from other tokens by whitespace +# - The '\' symbol is a quote character, so when specifying Windows paths you +# should use '/' or '\\' instead. +# +# More details about the syntax can be found at: +# +# http://boost.org/boost-build2/doc/html/bbv2/advanced.html#bbv2.advanced.jam_language +# + +# ------------------ +# GCC configuration. +# ------------------ + +# Configure gcc (default version). +# using gcc ; + +# Configure specific gcc version, giving alternative name to use. +# using gcc : 3.2 : g++-3.2 ; + +import os ; + +local androidNDK = [ os.environ ANDROID_NDK ] ; +local platform = [ os.environ PLATFORM ] ; +local version = [ os.environ VERSION ] ; + +using gcc : : i686-linux-android-g++ : + i686-linux-android-ar + i686-linux-android-ranlib + -fexceptions + -frtti + -fpic + -ffunction-sections + -funwind-tables +# -D__ARM_ARCH_5__ +# -D__ARM_ARCH_5T__ +# -D__ARM_ARCH_5E__ +# -D__ARM_ARCH_5TE__ + -Wno-psabi +# -march=armv5te +# -mtune=xscale +# -msoft-float +# -mthumb + -Os + -fomit-frame-pointer + -fno-strict-aliasing + -finline-limit=64 + -I$(androidNDK)/platforms/$(platform)/arch-x86/usr/include + -Wa,--noexecstack + -DANDROID + -D__ANDROID__ + -DNDEBUG + -O2 + -g + -I$(androidNDK)/sources/cxx-stl/gnu-libstdc++/$(version)/include + -I$(androidNDK)/sources/cxx-stl/gnu-libstdc++/$(version)/libs/armeabi/include + # @Moss - Above are the 'oficial' android flags + x86 + -fvisibility=hidden + -fvisibility-inlines-hidden + -fdata-sections +# -D__arm__ + -D_REENTRANT + -D_GLIBCXX__PTHREADS + ; + +# ------------------- +# MSVC configuration. +# ------------------- + +# Configure msvc (default version, searched for in standard locations and PATH). +# using msvc ; + +# Configure specific msvc version (searched for in standard locations and PATH). +# using msvc : 8.0 ; + + +# ---------------------- +# Borland configuration. +# ---------------------- +# using borland ; + + +# ---------------------- +# STLPort configuration. +# ---------------------- + +# Configure specifying location of STLPort headers. Libraries must be either +# not needed or available to the compiler by default. +# using stlport : : /usr/include/stlport ; + +# Configure specifying location of both headers and libraries explicitly. +# using stlport : : /usr/include/stlport /usr/lib ; + + +# ----------------- +# QT configuration. +# ----------------- + +# Configure assuming QTDIR gives the installation prefix. +# using qt ; + +# Configure with an explicit installation prefix. +# using qt : /usr/opt/qt ; + +# --------------------- +# Python configuration. +# --------------------- + +# Configure specific Python version. +# using python : 3.1 : /usr/bin/python3 : /usr/include/python3.1 : /usr/lib ; diff --git a/resource/patches/cereal_gcc46.patch b/resource/patches/cereal_gcc46.patch new file mode 100644 index 000000000..c4da84f72 --- /dev/null +++ b/resource/patches/cereal_gcc46.patch @@ -0,0 +1,485 @@ +From 17300ee96e42f8848d27db6fc97f04de293662d8 Mon Sep 17 00:00:00 2001 +From: Erich Keane +Date: Thu, 6 Nov 2014 14:37:00 -0800 +Subject: [PATCH] Get this to work on g++4.6.3 + +--- + include/cereal/cereal.hpp | 2 +- + include/cereal/details/helpers.hpp | 32 ++++++++-------- + include/cereal/details/traits.hpp | 61 +++++++++++++++++------------- + include/cereal/external/rapidjson/reader.h | 13 ++----- + include/cereal/external/rapidjson/writer.h | 12 ++---- + include/cereal/types/common.hpp | 19 +++++++--- + include/cereal/types/memory.hpp | 10 ++--- + 7 files changed, 77 insertions(+), 72 deletions(-) + +diff --git a/include/cereal/cereal.hpp b/include/cereal/cereal.hpp +index b2858af..a219729 100644 +--- a/include/cereal/cereal.hpp ++++ b/include/cereal/cereal.hpp +@@ -856,7 +856,7 @@ namespace cereal + std::uint32_t version; + + process( make_nvp("cereal_class_version", version) ); +- itsVersionedTypes.emplace_hint( lookupResult, hash, version ); ++ itsVersionedTypes.insert( lookupResult, std::pair(hash, version) ); + + return version; + } +diff --git a/include/cereal/details/helpers.hpp b/include/cereal/details/helpers.hpp +index e792d44..60e13c8 100644 +--- a/include/cereal/details/helpers.hpp ++++ b/include/cereal/details/helpers.hpp +@@ -55,7 +55,7 @@ namespace cereal + /*! To ensure compatability between 32, 64, etc bit machines, we need to use + * a fixed size type instead of size_t, which may vary from machine to + * machine. */ +- using size_type = uint64_t; ++ typedef uint64_t size_type; + + // forward decls + class BinaryOutputArchive; +@@ -138,12 +138,12 @@ namespace cereal + // otherwise, we store a reference. If we were passed an array, don't + // decay the type - keep it as an array, and then proceed as normal + // with the RValue business +- using DT = typename std::conditional::type>::value, ++ typedef typename std::conditional::type>::value, + typename std::remove_cv::type, +- typename std::decay::type>::type; +- using Type = typename std::conditional::value, ++ typename std::decay::type>::type DT; ++ typedef typename std::conditional::value, + DT, +- typename std::add_lvalue_reference

::type>::type; ++ typename std::add_lvalue_reference
::type>::type Type; + // prevent nested nvps + static_assert( !std::is_base_of::value, + "Cannot pair a name to a NameValuePair" ); +@@ -207,9 +207,9 @@ namespace cereal + { + //! Internally store the pointer as a void *, keeping const if created with + //! a const pointer +- using PT = typename std::conditional::type>::value, ++ typedef typename std::conditional::type>::value, + const void *, +- void *>::type; ++ void *>::type PT; + + BinaryData( T && d, uint64_t s ) : data(d), size(s) {} + +@@ -248,10 +248,10 @@ namespace cereal + private: + // If we get passed an RValue, we'll just make a local copy if it here + // otherwise, we store a reference +- using DT = typename std::decay::type; +- using Type = typename std::conditional::value, ++ typedef typename std::decay::type DT; ++ typedef typename std::conditional::value, + DT, +- typename std::add_lvalue_reference
::type>::type; ++ typename std::add_lvalue_reference
::type>::type Type; + + public: + SizeTag( T && sz ) : size(const_cast(sz)) {} +@@ -283,17 +283,17 @@ namespace cereal + template + struct MapItem + { +- using DecayKey = typename std::decay::type; +- using KeyType = typename std::conditional< ++ typedef typename std::decay::type DecayKey; ++ typedef typename std::conditional< + std::is_rvalue_reference::value, + DecayKey, +- typename std::add_lvalue_reference::type>::type; ++ typename std::add_lvalue_reference::type>::type KeyType; + +- using DecayValue = typename std::decay::type; +- using ValueType = typename std::conditional< ++ typedef typename std::decay::type DecayValue; ++ typedef typename std::conditional< + std::is_rvalue_reference::value, + DecayValue, +- typename std::add_lvalue_reference::type>::type; ++ typename std::add_lvalue_reference::type>::type ValueType; + + //! Construct a MapItem from a key and a value + /*! @internal */ +diff --git a/include/cereal/details/traits.hpp b/include/cereal/details/traits.hpp +index 871886f..011054b 100644 +--- a/include/cereal/details/traits.hpp ++++ b/include/cereal/details/traits.hpp +@@ -411,12 +411,12 @@ namespace cereal + }; + + template +- struct get_member_save_minimal_type { using type = void; }; ++ struct get_member_save_minimal_type { typedef void type; }; + + template + struct get_member_save_minimal_type + { +- using type = decltype( cereal::access::member_save_minimal( std::declval(), std::declval() ) ); ++ typedef decltype( cereal::access::member_save_minimal( std::declval(), std::declval() ) ) type; + }; + } // end namespace detail + +@@ -428,7 +428,7 @@ namespace cereal + "cereal detected a non-const member save_minimal. " + "save_minimal member functions must always be const" ); + +- using type = typename detail::get_member_save_minimal_type::type; ++ typedef typename detail::get_member_save_minimal_type::type type; + static_assert( (check::value && is_minimal_type::value) || !check::value, + "cereal detected a member save_minimal with an invalid return type. " + "return type must be arithmetic or string" ); +@@ -473,12 +473,12 @@ namespace cereal + }; + + template +- struct get_member_versioned_save_minimal_type { using type = void; }; ++ struct get_member_versioned_save_minimal_type { typedef void type; }; + + template + struct get_member_versioned_save_minimal_type + { +- using type = decltype( cereal::access::member_save_minimal( std::declval(), std::declval(), 0 ) ); ++ typedef decltype( cereal::access::member_save_minimal( std::declval(), std::declval(), 0 ) ) type; + }; + } // end namespace detail + +@@ -490,7 +490,7 @@ namespace cereal + "cereal detected a versioned non-const member save_minimal. " + "save_minimal member functions must always be const" ); + +- using type = typename detail::get_member_versioned_save_minimal_type::type; ++ typedef typename detail::get_member_versioned_save_minimal_type::type type; + static_assert( (check::value && is_minimal_type::value) || !check::value, + "cereal detected a versioned member save_minimal with an invalid return type. " + "return type must be arithmetic or string" ); +@@ -519,12 +519,12 @@ namespace cereal + }; + + template +- struct get_non_member_save_minimal_type { using type = void; }; ++ struct get_non_member_save_minimal_type { typedef void type; }; + + template + struct get_non_member_save_minimal_type + { +- using type = decltype( save_minimal( std::declval(), std::declval() ) ); ++ typedef decltype( save_minimal( std::declval(), std::declval() ) ) type; + }; + } // end namespace detail + +@@ -536,7 +536,7 @@ namespace cereal + "cereal detected a non-const type parameter in non-member save_minimal. " + "save_minimal non-member functions must always pass their types as const" ); + +- using type = typename detail::get_non_member_save_minimal_type::type; ++ typedef typename detail::get_non_member_save_minimal_type::type type; + static_assert( (check::value && is_minimal_type::value) || !check::value, + "cereal detected a non-member save_minimal with an invalid return type. " + "return type must be arithmetic or string" ); +@@ -565,12 +565,12 @@ namespace cereal + }; + + template +- struct get_non_member_versioned_save_minimal_type { using type = void; }; ++ struct get_non_member_versioned_save_minimal_type { typedef void type; }; + + template + struct get_non_member_versioned_save_minimal_type + { +- using type = decltype( save_minimal( std::declval(), std::declval(), 0 ) ); ++ typedef decltype( save_minimal( std::declval(), std::declval(), 0 ) ) type; + }; + } // end namespace detail + +@@ -582,7 +582,7 @@ namespace cereal + "cereal detected a non-const type parameter in versioned non-member save_minimal. " + "save_minimal non-member functions must always pass their types as const" ); + +- using type = typename detail::get_non_member_versioned_save_minimal_type::type; ++ typedef typename detail::get_non_member_versioned_save_minimal_type::type type; + static_assert( (check::value && is_minimal_type::value) || !check::value, + "cereal detected a non-member versioned save_minimal with an invalid return type. " + "return type must be arithmetic or string" ); +@@ -608,7 +608,7 @@ namespace cereal + template + struct NoConvertConstRef : NoConvertBase + { +- using type = Source; //!< Used to get underlying type easily ++ typedef Source type; //!< Used to get underlying type easily + + template ::value>::type> + operator Dest () = delete; +@@ -626,7 +626,7 @@ namespace cereal + template + struct NoConvertRef : NoConvertBase + { +- using type = Source; //!< Used to get underlying type easily ++ typedef Source type; //!< Used to get underlying type easily + + template ::value>::type> + operator Dest () = delete; +@@ -698,7 +698,7 @@ namespace cereal + "cereal detected member load_minimal but no valid member save_minimal. " + "cannot evaluate correctness of load_minimal without valid save_minimal." ); + +- using SaveType = typename detail::get_member_save_minimal_type::type; ++ typedef typename detail::get_member_save_minimal_type::type SaveType; + const static bool value = has_member_load_minimal_impl::value; + const static bool valid = has_member_load_minimal_type_impl::value; + +@@ -759,7 +759,7 @@ namespace cereal + "cereal detected member versioned load_minimal but no valid member versioned save_minimal. " + "cannot evaluate correctness of load_minimal without valid save_minimal." ); + +- using SaveType = typename detail::get_member_versioned_save_minimal_type::type; ++ typedef typename detail::get_member_versioned_save_minimal_type::type SaveType; + const static bool value = has_member_versioned_load_minimal_impl::value; + const static bool valid = has_member_versioned_load_minimal_type_impl::value; + +@@ -814,8 +814,8 @@ namespace cereal + "cereal detected non-member load_minimal but no valid non-member save_minimal. " + "cannot evaluate correctness of load_minimal without valid save_minimal." ); + +- using SaveType = typename detail::get_non_member_save_minimal_type::type; +- using check = has_non_member_load_minimal_impl; ++ typedef typename detail::get_non_member_save_minimal_type::type SaveType; ++ typedef has_non_member_load_minimal_impl check; + static const bool value = check::exists; + + static_assert( check::valid || !check::exists, "cereal detected different types in corresponding non-member load_minimal and save_minimal functions. " +@@ -866,8 +866,8 @@ namespace cereal + "cereal detected non-member versioned load_minimal but no valid non-member versioned save_minimal. " + "cannot evaluate correctness of load_minimal without valid save_minimal." ); + +- using SaveType = typename detail::get_non_member_versioned_save_minimal_type::type; +- using check = has_non_member_versioned_load_minimal_impl; ++ typedef typename detail::get_non_member_versioned_save_minimal_type::type SaveType; ++ typedef has_non_member_versioned_load_minimal_impl check;; + static const bool value = check::exists; + + static_assert( check::valid || !check::exists, "cereal detected different types in corresponding non-member versioned load_minimal and save_minimal functions. " +@@ -1182,9 +1182,16 @@ namespace cereal + }; + } + ++ // works around the lack of decltype inheritance in GCC 4.6 ++ template ++ struct shared_wrapper ++ { ++ typedef decltype(detail::shared_from_this_wrapper::check(std::declval())) type; ++ ++ }; + //! Determine if T or any base class of T has inherited from std::enable_shared_from_this + template +- struct has_shared_from_this : decltype(detail::shared_from_this_wrapper::check(std::declval())) ++ struct has_shared_from_this : shared_wrapper::type + { }; + + //! Get the type of the base class of T which inherited from std::enable_shared_from_this +@@ -1192,10 +1199,10 @@ namespace cereal + struct get_shared_from_this_base + { + private: +- using PtrType = decltype(detail::shared_from_this_wrapper::get(std::declval())); ++ typedef decltype(detail::shared_from_this_wrapper::get(std::declval())) PtrType; + public: + //! The type of the base of T that inherited from std::enable_shared_from_this +- using type = typename std::decay::type; ++ typedef typename std::decay::type type; + }; + + // ###################################################################### +@@ -1209,14 +1216,14 @@ namespace cereal + template ::value> + struct strip_minimal + { +- using type = T; ++ typedef T type; + }; + + //! Specialization for types wrapped in a NoConvert + template + struct strip_minimal + { +- using type = typename T::type; ++ typedef typename T::type type; + }; + } // namespace traits + +@@ -1232,10 +1239,12 @@ namespace cereal + { return nullptr; } + }; + ++ template ++ struct is_default_constructible : std::is_constructible{}; + template + struct Construct + { +- static_assert( std::is_default_constructible::value, ++ static_assert( is_default_constructible::value, + "Trying to serialize a an object with no default constructor. \n\n " + "Types must either be default constructible or define either a member or non member Construct function. \n " + "Construct functions generally have the signature: \n\n " +diff --git a/include/cereal/external/rapidjson/reader.h b/include/cereal/external/rapidjson/reader.h +index 7790907..3ee838c 100644 +--- a/include/cereal/external/rapidjson/reader.h ++++ b/include/cereal/external/rapidjson/reader.h +@@ -402,20 +402,13 @@ private: + } + + // cereal Temporary until constexpr support is added in RTM +-#ifdef _MSC_VER ++//#ifdef _MSC_VER + template + bool characterOk( Ch c ) + { + return c < 256; + } +- +- template <> +- bool characterOk( Ch ) +- { +- return true; +- } +- +-#else ++/*#else + // As part of a fix for GCC 4.7 + template + static constexpr int to_int( T t ){ return t; } +@@ -432,7 +425,7 @@ private: + characterOk(Ch c) + { return c < 256; } + #endif +- ++*/ + // Parse string, handling the prefix and suffix double quotes and escaping. + template + void ParseString(Stream& stream, Handler& handler) { +diff --git a/include/cereal/external/rapidjson/writer.h b/include/cereal/external/rapidjson/writer.h +index 0f87255..e02c27a 100644 +--- a/include/cereal/external/rapidjson/writer.h ++++ b/include/cereal/external/rapidjson/writer.h +@@ -177,20 +177,14 @@ protected: + } + + // cereal Temporary until constexpr support is added in RTM +-#ifdef _MSC_VER ++//#ifdef _MSC_VER + template + bool characterOk( Ch c ) + { + return c < 256; + } + +- template <> +- bool characterOk( Ch ) +- { +- return true; +- } +- +-#else ++/*#else + // As part of a fix for GCC 4.7 + template + static constexpr int to_int( T t ){ return t; } +@@ -206,7 +200,7 @@ protected: + typename std::enable_if< to_int(std::numeric_limits::max()) >= to_int(256), bool>::type + characterOk(Ch c) + { return c < 256; } +-#endif ++#endif*/ + + //! \todo Optimization with custom double-to-string converter. + void WriteDouble(double d) { +diff --git a/include/cereal/types/common.hpp b/include/cereal/types/common.hpp +index abb8bfd..5c014cd 100644 +--- a/include/cereal/types/common.hpp ++++ b/include/cereal/types/common.hpp +@@ -55,6 +55,15 @@ namespace cereal + + namespace + { ++ template ++ struct underlying_type ++ { ++ typedef typename std::conditional< ++ en(-1)::type, ++ typename std::make_unsigned::type ++ > ::type type; ++ }; + //! Gets the underlying type of an enum + /*! @internal */ + template +@@ -64,7 +73,7 @@ namespace cereal + /*! Specialization for when we actually have an enum + @internal */ + template +- struct enum_underlying_type { using type = typename std::underlying_type::type; }; ++ struct enum_underlying_type { typedef typename underlying_type::type type; }; + } // anon namespace + + //! Checks if a type is an enum +@@ -78,13 +87,13 @@ namespace cereal + class is_enum + { + private: +- using DecayedT = typename std::decay::type; +- using StrippedT = typename ::cereal::traits::strip_minimal::type; ++ typedef typename std::decay::type DecayedT; ++ typedef typename ::cereal::traits::strip_minimal::type StrippedT; + + public: + static const bool value = std::is_enum::value; +- using type = StrippedT; +- using base_type = typename enum_underlying_type::type; ++ typedef StrippedT type; ++ typedef typename enum_underlying_type::type base_type; + }; + } + +diff --git a/include/cereal/types/memory.hpp b/include/cereal/types/memory.hpp +index bf56c92..d2357ff 100644 +--- a/include/cereal/types/memory.hpp ++++ b/include/cereal/types/memory.hpp +@@ -115,9 +115,9 @@ namespace cereal + class EnableSharedStateHelper + { + // typedefs for parent type and storage type +- using BaseType = typename ::cereal::traits::get_shared_from_this_base::type; +- using ParentType = std::enable_shared_from_this; +- using StorageType = typename std::aligned_storage::type; ++ typedef typename ::cereal::traits::get_shared_from_this_base::type BaseType; ++ typedef std::enable_shared_from_this ParentType; ++ typedef typename std::aligned_storage::type StorageType; + + public: + //! Saves the state of some type inheriting from enable_shared_from_this +@@ -257,7 +257,7 @@ namespace cereal + { + // Storage type for the pointer - since we can't default construct this type, + // we'll allocate it using std::aligned_storage and use a custom deleter +- using ST = typename std::aligned_storage::type; ++ typedef typename std::aligned_storage::type ST; + + // Valid flag - set to true once construction finishes + // This prevents us from calling the destructor on +@@ -345,7 +345,7 @@ namespace cereal + { + // Storage type for the pointer - since we can't default construct this type, + // we'll allocate it using std::aligned_storage +- using ST = typename std::aligned_storage::type; ++ typedef typename std::aligned_storage::type ST; + + // Allocate storage - note the ST type so that deleter is correct if + // an exception is thrown before we are initialized +-- +1.9.3 + diff --git a/resource/releaseNotes/Aug5th2014.txt b/resource/releaseNotes/Aug5th2014.txt new file mode 100644 index 000000000..de7a8fdae --- /dev/null +++ b/resource/releaseNotes/Aug5th2014.txt @@ -0,0 +1,98 @@ +Release notes +Release date: Aug 5th, 2014. +OS: Ubuntu 12.0.4 and above +Requires boost version 1.55 to build. +NOTE: Boost is not distributed but should be installed in the Ubuntu machine. + +What’s new? +Class OCPlatform (Header file: OCPlatform.h) +registerResource API (signature update) +•This API provides the ability to register the resource with its name, type and list of properties +•Signature of this API has changed. The API takes reference to resource handle which will be filled upon successful registration. Other parameters include resource URI, resource Type, resource interface, entity handler address and resource property (whether discoverable, observable etc.). +•NOTE: This applies to server side functionality. +•NOTE: This API might get modified to accommodate for resource collection in future. + +notifyObservers API +•This new API provides the ability to notify core that resource’s attributes have changed. When entity handler is ready to indicate core that a resource has changed, notifyObservers API needs to be invoked. +•This API takes resource handle as the only parameter. +•NOTE: This applies to server side functionality. +•NOTE: This API might get modified to accommodate for resource collection in future. + +Class OCResource (Header file: OCResource.h) + +get API +•This new API provides the ability to get the attributes of a resource. This API takes a callback as parameter. Callback will be invoked with Attribute map which will provide representation of the resource. Callback will also include error code for GET operation. +•NOTE: This applies to client side functionality. +•NOTE: This API might get modified to accommodate for resource collection in future. + +put API +•This new API provides the ability to set the attributes of a resource via PUT. +•This API takes Attribute map, query parameter map and a callback as parameters. Callback will be invoked with Attribute map which will provide current representation of the resource. Callback will also include error code for PUT operation. +•NOTE: This applies to client side functionality. +•NOTE: This API might get modified to accommodate for resource collection in future. + +Observe API +•This new API provides the ability for the client to set observation on a resource +•This API provides callback as a parameter. Callback will be invoked with attribute map and with an error code for this operation. +•NOTE: This applies to client side functionality. + +cancelObserve API +•This new API provides the ability for the client to cancel observation on a resource +•This API provides callback as a parameter. Callback will be invoked with error code for this operation. +•NOTE: This applies to client side functionality. +Class OCResourceRequest (Header file: OCResourceRequest.h) +NOTE: This applies to server side functionality. + +getRequestType API +•This new API provides the ability to retrieve the type of request. This could be GET, PUT (and in future POST and DELETE). + +getQueryParams API +•This new API provides the ability to retrieve the query parameters from the URL request. + +getRequestHandlerFlag API +•This new API provides the ability to retrieve the request handler flag on the URL request. This could be either INIT, REQUEST or OBSERVE flag. + +getResourceRepresentation API +•This new API provides the ability to retrieve attribute representation of the resource. + +Class OCResourceResponse (Header file: OCResourceResponse.h) +NOTE: This applies to server side functionality. + +setErrorCode API +•This new API provides the ability to set the error code + +setResourceRepresentation API +•This new API provides the ability to set the attribute representation of a resource. + +Other Notes: +1. Security model is still open. +2. APIs have OCStackResult as return type. This is will indicate success or failure for the API operation. +3. Resource collection/hierarchy APIs are not checked into the code base. They will be given as separate header files. +4. Query parameters are not used in this deliverable. +5. Only single client observer has been tested. +6. Maximum length of URI supported is 64 bytes +7. Maximum length of response (for GET, PUT) from server is 128 bytes. + + +How to build: +1. Root folder oic-resource consists of ‘OIC’ folder. Inside OIC folder there is a Makefile. +2. Before building, make sure to have contents from oic-utilities repo at the folder level where oic-resource is. +3. Use ‘make’ to build the entire OIC code. This would build the C++ SDK, stack and samples. + +Samples: +1. We have a sample for hosting a resource on a server and a sample for client which will be able to discover resources. +2. Server sample location: OIC/examples/simpleserver.cpp +3. Client sample location: OIC/examples/simpleclient.cpp +4. In simpleserver.cpp, inside main, + +PlatformConfig cfg; +cfg.ipAddress = "134.134.161.33"; + +Modify the above IP address to the IP address of the machine where this server is running. + +Similarly, in simpleclient.cpp, inside main, modify the IP address to the IP address of the machine where the client is running. + +The server and client can run in same machine or in different machines. + +5. To run simpleServer do ‘./simpleServer’ and to run simpleClient do ‘./simpleClient’. + diff --git a/resource/releaseNotes/Dec20th2014.txt b/resource/releaseNotes/Dec20th2014.txt new file mode 100644 index 000000000..d14cd6a01 --- /dev/null +++ b/resource/releaseNotes/Dec20th2014.txt @@ -0,0 +1,130 @@ +Release notes +**************************************************************************** +Release date: Dec 20th, 2014. +OS: Ubuntu 12.0.4 and above +Requires boost version 1.55 to build. +Code buildable in gcc 4.6.3 and above. +NOTE: Boost is not distributed but should be installed in the Ubuntu machine. +***************************************************************************** + +What is new? + +Features: +--------- + +Device discovery: +----------------- +The device description resource is a virtual resource that provides a representation +that contains information about the device. It provides a standard mechanism to query +well-known device meta-data including but not limited to device id, name etc. Device +discovery feature provides a mechanism to find devices based on specific device-level +attributes. + +Samples demonstrating device discovery: +devicediscoveryserver and devicediscoveryclient in C++ +ocserver and occlient in C + + +------------ +API changes: +------------ + +-------------------------------------------- +Class OCPlatform (Header file: OCPlatform.h) +-------------------------------------------- + +*********************** +registerDeviceInfo API +*********************** + +This new API allows server app to provide the device information. + +*********************** +getDeviceInfo API +*********************** + +This new API allows client app to find the device and get the device information. + +-------------------------------------------- +Header file: ocstack.h +-------------------------------------------- + +*********************** +OCSetDeviceInfo API +*********************** + +This new API allows to set the device information. + + +------------ +Notes: +------------ +1. Multiple improvements in active discovery/presence +- Callback includes host information +- Added support to allow more than one presence resource type filter + +2. Klocwork issues fixed in C++ samples, SDK and C samples. + +3. Multiple bug fixes updated in Jira. + +General notes: +-------------- +Maximum length of URI supported is 64 bytes (sent from the client) +Maximum length of query supported is 64 bytes (sent from the client) +Maximum length of request from client and response from server for Arduino is is 256 bytes +Maximum length of request from client and response from server for non-Ardunio is is 1024 bytes + +OIC base supports Arduino WiFi shield. +This support has been tested with Arduino Mega 2560 and with Arduino 1.0.5 WiFi library. +Please refer to oic-resource/csdk/README file for building OIC base with WiFi support. + +-------- +Samples: +-------- + +C++ Samples +----------- + +A basic sample for hosting a resource on a server and a sample for client for discovering resources +are provided here: +Simple server sample location: oic-resource/examples/simpleserver.cpp +Simple client sample location: oic-resource/examples/simpleclient.cpp +Server and client mode (mode type both) location: oic-resource/examples/simpleclientserver.cpp +Simpleserver and simpleclient samples also provide examples for doing POST operation. +Simpleserver also demonstrates slow response case for a GET request. + +Garage samples provide usage of OCRepresentation, get/set attribute values +oic-resource/examples/garageclient.cpp +oic-resource/examples/garageserver.cpp + +Fridge samples provide usage of constructResourceObject API, std bind +(for mapping request and responses), default +device entity handler, header options support and Delete operation. +oic-resource/examples/fridgeclient.cpp +oic-resource/examples/fridgeserver.cpp + +Presence samples provides examples to use presence APIs +Sample with basic presence feature for server side: oic-resource/examples/presenceserver.cpp +Sample with basic presence feature for client side: oic-resource/examples/presenceclient.cpp + +Room samples provides examples to use resource collection. +oic-resource/examples/roomclient.cpp +oic-resource/examples/roomserver.cpp + +After building the code in oic-resource, executables for samples are in directory named +'oic-resource/samples/release'. +After building the code in oic-resource, executables are in directory named 'oic-resource/release'. + +C Samples +--------- +Collection samples are demonstrated in: +ocservercoll and occlientcoll + +Slow response feature is demonstrated in: +ocserverslow and occlientslow + +Client and server basic operations -- discovery, GET, PUT, POST (NON messages) demonstrated in: +ocserverbasicops and occlientbasicops + +Client and server - discovery, GET,PUT,POST,DELETE,OBS for both NON and CON demonstrated in: +ocserver and occlient diff --git a/resource/releaseNotes/Dec6th2014.txt b/resource/releaseNotes/Dec6th2014.txt new file mode 100644 index 000000000..266bacfb6 --- /dev/null +++ b/resource/releaseNotes/Dec6th2014.txt @@ -0,0 +1,238 @@ +Release notes +**************************************************************************** +Release date: Dec 6th, 2014. +OS: Ubuntu 12.0.4 and above +Requires boost version 1.55 to build. +Code buildable in gcc 4.6.3 and above. +NOTE: Boost is not distributed but should be installed in the Ubuntu machine. +***************************************************************************** + +Release commit number: de31af + +What is new? + +Features: +--------- + +Slow Response: +-------------- +This release includes slow response feature which allows a resource entity handler to provide +a 'slow response' to a client request. If a request is received but the server cannot response +immediately (example, response data is not available), then the server can response at a later +time. The same API is used for both immediate and slow response. + +GET/PUT request on the batch interface of a collection resource using the default collection +entity handler will result in each pointed resource’s entity handler being invoked, after which: +a) if all pointed resources of the collection are local and not-slow, an aggregated +response will be sent +b) if collection includes slow local resource(s), an aggregated response is sent only after +the slowest resource’s entity handler responds with a payload. If one or more slow resource +entity handlers do not respond, no response is sent to the request, i.e. there is no timeout +mechanism in current release + +Samples demonstrating slow response: +simpleserver and simpleclient in C++ +ocserverslow and occlientslow in C + +Security: +---------- +1. OCStack is compiled with security only if a valid libtinydtls.a is available +under oic-resource/resource/csdk/tinydtls directory. +2. This release provides an API to set device identity and PSK credentials. +3. Security is NOT supported for Arduino platform. + +JSON serialization using Cereal libray +-------------------------------------- +This release includes modifications which consists of using +open source library cereal to perform JSON serialization +and de-serialization in C++ layer. (NOTE: previously we were +using boost::property tree for JSON parsing) + +NOTE: For a nested (array of array of array..) JSON value, we limit to 3-level deep nesting. +Refer AttributeValue.h for more details. + +------------ +API changes: +------------ + +-------------------------------------------- +Class OCPlatform (Header file: OCPlatform.h) +-------------------------------------------- + +***************** +sendResponse API +***************** + +This new API allows the application entity handler to send response to a request. +This API is used in sending a response immediately (if available) or in cases of +slow response. Due to this change, signature of application entity handler has +been modified. This introduces changes in application entity handler code. +Please see below. +All C++ samples demonstrate the use of sendResponse API. + +-------------------------------------------- +Header file: OCApi.h +-------------------------------------------- + +typedef std::function)> EntityHandler; + +Signature of application entity handler has changed. New signature consists only of +one parameter which is OCResourceRequest pointer. Response is formed and sent via +sendResponse API. All C++ samples are updated to showcase this modification. + +---------------------------------------------------------- +Class OCResourceRequest (Header file: OCResourceRequest.h) +---------------------------------------------------------- + +******************** +getRequestHandle API +******************** + +This new API allows the application entity handler to retrieve request handle +from the incoming request. +All C++ samples demonstrate the use of getRequestHandle API. + +********************* +getResourceHandle API +********************* + +This new API allows the application entity handler to retrieve resource handle +from the incoming request. +All C++ samples demonstrate the use of getResourceHandle API. + +------------------------------------------------------------- +Class OCResourceResponse (Header file: OCResourceResponse.h) +------------------------------------------------------------- + +******************** +setRequestHandle API +******************** + +This new API allows the application entity handler to set request handle in +the response. +All C++ samples demonstrate the use of setRequestHandle API. + +********************* +setResourceHandle API +********************* + +This new API allows the application entity handler to set resource handle in +the response. +All C++ samples demonstrate the use of setResourceHandle API. + +********************* +setResponseResult API +********************* + +This new API allows the application entity handler to set result in +the response. +All C++ samples demonstrate the use of setResponseResult API. + +------------------------------------------------------------- +Header file: OCStack.h +------------------------------------------------------------- + +*************************** +OCDoResponse API +*************************** + +This new C API allows the application entity handler to send response to a request. +This API is used in sending a response immediately (if available) or in cases of +slow response. + +------------------------------------------------------------- +Header file: OCSecurity.h +------------------------------------------------------------- + +*************************** +OCSetDtlsPskCredentials API +*************************** + +This new API allows to set DTLS PSK credentials. + +------------ +Notes: +------------ + +Known issues: +------------- +1. When observation is used, server shutdown causes an error (segmentation fault). + +Active discovery- +1. In case of unicast presence with rt, only one rt is permitted per IP address for +subscribePresence. If multiple subscriptions are done, only first subscribePresence’s rt is used. +2. For multicast presence, server shutdown (ungraceful) scenario is not notified to the client, +but graceful shutdowns are notified. +3. IOT 85 + +Issues Fixed: +------------- +1. IOT 65 (Stopping presence subscription gets infinite callback to handlePresence) +2. IOT 79 (3 Presence Notifications when a resource is created on the server) + +General notes: +-------------- +Maximum length of URI supported is 64 bytes (sent from the client) +Maximum length of query supported is 64 bytes (sent from the client) +Maximum length of request from client and response from server for Arduino is is 256 bytes +Maximum length of request from client and response from server for non-Ardunio is is 1024 bytes + +OIC base supports Arduino WiFi shield. +This support has been tested with Arduino Mega 2560 and with Arduino 1.0.5 WiFi library. +Please refer to oic-resource/csdk/README file for building OIC base with WiFi support. + +------------- +How to build: +------------- + +REFER https://oic-review.01.org/gerrit for more details on getting oic-resource repo. +If the code is not cloned: +Clone the oic-resource repo using this command: git clone oic:oic-resource + +NOTE: If the repo is already cloned, use 'git pull' inside oic-resource folder to get the +latest code. + +In repo oic-resource, root folder consists of 'resource' folder. Inside OIC folder there +is a Makefile. + +Inside oic-resource directory, use 'make'to build the entire OIC code. This would build the C++ SDK, +core(i.e base) and samples. + +Use 'make BUILD=debug' to build the entire OIC code in debug mode. This would build the C++ SDK, +core(i.e base) and samples. + +-------- +Samples: +-------- + +A basic sample for hosting a resource on a server and a sample for client for discovering resources +are provided here: +Simple server sample location: oic-resource/examples/simpleserver.cpp +Simple client sample location: oic-resource/examples/simpleclient.cpp +Server and client mode (mode type both) location: oic-resource/examples/simpleclientserver.cpp +Simpleserver and simpleclient samples also provide examples for doing POST operation. +Simpleserver also demonstrates slow response case for a GET request. + +Garage samples provide usage of OCRepresentation, get/set attribute values +oic-resource/examples/garageclient.cpp +oic-resource/examples/garageserver.cpp + +Fridge samples provide usage of constructResourceObject API, std bind +(for mapping request and responses), default +device entity handler, header options support and Delete operation. +oic-resource/examples/fridgeclient.cpp +oic-resource/examples/fridgeserver.cpp + +Presence samples provides examples to use presence APIs +Sample with basic presence feature for server side: oic-resource/examples/presenceserver.cpp +Sample with basic presence feature for client side: oic-resource/examples/presenceclient.cpp + +Room samples provides examples to use resource collection. +oic-resource/examples/roomclient.cpp +oic-resource/examples/roomserver.cpp + +After building the code in oic-resource, executables for samples are in directory named +'oic-resource/samples/release'. +After building the code in oic-resource, executables are in directory named 'oic-resource/release'. + diff --git a/resource/releaseNotes/Nov15th2014.txt b/resource/releaseNotes/Nov15th2014.txt new file mode 100644 index 000000000..b3e6bba8c --- /dev/null +++ b/resource/releaseNotes/Nov15th2014.txt @@ -0,0 +1,119 @@ +Release notes +**************************************************************************** +Release date: Nov 15th, 2014. +OS: Ubuntu 12.0.4 and above +Requires boost version 1.55 to build. +Code buildable in gcc 4.6.3 and above. +NOTE: Boost is not distributed but should be installed in the Ubuntu machine. +***************************************************************************** + +Release commit number: acf4c1 + +What is new? + +-------------------------------------------- +Class OCPlatform (Header file: OCPlatform.h) +-------------------------------------------- + +*************** +subscribePresence API +*************** +Existing subscribePresence API has been overloaded with a resource type parameter. +Client can now subscribe presence with interested resource type. +This release also supports multicast presence subscription. + +Available subscription options are: + +Unicast presence subscription without resource type. +Multicast presence subscription without resource type. +Unicast presence subscription with resource type. +Multicast presence subscription with resource type. + +------------ +Other Notes: +------------ + +Maximum length of URI supported is 64 bytes (sent from the client) +Maximum length of query supported is 64 bytes (sent from the client) +Maximum length of request and response from server for Ardunio is is 256 bytes +Maximum length of request and response from server for non-Ardunio is is 1024 bytes + +OIC base supports Arduino WiFi shield. +This support has been tested with Arduino Mega 2560 and with Arduino 1.0.5 WiFi library. +Please refer to oic-resource/csdk/README file for building OIC base with WiFi support. + +Security: +1. OCStack is compiled with security only if a valid libtinydtls.a is available +under oic-resource/resource/csdk/tinydtls directory. +2. Currently, security credentials for resource and client are hard-coded in the stack source files. +3. Currently, tinyDTLS does not support establishing new associations with existing parameters. +Due to this limitation, if the client application is re-started and attempts to create a new DTLS +session with an existing server, tinyDTLS server rejects the request. +4. Security is NOT supported for Arduino platform. + +Known issues: + +1. When observation is used, server shutdown causes an error. + +Active discovery- +1. In case of unicast presence with rt, only one rt is permitted per IP address for +subscribePresence. If multiple subscriptions are done, only first subscribePresence’s rt is used. +2. For multicast presence, server shutdown (ungraceful) scenario is not notified to the client, +but graceful shutdowns are notified. +3. IOT 65 +4. IOT 79 +5. IOT 85 + +------------- +How to build: +------------- + +REFER https://oic-review.01.org/gerrit for more details on getting oic-resource repo. +If the code is not cloned: +Clone the oic-resource repo using this command: git clone oic:oic-resource + +NOTE: If the repo is already cloned, use 'git pull' inside oic-resource folder to get the +latest code. + +In repo oic-resource, root folder consists of 'resource' folder. Inside OIC folder there +is a Makefile. + +Inside oic-resource directory, use 'make'to build the entire OIC code. This would build the C++ SDK, +core(i.e base) and samples. + +Use 'make BUILD=debug' to build the entire OIC code in debug mode. This would build the C++ SDK, +core(i.e base) and samples. + +-------- +Samples: +-------- + +A basic sample for hosting a resource on a server and a sample for client for discovering resources +are provided here: +Simple server sample location: oic-resource/examples/simpleserver.cpp +Simple client sample location: oic-resource/examples/simpleclient.cpp +Server and client mode (mode type both) location: oic-resource/examples/simpleclientserver.cpp +Simpleserver and simpleclient samples also provide examples for doing POST operation. + +Garage samples provide usage of OCRepresentation, get/set attribute values +oic-resource/examples/garageclient.cpp +oic-resource/examples/garageserver.cpp + +Fridge samples provide usage of constructResourceObject API, std bind +(for mapping request and responses), default +device entity handler, header options support and Delete operation. +oic-resource/examples/fridgeclient.cpp +oic-resource/examples/fridgeserver.cpp + +Presence samples provides examples to use presence APIs +Sample with basic presence feature for server side: oic-resource/examples/presenceserver.cpp +Sample with basic presence feature for client side: oic-resource/examples/presenceclient.cpp + +Room samples provides examples to use resource collection. +oic-resource/examples/roomclient.cpp +oic-resource/examples/roomserver.cpp + +After building the code in oic-resource, executables for samples are in directory named +'oic-resource/samples/release'. +After building the code in oic-resource, executables are in directory named 'oic-resource/release'. + diff --git a/resource/releaseNotes/Oct14th2014.txt b/resource/releaseNotes/Oct14th2014.txt new file mode 100644 index 000000000..9d6f289b0 --- /dev/null +++ b/resource/releaseNotes/Oct14th2014.txt @@ -0,0 +1,159 @@ +Release notes +**************************************************************************** +Release date: Oct 14th, 2014. +OS: Ubuntu 12.0.4 and above +Requires boost version 1.55 to build. +Code buildable in gcc 4.6.3 and above. +NOTE: Boost is not distributed but should be installed in the Ubuntu machine. +***************************************************************************** + +What is new? + +-------------------------------------------- +Class OCPlatform (Header file: OCPlatform.h) +-------------------------------------------- + +OCPlatform has new set of overloaded APIs for QoS support +- findResource +- notifyAllObservers +- notifyListOfObservers + +These overloaded APIs allow app developers to specify QoS level. Please see 'Other notes' section for +details in QoS. + +-------------------------------------------- +Class OCResource (Header file: OCResource.h) +-------------------------------------------- + +OCResource has new set of overloaded APIs for QoS support +- get +- put +- post +- observe +- cancelObserve +- deleteResource + +These overloaded APIs allow app developers to specify QoS level. Please see 'Other notes' section for +details in QoS. + +***************** +deleteResource API +***************** + +This new API allows the client to perform Delete operations on a resource. + +NOTE: This applies to client side functionality. + +***************** +setHeaderOptions API +***************** + +This new API allows the client to set header options. + +NOTE: Once headers options are set, it will be applicable to GET, PUT and observe request. +NOTE: This applies to client side functionality. + +***************** +unsetHeaderOptions API +***************** + +This new API allows the client to unset header options. +NOTE: This applies to client side functionality. + +-------------------------------------------- +Class OCHeaderOption (Header file: OCHeaderOption.h) +-------------------------------------------- +OCHeaderOption class allows to create instances which comprises optionID +and optionData as members. These are used in setting Header options. +After creating instances of OCHeaderOptions, setHeaderOptions API +(in OCResource.h) can be used to set header Options. +NOTE: HeaderOptionID is an unsigned integer value which MUST be within +range of 2048 to 3000 inclusive of lower and upper bound. +HeaderOptions instance creation fails if above condition is not satisfied. + +Refer 'Other Notes' section for more details on Header options. +------------ +Other Notes: +------------ + +Security model is still open. + +Maximum length of URI supported is 64 bytes (sent from the client) +Maximum length of query supported is 64 bytes (sent from the client) +Maximum length of request and response from server for Ardunio is is 256 bytes +Maximum length of request and response from server for non-Ardunio is is 1024 bytes + +OIC base supports Arduino WiFi shield. +This support has been tested with Arduino Mega 2560 and with Arduino 1.0.5 WiFi library. +Please refer to oic-resource/csdk/README file for building OIC base with WiFi support. + +Bug fixes: +IOT-58 + +QoS +-QoSlevels support LowQoS, MidQoS, HighQoS and NaQoS. +-LowQoS and MidQoS are translated to non-conifirmable in CoAP. +-HighQoS translated to confirmable in CoAP. +-NaQoS allows the base to choose appropriate QoS level. It defaults to LowQoS. +-In observe notifications, it uses the same QoS level the observer used in the observe registration request. + +On graceful server shutdown: +-Client-observers will now be notified when the resource they are observing is being deleted. +-Also applies for presence notifications. + +Header options support: +- This support provides the client to send custom header options to server and vice-versa. +- Server handles the header options received from the clients in the entity handler. +- Header options sent from the server are received in get, put, post, delete, observe callbacks. +- Sample shown in fridge samples. + +Entity handler modification: +-Returns OCEntityHandlerResult instead of void. +-OCEntityHandlerResult return types are OC_EH_RESOURCE_CREATED and OC_EH_RESOURCE_DELETED. + +Exception handling: +-This release includes enhancements in exception handling. +------------- +How to build: +------------- + +REFER https://oic-review.01.org/gerrit for more details on getting oic-resource repo. +If the code is not cloned: +Clone the oic-resource repo using this command: git clone oic:oic-resource +Clone the oic-utilities repo using this command: git clone oic:oic-utilities + +NOTE: If the repo is already cloned, use 'git pull' inside oic-resource folder to get the latest code. + +In repo oic-core, root folder ccf-opensource consists of 'OIC' folder. Inside OIC folder there is a Makefile. + +Before building, make sure to have contents from oic-utilities repo at the folder level where oic-resource is. + +Inside oic-resource directory, use 'make'to build the entire OIC code. This would build the C++ SDK, core(i.e base) and samples. + +Use 'make BUILD=debug' to build the entire OIC code in debug mode. This would build the C++ SDK, core(i.e base) and samples. All the executables for debug build +are in 'oic-resource/debug'. + +-------- +Samples: +-------- + +Garage samples provide usage of OCRepresentation, get/set attribute values + +oic-resource/examples/fridgeclient.cpp +oic-resource/examples/fridgeserver.cpp + +Fridge samples provide usage of constructResourceObject API, std bind (for mapping request and responses), default +device entity handler, header options support and Delete operation. + +Simpleserver and simpleclient samples provide examples for doing POST operation. + +After building the code in oic-resource, executables for samples are in directory named 'oic-resource/samples/release'. +After building the code in oic-resource, executables are in directory named 'oic-resource/release'. +A sample for hosting a resource on a server and a sample for client for discovering resources are provided in the following paths: + +Server sample location: oic-resource/examples/simpleserver.cpp +Client sample location: oic-resource/examples/simpleclient.cpp +Server and client mode (mode type both) location: oic-resource/examples/simpleclientserver.cpp + +Sample with basic presence feature for server side: oic-resource/examples/presenceserver.cpp +Sample with basic presence feature for client side: oic-resource/examples/presenceclient.cpp diff --git a/resource/releaseNotes/Oct31st2014.txt b/resource/releaseNotes/Oct31st2014.txt new file mode 100644 index 000000000..74d059eff --- /dev/null +++ b/resource/releaseNotes/Oct31st2014.txt @@ -0,0 +1,110 @@ +Release notes +**************************************************************************** +Release date: Oct 31st, 2014. +OS: Ubuntu 12.0.4 and above +Requires boost version 1.55 to build. +Code buildable in gcc 4.6.3 and above. +NOTE: Boost is not distributed but should be installed in the Ubuntu machine. +***************************************************************************** + +Release commit number: c8ba162fe83db3832ae889a0cb31904d888826d1 + +What is new? + +-------------------------------------------- +Class OCPlatform (Header file: OCPlatform.h) +-------------------------------------------- +This release includes support for using OCPlatform instance in multiple threads. +OCPlatform functions are now supported to be called from multiple threads. +Applications need not create OCPlatform object explicitly. + + +*************** +Configure API +*************** +Applications can set the PlatformConfig and then invoke new API "Configure" in OCPlatform.h. +NOTE: This API is optional. First time an OCPlatform API is called, stack creates the singleton +instance internally. After which, setting the configuration will have no effect. + +NOTE: OCPlatform functions can be called without OCPlatform instance. +Sample: + +OCStackResult result = OCPlatform::registerResource(... ); + +NOTE: For clarity, registerResource parameters are not shown above. +NOTE: Iotivity stack internally creates a singleton instance. +NOTE: C++ sample applications are updated accordingly. Please refer oic-resource/examples + +------------ +Other Notes: +------------ + +Security model is still open. + +Maximum length of URI supported is 64 bytes (sent from the client) +Maximum length of query supported is 64 bytes (sent from the client) +Maximum length of request and response from server for Ardunio is is 256 bytes +Maximum length of request and response from server for non-Ardunio is is 1024 bytes + +OIC base supports Arduino WiFi shield. +This support has been tested with Arduino Mega 2560 and with Arduino 1.0.5 WiFi library. +Please refer to oic-resource/csdk/README file for building OIC base with WiFi support. + +Minor bug fixes done. + +Simple attribute sample update: +This release has updates to roomserver and roomclient applications to demonstrate simple +attribute support in collections. + +C++ unit test infrastructure: +This release includes infrastructure for C++ unit tests (oic-resource/unittests) +------------- +How to build: +------------- + +REFER https://oic-review.01.org/gerrit for more details on getting oic-resource repo. +If the code is not cloned: +Clone the oic-resource repo using this command: git clone oic:oic-resource +Clone the oic-utilities repo using this command: git clone oic:oic-utilities + +NOTE: If the repo is already cloned, use 'git pull' inside oic-resource folder to get the latest code. + +In repo oic-core, root folder ccf-opensource consists of 'OIC' folder. Inside OIC folder there is a Makefile. + +Before building, make sure to have contents from oic-utilities repo at the folder level where oic-resource is. + +Inside oic-resource directory, use 'make'to build the entire OIC code. This would build the C++ SDK, core(i.e base) and samples. + +Use 'make BUILD=debug' to build the entire OIC code in debug mode. This would build the C++ SDK, core(i.e base) and samples. All the executables for debug build +are in 'oic-resource/debug'. + +-------- +Samples: +-------- + +A basic sample for hosting a resource on a server and a sample for client for discovering resources are provided here: +Simple server sample location: oic-resource/examples/simpleserver.cpp +Simple client sample location: oic-resource/examples/simpleclient.cpp +Server and client mode (mode type both) location: oic-resource/examples/simpleclientserver.cpp +Simpleserver and simpleclient samples also provide examples for doing POST operation. + +Garage samples provide usage of OCRepresentation, get/set attribute values +oic-resource/examples/garageclient.cpp +oic-resource/examples/garageserver.cpp + +Fridge samples provide usage of constructResourceObject API, std bind (for mapping request and responses), default +device entity handler, header options support and Delete operation. +oic-resource/examples/fridgeclient.cpp +oic-resource/examples/fridgeserver.cpp + +Presence samples provides examples to use presence APIs +Sample with basic presence feature for server side: oic-resource/examples/presenceserver.cpp +Sample with basic presence feature for client side: oic-resource/examples/presenceclient.cpp + +Room samples provides examples to use resource collection. +oic-resource/examples/roomclient.cpp +oic-resource/examples/roomserver.cpp + +After building the code in oic-resource, executables for samples are in directory named 'oic-resource/samples/release'. +After building the code in oic-resource, executables are in directory named 'oic-resource/release'. + diff --git a/resource/releaseNotes/Sept17th2014.txt b/resource/releaseNotes/Sept17th2014.txt new file mode 100644 index 000000000..7fdd60cb2 --- /dev/null +++ b/resource/releaseNotes/Sept17th2014.txt @@ -0,0 +1,146 @@ +Release notes +**************************************************************************** +Release date: Sept 17th, 2014. +OS: Ubuntu 12.0.4 and above +Requires boost version 1.55 to build. +Code buildable in gcc 4.6.3 and above. +NOTE: Boost is not distributed but should be installed in the Ubuntu machine. +***************************************************************************** + +What is new? + +-------------------------------------------- +Class OCPlatform (Header file: OCPlatform.h) +-------------------------------------------- + +***************** +notifyAllObservers API +***************** + +Previously, this API was named as 'notifyObservers'. This API is used for notifying base that resource's attributes have changed. +NOTE: This applies to server side functionality only. + +******************* +notifyListOfObservers API +******************* + +This new API allows server's entity handler to specify a list of observers to be notified. Parameters of this API include +resource handle, vector of observation IDs for which notification needs to be sent and OCResourceResponse pointer to fill the +response. Before this API is invoked by entity handler, server app would have finished processing queries for the associated +observers. + +NOTE: This applies to server side functionality. + +-------------------------------------------- + Header file: OCStack.h (in base) +-------------------------------------------- + +***************** +OCNotifyAllObservers API +***************** + +Previously, this API was named as 'notifyObservers'. This API is used for notifying base that resource's attributes have changed. + +NOTE: This applies to server side functionality only. + +******************* +OCNotifyListOfObservers API +******************* + +This new API allows server's entity handler to specify a list of observers to be notified. Parameters of this API include +resource handle, pointer to array of observation IDs for which notification needs to be sent, number of observation IDS and +buffer for response. Before this API is invoked by entity handler, server app would have finished processing queries for the associated +observers. + +NOTE: This applies to server side functionality. + +------------ +Other Notes: +------------ + +Security model is still open. +APIs have OCStackResult as return type. This is will indicate success or failure for the API operation. + +Maximum length of URI supported is 64 bytes (sent from the client) +Maximum length of query supported is 64 bytes (sent from the client) +Maximum length of request and response from server for Ardunio is is 256 bytes +Maximum length of request and response from server for non-Ardunio is is 1024 bytes + +OIC base now supports Arduino WiFi shield. +This support has been tested with Arduino Mega 2560 and with Arduino 1.0.5 WiFi library. +Please refer to oic-resource/csdk/README file for building OIC base with WiFi support. + +As part of this release, clean up items included are: +Removal of header files, source files, folders which are not used as part of build. OCLib +More typedefs for clarity and readability. +More comments in sample files. + +Bug fixes: +IOT-25 +IOT-31 +IOT-45 +IOT-48 +Minor bugs fixed +Memory leak issues fixed + +Presence notifications: +OCStartPresence and OCStopPresence are updated so that if can be called when server comes online and offline respectively. +Notifications will now be sent when a resource is modified or deleted. +Now notifications to the app are sent only when there is a change in nonce. + +Observe notifications: +When using OCNotifyListOfObservers, the memory for obsIdList and notificationJSONPayload is managed by the entity handler invoking the API. +The maximum size of the notification is 1015 bytes for non-Arduino platforms and 247 bytes for Arduino platforms. + +Server sample (oic-resource/examples/simpleserver.cpp) has been updated to showcase invoking either notifyAllObservers or notifyListOfObservers. +Once the samples are built (see 'How to build' section below), if notifyAllObservers needs to be used, the app can be run as +'./simpleserver 0" +Note: './simpleserver' without any input parameter will also invoke notifyAllObservers. + +If notifyListOfObservers needs to be used, the app can be run as +'./simpleserver 1' + +Improvements: +OCRepresentation provides simpler interface to setValue and getValue from the apps. Apps do not need to use AttributeMap in OCRepresentation. +OCRepresentation now supports serialization/deserilization for primitive (numbers, booleans and strings), so app need not directly have to +deal with strings. + +Known issues: +More than one presence notification is sent out when a new resource is created instead of one notification (IOT-49) +When OCNotifyListOfObservers is invoked with a list of observer IDs and if any of observer ID does not exist in the base, flow continues processing +other observe IDs. + +------------- +How to build: +------------- + +REFER https://oic-review.01.org/gerrit for more details on getting oic-resource repo. +If the code is not cloned: +Clone the oic-resource repo using this command: git clone oic:oic-resource +Clone the oic-utilities repo using this command: git clone oic:oic-utilities + +NOTE: If the repo is already cloned, use 'git pull' inside oic-resource folder to get the latest code. + +In repo oic-core, root folder ccf-opensource consists of 'OIC' folder. Inside OIC folder there is a Makefile. + +Before building, make sure to have contents from oic-utilities repo at the folder level where oic-resource is. + +Inside oic-resource directory, use 'make'to build the entire OIC code. This would build the C++ SDK, core(i.e base) and samples. + +Use 'make BUILD=debug' to build the entire OIC code in debug mode. This would build the C++ SDK, core(i.e base) and samples. All the executables for debug build +are in 'oic-resource/debug'. + +-------- +Samples: +-------- + +After building the code in oic-resource, executables for samples are in directory named 'oic-resource/samples/release'. +After building the code in oic-resource, executables are in directory named 'oic-resource/release'. +A sample for hosting a resource on a server and a sample for client for discovering resources are provided in the following paths: + +Server sample location: oic-resource/examples/simpleserver.cpp +Client sample location: oic-resource/examples/simpleclient.cpp +Server and client mode (mode type both) location: oic-resource/examples/simpleclientserver.cpp + +Sample with basic presence feature for server side: oic-resource/examples/presenceserver.cpp +Sample with basic presence feature for client side: oic-resource/examples/presenceclient.cpp diff --git a/resource/releaseNotes/Sept2nd2014.txt b/resource/releaseNotes/Sept2nd2014.txt new file mode 100644 index 000000000..6ab1dc006 --- /dev/null +++ b/resource/releaseNotes/Sept2nd2014.txt @@ -0,0 +1,116 @@ +Release notes +**************************************************************************** +Release date: Sept 2nd, 2014. +OS: Ubuntu 12.0.4 and above +Requires boost version 1.55 to build. +Code buildable in gcc 4.6.3 and above. +NOTE: Boost is not distributed but should be installed in the Ubuntu machine. +***************************************************************************** + +What’s new? + +-------------------------------------------- +Class OCPlatform (Header file: OCPlatform.h) +-------------------------------------------- + +***************** +startPresence API +***************** + +This API allows the server to notify its presence via multicast. + +NOTE: This applies to server side functionality only. + +******************* +stopPresence API +******************* + +This API allows the server to stop presence notification. + +NOTE: This applies to server side functionality. + + +****************** +subscribePresence API +****************** + +This API allows a client to subscribe to a device's presence notifications. Notifications include new addition of resource on the device, deletion of a resource on the device, change in properties of a resource. + +NOTE: This applies to client side functionality only. +NOTE: In this release, when client uses subscribePresence API, it gets notified only for new addition of resource on the device (server). + +******************* +unsubscribePresence API +******************* + +This API allows a client to unsubscribe from a device's presence events. + +NOTE: This applies to client side functionality only. + +-------------------------------------------- + Header file: OCStack.h (in base) +-------------------------------------------- + +***************** +OCStartPresence API +***************** + +This API will start sending out presence notifications to clients via multicast. + +NOTE: This applies to server side functionality only. + +******************* +OCStopPresence API +******************* + +This API will stop sending out presence notifications to clients via multicast. + +NOTE: This applies to server side functionality. + +------------ +Other Notes: +------------ + +Security model is still open. +APIs have OCStackResult as return type. This is will indicate success or failure for the API operation. + +Implementation for presence code is in both C (base) and C++ (SDK). In C (base) stack, presence code is defined with 'WITH_PRESENCE' preprocessor macro. + +Maximum length of URI supported is 64 bytes (sent from the client) +Maximum length of query supported is 64 bytes (sent from the client) +Maximum length of request and response from server for Ardunio is is 256 bytes +Maximum length of request and response from server for non-Ardunio is is 1024 bytes + +------------- +How to build: +------------- + +REFER https://oic-review.01.org/gerrit for more details on getting oic-resource repo. +If the code is not cloned: +Clone the oic-resource repo using this command: git clone oic:oic-resource +Clone the oic-utilities repo using this command: git clone oic:oic-utilities + +NOTE: If the repo is already cloned, use 'git pull' inside oic-resource folder to get the latest code. + +In repo oic-core, root folder ccf-opensource consists of ‘OIC’ folder. Inside OIC folder there is a Makefile. + +Before building, make sure to have contents from oic-utilities repo at the folder level where oic-resource is. + +Inside oic-resource directory, use ‘make’ to build the entire OIC code. This would build the C++ SDK, core(i.e base) and samples. + +Use ‘make BUILD=debug’ to build the entire OIC code in debug mode. This would build the C++ SDK, core(i.e base) and samples. All the executables for debug build +are in 'debug/samples'. + +-------- +Samples: +-------- + +After building the code in oic-resource, executables are in directory named 'release/samples'. +A sample for hosting a resource on a server and a sample for client for discovering resources are provided in the following paths: + +Server sample location: oic-resource/examples/simpleserver.cpp +Client sample location: oic-resource/examples/simpleclient.cpp +Server and client mode (mode type both) location: oic-resource/examples/simpleclientserver.cpp + +Sample with basic presence feature for server side: oic-resource/examples/presenceserver.cpp +Sample with basic presence feature for client side: oic-resource/examples/presenceclient.cpp diff --git a/resource/releaseNotes/Sept30th2014.txt b/resource/releaseNotes/Sept30th2014.txt new file mode 100644 index 000000000..8d53151b9 --- /dev/null +++ b/resource/releaseNotes/Sept30th2014.txt @@ -0,0 +1,162 @@ +Release notes +**************************************************************************** +Release date: Sept 30th, 2014. +OS: Ubuntu 12.0.4 and above +Requires boost version 1.55 to build. +Code buildable in gcc 4.6.3 and above. +NOTE: Boost is not distributed but should be installed in the Ubuntu machine. +***************************************************************************** + +What is new? + +-------------------------------------------- +Class OCPlatform (Header file: OCPlatform.h) +-------------------------------------------- + +***************** +setDefaultDeviceEntityHandler API +***************** + +This new API allows the server side app developer to provide a default device entity handler. +If server receives a request in which the resource URI does not match any of the existing +resource URIs, base will invoke this default entity handler. It is app developer's responsibility +to handle the implementation of default device entity handler accordingly. +If the default device entity handler is not configured and the URI in the request does not match +any of the existing resource URIs, server will return OC_STACK_NO_RESOURCE. + + +NOTE: This applies to server side functionality. + +-------------------------------------------- +Class OCResource (Header file: OCResource.h) +-------------------------------------------- + +***************** +post API +***************** + +This new API allows the client to perform POST operation on a resource. + +NOTE: This applies to client side functionality. + +-------------------------------------------- +Class OCRepresentation (Header file: OCApi.h) +-------------------------------------------- + +OCRepresentation has modifications which provides +- Ability to get/set OCRepresenation (JSON object) in the OCRepresentation. +- Ability to get/set vector of strings, booleans, double, integers, null. +- Has additional functions + +***************** +erase API +***************** +This removes an attribute from the representation + +***************** +setNULL API +***************** +This sets given attribute to null + +***************** +isNULL API +***************** +This returns true if the given attribute is null + +***************** +hasAttribute API +***************** +This returns true if the attribute exists in the representation + +***************** +numberOfAttributes API +***************** +This returns the number of attributes in the representation + +-------------------------------------------- + Header file: OCStack.h (in base) +-------------------------------------------- + +***************** +OCSetDefaultDeviceEntityHandler API +***************** + +This new API allows the server side app developer to provide a default device entity handler. +If server receives a request in which the resource URI does not match any of the existing +resource URIs, base will invoke this default entity handler. It is app developer's responsibility +to handle the implementation of default device entity handler accordingly. +If the default device entity handler is not configured and the URI in the request does not match +any of the existing resource URIs, server will return OC_STACK_NO_RESOURCE. + +NOTE: This applies to server side functionality only. + +------------ +Other Notes: +------------ + +Security model is still open. +APIs have OCStackResult as return type. This is will indicate success or failure for the API operation. + +Maximum length of URI supported is 64 bytes (sent from the client) +Maximum length of query supported is 64 bytes (sent from the client) +Maximum length of request and response from server for Ardunio is is 256 bytes +Maximum length of request and response from server for non-Ardunio is is 1024 bytes + +OIC base now supports Arduino WiFi shield. +This support has been tested with Arduino Mega 2560 and with Arduino 1.0.5 WiFi library. +Please refer to oic-resource/csdk/README file for building OIC base with WiFi support. + +Bug fixes: +IOT-36 +Minor bugs fixed + +Known issues: +1. POST operation does not create new resources +2. Header options from client to server and vice-versa is not available. +3. Setting CON/NON-CON option is possible only during initialization configuration. +------------- +How to build: +------------- + +REFER https://oic-review.01.org/gerrit for more details on getting oic-resource repo. +If the code is not cloned: +Clone the oic-resource repo using this command: git clone oic:oic-resource +Clone the oic-utilities repo using this command: git clone oic:oic-utilities + +NOTE: If the repo is already cloned, use 'git pull' inside oic-resource folder to get the latest code. + +In repo oic-core, root folder ccf-opensource consists of 'OIC' folder. Inside OIC folder there is a Makefile. + +Before building, make sure to have contents from oic-utilities repo at the folder level where oic-resource is. + +Inside oic-resource directory, use 'make'to build the entire OIC code. This would build the C++ SDK, core(i.e base) and samples. + +Use 'make BUILD=debug' to build the entire OIC code in debug mode. This would build the C++ SDK, core(i.e base) and samples. All the executables for debug build +are in 'oic-resource/debug'. + +-------- +Samples: +-------- + +New Samples added: +oic-resource/examples/garageclient.cpp +oic-resource/examples/garageserver.cpp + +Garage samples provide usage of OCRepresentation, get/set attribute values + +oic-resource/examples/fridgeclient.cpp +oic-resource/examples/fridgeserver.cpp + +Fridge samples provide usage of constructResourceObject API, std bind (for mapping request and responses) and default +device entity handler + +After building the code in oic-resource, executables for samples are in directory named 'oic-resource/samples/release'. +After building the code in oic-resource, executables are in directory named 'oic-resource/release'. +A sample for hosting a resource on a server and a sample for client for discovering resources are provided in the following paths: + +Server sample location: oic-resource/examples/simpleserver.cpp +Client sample location: oic-resource/examples/simpleclient.cpp +Server and client mode (mode type both) location: oic-resource/examples/simpleclientserver.cpp + +Sample with basic presence feature for server side: oic-resource/examples/presenceserver.cpp +Sample with basic presence feature for client side: oic-resource/examples/presenceclient.cpp diff --git a/resource/src/InProcClientWrapper.cpp b/resource/src/InProcClientWrapper.cpp new file mode 100644 index 000000000..83e4ef87e --- /dev/null +++ b/resource/src/InProcClientWrapper.cpp @@ -0,0 +1,744 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "InProcClientWrapper.h" +#include "ocstack.h" + +#include "OCPlatform.h" +#include "OCResource.h" +#include +using namespace std; + +namespace OC +{ + InProcClientWrapper::InProcClientWrapper( + std::weak_ptr csdkLock, PlatformConfig cfg) + : m_threadRun(false), m_csdkLock(csdkLock), + m_cfg { cfg } + { + // if the config type is server, we ought to never get called. If the config type + // is both, we count on the server to run the thread and do the initialize + + if(m_cfg.mode == ModeType::Client) + { + OCStackResult result = OCInit(m_cfg.ipAddress.c_str(), m_cfg.port, OC_CLIENT); + + if(OC_STACK_OK != result) + { + throw InitializeException(OC::InitException::STACK_INIT_ERROR, result); + } + + m_threadRun = true; + m_listeningThread = std::thread(&InProcClientWrapper::listeningFunc, this); + } + } + + InProcClientWrapper::~InProcClientWrapper() + { + if(m_threadRun && m_listeningThread.joinable()) + { + m_threadRun = false; + m_listeningThread.join(); + } + + // only stop if we are the ones who actually called 'init'. We are counting + // on the server to do the stop. + if(m_cfg.mode == ModeType::Client) + { + OCStop(); + } + } + + void InProcClientWrapper::listeningFunc() + { + while(m_threadRun) + { + OCStackResult result; + auto cLock = m_csdkLock.lock(); + if(cLock) + { + std::lock_guard lock(*cLock); + result = OCProcess(); + } + else + { + result = OC_STACK_ERROR; + } + + if(result != OC_STACK_OK) + { + // TODO: do something with result if failed? + } + + // To minimize CPU utilization we may wish to do this with sleep + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + } + + OCRepresentation parseGetSetCallback(OCClientResponse* clientResponse) + { + if(clientResponse->resJSONPayload == nullptr || clientResponse->resJSONPayload[0] == '\0') + { + throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_ERROR); + } + + MessageContainer oc; + oc.setJSONRepresentation(clientResponse->resJSONPayload); + + std::vector::const_iterator it = oc.representations().begin(); + if(it == oc.representations().end()) + { + throw OCException(OC::Exception::INVALID_REPRESENTATION, OC_STACK_ERROR); + } + + // first one is considered the root, everything else is considered a child of this one. + OCRepresentation root = *it; + ++it; + + std::for_each(it, oc.representations().end(), + [&root](const OCRepresentation& repItr) + {root.addChild(repItr);}); + return root; + + } + + OCStackApplicationResult listenCallback(void* ctx, OCDoHandle handle, + OCClientResponse* clientResponse) + { + ClientCallbackContext::ListenContext* context = + static_cast(ctx); + + if(clientResponse->result != OC_STACK_OK) + { + oclog() << "listenCallback(): failed to create resource. clientResponse: " + << clientResponse->result + << std::flush; + + return OC_STACK_KEEP_TRANSACTION; + } + + auto clientWrapper = context->clientWrapper.lock(); + + if(!clientWrapper) + { + oclog() << "listenCallback(): failed to get a shared_ptr to the client wrapper" + << std::flush; + return OC_STACK_KEEP_TRANSACTION; + } + + std::stringstream requestStream; + requestStream << clientResponse->resJSONPayload; + + try + { + ListenOCContainer container(clientWrapper, *clientResponse->addr, + requestStream); + + // loop to ensure valid construction of all resources + for(auto resource : container.Resources()) + { + std::thread exec(context->callback, resource); + exec.detach(); + } + + } + catch(const std::exception& e) + { + oclog() << "listenCallback failed to parse a malformed message: " + << e.what() + << std::endl <result + << std::flush; + return OC_STACK_KEEP_TRANSACTION; + } + + return OC_STACK_KEEP_TRANSACTION; + } + + OCStackResult InProcClientWrapper::ListenForResource(const std::string& serviceUrl, + const std::string& resourceType, FindCallback& callback, QualityOfService QoS) + { + OCStackResult result; + + OCCallbackData cbdata = {0}; + + ClientCallbackContext::ListenContext* context = new ClientCallbackContext::ListenContext(); + context->callback = callback; + context->clientWrapper = shared_from_this(); + + cbdata.context = static_cast(context); + cbdata.cb = listenCallback; + cbdata.cd = [](void* c){delete static_cast(c);}; + + auto cLock = m_csdkLock.lock(); + if(cLock) + { + std::lock_guard lock(*cLock); + OCDoHandle handle; + result = OCDoResource(&handle, OC_REST_GET, + resourceType.c_str(), + nullptr, nullptr, + static_cast(QoS), + &cbdata, + NULL, 0); + } + else + { + delete context; + result = OC_STACK_ERROR; + } + return result; + } + + OCStackApplicationResult listenDeviceCallback(void* ctx, OCDoHandle handle, + OCClientResponse* clientResponse) + { + ClientCallbackContext::DeviceListenContext* context = + static_cast(ctx); + + OCRepresentation rep = parseGetSetCallback(clientResponse); + std::thread exec(context->callback, rep); + exec.detach(); + + return OC_STACK_KEEP_TRANSACTION; + } + + OCStackResult InProcClientWrapper::ListenForDevice(const std::string& serviceUrl, + const std::string& deviceURI, FindDeviceCallback& callback, QualityOfService QoS) + { + OCStackResult result; + + OCCallbackData cbdata = {0}; + + ClientCallbackContext::DeviceListenContext* context = + new ClientCallbackContext::DeviceListenContext(); + context->callback = callback; + context->clientWrapper = shared_from_this(); + + cbdata.context = static_cast(context); + cbdata.cb = listenDeviceCallback; + cbdata.cd = [](void* c){delete static_cast(c);}; + + auto cLock = m_csdkLock.lock(); + if(cLock) + { + std::lock_guard lock(*cLock); + OCDoHandle handle; + result = OCDoResource(&handle, OC_REST_GET, + deviceURI.c_str(), + nullptr, nullptr, + static_cast(QoS), + &cbdata, + NULL, 0); + } + else + { + result = OC_STACK_ERROR; + } + return result; + } + + void parseServerHeaderOptions(OCClientResponse* clientResponse, + HeaderOptions& serverHeaderOptions) + { + if(clientResponse) + { + // Parse header options from server + uint16_t optionID; + std::string optionData; + + for(int i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++) + { + optionID = clientResponse->rcvdVendorSpecificHeaderOptions[i].optionID; + optionData = reinterpret_cast + (clientResponse->rcvdVendorSpecificHeaderOptions[i].optionData); + HeaderOption::OCHeaderOption headerOption(optionID, optionData); + serverHeaderOptions.push_back(headerOption); + } + } + else + { + // clientResponse is invalid + // TODO check proper logging + std::cout << " Invalid response " << std::endl; + } + } + + OCStackApplicationResult getResourceCallback(void* ctx, OCDoHandle handle, + OCClientResponse* clientResponse) + { + ClientCallbackContext::GetContext* context = + static_cast(ctx); + + OCRepresentation rep; + HeaderOptions serverHeaderOptions; + if(clientResponse->result == OC_STACK_OK) + { + parseServerHeaderOptions(clientResponse, serverHeaderOptions); + rep = parseGetSetCallback(clientResponse); + } + + std::thread exec(context->callback, serverHeaderOptions, rep, clientResponse->result); + exec.detach(); + return OC_STACK_DELETE_TRANSACTION; + } + + OCStackResult InProcClientWrapper::GetResourceRepresentation(const std::string& host, + const std::string& uri, const QueryParamsMap& queryParams, + const HeaderOptions& headerOptions, GetCallback& callback, + QualityOfService QoS) + { + OCStackResult result; + OCCallbackData cbdata = {0}; + + ClientCallbackContext::GetContext* ctx = new ClientCallbackContext::GetContext(); + ctx->callback = callback; + cbdata.context = static_cast(ctx); + cbdata.cb = &getResourceCallback; + cbdata.cd = [](void* c){delete static_cast(c);}; + + auto cLock = m_csdkLock.lock(); + + if(cLock) + { + std::ostringstream os; + os << host << assembleSetResourceUri(uri, queryParams).c_str(); + + std::lock_guard lock(*cLock); + OCDoHandle handle; + OCHeaderOption options[MAX_HEADER_OPTIONS]; + + assembleHeaderOptions(options, headerOptions); + result = OCDoResource(&handle, OC_REST_GET, os.str().c_str(), + nullptr, nullptr, + static_cast(QoS), + &cbdata, + options, headerOptions.size()); + } + else + { + delete ctx; + result = OC_STACK_ERROR; + } + return result; + } + + + OCStackApplicationResult setResourceCallback(void* ctx, OCDoHandle handle, + OCClientResponse* clientResponse) + { + ClientCallbackContext::SetContext* context = + static_cast(ctx); + OCRepresentation attrs; + HeaderOptions serverHeaderOptions; + + if (OC_STACK_OK == clientResponse->result || + OC_STACK_RESOURCE_CREATED == clientResponse->result || + OC_STACK_RESOURCE_DELETED == clientResponse->result) + { + parseServerHeaderOptions(clientResponse, serverHeaderOptions); + attrs = parseGetSetCallback(clientResponse); + } + + std::thread exec(context->callback, serverHeaderOptions, attrs, clientResponse->result); + exec.detach(); + return OC_STACK_DELETE_TRANSACTION; + } + + std::string InProcClientWrapper::assembleSetResourceUri(std::string uri, + const QueryParamsMap& queryParams) + { + if(uri.back() == '/') + { + uri.resize(uri.size()-1); + } + + ostringstream paramsList; + if(queryParams.size() > 0) + { + paramsList << '?'; + } + + for(auto& param : queryParams) + { + paramsList << param.first <<'='<callback = callback; + cbdata.cb = &setResourceCallback; + cbdata.cd = [](void* c){delete static_cast(c);}; + cbdata.context = static_cast(ctx); + + // TODO: in the future the cstack should be combining these two strings! + ostringstream os; + os << host << assembleSetResourceUri(uri, queryParams).c_str(); + // TODO: end of above + + auto cLock = m_csdkLock.lock(); + + if(cLock) + { + std::lock_guard lock(*cLock); + OCHeaderOption options[MAX_HEADER_OPTIONS]; + OCDoHandle handle; + + assembleHeaderOptions(options, headerOptions); + result = OCDoResource(&handle, OC_REST_POST, + os.str().c_str(), nullptr, + assembleSetResourcePayload(rep).c_str(), + static_cast(QoS), + &cbdata, options, headerOptions.size()); + } + else + { + delete ctx; + result = OC_STACK_ERROR; + } + + return result; + } + + + OCStackResult InProcClientWrapper::PutResourceRepresentation(const std::string& host, + const std::string& uri, const OCRepresentation& rep, + const QueryParamsMap& queryParams, const HeaderOptions& headerOptions, + PutCallback& callback, QualityOfService QoS) + { + OCStackResult result; + OCCallbackData cbdata = {0}; + + ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(); + ctx->callback = callback; + cbdata.cb = &setResourceCallback; + cbdata.cd = [](void* c){delete static_cast(c);}; + cbdata.context = static_cast(ctx); + + // TODO: in the future the cstack should be combining these two strings! + ostringstream os; + os << host << assembleSetResourceUri(uri, queryParams).c_str(); + // TODO: end of above + + auto cLock = m_csdkLock.lock(); + + if(cLock) + { + std::lock_guard lock(*cLock); + OCDoHandle handle; + OCHeaderOption options[MAX_HEADER_OPTIONS]; + + assembleHeaderOptions(options, headerOptions); + result = OCDoResource(&handle, OC_REST_PUT, + os.str().c_str(), nullptr, + assembleSetResourcePayload(rep).c_str(), + static_cast(QoS), + &cbdata, + options, headerOptions.size()); + } + else + { + delete ctx; + result = OC_STACK_ERROR; + } + + return result; + } + + OCStackApplicationResult deleteResourceCallback(void* ctx, OCDoHandle handle, + OCClientResponse* clientResponse) + { + ClientCallbackContext::DeleteContext* context = + static_cast(ctx); + HeaderOptions serverHeaderOptions; + + if(clientResponse->result == OC_STACK_OK) + { + parseServerHeaderOptions(clientResponse, serverHeaderOptions); + } + std::thread exec(context->callback, serverHeaderOptions, clientResponse->result); + exec.detach(); + return OC_STACK_DELETE_TRANSACTION; + } + + OCStackResult InProcClientWrapper::DeleteResource(const std::string& host, + const std::string& uri, const HeaderOptions& headerOptions, + DeleteCallback& callback, QualityOfService QoS) + { + OCStackResult result; + OCCallbackData cbdata = {0}; + + ClientCallbackContext::DeleteContext* ctx = new ClientCallbackContext::DeleteContext(); + ctx->callback = callback; + cbdata.cb = &deleteResourceCallback; + cbdata.cd = [](void* c){delete static_cast(c);}; + cbdata.context = static_cast(ctx); + + ostringstream os; + os << host << uri; + + auto cLock = m_csdkLock.lock(); + + if(cLock) + { + OCHeaderOption options[MAX_HEADER_OPTIONS]; + OCDoHandle handle; + + assembleHeaderOptions(options, headerOptions); + + std::lock_guard lock(*cLock); + + result = OCDoResource(&handle, OC_REST_DELETE, + os.str().c_str(), nullptr, + nullptr, static_cast(m_cfg.QoS), + &cbdata, options, headerOptions.size()); + } + else + { + delete ctx; + result = OC_STACK_ERROR; + } + + return result; + } + + OCStackApplicationResult observeResourceCallback(void* ctx, OCDoHandle handle, + OCClientResponse* clientResponse) + { + ClientCallbackContext::ObserveContext* context = + static_cast(ctx); + OCRepresentation attrs; + HeaderOptions serverHeaderOptions; + uint32_t sequenceNumber = clientResponse->sequenceNumber; + + if(clientResponse->result == OC_STACK_OK) + { + parseServerHeaderOptions(clientResponse, serverHeaderOptions); + attrs = parseGetSetCallback(clientResponse); + } + std::thread exec(context->callback, serverHeaderOptions, attrs, + clientResponse->result, sequenceNumber); + exec.detach(); + return OC_STACK_KEEP_TRANSACTION; + } + + OCStackResult InProcClientWrapper::ObserveResource(ObserveType observeType, OCDoHandle* handle, + const std::string& host, const std::string& uri, const QueryParamsMap& queryParams, + const HeaderOptions& headerOptions, ObserveCallback& callback, QualityOfService QoS) + { + OCStackResult result; + OCCallbackData cbdata = {0}; + + ClientCallbackContext::ObserveContext* ctx = new ClientCallbackContext::ObserveContext(); + ctx->callback = callback; + cbdata.context = static_cast(ctx); + cbdata.cb = &observeResourceCallback; + cbdata.cd = [](void* c){delete static_cast(c);}; + + OCMethod method; + if (observeType == ObserveType::Observe) + { + method = OC_REST_OBSERVE; + } + else if (observeType == ObserveType::ObserveAll) + { + method = OC_REST_OBSERVE_ALL; + } + else + { + method = OC_REST_OBSERVE_ALL; + } + + auto cLock = m_csdkLock.lock(); + + if(cLock) + { + std::ostringstream os; + os << host << assembleSetResourceUri(uri, queryParams).c_str(); + + std::lock_guard lock(*cLock); + OCHeaderOption options[MAX_HEADER_OPTIONS]; + + assembleHeaderOptions(options, headerOptions); + result = OCDoResource(handle, method, + os.str().c_str(), nullptr, + nullptr, + static_cast(QoS), + &cbdata, + options, headerOptions.size()); + } + else + { + delete ctx; + return OC_STACK_ERROR; + } + + return result; + } + + OCStackResult InProcClientWrapper::CancelObserveResource(OCDoHandle handle, + const std::string& host, const std::string& uri, const HeaderOptions& headerOptions, + QualityOfService QoS) + { + OCStackResult result; + auto cLock = m_csdkLock.lock(); + + if(cLock) + { + std::lock_guard lock(*cLock); + OCHeaderOption options[MAX_HEADER_OPTIONS]; + + assembleHeaderOptions(options, headerOptions); + result = OCCancel(handle, static_cast(QoS), options, + headerOptions.size()); + } + else + { + result = OC_STACK_ERROR; + } + + return result; + } + + OCStackApplicationResult subscribePresenceCallback(void* ctx, OCDoHandle handle, + OCClientResponse* clientResponse) + { + char stringAddress[DEV_ADDR_SIZE_MAX]; + ostringstream os; + uint16_t port; + + if(OCDevAddrToString(clientResponse->addr, stringAddress) == 0 && + OCDevAddrToPort(clientResponse->addr, &port) == 0) + { + os<(ctx); + + std::thread exec(context->callback, clientResponse->result, + clientResponse->sequenceNumber, os.str()); + + exec.detach(); + } + else + { + oclog() << "subscribePresenceCallback(): OCDevAddrToString() or OCDevAddrToPort() " + <<"failed"<< std::flush; + } + return OC_STACK_KEEP_TRANSACTION; + } + + OCStackResult InProcClientWrapper::SubscribePresence(OCDoHandle* handle, + const std::string& host, const std::string& resourceType, + SubscribeCallback& presenceHandler) + { + OCCallbackData cbdata = {0}; + + ClientCallbackContext::SubscribePresenceContext* ctx = + new ClientCallbackContext::SubscribePresenceContext(); + ctx->callback = presenceHandler; + cbdata.cb = &subscribePresenceCallback; + cbdata.context = static_cast(ctx); + cbdata.cd = [](void* c) + {delete static_cast(c);}; + auto cLock = m_csdkLock.lock(); + + std::ostringstream os; + os << host << "/oc/presence"; + + if(!resourceType.empty()) + { + os << "?rt=" << resourceType; + } + + if(!cLock) + { + delete ctx; + return OC_STACK_ERROR; + } + + return OCDoResource(handle, OC_REST_PRESENCE, os.str().c_str(), nullptr, nullptr, + OC_LOW_QOS, &cbdata, NULL, 0); + } + + OCStackResult InProcClientWrapper::UnsubscribePresence(OCDoHandle handle) + { + OCStackResult result; + auto cLock = m_csdkLock.lock(); + + if(cLock) + { + std::lock_guard lock(*cLock); + result = OCCancel(handle, OC_LOW_QOS, NULL, 0); + } + else + { + result = OC_STACK_ERROR; + } + + return result; + } + + OCStackResult InProcClientWrapper::GetDefaultQos(QualityOfService& qos) + { + qos = m_cfg.QoS; + return OC_STACK_OK; + } + + void InProcClientWrapper::assembleHeaderOptions(OCHeaderOption options[], + const HeaderOptions& headerOptions) + { + int i = 0; + + for (auto it=headerOptions.begin(); it != headerOptions.end(); ++it) + { + options[i].protocolID = OC_COAP_ID; + options[i].optionID = static_cast(it->getOptionID()); + options[i].optionLength = (it->getOptionData()).length() + 1; + memcpy(options[i].optionData, (it->getOptionData()).c_str(), + (it->getOptionData()).length() + 1); + i++; + } + } +} diff --git a/resource/src/InProcServerWrapper.cpp b/resource/src/InProcServerWrapper.cpp new file mode 100644 index 000000000..0159bb89e --- /dev/null +++ b/resource/src/InProcServerWrapper.cpp @@ -0,0 +1,606 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace OC; + +std::map entityHandlerMap; +std::map resourceUriMap; +EntityHandler defaultDeviceEntityHandler = 0; + +void formResourceRequest(OCEntityHandlerFlag flag, + OCEntityHandlerRequest * entityHandlerRequest, + std::shared_ptr pRequest) +{ + pRequest->setRequestHandle(entityHandlerRequest->requestHandle); + pRequest->setResourceHandle(entityHandlerRequest->resource); + + if(flag & OC_INIT_FLAG) + { + pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::InitFlag); + } + + if(flag & OC_REQUEST_FLAG) + { + pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::RequestFlag); + + if(entityHandlerRequest) + { + if(entityHandlerRequest->query) + { + std::string querystr(reinterpret_cast(entityHandlerRequest->query)); + + OC::Utilities::QueryParamsKeyVal qp = OC::Utilities::getQueryParams(querystr); + + if(qp.size() > 0) + { + pRequest->setQueryParams(qp); + } + } + if(entityHandlerRequest->numRcvdVendorSpecificHeaderOptions != 0) + { + //Set the header options here. + uint16_t optionID; + std::string optionData; + HeaderOptions headerOptions; + + for(int i = 0; + i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions; + i++) + { + optionID = entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionID; + optionData = reinterpret_cast + (entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionData); + HeaderOption::OCHeaderOption headerOption(optionID, optionData); + headerOptions.push_back(headerOption); + } + pRequest->setHeaderOptions(headerOptions); + } + + if(OC_REST_GET == entityHandlerRequest->method) + { + pRequest->setRequestType(OC::PlatformCommands::GET); + } + else if(OC_REST_PUT == entityHandlerRequest->method) + { + pRequest->setRequestType(OC::PlatformCommands::PUT); + pRequest->setPayload(std::string(reinterpret_cast + (entityHandlerRequest->reqJSONPayload))); + } + else if(OC_REST_POST == entityHandlerRequest->method) + { + pRequest->setRequestType(OC::PlatformCommands::POST); + pRequest->setPayload(std::string(reinterpret_cast + (entityHandlerRequest->reqJSONPayload))); + } + else if(OC_REST_DELETE == entityHandlerRequest->method) + { + pRequest->setRequestType(OC::PlatformCommands::DELETE); + } + } + } + + if(flag & OC_OBSERVE_FLAG) + { + pRequest->setRequestHandlerFlag( + OC::RequestHandlerFlag::RequestFlag | OC::RequestHandlerFlag::ObserverFlag); + + if(entityHandlerRequest) + { + OC::ObservationInfo observationInfo; + observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo.action; + observationInfo.obsId = entityHandlerRequest->obsInfo.obsId; + pRequest->setObservationInfo(observationInfo); + } + } +} + +OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag, + OCEntityHandlerRequest * entityHandlerRequest, + char* uri) +{ + OCEntityHandlerResult result = OC_EH_ERROR; + + OC::oclog() << "In Default device entity handler wrapper"; + + if(NULL == entityHandlerRequest) + { + oclog() << "Entity handler request is NULL."; + return OC_EH_ERROR; + } + + auto pRequest = std::make_shared(); + + formResourceRequest(flag, entityHandlerRequest, pRequest); + + pRequest->setResourceUri(std::string(uri)); + + if(defaultDeviceEntityHandler) + { + result = defaultDeviceEntityHandler(pRequest); + } + else + { + oclog() << "Default device entity handler was not set."; + return OC_EH_ERROR; + } + + return result; +} + + +OCEntityHandlerResult EntityHandlerWrapper(OCEntityHandlerFlag flag, + OCEntityHandlerRequest * entityHandlerRequest) +{ + OCEntityHandlerResult result = OC_EH_ERROR; + + oclog() << "\nIn entity handler wrapper: " << endl; + + if(NULL == entityHandlerRequest) + { + oclog() << "Entity handler request is NULL." << endl; + return OC_EH_ERROR; + } + + auto pRequest = std::make_shared(); + + formResourceRequest(flag, entityHandlerRequest, pRequest); + + // Finding the corresponding URI for a resource handle and set the URI in the request + auto resourceUriEntry = resourceUriMap.find(entityHandlerRequest->resource); + if(resourceUriEntry != resourceUriMap.end()) + { + pRequest->setResourceUri(resourceUriEntry->second); + } + else + { + oclog() << "Resource handle not found; Resource URI not set in request"; + return OC_EH_ERROR; + } + + // Finding the corresponding CPP Application entityHandler for a given resource + auto entityHandlerEntry = entityHandlerMap.find(entityHandlerRequest->resource); + + if(entityHandlerEntry != entityHandlerMap.end()) + { + // Call CPP Application Entity Handler + if(entityHandlerEntry->second) + { + result = entityHandlerEntry->second(pRequest); + } + else + { + oclog() << "C stack should not call again for parent resource\n"; + return OC_EH_ERROR; + } + } + else + { + oclog() << "No entity handler found." << endl; + return OC_EH_ERROR; + } + + return result; +} + +namespace OC +{ + InProcServerWrapper::InProcServerWrapper( + std::weak_ptr csdkLock, PlatformConfig cfg) + : m_csdkLock(csdkLock) + { + OCMode initType; + + if(cfg.mode == ModeType::Server) + { + initType = OC_SERVER; + } + else if (cfg.mode == ModeType::Both) + { + initType = OC_CLIENT_SERVER; + } + else + { + throw InitializeException(OC::InitException::NOT_CONFIGURED_AS_SERVER, + OC_STACK_INVALID_PARAM); + } + + OCStackResult result = OCInit(cfg.ipAddress.c_str(), cfg.port, initType); + + if(OC_STACK_OK != result) + { + throw InitializeException(OC::InitException::STACK_INIT_ERROR, result); + } + + m_threadRun = true; + m_processThread = std::thread(&InProcServerWrapper::processFunc, this); + } + + void InProcServerWrapper::processFunc() + { + auto cLock = m_csdkLock.lock(); + while(cLock && m_threadRun) + { + OCStackResult result; + + { + std::lock_guard lock(*cLock); + result = OCProcess(); + } + + // ...the value of variable result is simply ignored for now. + if(OC_STACK_ERROR == result) + ; + + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + } + + OCStackResult InProcServerWrapper::registerDeviceInfo(const OCDeviceInfo deviceInfo) + { + auto cLock = m_csdkLock.lock(); + OCStackResult result = OC_STACK_ERROR; + if(cLock) + { + std::lock_guard lock(*cLock); + result = OCSetDeviceInfo(deviceInfo); + } + return result; + } + + OCStackResult InProcServerWrapper::registerResource( + OCResourceHandle& resourceHandle, + std::string& resourceURI, + const std::string& resourceTypeName, + const std::string& resourceInterface, + EntityHandler& eHandler, + uint8_t resourceProperties) + + { + OCStackResult result = OC_STACK_ERROR; + + auto cLock = m_csdkLock.lock(); + + if(cLock) + { + std::lock_guard lock(*cLock); + + if(NULL != eHandler) + { + result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle + resourceTypeName.c_str(), // const char * resourceTypeName + resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this + resourceURI.c_str(), // const char * uri + EntityHandlerWrapper, // OCEntityHandler entityHandler + resourceProperties // uint8_t resourceProperties + ); + } + else + { + result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle + resourceTypeName.c_str(), // const char * resourceTypeName + resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this + resourceURI.c_str(), // const char * uri + NULL, // OCEntityHandler entityHandler + resourceProperties // uint8_t resourceProperties + ); + } + + if(result != OC_STACK_OK) + { + resourceHandle = (OCResourceHandle) 0; + } + else + { + entityHandlerMap[resourceHandle] = eHandler; + resourceUriMap[resourceHandle] = resourceURI; + } + } + else + { + result = OC_STACK_ERROR; + } + + return result; + } + + OCStackResult InProcServerWrapper::registerResourceWithHost( + OCResourceHandle& resourceHandle, + std::string& resourceHOST, + std::string& resourceURI, + const std::string& resourceTypeName, + const std::string& resourceInterface, + EntityHandler& eHandler, + uint8_t resourceProperties) + + { + OCStackResult result = OC_STACK_ERROR; + + auto cLock = m_csdkLock.lock(); + + if (cLock) + { + std::lock_guard < std::recursive_mutex > lock(*cLock); + + if (NULL != eHandler) + { + result = OCCreateResourceWithHost(&resourceHandle, // OCResourceHandle *handle + resourceTypeName.c_str(), // const char * resourceTypeName + resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix + resourceHOST.c_str(), // const char * host + (resourceHOST + resourceURI).c_str(), // const char * uri + EntityHandlerWrapper, // OCEntityHandler entityHandler + resourceProperties // uint8_t resourceProperties + ); + } + else + { + result = OCCreateResourceWithHost(&resourceHandle, // OCResourceHandle *handle + resourceTypeName.c_str(), // const char * resourceTypeName + resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix + resourceHOST.c_str(), // const char * host + (resourceHOST + resourceURI).c_str(), // const char * uri + nullptr, // OCEntityHandler entityHandler + resourceProperties // uint8_t resourceProperties + ); + } + + if (result != OC_STACK_OK) + { + resourceHandle = nullptr; + } + else + { + entityHandlerMap[resourceHandle] = eHandler; + resourceUriMap[resourceHandle] = resourceURI; + } + } + else + { + result = OC_STACK_ERROR; + } + + return result; + } + + OCStackResult InProcServerWrapper::setDefaultDeviceEntityHandler + (EntityHandler entityHandler) + { + OCStackResult result = OC_STACK_ERROR; + + defaultDeviceEntityHandler = entityHandler; + + if(entityHandler) + { + result = OCSetDefaultDeviceEntityHandler(DefaultEntityHandlerWrapper); + } + else + { + // If Null passed we unset + result = OCSetDefaultDeviceEntityHandler(NULL); + } + + return result; + } + + OCStackResult InProcServerWrapper::unregisterResource(const OCResourceHandle& resourceHandle) + { + auto cLock = m_csdkLock.lock(); + OCStackResult result = OC_STACK_ERROR; + + if(cLock) + { + std::lock_guard lock(*cLock); + result = OCDeleteResource(resourceHandle); + + if(result == OC_STACK_OK) + { + resourceUriMap.erase(resourceHandle); + } + else + { + throw OCException(OC::Exception::RESOURCE_UNREG_FAILED, result); + } + } + else + { + result = OC_STACK_ERROR; + } + + return result; + } + + OCStackResult InProcServerWrapper::bindTypeToResource(const OCResourceHandle& resourceHandle, + const std::string& resourceTypeName) + { + auto cLock = m_csdkLock.lock(); + OCStackResult result; + if(cLock) + { + std::lock_guard lock(*cLock); + result = OCBindResourceTypeToResource(resourceHandle, resourceTypeName.c_str()); + } + else + { + result = OC_STACK_ERROR; + } + + if (result != OC_STACK_OK) + { + throw OCException(OC::Exception::BIND_TYPE_FAILED, result); + } + return result; + } + + OCStackResult InProcServerWrapper::bindInterfaceToResource( + const OCResourceHandle& resourceHandle, + const std::string& resourceInterfaceName) + { + auto cLock = m_csdkLock.lock(); + OCStackResult result; + if(cLock) + { + std::lock_guard lock(*cLock); + result = OCBindResourceInterfaceToResource(resourceHandle, + resourceInterfaceName.c_str()); + } + else + { + result = OC_STACK_ERROR; + } + + if (result != OC_STACK_OK) + { + throw OCException(OC::Exception::BIND_INTERFACE_FAILED, result); + } + return result; + } + + OCStackResult InProcServerWrapper::startPresence(const unsigned int seconds) + { + auto cLock = m_csdkLock.lock(); + OCStackResult result = OC_STACK_ERROR; + if(cLock) + { + std::lock_guard lock(*cLock); + result = OCStartPresence(seconds); + } + + if(result != OC_STACK_OK) + { + throw OCException(OC::Exception::START_PRESENCE_FAILED, result); + } + return result; + } + + OCStackResult InProcServerWrapper::stopPresence() + { + auto cLock = m_csdkLock.lock(); + OCStackResult result = OC_STACK_ERROR; + if(cLock) + { + std::lock_guard lock(*cLock); + result = OCStopPresence(); + } + + if(result != OC_STACK_OK) + { + throw OCException(OC::Exception::END_PRESENCE_FAILED, result); + } + return result; + } + + OCStackResult InProcServerWrapper::sendResponse( + const std::shared_ptr pResponse) + { + auto cLock = m_csdkLock.lock(); + OCStackResult result = OC_STACK_ERROR; + + if(!pResponse) + { + result = OC_STACK_MALFORMED_RESPONSE; + throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE); + } + else + { + OCEntityHandlerResponse response; + std::string payLoad; + HeaderOptions serverHeaderOptions; + + payLoad = pResponse->getPayload(); + serverHeaderOptions = pResponse->getHeaderOptions(); + + response.requestHandle = pResponse->getRequestHandle(); + response.resourceHandle = pResponse->getResourceHandle(); + response.ehResult = pResponse->getResponseResult(); + response.payload = (unsigned char*) payLoad.c_str(); + response.payloadSize = payLoad.length() + 1; + response.persistentBufferFlag = 0; + + response.numSendVendorSpecificHeaderOptions = serverHeaderOptions.size(); + int i = 0; + for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it) + { + response.sendVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID; + response.sendVendorSpecificHeaderOptions[i].optionID = + static_cast(it->getOptionID()); + response.sendVendorSpecificHeaderOptions[i].optionLength = + (it->getOptionData()).length() + 1; + memcpy(response.sendVendorSpecificHeaderOptions[i].optionData, + (it->getOptionData()).c_str(), + (it->getOptionData()).length() + 1); + i++; + } + + if(OC_EH_RESOURCE_CREATED == response.ehResult) + { + std::string createdUri = pResponse->getNewResourceUri(); + strncpy(reinterpret_cast(response.resourceUri), + createdUri.c_str(), + createdUri.length() + 1); + } + + if(cLock) + { + std::lock_guard lock(*cLock); + result = OCDoResponse(&response); + } + else + { + result = OC_STACK_ERROR; + } + + if(result != OC_STACK_OK) + { + oclog() << "Error sending response\n"; + } + return result; + } + } + + InProcServerWrapper::~InProcServerWrapper() + { + if(m_processThread.joinable()) + { + m_threadRun = false; + m_processThread.join(); + } + + OCStop(); + } +} diff --git a/resource/src/OCApi.cpp b/resource/src/OCApi.cpp new file mode 100644 index 000000000..a5e82fc03 --- /dev/null +++ b/resource/src/OCApi.cpp @@ -0,0 +1,21 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "ocapi.h" diff --git a/resource/src/OCException.cpp b/resource/src/OCException.cpp new file mode 100644 index 000000000..9bea2e269 --- /dev/null +++ b/resource/src/OCException.cpp @@ -0,0 +1,92 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "OCException.h" +#include "StringConstants.h" + +std::string OC::OCException::reason(const OCStackResult sr) +{ + switch(sr) + { + case OC_STACK_OK: + return OC::Exception::NO_ERROR; + case OC_STACK_RESOURCE_CREATED: + return OC::Exception::RESOURCE_CREATED; + case OC_STACK_RESOURCE_DELETED: + return OC::Exception::RESOURCE_DELETED; + case OC_STACK_INVALID_URI: + return OC::Exception::INVALID_URI; + case OC_STACK_INVALID_IP: + return OC::Exception::INVALID_IP; + case OC_STACK_INVALID_PORT: + return OC::Exception::INVALID_PORT; + case OC_STACK_INVALID_CALLBACK: + return OC::Exception::INVALID_CB; + case OC_STACK_INVALID_METHOD: + return OC::Exception::INVALID_METHOD; + case OC_STACK_INVALID_QUERY: + return OC::Exception::INVALID_QUERY; + case OC_STACK_INVALID_PARAM: + return OC::Exception::INVALID_PARAM; + case OC_STACK_INVALID_OBSERVE_PARAM: + return OC::Exception::INVALID_OBESERVE; + case OC_STACK_NO_MEMORY: + return OC::Exception::NO_MEMORY; + case OC_STACK_COMM_ERROR: + return OC::Exception::COMM_ERROR; + case OC_STACK_NOTIMPL: + return OC::Exception::NOT_IMPL; + case OC_STACK_NO_RESOURCE: + return OC::Exception::NOT_FOUND; + case OC_STACK_RESOURCE_ERROR: + return OC::Exception::RESOURCE_ERROR; + case OC_STACK_SLOW_RESOURCE: + return OC::Exception::SLOW_RESOURCE; + case OC_STACK_NO_OBSERVERS: + return OC::Exception::NO_OBSERVERS; + case OC_STACK_OBSERVER_NOT_FOUND: + return OC::Exception::OBSV_NO_FOUND; +#ifdef WITH_PRESENCE + case OC_STACK_PRESENCE_STOPPED: + return OC::Exception::PRESENCE_STOPPED; + case OC_STACK_PRESENCE_TIMEOUT: + return OC::Exception::PRESENCE_TIMEOUT; + case OC_STACK_PRESENCE_DO_NOT_HANDLE: + return OC::Exception::PRESENCE_NOT_HANDLED; +#endif + case OC_STACK_VIRTUAL_DO_NOT_HANDLE: + return OC::Exception::VIRTUAL_DO_NOT_HANDLE; + case OC_STACK_INVALID_OPTION: + return OC::Exception::INVALID_OPTION; + case OC_STACK_MALFORMED_RESPONSE: + return OC::Exception::MALFORMED_STACK_RESPONSE; + case OC_STACK_PERSISTENT_BUFFER_REQUIRED: + return OC::Exception::PERSISTENT_BUFFER_REQUIRED; + case OC_STACK_CONTINUE: + return OC::Exception::STACK_CONTINUE; + case OC_STACK_INVALID_REQUEST_HANDLE: + return OC::Exception::INVALID_REQUEST_HANDLE; + case OC_STACK_ERROR: + return OC::Exception::GENERAL_FAULT; + } + + return OC::Exception::UNKNOWN_ERROR; +} + diff --git a/resource/src/OCPlatform.cpp b/resource/src/OCPlatform.cpp new file mode 100644 index 000000000..9a17833ab --- /dev/null +++ b/resource/src/OCPlatform.cpp @@ -0,0 +1,219 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +//****************************************************************** +// File name: +// OCPlatform.cpp +// +// Description: Implementation of the OCPlatform. +// +// +// +//********************************************************************* +#include +namespace OC +{ + namespace OCPlatform + { + void Configure(const PlatformConfig& config) + { + OCPlatform_impl::Configure(config); + } + + OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler) + { + return OCPlatform_impl::Instance().setDefaultDeviceEntityHandler(entityHandler); + } + + OCStackResult notifyAllObservers(OCResourceHandle resourceHandle, + QualityOfService QoS) + { + return OCPlatform_impl::Instance().notifyAllObservers(resourceHandle, QoS); + } + + OCStackResult notifyAllObservers(OCResourceHandle resourceHandle) + { + return OCPlatform_impl::Instance().notifyAllObservers(resourceHandle); + } + + OCStackResult notifyListOfObservers(OCResourceHandle resourceHandle, + ObservationIds& observationIds, + const std::shared_ptr pResponse) + { + return OCPlatform_impl::Instance().notifyListOfObservers(resourceHandle, + observationIds, pResponse); + } + + OCStackResult notifyListOfObservers(OCResourceHandle resourceHandle, + ObservationIds& observationIds, + const std::shared_ptr pResponse, + QualityOfService QoS) + { + return OCPlatform_impl::Instance().notifyListOfObservers(resourceHandle, + observationIds, pResponse, QoS); + } + + OCResource::Ptr constructResourceObject(const std::string& host, + const std::string& uri, + bool isObservable, + const std::vector& resourceTypes, + const std::vector& interfaces) + { + return OCPlatform_impl::Instance().constructResourceObject(host, uri, isObservable, + resourceTypes, interfaces); + } + + OCStackResult findResource(const std::string& host, + const std::string& resourceName, + FindCallback resourceHandler) + { + return OCPlatform_impl::Instance().findResource(host, resourceName, resourceHandler); + } + + OCStackResult findResource(const std::string& host, + const std::string& resourceName, + FindCallback resourceHandler, QualityOfService QoS) + { + return OCPlatform_impl::Instance().findResource(host, resourceName, + resourceHandler, QoS); + } + + OCStackResult getDeviceInfo(const std::string& host, + const std::string& deviceURI, + FindDeviceCallback deviceInfoHandler) + { + return OCPlatform_impl::Instance().getDeviceInfo(host, deviceURI, deviceInfoHandler); + } + + OCStackResult getDeviceInfo(const std::string& host, + const std::string& deviceURI, + FindDeviceCallback deviceInfoHandler, + QualityOfService QoS) + { + return OCPlatform_impl::Instance().getDeviceInfo(host, deviceURI, + deviceInfoHandler, QoS); + } + + + OCStackResult registerResource(OCResourceHandle& resourceHandle, + std::string& resourceURI, + const std::string& resourceTypeName, + const std::string& resourceInterface, + EntityHandler entityHandler, + uint8_t resourceProperty) + { + return OCPlatform_impl::Instance().registerResource(resourceHandle, resourceURI, + resourceTypeName, resourceInterface, + entityHandler, resourceProperty); + } + + OCStackResult registerResource(OCResourceHandle& resourceHandle, + const std::shared_ptr< OCResource > resource) + { + return OCPlatform_impl::Instance().registerResource(resourceHandle, resource); + } + + OCStackResult registerDeviceInfo(const OCDeviceInfo deviceInfo) + { + return OCPlatform_impl::Instance().registerDeviceInfo(deviceInfo); + } + + OCStackResult unregisterResource(const OCResourceHandle& resourceHandle) + { + return OCPlatform_impl::Instance().unregisterResource(resourceHandle); + } + + OCStackResult unbindResource(OCResourceHandle collectionHandle, + OCResourceHandle resourceHandle) + { + return OCPlatform_impl::Instance().unbindResource(collectionHandle, resourceHandle); + } + + OCStackResult unbindResources(const OCResourceHandle collectionHandle, + const std::vector& resourceHandles + ) + { + return OCPlatform_impl::Instance().unbindResources(collectionHandle, resourceHandles); + } + + OCStackResult bindResource(const OCResourceHandle collectionHandle, + const OCResourceHandle resourceHandle) + { + return OCPlatform_impl::Instance().bindResource(collectionHandle, resourceHandle); + } + + OCStackResult bindResources(const OCResourceHandle collectionHandle, + const std::vector& resourceHandles + ) + { + return OCPlatform_impl::Instance().bindResources(collectionHandle, resourceHandles); + } + + OCStackResult bindTypeToResource(const OCResourceHandle& resourceHandle, + const std::string& resourceTypeName) + { + return OCPlatform_impl::Instance().bindTypeToResource(resourceHandle,resourceTypeName); + } + + OCStackResult bindInterfaceToResource(const OCResourceHandle& resourceHandle, + const std::string& resourceInterfaceName) + { + return OCPlatform_impl::Instance().bindInterfaceToResource(resourceHandle, + resourceInterfaceName); + } + + OCStackResult startPresence(const unsigned int announceDurationSeconds) + { + return OCPlatform_impl::Instance().startPresence(announceDurationSeconds); + } + + OCStackResult stopPresence() + { + return OCPlatform_impl::Instance().stopPresence(); + } + + OCStackResult subscribePresence(OCPresenceHandle& presenceHandle, + const std::string& host, + SubscribeCallback presenceHandler) + { + return OCPlatform_impl::Instance().subscribePresence(presenceHandle, host, + presenceHandler); + } + + OCStackResult subscribePresence(OCPresenceHandle& presenceHandle, + const std::string& host, + const std::string& resourceType, + SubscribeCallback presenceHandler) + { + return OCPlatform_impl::Instance().subscribePresence(presenceHandle, host, + resourceType, presenceHandler); + } + + OCStackResult unsubscribePresence(OCPresenceHandle presenceHandle) + { + return OCPlatform_impl::Instance().unsubscribePresence(presenceHandle); + } + + OCStackResult sendResponse(const std::shared_ptr pResponse) + { + return OCPlatform_impl::Instance().sendResponse(pResponse); + } + } // namespace OCPlatform +} //namespace OC diff --git a/resource/src/OCPlatform_impl.cpp b/resource/src/OCPlatform_impl.cpp new file mode 100644 index 000000000..9d9ae52d9 --- /dev/null +++ b/resource/src/OCPlatform_impl.cpp @@ -0,0 +1,321 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +//****************************************************************** +// File name: +// OCPlatform_impl.cpp +// +// Description: Implementation of the OCPlatform functionality. It contains +// a singleton interface that is used only by the OCPlatform namespace and is the +// central entrance to the stack. +// +// +// +//********************************************************************* + +#include +#include +#include + +#include "ocstack.h" + +#include "OCPlatform.h" +#include "OCApi.h" +#include "OCException.h" +#include "OCUtilities.h" + +#include "oc_logger.hpp" + +namespace OC +{ + + PlatformConfig& OCPlatform_impl::globalConfig() + { + static PlatformConfig s_config; + return s_config; + } + + void OCPlatform_impl::Configure(const PlatformConfig& config) + { + globalConfig() = config; + } + + OCPlatform_impl& OCPlatform_impl::Instance() + { + static OCPlatform_impl platform(globalConfig()); + return platform; + } + + void OCPlatform_impl::init(const PlatformConfig& config) + { + switch(config.mode) + { + case ModeType::Server: + m_server = m_WrapperInstance->CreateServerWrapper(m_csdkLock, config); + break; + + case ModeType::Client: + m_client = m_WrapperInstance->CreateClientWrapper(m_csdkLock, config); + break; + + case ModeType::Both: + m_server = m_WrapperInstance->CreateServerWrapper(m_csdkLock, config); + m_client = m_WrapperInstance->CreateClientWrapper(m_csdkLock, config); + break; + } + } + + OCPlatform_impl::OCPlatform_impl(const PlatformConfig& config) + : m_cfg { config }, + m_WrapperInstance { make_unique() }, + m_csdkLock { make_shared() } + { + init(m_cfg); + } + + OCPlatform_impl::~OCPlatform_impl(void) + { + } + + OCStackResult OCPlatform_impl::setDefaultDeviceEntityHandler(EntityHandler entityHandler) + { + return checked_guard(m_server, &IServerWrapper::setDefaultDeviceEntityHandler, + entityHandler); + } + + OCStackResult OCPlatform_impl::notifyAllObservers(OCResourceHandle resourceHandle, + QualityOfService QoS) + { + return result_guard(OCNotifyAllObservers(resourceHandle, + static_cast(QoS))); + } + + OCStackResult OCPlatform_impl::notifyAllObservers(OCResourceHandle resourceHandle) + { + return notifyAllObservers(resourceHandle, m_cfg.QoS); + } + + OCStackResult OCPlatform_impl::notifyListOfObservers(OCResourceHandle resourceHandle, + ObservationIds& observationIds, + const std::shared_ptr pResponse) + { + return notifyListOfObservers(resourceHandle, observationIds, pResponse, m_cfg.QoS); + } + + OCStackResult OCPlatform_impl::notifyListOfObservers(OCResourceHandle resourceHandle, + ObservationIds& observationIds, + const std::shared_ptr pResponse, + QualityOfService QoS) + { + if(!pResponse) + { + return result_guard(OC_STACK_ERROR); + } + + std::string payload(pResponse->getResourceRepresentation().getJSONRepresentation()); + + return result_guard( + OCNotifyListOfObservers(resourceHandle, + &observationIds[0], observationIds.size(), + reinterpret_cast(const_cast(payload.c_str())), + static_cast(QoS))); + } + + OCResource::Ptr OCPlatform_impl::constructResourceObject(const std::string& host, + const std::string& uri, + bool isObservable, + const std::vector& resourceTypes, + const std::vector& interfaces) + { + if(!m_client) + { + return std::shared_ptr(); + } + + return std::shared_ptr(new OCResource(m_client, + host, + uri, + isObservable, + resourceTypes, + interfaces)); + } + + OCStackResult OCPlatform_impl::findResource(const std::string& host, + const std::string& resourceName, + FindCallback resourceHandler) + { + return findResource(host, resourceName, resourceHandler, m_cfg.QoS); + } + + OCStackResult OCPlatform_impl::findResource(const std::string& host, + const std::string& resourceName, + FindCallback resourceHandler, QualityOfService QoS) + { + return checked_guard(m_client, &IClientWrapper::ListenForResource, + host, resourceName, resourceHandler, QoS); + } + + OCStackResult OCPlatform_impl::getDeviceInfo(const std::string& host, + const std::string& deviceURI, + FindDeviceCallback deviceInfoHandler) + { + return result_guard(getDeviceInfo(host, deviceURI, deviceInfoHandler, m_cfg.QoS)); + } + + OCStackResult OCPlatform_impl::getDeviceInfo(const std::string& host, + const std::string& deviceURI, + FindDeviceCallback deviceInfoHandler, + QualityOfService QoS) + { + return checked_guard(m_client, &IClientWrapper::ListenForDevice, + host, deviceURI, deviceInfoHandler, QoS); + } + + OCStackResult OCPlatform_impl::registerResource(OCResourceHandle& resourceHandle, + std::string& resourceURI, + const std::string& resourceTypeName, + const std::string& resourceInterface, + EntityHandler entityHandler, + uint8_t resourceProperty) + { + return checked_guard(m_server, &IServerWrapper::registerResource, + ref(resourceHandle), resourceURI, resourceTypeName, + resourceInterface, entityHandler, resourceProperty); + } + + OCStackResult OCPlatform_impl::registerDeviceInfo(const OCDeviceInfo deviceInfo) + { + return checked_guard(m_server, &IServerWrapper::registerDeviceInfo, deviceInfo); + } + + OCStackResult OCPlatform_impl::registerResource(OCResourceHandle& resourceHandle, + const std::shared_ptr< OCResource > resource) + { + uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE; + std::vector resourceTypes = resource->getResourceTypes(); + + return checked_guard(m_server, &IServerWrapper::registerResourceWithHost, + ref(resourceHandle), resource->host(), resource->uri(), resourceTypes[0]/*"core.remote"*/, "oc.mi.def", + (EntityHandler) nullptr, resourceProperty); + } + + OCStackResult OCPlatform_impl::unregisterResource(const OCResourceHandle& resourceHandle) const + { + return checked_guard(m_server, &IServerWrapper::unregisterResource, + resourceHandle); + } + + OCStackResult OCPlatform_impl::unbindResource(OCResourceHandle collectionHandle, + OCResourceHandle resourceHandle) + { + return result_guard(OCUnBindResource(ref(collectionHandle), ref(resourceHandle))); + } + + OCStackResult OCPlatform_impl::unbindResources(const OCResourceHandle collectionHandle, + const std::vector& resourceHandles) + { + for(const auto& h : resourceHandles) + { + OCStackResult r; + + if(OC_STACK_OK != (r = result_guard(OCUnBindResource(collectionHandle, h)))) + { + return r; + } + } + + return OC_STACK_OK; + } + + OCStackResult OCPlatform_impl::bindResource(const OCResourceHandle collectionHandle, + const OCResourceHandle resourceHandle) + { + return result_guard(OCBindResource(collectionHandle, resourceHandle)); + } + + OCStackResult OCPlatform_impl::bindResources(const OCResourceHandle collectionHandle, + const std::vector& resourceHandles) + { + for(const auto& h : resourceHandles) + { + OCStackResult r; + + if(OC_STACK_OK != (r = result_guard(OCBindResource(collectionHandle, h)))) + { + return r; + } + } + + return OC_STACK_OK; + } + + OCStackResult OCPlatform_impl::bindTypeToResource(const OCResourceHandle& resourceHandle, + const std::string& resourceTypeName) const + { + return checked_guard(m_server, &IServerWrapper::bindTypeToResource, + resourceHandle, resourceTypeName); + } + + OCStackResult OCPlatform_impl::bindInterfaceToResource(const OCResourceHandle& resourceHandle, + const std::string& resourceInterfaceName) const + { + return checked_guard(m_server, &IServerWrapper::bindInterfaceToResource, + resourceHandle, resourceInterfaceName); + } + + OCStackResult OCPlatform_impl::startPresence(const unsigned int announceDurationSeconds) + { + return checked_guard(m_server, &IServerWrapper::startPresence, + announceDurationSeconds); + } + + OCStackResult OCPlatform_impl::stopPresence() + { + return checked_guard(m_server, &IServerWrapper::stopPresence); + } + + OCStackResult OCPlatform_impl::subscribePresence(OCPresenceHandle& presenceHandle, + const std::string& host, + SubscribeCallback presenceHandler) + { + return subscribePresence(presenceHandle, host, "", presenceHandler); + } + + OCStackResult OCPlatform_impl::subscribePresence(OCPresenceHandle& presenceHandle, + const std::string& host, + const std::string& resourceType, + SubscribeCallback presenceHandler) + { + return checked_guard(m_client, &IClientWrapper::SubscribePresence, + &presenceHandle, host, resourceType, presenceHandler); + } + + OCStackResult OCPlatform_impl::unsubscribePresence(OCPresenceHandle presenceHandle) + { + return checked_guard(m_client, &IClientWrapper::UnsubscribePresence, + ref(presenceHandle)); + } + + OCStackResult OCPlatform_impl::sendResponse(const std::shared_ptr pResponse) + { + return checked_guard(m_server, &IServerWrapper::sendResponse, + pResponse); + } +} //namespace OC diff --git a/resource/src/OCRepresentation.cpp b/resource/src/OCRepresentation.cpp new file mode 100644 index 000000000..99b3e655d --- /dev/null +++ b/resource/src/OCRepresentation.cpp @@ -0,0 +1,651 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +/// @file OCRepresentation.cpp + +/// @brief This file contains the implementation of classes and its members +/// related to OCRepresentation + +#ifdef __ANDROID__ +#include "OCAndroid.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include + +// code needed to serialize a string=>Attribute value map +namespace OC +{ + namespace detail + { + template + class WriteAttributeValue : public boost::static_visitor<> + { + public: + WriteAttributeValue(const std::string& name, Archive& ar) + :m_name(name), m_archive(ar) + {} + + template + void operator()(const T& value) const + { + m_archive(cereal::make_nvp(m_name, value)); + } + private: + std::string m_name; + Archive& m_archive; + }; + } +} + +namespace cereal +{ + // take no action when serializing the null type, because the 'save' below + // doesn't use the visitor for this type. + template + void serialize(Archive&, OC::NullType t) + {} + + template + void save(Archive& ar, const std::map& vals) + { + for(const auto& kv : vals) + { + const auto& k = kv.first; + const auto& v = kv.second; + + if(v.which() != OC::AttributeValueNullIndex) + { + OC::detail::WriteAttributeValue writer(k,ar); + boost::apply_visitor(writer, v); + } + else + { + ar.setNextName(k.c_str()); + ar.writeName(); + ar.saveValue(); + } + } + } + + template + void load(Archive& ar, std::map& vals) + { + ar.loadAttributeValues(vals); + } +} + +namespace OC +{ + typedef cereal::JSONOutputArchive OutputArchiveType; + typedef cereal::JSONInputArchive InputArchiveType; + + void MessageContainer::setJSONRepresentation(const std::string& payload) + { + std::stringstream os(payload); + { + InputArchiveType archive(os); + archive(cereal::make_nvp(OC::Key::OCKEY, m_reps)); + } + } + + void MessageContainer::setJSONRepresentation(const unsigned char* payload) + { + setJSONRepresentation(std::string(reinterpret_cast(payload))); + } + + std::string MessageContainer::getJSONRepresentation(OCInfoFormat f) const + { + std::stringstream os; + + // note: the block is required because cereal closes the JSON string + // upon destruction, so the archive needs to be destroyed before accessing + // the data + { + if(f == OCInfoFormat::IncludeOC) + { + OutputArchiveType archive(os); + archive(cereal::make_nvp(OC::Key::OCKEY, m_reps)); + } + else if(f== OCInfoFormat::ExcludeOC) + { + bool firstPrinted = false; + for(std::vector::size_type i = 0; i< m_reps.size();++i) + { + if(!m_reps[i].empty()) + { + if(firstPrinted) + { + os<<','; + } + firstPrinted=true; + os << m_reps[i].getJSONRepresentation(); + } + } + } + } + return os.str(); + } + + const std::vector& MessageContainer::representations() const + { + return m_reps; + } + + void MessageContainer::addRepresentation(const OCRepresentation& rep) + { + m_reps.push_back(rep); + } +} + +namespace OC +{ + OCRepresentation::OCRepresentation() + :m_interfaceType(InterfaceType::None) + { } + std::string OCRepresentation::getJSONRepresentation() const + { + if(empty()) + { + return "{}"; + } + + std::stringstream os; + + // note: the block is required because cereal closes the JSON string + // upon destruction, so the archive needs to be destroyed before accessing + // the data + { + OutputArchiveType archive (os); + save(archive); + } + + return os.str(); + } + + void OCRepresentation::addChild(const OCRepresentation& rep) + { + m_children.push_back(rep); + } + + void OCRepresentation::clearChildren() + { + m_children.clear(); + } + + const std::vector& OCRepresentation::getChildren() const + { + return m_children; + } + + void OCRepresentation::setUri(const std::string& uri) + { + m_uri = uri; + } + + std::string OCRepresentation::getUri() const + { + return m_uri; + } + + const std::vector& OCRepresentation::getResourceTypes() const + { + return m_resourceTypes; + } + + void OCRepresentation::setResourceTypes(const std::vector& resourceTypes) + { + m_resourceTypes = resourceTypes; + } + + const std::vector& OCRepresentation::getResourceInterfaces() const + { + return m_interfaces; + } + + void OCRepresentation::setResourceInterfaces(const std::vector& resourceInterfaces) + { + m_interfaces = resourceInterfaces; + } + + bool OCRepresentation::hasAttribute(const std::string& str) const + { + return m_values.find(str) != m_values.end(); + } + + bool OCRepresentation::empty() const + { + // This logic is meant to determine whether based on the JSON serialization rules + // if this object will result in empty JSON. URI is only serialized if there is valid + // data, ResourceType and Interfaces are only serialized if we are a nothing, a + // child of a default or link item. + // Our values array is only printed in the if we are the child of a Batch resource, + // the parent in a 'default' situation, or not in a child/parent relationship. + if(!m_uri.empty()) + { + return false; + } + else if ((m_interfaceType == InterfaceType::None + || m_interfaceType==InterfaceType::DefaultChild + || m_interfaceType==InterfaceType::LinkChild) + && (m_resourceTypes.size()>0 || m_interfaces.size()>0)) + { + return false; + } + else if((m_interfaceType == InterfaceType::None + || m_interfaceType == InterfaceType::BatchChild + || m_interfaceType == InterfaceType::DefaultParent) + && m_values.size()>0) + { + return false; + } + + if(m_children.size() > 0) + { + return false; + } + + return true; + } + + int OCRepresentation::numberOfAttributes() const + { + return m_values.size(); + } + + bool OCRepresentation::erase(const std::string& str) + { + return m_values.erase(str); + } + + void OCRepresentation::setNULL(const std::string& str) + { + m_values[str] = OC::NullType(); + } + + bool OCRepresentation::isNULL(const std::string& str) const + { + auto x = m_values.find(str); + + if(m_values.end() != x) + { + return x->second.which() == AttributeValueNullIndex; + } + else + { + throw OCException(OC::Exception::INVALID_ATTRIBUTE+ str); + } + } +} + +namespace OC +{ + template + void OCRepresentation::optional_load(Archive& ar, Val&& v) + { + try + { + ar(v); + } + catch(cereal::Exception& e) + { + ar.setNextName(nullptr); + // Loading a key that doesn't exist results in an exception + // Since "Not Found" is a valid condition for us, we swallow + // this exception and the archive will not load anything + } + } + + template + void OCRepresentation::save(Archive& ar) const + { + // printed for all interface types + if(!m_uri.empty()) + { + ar(cereal::make_nvp(Key::URIKEY, m_uri)); + } + + if((m_interfaceType == InterfaceType::None + || m_interfaceType==InterfaceType::DefaultChild + || m_interfaceType==InterfaceType::LinkChild) + && (m_resourceTypes.size()>0 || m_interfaces.size()>0)) + { + // The Prop object requires that it refer to non-const vectors + // so that it can alter them in the 'load' case. In the save case + // (initiated here) it will not modify the object. So, to keep the + // compiler happy, removing the 'const' context here is necessary. + const std::vector& rt(m_resourceTypes); + const std::vector& intf(m_interfaces); + Prop temp(const_cast&>(rt), + const_cast&>(intf)); + ar(cereal::make_nvp(Key::PROPERTYKEY, temp)); + } + + // printed only for BatchChildren and DefaultParent + if((m_interfaceType == InterfaceType::None + || m_interfaceType == InterfaceType::BatchChild + || m_interfaceType == InterfaceType::DefaultParent) + && m_values.size()>0) + { + ar(cereal::make_nvp(Key::REPKEY, m_values)); + } + } + + template + void OCRepresentation::load(Archive& ar) + { + optional_load(ar, cereal::make_nvp(Key::URIKEY, m_uri)); + { + Prop temp(m_resourceTypes, m_interfaces); + optional_load(ar, cereal::make_nvp(Key::PROPERTYKEY, temp)); + } + optional_load(ar, cereal::make_nvp(Key::REPKEY, m_values)); + } + + template + void OCRepresentation::Prop::save(Archive& ar) const + { + if(m_types.size() > 0) + { + ar(cereal::make_nvp(Key::RESOURCETYPESKEY, m_types)); + } + + if(m_interfaces.size()>0) + { + ar(cereal::make_nvp(Key::INTERFACESKEY, m_interfaces)); + } + } + + template + void OCRepresentation::Prop::load(Archive& ar) + { + optional_load(ar, cereal::make_nvp(Key::RESOURCETYPESKEY, m_types)); + optional_load(ar, cereal::make_nvp(Key::INTERFACESKEY, m_interfaces)); + } +} + +// note: the below is used to load an AttributeValue map out of JSON +namespace OC +{ + namespace detail + { + enum class typeTag:uint8_t + { + NOTHING = 0, + _string, + _int, + _double, + _bool, + _representation + }; + + typedef rapidjson::Document::GenericValue GenericValue; + + AttributeValue parseAttributeValue(const GenericValue& v); + AttributeValue parseAttributeValue(const GenericValue& v, + const unsigned int curLevel, unsigned int& maxDepth, typeTag& t); + AttributeValue parseAttributeValueObject(const GenericValue& v, typeTag& t); + AttributeValue parseAttributeValueArray(const GenericValue& v, + const unsigned int curLevel, unsigned int& maxDepth, typeTag& t); + AttributeValue parseAttributeValuePrimitive(const GenericValue& v, typeTag& t); + + AttributeValue parseAttributeValue(const GenericValue& v) + { + // base entrance, start everything at '0' + unsigned int max_depth {0}; + typeTag t {typeTag::NOTHING}; + + return parseAttributeValue(v, 0, max_depth, t); + } + + AttributeValue parseAttributeValue(const GenericValue& v, + const unsigned int curLevel, unsigned int& maxDepth, typeTag& t) + { + if(v.IsObject()) + { + return parseAttributeValueObject(v, t); + } + else if(v.IsArray()) + { + return parseAttributeValueArray(v, curLevel + 1, maxDepth, t); + } + else + { + return parseAttributeValuePrimitive(v,t); + } + } + + AttributeValue parseAttributeValueObject(const GenericValue& v, typeTag& t) + { + typedef rapidjson::Value::ConstMemberIterator CMI; + t = typeTag::_representation; + OC::OCRepresentation rep; + + for(CMI itr = v.MemberBegin(); itr!= v.MemberEnd(); ++itr) + { + std::string keyName = itr->name.GetString(); + + if(keyName == OC::Key::URIKEY) + { + rep.setUri(boost::get(parseAttributeValue(itr->value))); + } + else if (keyName == OC::Key::PROPERTYKEY) + { + for(CMI itr2 = itr->value.MemberBegin(); + itr->value.MemberEnd()!=itr2; + ++itr2) + { + if(keyName == OC::Key::RESOURCETYPESKEY) + { + rep.setResourceTypes( + boost::get>( + parseAttributeValue(itr->value))); + } + else if(keyName == OC::Key::PROPERTYKEY) + { + rep.setResourceInterfaces( + boost::get>( + parseAttributeValue(itr->value))); + } + } + } + else if (keyName == OC::Key::REPKEY) + { + for(CMI itr2 = itr->value.MemberBegin(); + itr->value.MemberEnd()!=itr2; + ++itr2) + { + rep.setValue(itr2->name.GetString(), + parseAttributeValue(itr2->value)); + } + } + } + + return rep; + } + + AttributeValue parseAttributeValuePrimitive(const GenericValue& v, typeTag& t) + { + if(v.IsString()) + { + t = typeTag::_string; + return std::string(v.GetString()); + } + else if (v.IsNumber()) + { + if(v.IsDouble()) + { + t = typeTag::_double; + return double(v.GetDouble()); + } + else if (v.IsInt()) + { + t = typeTag::_int; + return int(v.GetInt()); + } + else + { + throw OC::OCException(OC::Exception::INVALID_JSON_NUMERIC + + std::to_string(v.GetType())); + } + } + else if(v.IsBool_()) + { + t=typeTag::_bool; + return bool(v.GetBool_()); + } + else if(v.IsNull_()) + { + return OC::NullType(); + } + else + { + throw OC::OCException(OC::Exception::INVALID_JSON_TYPE + + std::to_string(v.GetType())); + } + } + + std::vector gatherArrayContents(const GenericValue& v, + const unsigned int curLevel, unsigned int& maxDepth, typeTag& t) + { + std::vector out; + + std::transform(v.Begin(), v.End(), back_inserter(out), + [curLevel, &maxDepth, &t](const GenericValue& x) + { + return parseAttributeValue(x, curLevel, maxDepth, t); + }); + return out; + } + + template + struct valueToConcrete + { + OutT operator()(const AttributeValue& v) + { + return boost::get(v); + } + + }; + + template + OutSeqT valuesToConcreteVectors(const std::vector& vs) + { + OutSeqT ret; + + std::transform(begin(vs),end(vs), back_inserter(ret), + valueToConcrete()); + return ret; + } + + template + AttributeValue remapArrayDepth(const unsigned int curLevel, + const std::vector& vs) + { + switch(curLevel) + { + default: + throw OC::OCException(OC::Exception::INVALID_JSON_ARRAY_DEPTH); + break; + case 1: + return valuesToConcreteVectors>(vs); + break; + case 2: + return valuesToConcreteVectors>>(vs); + break; + case 3: + return valuesToConcreteVectors + >>>(vs); + break; + } + } + + AttributeValue convertArrayToConcretes(const typeTag t, + const unsigned int curLevel, const std::vector& vs) + { + // This function converts a std::vector of AttributeValue to a std::vector + // of concrete types. Since we don't use a recursive Variant, we need + // to get back to a 'base' primitive type + switch(t) + { + default: + case typeTag::NOTHING: + throw OC::OCException(OC::Exception::INVALID_JSON_TYPE_TAG); + break; + case typeTag::_string: + return remapArrayDepth(curLevel, vs); + break; + case typeTag::_int: + return remapArrayDepth(curLevel, vs); + break; + case typeTag::_double: + return remapArrayDepth(curLevel, vs); + break; + case typeTag::_bool: + return remapArrayDepth(curLevel, vs); + break; + case typeTag::_representation: + return remapArrayDepth(curLevel, vs); + break; + } + } + + AttributeValue parseAttributeValueArray(const GenericValue& v, + const unsigned int curLevel, unsigned int& maxDepth, typeTag& t) + { + const unsigned int max_level = 3; + + if(curLevel > max_level) + { + throw OC::OCException(OC::Exception::INVALID_JSON_ARRAY_DEPTH); + } + + if(curLevel > maxDepth) + { + maxDepth = curLevel; + } + + auto arrayItems = gatherArrayContents(v, curLevel, maxDepth, t); + const int remapLevel = maxDepth - (curLevel -1); + return convertArrayToConcretes(t, remapLevel, arrayItems); + } + } +} + +namespace cereal +{ + void JSONInputArchive::loadAttributeValues(std::map& map) + { + for(auto&b = itsIteratorStack.back(); + b.Member && b.itsMemberItEnd != b.itsMemberItBegin+b.itsIndex; + ++b) + { + std::string key = b.itsMemberItBegin[b.itsIndex].name.GetString(); + const GenericValue& v = itsIteratorStack.back().value(); + map[key] = OC::detail::parseAttributeValue(v); + } + } +} diff --git a/resource/src/OCResource.cpp b/resource/src/OCResource.cpp new file mode 100644 index 000000000..df5ff60be --- /dev/null +++ b/resource/src/OCResource.cpp @@ -0,0 +1,273 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "OCResource.h" +#include "OCUtilities.h" + +namespace OC { + +using OC::nil_guard; +using OC::result_guard; +using OC::checked_guard; + +OCResource::OCResource(std::weak_ptr clientWrapper, const std::string& host, + const std::string& uri, bool observable, const std::vector& resourceTypes, + const std::vector& interfaces) + : m_clientWrapper(clientWrapper), m_uri(uri), m_host(host), m_isObservable(observable), + m_isCollection(false), m_resourceTypes(resourceTypes), m_interfaces(interfaces), + m_observeHandle(nullptr) +{ + m_isCollection = std::find(m_interfaces.begin(), m_interfaces.end(), LINK_INTERFACE) + != m_interfaces.end(); + + if (m_uri.empty() || + resourceTypes.empty() || + interfaces.empty()|| + m_clientWrapper.expired()) + { + throw ResourceInitException(m_uri.empty(), resourceTypes.empty(), + interfaces.empty(), m_clientWrapper.expired(), false, false); + } +} + +OCResource::~OCResource() +{ +} + +OCStackResult OCResource::get(const QueryParamsMap& queryParametersMap, + GetCallback attributeHandler, QualityOfService QoS) +{ + return checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetResourceRepresentation, + m_host, m_uri, queryParametersMap, m_headerOptions, attributeHandler, QoS); +} + +OCStackResult OCResource::get(const QueryParamsMap& queryParametersMap, + GetCallback attributeHandler) +{ + QualityOfService defaultQos = OC::QualityOfService::NaQos; + checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos); + return result_guard(get(queryParametersMap, attributeHandler, defaultQos)); +} + +OCStackResult OCResource::get(const std::string& resourceType, + const std::string& resourceInterface, const QueryParamsMap& queryParametersMap, + GetCallback attributeHandler) +{ + QualityOfService defaultQoS = OC::QualityOfService::NaQos; + checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS); + + return result_guard(get(resourceType, resourceInterface, queryParametersMap, attributeHandler, defaultQoS)); +} + +OCStackResult OCResource::get(const std::string& resourceType, const std::string& resourceInterface, const QueryParamsMap& queryParametersMap, GetCallback attributeHandler, + QualityOfService QoS) +{ + QueryParamsMap mapCpy(queryParametersMap); + + if(!resourceType.empty()) + { + mapCpy[OC::Key::RESOURCETYPESKEY]=resourceType; + } + + if(!resourceInterface.empty()) + { + mapCpy[OC::Key::INTERFACESKEY]= resourceInterface; + } + + return result_guard(get(mapCpy, attributeHandler, QoS)); +} + +OCStackResult OCResource::put(const OCRepresentation& rep, + const QueryParamsMap& queryParametersMap, PutCallback attributeHandler, + QualityOfService QoS) +{ + return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PutResourceRepresentation, + m_host, m_uri, rep, queryParametersMap, m_headerOptions, attributeHandler, QoS); +} + +OCStackResult OCResource::put(const OCRepresentation& rep, + const QueryParamsMap& queryParametersMap, PutCallback attributeHandler) +{ + QualityOfService defaultQos = OC::QualityOfService::NaQos; + checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos); + return result_guard(put(rep, queryParametersMap, attributeHandler, defaultQos)); +} + +OCStackResult OCResource::put(const std::string& resourceType, + const std::string& resourceInterface, const OCRepresentation& rep, + const QueryParamsMap& queryParametersMap, + PutCallback attributeHandler) +{ + QualityOfService defaultQos = OC::QualityOfService::NaQos; + checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos); + + return result_guard(put(resourceType, resourceInterface, rep, queryParametersMap, + attributeHandler, defaultQos)); +} + +OCStackResult OCResource::put(const std::string& resourceType, + const std::string& resourceInterface, const OCRepresentation& rep, + const QueryParamsMap& queryParametersMap, + PutCallback attributeHandler, + QualityOfService QoS) +{ + QueryParamsMap mapCpy(queryParametersMap); + + if(!resourceType.empty()) + { + mapCpy[OC::Key::RESOURCETYPESKEY]=resourceType; + } + + if(!resourceInterface.empty()) + { + mapCpy[OC::Key::INTERFACESKEY]=resourceInterface; + } + + return result_guard(put(rep, mapCpy, attributeHandler, QoS)); +} + +OCStackResult OCResource::post(const OCRepresentation& rep, + const QueryParamsMap& queryParametersMap, PostCallback attributeHandler, + QualityOfService QoS) +{ + return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PostResourceRepresentation, + m_host, m_uri, rep, queryParametersMap, m_headerOptions, attributeHandler, QoS); +} + +OCStackResult OCResource::post(const OCRepresentation& rep, + const QueryParamsMap& queryParametersMap, PutCallback attributeHandler) +{ + QualityOfService defaultQos = OC::QualityOfService::NaQos; + checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos); + return result_guard(post(rep, queryParametersMap, attributeHandler, defaultQos)); +} + +OCStackResult OCResource::post(const std::string& resourceType, + const std::string& resourceInterface, const OCRepresentation& rep, + const QueryParamsMap& queryParametersMap, + PostCallback attributeHandler) +{ + QualityOfService defaultQoS = OC::QualityOfService::NaQos; + checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS); + + return result_guard(post(resourceType, resourceInterface, rep, queryParametersMap, attributeHandler, + defaultQoS)); +} + +OCStackResult OCResource::post(const std::string& resourceType, + const std::string& resourceInterface, const OCRepresentation& rep, + const QueryParamsMap& queryParametersMap, + PostCallback attributeHandler, + QualityOfService QoS) +{ + QueryParamsMap mapCpy(queryParametersMap); + + if(!resourceType.empty()) + { + mapCpy[OC::Key::RESOURCETYPESKEY]=resourceType; + } + + if(!resourceInterface.empty()) + { + mapCpy[OC::Key::INTERFACESKEY]=resourceInterface; + } + + return result_guard(post(rep, mapCpy, attributeHandler, QoS)); +} + +OCStackResult OCResource::deleteResource(DeleteCallback deleteHandler, QualityOfService QoS) +{ + return checked_guard(m_clientWrapper.lock(), &IClientWrapper::DeleteResource, + m_host, m_uri, m_headerOptions, deleteHandler, QoS); +} + +OCStackResult OCResource::deleteResource(DeleteCallback deleteHandler) +{ + QualityOfService defaultQos = OC::QualityOfService::NaQos; + checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos); + + return result_guard(deleteResource(deleteHandler, defaultQos)); +} + +OCStackResult OCResource::observe(ObserveType observeType, + const QueryParamsMap& queryParametersMap, ObserveCallback observeHandler, + QualityOfService QoS) +{ + if(m_observeHandle != nullptr) + { + return result_guard(OC_STACK_INVALID_PARAM); + } + + return checked_guard(m_clientWrapper.lock(), &IClientWrapper::ObserveResource, + observeType, &m_observeHandle, m_host, + m_uri, queryParametersMap, m_headerOptions, observeHandler, QoS); +} + +OCStackResult OCResource::observe(ObserveType observeType, + const QueryParamsMap& queryParametersMap, ObserveCallback observeHandler) +{ + QualityOfService defaultQoS = OC::QualityOfService::NaQos; + checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS); + + return result_guard(observe(observeType, queryParametersMap, observeHandler, defaultQoS)); +} + +OCStackResult OCResource::cancelObserve() +{ + QualityOfService defaultQoS = OC::QualityOfService::NaQos; + checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS); + return result_guard(cancelObserve(defaultQoS)); +} + +OCStackResult OCResource::cancelObserve(QualityOfService QoS) +{ + if(m_observeHandle == nullptr) + { + return result_guard(OC_STACK_INVALID_PARAM); + } + + OCStackResult result = checked_guard(m_clientWrapper.lock(), + &IClientWrapper::CancelObserveResource, + m_observeHandle, m_host, m_uri, m_headerOptions, QoS); + + if(result == OC_STACK_OK) + { + m_observeHandle = nullptr; + } + + return result; +} + +std::string OCResource::host() const +{ + return m_host; +} + +std::string OCResource::uri() const +{ + return m_uri; +} + +bool OCResource::isObservable() const +{ + return m_isObservable; +} + +} // namespace OC diff --git a/resource/src/OCSecurityModel.cpp b/resource/src/OCSecurityModel.cpp new file mode 100644 index 000000000..c9bb57f2a --- /dev/null +++ b/resource/src/OCSecurityModel.cpp @@ -0,0 +1,32 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "OCSecurityModel.h" + +namespace OC { + OCSecurityModel::OCSecurityModel(void) + { + } + + + OCSecurityModel::~OCSecurityModel(void) + { + } +} \ No newline at end of file diff --git a/resource/src/OCUtilities.cpp b/resource/src/OCUtilities.cpp new file mode 100644 index 000000000..530f673d2 --- /dev/null +++ b/resource/src/OCUtilities.cpp @@ -0,0 +1,216 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include + +#include "OCUtilities.h" + +#include + +#include +#include +#include + +extern "C" { +#include // libcoap +#include // libcoap +} + +namespace OC { + + // Helper function to escape special character. + std::string escapeString(const std::string& value) + { + std::ostringstream stringStream; + for (const char& c : value) + { + switch (c) + { + case '\\': stringStream << "\\\\"; + break; + case '"': stringStream << "\\\""; + break; + case '/': stringStream << "\\/"; + break; + case '\b': stringStream << "\\b"; + break; + case '\f': stringStream << "\\f"; + break; + case '\n': stringStream << "\\n"; + break; + case '\r': stringStream << "\\r"; + break; + case '\t': stringStream << "\\t"; + break; + default: stringStream << c; + break; + } + } + return stringStream.str(); + } +} +// [TODO] remove this function +// it seems that the C stack is parsing and giving out the query separately. +// the entire URI need not be parsed +static OC::Utilities::QueryParamsKeyVal tempPatch(const std::string& _uri) +{ + OC::Utilities::QueryParamsKeyVal qp; + if(_uri.empty()) + { + return qp; + } + + std::vector queryparams; + boost::split(queryparams, _uri, boost::is_any_of("&")); + + for(std::string& it: queryparams) + { + std::vector keyval; + boost::split(keyval, it, boost::is_any_of("=")); + if(2 == keyval.size()) + { + qp[keyval.at(0)] = keyval.at(1); + } + } + + return qp; +} + +// implementation can be split into two functions if needed +// uses do{}while(0) to avoid returning from multiple locations +OC::Utilities::QueryParamsKeyVal OC::Utilities::getQueryParams(const std::string& _uri) +{ + + // this is a temporary fix. [TODO] remove this after permanent fix + return tempPatch(_uri); + + OC::Utilities::QueryParamsKeyVal qp; + unsigned char *bufptr = nullptr; // don't delete via bufptr + unsigned char *bufptrToDelete = nullptr; // bufptr may be incremented. need this one to keep track. + do // while(0) + { + if(_uri.empty()) + { + break; + } + + coap_uri_t coapuri = {{0}}; + unsigned char* uristr = reinterpret_cast(const_cast(_uri.c_str())); + + if(coap_split_uri(uristr, _uri.length(), &coapuri) < 0) + { + break; + } + + size_t buflen = 2048; // this is big enough buffer. [TODO] may want to downsize it. I have seen that the size may have to be greater than coap.query.length, which is counterintuitve but there may be a bug in coap uri parser. + bufptrToDelete = bufptr = new (std::nothrow) unsigned char[buflen](); // why heap? will need it for incrementing the pointer in the logic below + + if(!bufptr) + { + break; + } + + int segments = -1; + if((segments = coap_split_query(coapuri.query.s, coapuri.query.length, bufptr, &buflen)) < 0) + { + break; + } + + // coap uri parser has weird api. its not straighforward to understand what the coap function calls below do. + // coap uri parser lacks ability to split the key value pair in query params. that will be done in getQueryParams() function + std::vector queryparams; + while(segments--) + { + queryparams.push_back(std::string (reinterpret_cast(coap_opt_value(bufptr)), coap_opt_length(bufptr))); + bufptr += coap_opt_size(bufptr); + } + + if(queryparams.empty()) + { + break; + } + + //[TODO] use foreach + for(std::string& it : queryparams) + { + std::vector keyval; + boost::split(keyval, it, boost::is_any_of("=")); + if(2 == keyval.size()) + { + qp[keyval.at(0)] = keyval.at(1); + } + } + } + while(0); + + if(bufptrToDelete) + { + delete [] bufptrToDelete; + } + return qp; +} + +namespace OC { + +OCStackResult result_guard(const OCStackResult r) +{ + std::ostringstream os; + + switch(r) + { + default: + os << "result_guard(): unhandled exception: " << OCException::reason(r); + throw OCException(os.str(), r); + + /* Exceptional conditions: */ + case OC_STACK_NO_MEMORY: + case OC_STACK_COMM_ERROR: + case OC_STACK_NOTIMPL: + case OC_STACK_INVALID_URI: + case OC_STACK_INVALID_QUERY: + case OC_STACK_INVALID_IP: + case OC_STACK_INVALID_PORT: + case OC_STACK_INVALID_CALLBACK: + case OC_STACK_INVALID_METHOD: + case OC_STACK_INVALID_PARAM: + case OC_STACK_INVALID_OBSERVE_PARAM: + os << "result_guard(): " << r << ": " << OCException::reason(r); + throw OCException(os.str(), r); + + /* Non-exceptional failures or success: */ + case OC_STACK_OK: + case OC_STACK_NO_RESOURCE: + case OC_STACK_RESOURCE_ERROR: + case OC_STACK_SLOW_RESOURCE: + case OC_STACK_NO_OBSERVERS: + case OC_STACK_OBSERVER_NOT_FOUND: +#ifdef WITH_PRESENCE + case OC_STACK_PRESENCE_STOPPED: + case OC_STACK_PRESENCE_TIMEOUT: + case OC_STACK_PRESENCE_DO_NOT_HANDLE: +#endif + + break; + } + + return r; +} + +} // namespace OC diff --git a/resource/src/SConscript b/resource/src/SConscript new file mode 100644 index 000000000..3a50c870c --- /dev/null +++ b/resource/src/SConscript @@ -0,0 +1,53 @@ +## +# OCLib (share library) build script +## +Import('env') + +# Add third party libraries +lib_env = env.Clone() +SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env') + +oclib_env = lib_env.Clone() +###################################################################### +# Build flags +###################################################################### +oclib_env.AppendUnique(CPPPATH = [ + '../include/', + '../csdk/stack/include', + '../csdk/ocsocket/include', + '../csdk/ocrandom/include', + '../csdk/logger/include', + '../csdk/libcoap', + '../oc_logger/include' + ]) + +target_os = env.get('TARGET_OS') +if target_os not in ['windows', 'winrt']: + oclib_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-fPIC']) + +if target_os == 'android': + oclib_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions']) + oclib_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')]) + oclib_env.AppendUnique(LIBS = ['octbstack', 'coap', 'oc_logger', 'boost_thread', 'gnustl_static', 'log', 'compatibility']) + +if target_os in ['darwin', 'ios']: + oclib_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')]) + oclib_env.AppendUnique(LIBS = ['octbstack', 'coap', 'oc_logger']) + +###################################################################### +# Source files and Targets +###################################################################### +oclib_src = [ + 'OCPlatform.cpp', + 'OCPlatform_impl.cpp', + 'OCResource.cpp', + 'OCUtilities.cpp', + 'OCException.cpp', + 'OCRepresentation.cpp', + 'InProcServerWrapper.cpp', + 'InProcClientWrapper.cpp' + ] + +shared_oclib = oclib_env.SharedLibrary('oc', oclib_src) +static_oclib = oclib_env.StaticLibrary('oc', oclib_src) +oclib_env.InstallTarget([shared_oclib, static_oclib], 'liboc') diff --git a/resource/third_party_libs.scons b/resource/third_party_libs.scons new file mode 100644 index 000000000..4b1c90278 --- /dev/null +++ b/resource/third_party_libs.scons @@ -0,0 +1,60 @@ +###################################################################### +# This script manages third party libraries +# +#Note: The paths must keep consistent with oic-utilities +###################################################################### +import os +import platform + +Import('env', 'lib_env') + +target_os = env.get('TARGET_OS') +target_arch = env.get('TARGET_ARCH') +src_dir = env.get('SRC_DIR') + + +###################################################################### +# Check dependent packages (Linux only) +###################################################################### +if target_os in ['linux', 'tizen']: + if not env.GetOption('help'): + if not target_arch == platform.machine(): + print ''' +*********************************** Warning *********************************** +* You are trying cross build, please make sure (%s) version libraries are +* installed! * +******************************************************************************* +''' % target_arch + + conf = Configure(lib_env) + + if not conf.CheckLib('boost_program_options'): + print 'Did not find boost_program_options, exiting!' + Exit(1) + + conf.Finish() + + +###################################################################### +# The path of third party libraries binary +###################################################################### +if target_os == 'android': + if target_arch == 'armeabi-v7a-hard': + target_arch = 'armeabi-v7a' + + if target_arch not in ['x86', 'armeabi', 'armeabi-v7a']: + if not env.GetOption('help') and not env.GetOption('clean'): + print ''' +*********************************** Warning *********************************** +* current only x86, armeabi, armeabi-v7a libraries are provided! * +******************************************************************************* +''' + else: + # Too much boost warning, suppress the warning + lib_env.AppendUnique(CCFLAGS = ['-w']) + +elif target_os == 'ios': + lib_env.AppendUnique(FRAMEWORKS = ['boost']) +elif target_os == 'darwin': + lib_env.AppendUnique(CPPPATH = ['/usr/local/include']) + lib_env.AppendUnique(LIBPATH = ['/usr/local/lib']) diff --git a/resource/unittests/README b/resource/unittests/README new file mode 100644 index 000000000..0fd09ea53 --- /dev/null +++ b/resource/unittests/README @@ -0,0 +1,27 @@ +//--------------------------------------------------------------------- +// NOTICE - Transition to SCONS +//--------------------------------------------------------------------- + +The IoTivity build system is transitioning to SCONS. Although the +makefiles are still available (until v1.0) and some developers are +still using them, they are currently no longer supported. To learn more +about building using SCONS see Readme.scons.txt in the repository root +directory. The build steps used in continuous integration can be found +in auto_build.sh which is also in the the repository root directory. + +//--------------------------------------------------------------------- + +tests.cpp contains unittests for C++ APIs. It uses Google Test for the unit +tests. Note that the unit tests are only to test the functionality of OCApi.h. +It is not a system or end-to-end test. + +Unit Test Requirements: + +1. To run the unit test, first build the unit tests with the following command + from : + + make -f buildScript.mk linux_ub_unittests + +2. Run the unit test by issuing the following command from : + + ./unittests/tests diff --git a/resource/unittests/makefile b/resource/unittests/makefile new file mode 100644 index 000000000..6a05e8043 --- /dev/null +++ b/resource/unittests/makefile @@ -0,0 +1,82 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +# override with `make BUILD=debug` +# default to release build +BUILD := release +PLATFORM := linux +CXX := g++ + +ROOT_DIR = ./ + +# You must create the file "local.properties" on your local machine which contains any local paths, etc +# local.properties should NOT be committed to repo +include $(ROOT_DIR)/../csdk/local.properties + +GTEST_DIR= ../../extlibs/gtest-1.7.0 +OUT_DIR := $(BUILD) + +ifeq ($(ROOT_DIR),) + ROOT_DIR:=$(PWD) +endif + +INC_DIRS := -I../include/ +INC_DIRS += -I../oc_logger/include +INC_DIRS += -I../csdk/stack/include +INC_DIRS += -I../csdk/ocsocket/include +INC_DIRS += -I../csdk/ocrandom/include +INC_DIRS += -I../csdk/logger/include +INC_DIRS += -I../csdk/libcoap +INC_DIRS += -I$(GTEST_DIR)/include + +LIB_OC_LOGGER := ../oc_logger/lib/oc_logger.a + +GTEST_LIBS := $(GTEST_DIR)/lib/.libs/libgtest.a $(GTEST_DIR)/lib/.libs/libgtest_main.a +CXX_LIBS := ../$(BUILD)/obj/liboc.a ../csdk/$(PLATFORM)/$(BUILD)/liboctbstack.a $(LIB_OC_LOGGER) +CXX_LIBS += $(GTEST_LIBS) + +CC_FLAGS.debug := -g -O0 -g3 -Wall -ffunction-sections -fdata-sections \ + -std=c++0x -pedantic $(INC_DIRS) -L$(ROOT_DIR)/$(BUILD) -DTB_LOG +CC_FLAGS.release := -Os -Wall -fdata-sections -Wl,--gc-sections -Wl,-s \ + -std=c++0x $(INC_DIRS) -L$(ROOT_DIR)/$(BUILD) + +CPPFLAGS += $(CC_FLAGS.$(BUILD)) $(CXX_LIBS) -lpthread + +all: prep_dirs tests + +prep_dirs: + -mkdir -p $(OUT_DIR) + +tests: tests.cpp $(GTEST_LIBS) + $(CXX) $^ $(CPPFLAGS) -o $(OUT_DIR)/$@ + +$(GTEST_LIBS): $(GTEST_DIR) + cd $(GTEST_DIR) && ./configure && make + +$(GTEST_DIR): + cd ../../extlibs && \ + wget -q https://googletest.googlecode.com/files/gtest-1.7.0.zip && \ + unzip gtest-1.7.0.zip + +.PHONY: clean + +clean: + -rm -rf release + -rm -rf debug diff --git a/resource/unittests/tests.cpp b/resource/unittests/tests.cpp new file mode 100644 index 000000000..e299b43c5 --- /dev/null +++ b/resource/unittests/tests.cpp @@ -0,0 +1,101 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + +#include +#include +#include +#include + +#include +#include + +#include + +namespace PH = std::placeholders; + +using namespace OC; +using namespace std; + +// Entity handler used for register and find test +OCEntityHandlerResult entityHandler_rf(std::shared_ptr request) +{ + return OC_EH_OK; +} + +// Condition variables used for register and find +std::mutex mutex_rf; +std::condition_variable cv_rf; +std::shared_ptr res_rf; + +void foundResource_rf(std::shared_ptr resource) +{ + if(resource) + { + res_rf = resource; + cv_rf.notify_all(); + } +} + +// Resource : Register and find test +TEST(Resource, rf) { + // Create PlatformConfig object + PlatformConfig cfg { + OC::ServiceType::InProc, + OC::ModeType::Both, + "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces + 0, // Uses randomly available port + OC::QualityOfService::LowQos + }; + OCPlatform::Configure(cfg); + + std::string resourceURI = "/a/res"; + std::string resourceTypeName = "core.res"; + std::string resourceInterface = DEFAULT_INTERFACE; + + uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE; + + OCResourceHandle resourceHandle; + + // This will internally create and register the resource. + if(OC_STACK_OK == OCPlatform::registerResource( + resourceHandle, resourceURI, resourceTypeName, + resourceInterface, entityHandler_rf, resourceProperty)) + { + OCPlatform::findResource("","coap://224.0.1.187/oc/core?rt=core.res", foundResource_rf); + + { + std::unique_lock lk(mutex_rf); + cv_rf.wait(lk); + } + + if(res_rf) + { + EXPECT_EQ(res_rf->uri(), "/a/res"); + vector rts = res_rf->getResourceTypes(); + EXPECT_EQ(rts.size(), (unsigned) 1); + EXPECT_EQ(rts[0], "core.res"); + vector ifs = res_rf->getResourceInterfaces(); + EXPECT_EQ(ifs.size(), (unsigned) 1); + EXPECT_EQ(ifs[0], DEFAULT_INTERFACE); + } + } +} + diff --git a/scons_script_how_to.txt b/scons_script_how_to.txt new file mode 100644 index 000000000..5c495335b --- /dev/null +++ b/scons_script_how_to.txt @@ -0,0 +1,240 @@ +== How to write IoTivity build script == + +IoTivity projects are built with Scons. Scons is a cross-platform build tool, +it's quite similar to 'make'. 'SConstruct' is the entrance of scons build, it's +equivalent to 'Makefile' to 'make'. + +This document only a brief reference. Detail about how to write scons script, +please refer to: + http://www.scons.org/doc/production/HTML/scons-user.html# + +== Background: How to control source code compiling == + +Environment is a base conception of Scons. An environment is a collection of +values that can affect how a program is built. + +e.g. There is a C file named hello.c, enter the following into a file named +SConstruct: + env = Environment() + env.Program('H', 'hello.c') + +When run Scons in console, following will be executed: +cc -o hello.o -c hello.c +cc -o H hello.o + +If you would like keep debug information in the binary, '-g' flag should be added +when build the source code. To do this, append a C compiler flags as following: + env = Environment() + env.AppendUnique(CFLAGS = ['-g']) + env.Program('H', 'hello.c') + +When run Scons, following will be executed: +cc -o hello.o -c -g hello.c +cc -o H hello.o + +In above example, 'CFLAGS' is changed. Following list the frequently used keys: + +CFLAGS: General options that are passed to the C compiler +CCFLAGS: General options that are passed to the C & C++ compiler +CXXFLAGS: General options that are passed to the C++ compiler +CPPPATH: The directories that the preprocessor will search for include headers. +CPPDEFINES: Platform independent specification of C preprocessor definitions. + +Note: CPPPATH and CPPDEFINES is common for all compiler. But others are +compiler specific, when change the key value, it may requried to specify the +target platform(actually the compiler). + +e.g. + env.AppendUnique(CPPPATH = ['.', 'include']) + env.AppendUnique(CPPDEFINES = ['NDEBUG', 'VER_TEST']) +Above two lines are fine for all target platform. but below line: + env.AppenUnique(CXXFLAGS = ['-g']) +is only fine for gcc compiler, as '-g' is a gcc flag, other compiler may don't +understand it. so it may should be: + if target_os not in ['windows', 'winrt']: + env.AppenUnique(CXXFLAGS = ['-g']) + +Still take the hello.c as example. Assume hello.h is in ./include/ directory, +#include "hello.h" +int main(int argc, char** argv) +{ +#ifdef LANG_FR + printf("Bonjour\n"); +#else + printf("Hello\n"); +#endif +} + +The Scons configure file should as following: + env = Environment() + env.AppendUnique(CFLAGS = ['-g']) + env.AppendUnique(CPPPATH = ['include']) + env.AppendUnique(CPPDEFINES = ['LANG_FR']) + env.Program('H', 'hello.c') + +When run Scons, following will be executed: +cc -o hello.o -c -g -Iinclude -DLANG_FR hello.c +cc -o H hello.o + +=== Get extra information === + +In above example, 'target_os' is used. How to get it? + +User can build IoTivity project on Linux / Windows / MAC OSX for various +targets(Linux, Tizen, Android, Arduino, Windows, MAC OSX, IOS ...). Most +platform specific configures have been done in the common scripts which are in +build_common. The common scripts prepare an environment named 'env' with +target platform specific configuration. + +When write IoTivity project build script, you can get this environment as +following: + Import('env') + +You can use 'env' directly after import it. You can also clone a new environment +and update its keys. + + new_env1 = Clone('env') + new_env2 = Clone('env') + new_env1.AppendUnqiue(xxx = [...]) + new_env2.AppendUnqiue(xxx = [...]) + +The 'env' environment contains platform specific configuration, besides, there is +some common information. You can get the information with following line: + env.get('XXX') +or + env['XXX'] + +XXX is the information name, below are the extra information added by IoTivity +common scrirpts: +BUILD_DIR: the path of the build directory, all output are in this directory +SRC_DIR: the path of the top directory of the source code +OIC_UTILS: the path of oic-utilities project +RELEASE: build type, boolean. True - release build, False - debug build +TARGET_OS: the name of the target OS. The possible value depends on the host + platform. Bellow is the list of host and possible target OS. (darwin means + MAC OSX) + linux: linux / android / arduino / tizen +(the line means on Linux, you can build the project for Linux/Android/Arduino/Tizen) + windows: windows / winrt / android / arduino + darwin: darwin / ios / android / arduino + +TARGET_ARCH: the target CPU arch. Its possible value depend on the target OS. + Bellow list the target OS and allowed CPU architecture. + linux: x86 / x86_64 / arm / arm64 +(above line means if the target OS is Linux, the CPU arch can be x86/x86_64/arm/arm64) + android: x86 / x86_64 / armeabi / armeabi-v7a / armeabi-v7a-hard / arm64-v8a + windows: x86 / amd64 / arm + winrt: arm + darwin: i386 / x86_64 + ios: i386 / x86_64 / armv7 / armv7s / arm64, + arduino: avr / arm + +=== Extra functions === + +For convenience, in the common scripts, some extra functions are added. + +PrintTargets(): print all targets in the help information. +AppendTarget(target): add 'target' into targets list, when use PrintTargets, + the 'target' will be print. +InstallTarget(files, name): it takes the same action as AppendTarget, besides, + it installs the 'files' to BUILD_DIR. + +Following functions are only for Arduino: +ImportLib(lib): Arduino IDE includes many libraries. By default, no library is +compiled. If your project use some libraries, you can import the library by +this function. 'lib' is the name of the library to import. The 'include' path +will be auto added to the environment and the library will be built and linked +into the final binary. + +CreateBin('bin', src): For Arduino, after build the program, it's required to +be converted into specific format (e.g .hex). This function will genearate the +required .hex (and .eep if target arch is avr) file. + +UploadHelp(): For different board, the upload command line is different, this +function print the recommended upload command line. You can see the recommended +upload command line in the help information(the output of command "scons +[options] -h") + +==== Scripts Hierarchy ==== + +Scons provides a function 'SConscript(scripts, [exports, variant_dir, duplicate])' +It tells scons to execute one or more subsidiary configuration files(A script, +usually named SConscript). Take below project hierarchy as example to show how +to organize the scripts. + + prj + |-------prj_1 + | |--------sub_prj_11 + | |--------sub_prj_.. + | |--------sub_prj_1n + |-------prj_2 + | + | ... ... + | + |-------prj_n + +As above project hierarchy, in 'SConstruct' file in the 'prj' directory, there +should include some lines like these: + +#Please change this part according to the organization of your projects. +#Note: To make the output is in build_dir, the path of the scripts should +#be relevant to build_dir +SConscript(build_dir + 'prj_1/SConscript') +SConscript(build_dir + 'prj_2/SConscript') +... ... +SConscript(build_dir + 'prj_n/SConscript') + + +It's the same, in the 'prj_1/SConscript', there should include lines like +these: +SConscript('sub_prj_11/SConscript') +... ... +SConscript('sub_prj_1n/SConscript') + +The path is relevant to 'prj_1/SConscript'. You can also use the full path +build_dir + 'prj_1/sub_prj_1x/SConscript', but it's not recommended. + +Above just to show a recommended way to manage subsidiary scripts. You don't +need restrictly follow it. + +==== The content of a typical script ==== + +After run the scripts in build_common (usally it's done at the beginning of +SConstruct), an global environment 'env' is exported, 'env' has include the +default configuration of the target OS and arch. 'env' is used in all projects, +should avoid to change its keys. To avoid change 'env', usually clone 'env' and +update it accroding to the requirement of cuurent sub project. Then specify the +target(usually binary) to build. + +Below is an example: + # import the global enviroment 'env' + Import('env') + + # Clone a new enviroment from 'env' + new_env = env.Clone() + + # Update the new enviroment, usally include add header file paths, + # library path, libs to link and other compiler flags. This part is + # optional. If not present, the default configuration will be used + new_env.AppeneUnique(xxx = [ .... ]) + + # Specify the target(application, library, object or others) to build + ts = new_env.Program('progam_name', [source_list]) + + # Install the target (optional) + # If it's an important library or daemon to be published + new_env.InstallTarget(ts, 'target_name') +or + # If is't examples or test program or others will not be published + new_env.Alias('target_name', ts) + new_env.AppendTarget('target_name') + +==== Tips ==== +1. library order: if A lib use B lib, both A and B are linked to target T, the + when specify libraries, A should in front of B, otherwise there may be link + error. +2. On android: + (1)'pthread' is in libc. So don't use '-lpthread' for android + (2)By default 'rtti' and 'exception' is disabled, to enable it, you need + add flags '-frtti' and '-fexceptions' + (3)If STL is used, need link 'gnustl_static' library diff --git a/service/SConscript b/service/SConscript new file mode 100644 index 000000000..e8d873e3d --- /dev/null +++ b/service/SConscript @@ -0,0 +1,24 @@ +## +# 'service' sub-project main build script +# +## +Import('env') + +target_os = env.get('TARGET_OS') + +if target_os != 'arduino': + # Build things manager project + SConscript('things-manager/SConscript') + + # Build soft sensor manager project + SConscript('soft-sensor-manager/SConscript') + + # Build protocol plugin project + # protocol-plugin use 'inotify', this feature isn't support by MAC OSX + if target_os not in ['darwin', 'ios', 'android']: + SConscript('protocol-plugin/SConscript') + + # Build notification manager project +# SConscript('notification-manager/SConscript') +#else: +# SConscript('notification-manager/SampleApp/arduino/SConscript') diff --git a/service/docs/Control Manager-Programmer's guide_v0.9.0.pdf b/service/docs/Control Manager-Programmer's guide_v0.9.0.pdf new file mode 100644 index 0000000000000000000000000000000000000000..4af41b9627f6ceca4c025ab90fa72cca06d3001c GIT binary patch literal 729724 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

oNB&?EX2V&=K_kt6BS|hET$O#(|aW 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�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

sKmQG*p#{)=Q%(yu`x`74)ELIakfp?fh|; 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 X4Th$Trk@Tvdth%mg`ZQbe>MG|dv0CP literal 0 HcmV?d00001 diff --git a/service/docs/PPM - Programmer's Guide_v0.9.0.pdf b/service/docs/PPM - Programmer's Guide_v0.9.0.pdf new file mode 100644 index 0000000000000000000000000000000000000000..03cb35a718b536797a62aaa39bcdfbffe6abf001 GIT binary patch literal 399274 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 !FOvZ!e;FuL%g4&F6I++ZnQz0{>MY_<{ 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%0DJTIyKy!T8))aC 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 literal 0 HcmV?d00001 diff --git a/service/docs/SSM - Programmer's guide_v0.9.0.pdf b/service/docs/SSM - Programmer's guide_v0.9.0.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ebf8178874eb9692acc5f6408ccc031ba4fe175f GIT binary patch literal 822752 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

`~f&K(-EW(|OK821Cg<`{lj1L_J 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 y>0fVL6*;v1ms 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�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

YZuC>RQiI5Eh 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%0A4_RD) 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 literal 0 HcmV?d00001 diff --git a/service/docs/Things Manager - Programmer's guide_v0.9.0.pdf b/service/docs/Things Manager - Programmer's guide_v0.9.0.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7d98810c89ea8f60c2c6dcc70fa3b3acf6ed2cbb GIT binary patch literal 1501485 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

1HiFpLBEuO*> zke`!#lvrJTXIki>fHYYs!NB%tHaXk{sFbKNz8L>)MT3M{?s4|$qWIZ^iqzvzmJqK1 z`vDbF;^4PLRQJ)8l=Yi`oD?R;(Qje|UAXauB;QW-Q;wea!u6W{|{#P;LJ>D9=ggB;F>bkw2IRAui z;pftMLOV-8%aokzH2d<<0_`xVV#q#a&$9KCn-&V9gsh34Sg2Nf*||uf3kP%P{FK=< zH=>|!Want5X5Sth{m){h&p9F0Dme$^W)APAumBtUwhAx23dX_XgI_9mD8wT@^7#PS_k#cRvHUdu5Ce=G#@ucwU( zH}xKCvxXL<9=RHXFxV#bWoz&79uMku)2@@N4HP7&Wct|5sa7O+lR9}j}ZL}@h6tF4kcNTqs!0w+1TL_y&rE8 zgD)fevkwYwziNy@GGcReD0?T$8^^LMpSLqet1`+%oLwwo#n9kboXW*j`H2j96mZO< zj3mfK?%>b|rIYZZ`%{+;hbE7*_o$G5$C9~5HAMvPsElFhihaW9UN~3YA&WY1@clw7 zn=2pJw}mnOTSi=X3e7Y_{H{%MY7Qq#lUbZ`d}=PXn^U}QyJ>EE*RzZ>a(@pUO5 zHI0J{jwX3+-?q5DyzJ)jG%c??BCamJB9A#R_>Be=RP1*SW$&DS4PqF(Q{<))<3A7o zPe_)KOc)uNesf`9Z(QB(F{(KU>FU+j?aqF?-3}2h_AICp*zIW7)uh6CvgKwj)>EQS zv~96oV_5u3*mgCZ*q0sn*vhZdtV^HNp|!h!x_BwBoNqC|bDm=)$m|#T5iOe?Pht%Q z_9S0Pr@?n}W(JTpS%aIvZ6dH)9n0#D+Awfb7TvtZpu$HA)mhjSp6#6_X~pj^%m~(T zsPy@H6VcsGZ%>f=tMks%ug2T5tNnXqQ;SndiSY0OOeOr+EhMw0qI0>I7xa|bBeN~I zQ!VMjbLa~h_x!b(JO;wbUq$SG9&{0fETA&P+nQ_ixvU$}?59HBMIg4U<=4Kpg@b9GrWjMTo0d2SqK|)`Vuvo zZZ!cIe#X~>inMAq_y00@K`sFf&�{q021p=BKf^kz;|h#)q>#jI^hDTEde`w+*?w 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

^U3**d^*v&N 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 ZC^8*l(^|@}z=tEtm1v7ucfE7Dxu?S(xWWM8 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%0D?&^pEOG-I2*feMa4-6YYHwhm>jiXoO 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

d)oj!Edpy`j%=xTSLR=!T1bOgDiI7#2)x@ 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

TLFIO6!tYsyBJP7F6(%aTN&cld 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%0A$znF1lX&-OW&(6I7;Ky^lv+WboRp zu=YMt)>F0aZ2YA#$^@gjae*5S>?wC|p zhf~o@_uNUR_?!7LtITk%vJJvr#88)7?M}?XaSny(C=Q{$DXN>DLUZofYKM_iQIBSu z`3)|I@8K2Liq&3U>jlzpa;oHt_EX8M*cHN~I4r(|EA|oNlChfP3GNy129q3~DwX6F z-lUFNXAa02oRHT}Q%@!G9(k#&!43X|!DoTF94goh4|Obq)^d<~uE68GG0XnNNOP_c z;9~f>jPL3xcI9Y>bAg!0UPYKA(XE~8I{7>tnK*xlZv)hZRtqgU5%b>5v>b#2U?ry_ zUlsSIH%qmbfpL8j>t?84XxMAcemmIdMyUilSSWK^iuk9R?5(e3wPX!CV}}iueK!v$ zfMT`zd3a}!@rti!opjVk$`#1S3pLG#+PZy|aq=#qUZC})!bB`6Nwt&ysYBkH*Riaj zz^`@Ec^@h6$sJ6d8|+!2S!O!*^Q$%ycEpp57P zTqB$Za=MDgqBg4aEm4kxH6w0Pf8qrN_xvMVe>87>0h_lZ8|rG2=IAOH1Pd&O#+{Q^ zkwNj!z#u)LeRl${hL6{JXI3TCa#0Nu^E2DZzaojw#a-dOfQ!Il0YK6Dw%f9oJk zyr_n6ZhV{dis?VD5#(CGm|mWoC{g;yB(`_HlLZ!-Cq(uKI^D;M0S-bdLNhwY<1<3F ze=+msVXZ_^!Csq1m_GN_+^N9t`w>WEEqvf)=3VLOIOk6F9?A%_?#pcHb3vK+Lm6J> zeVG|O9oO7x@4!pVJ^ zBt0F^+$rhEJr+0wOISTm`dm;Za9?I?$1rjID5hy$MaiLIryeNP*2H{EOyLCrop(vr zk2SaHGwJH+iK6B=dD=&4N|$7^Z+;(C?Zwzo7wP)Kt5mEJ{5Wom_0M0no@cxl0b+*5 z0ITqZCj){>*L0I^U3i7f4Z7Ih?*@J&XDX7{J+B|4jgp?;hY~h6fB_Jp;lj0O)xS@I?Fq2GCU%bu+Ts`|cj# zR`BILz;s-ymvg5GMfbudr&59qGMI%Gcu-aH{-MKR&YoG1*L2=pDj_1^V8w*Yi%AvZ zKS{ut@PMmU8>2h3_5_OqxsOihS&J&A0HU+}Y2JoAX zw$Zfjne-u72*7vA`f+=F3z1IJpDc%qADkd37TQlp&HW*|t zs5#ij-B9W*Ih@xKOL2D=djveQ-1j{?1Vx| z>p#nc<@Nq49fBvr!%#S_ruZR(uMlGVKVt0#Uk4j7n|I#H7-nKSyi-d>XvLI=WGy_e zxS~Ybi>+MF-w~R;H*zg?vk&K@NWm(0xFa`F%YDS`R%d(nio>W?sZFss{2>iDDbQZX zcs>~wJ)!q+gUCJK)729Y*fB_PWqt+j?*uc+Xis;6#{b+3RZ3#dXHLzN$h!(dpMY;Tg zI5B$Pwf-bOEK^m?LCSAXsg6$B*c+-%q@JpG5Vg5rigJB_=frpe5h*1vTk4EvKg)-n z|Cp9ays_T8pmcQ<^Q^Ddv*>0{M0kq1lSmeJ87U>W_vcJBLVb=$Wld(40N9TNxJo!; z0Q(A0BUR7ju_(q=1a{0F0{j!Q{oUZgCi~2OrH*(|&$PSJMYD$Kxz24{r}`JsVk>+p zfeJ+rrcGb@irn=XOkNeI>FGSHtjYU68y#-2cTYoH(sGz_xL4E`8feOechhcu;-Ab$ z8;sq>SSSxwk&pN+OC@Z@-ulBf6)FQ4wizL6?SVMX-n9rGr4Lpzt$ z7q3Js<)I3&ytW!z<1$>Mz;+ij<;l}c9kUcaZBEw{RoVVhR=eSM3s#V?r8k+}L`R+n zNq<_e@4-JIxuR5!AeQW%+0(g|1eTHU;`g7Q7sryAwTaIM+eQMdljWr^D68M&O9@qA z>M(8I)qS;7X7vSX60lCDS+oD9KDx@seB&?9hApKp+n+>BsqULu!--a=w>(v5V6Z&L z=}BHm8U88p#_gLZ0zGRI?IpuNH1Y~!bIXk>&iw&PEVK;HhoEC z<3`hp*ctC1^q>8$Kek7sKPEeasZDpeeSCO7T0z?^aM*mPS5L>4JhQSYQ5@S305M?~ zc&j8Om>#@DYj8OKe$jRloRonb>=ciR>EA%iDX@i=HQ}q?zFHUGbqPIKI6|r}v5af} zVEn6}Y2kGZt%Q6T+fvvi{Bf8E?-eDm?qko~?Gkftuq(Cpo(}2?x;1 CyX7xV>p^ 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%0Aamv*o;jrMOO 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

d`4Hr(&(cE9XLhd?cG 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 gZ|l{z7= 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 z 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 pKjlk&1_Ovod)(__KJkGyyFH5PjS;OLZ=tppiJs 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%0Djs<}uK;*N_n0H}n}~Woguq;}HC?xOK?yF_yNM^p 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Ðr9`Wp#_R*FVr|YJM75R$hV7z7L))8NDqL;%= zJpKakX0g1vXgIXlCvf(VQhB+I@J!LMzx7hl@oJ+1sF@{g<-u_VDJUu_pBz$NuH(9e zie2cNR9e;{5PwMm?XqytVxtYy6cdX^UmHjnJaP$BNdX(Z7WUy<~@u_(69>0=Q&_4(vr&*$p~#}DFqCp|@5 z0<>RbX}>lJ|Cs2hH*Y@9RK`_GOdF-RV134C`W|29BQf~kxzKXnm{Nb;ah+T|Wjg*{ zA?3(_xq*&J#u%z$7cgag z+9zAf*xGFWS7$sEqFDoj`F6@$1o{*dHvC7UW&#sIc zRVtW3uS*r1OJ4&V6b;bVDIUMIbAx zehtUIjJ;(3=l;@+)@uMo!(`Zk%=y`ea1~y2tsPi>ETrT0_mh67jAB}1W%Ty~qN}%X z3ELR?XB%#$e7#8k&GaJgPcjBHgSKP)TBG!X z=Z&sdr`OFk_cx`kHLyttyD{ud)ySG;ypR&7(Qkiz!_Xrkn`to#h&h^*I5Zwq+M~Op zE~Lo8bW40zRyjjb&+F;C)S1wZ?aP(SD$CZ)!Ie!DUHvfsTZg_Cn<|W&9APpfxwlm+ z#ty~hhVb)mi|L@WBA`ErjLgjUzazrl!lcdA_n7Uw#kq^M%`u*nCq4u{uZ2UcN z=}kgqK3={-I9X{C9I_772-jPqe(JRkcw8R7dx9z(AJPh2DdO)PYTu$1M^Z>Q)02rf z%kC+#he%M!6`{sAJGuoF!Nt4Cu>iiq+W(O>x%(Xq@X;v69K*LO~%<}>L$ zi6luKIw8nYP+$46c*xYer3b!-3MGUy`*7-m)0maNBpX#em|_lbipk;1u9n9^4^?xg zKYA3?f_5hY;n^#NQj9xW2@Zo9&~&KYBn_NzDg%{<&zXOXypP-3)1lOl`IliWR&+Ht z0-_OZ;?@>D#)cOy9ZCS>R|97lok7~zt@+Dt%?nDXv^$N2oi}MLN(su@hSl$?TNzK| zuD)~_jVMLMZnbQYb{H&0wh1K|U+zwQEx?JB7bh=JLz$ocWl?;{sG1ROxr?*-H8n+n z74xNXt?>P^pf|f8Xu|~-R>c1<)D21~+KulWcruPC7eDt%2XhU|&Pzb8I}KqCn&9Kx zw?TfMeBTid4t1s8`6=w9nBUT4zLn4o#eeU+$)C9CtMd_Rk+?{X=n=`UEk_sUjcfC7 zTir?#G`xNoREQJ9p=5cFKNUwG;j?6x(tAJWYUPi0ADUiw%p@`X;LE~qCj2c4T2Gfc zz+C`>_{qlVXT+O1P$te6iaC@nei3vL9~Mi+d#7$&{$e3Sd4f1%sOvAr$N^vbrfEM- ze{eIi{9+htvVT$T9hd8^1Hi-lVM;(5D?<(Zo=9py_{H!oU?xzcj53$>qr8hq=Y#=O z*re|?b4;}>(M)FT5ot0DbP=%2&|K7#EPH!na2DNhz9+NV)yqQoo1tM*xm=mA4vH2^ z3%e}WXQ@FR%vl7=J7`_YTjly7Kc*kx4}p_WZFwaz8UFuD@xZL!({+#0^lQa3Kb(@6Fdmcc=wTy!vd zC^HsyWL29@U7eZQ-KBa^LQjYm`W}>e#(h z_cVb9u=re}$z#RMPp|TFHe~QP@Vz5skmI>y1l9P}e2n5T-sN~cnD8Vdgfg5>+~1~) z16RW-x4ev)>cN6e!m+$+7)V#`jXvNU>aIg)5Z@cwX8I)KWP7H0&naEN#RH z|Bi=w_Zr1CjL6;L!z)~d73==3bIRaddQp-Nf*opMip*}X97n#4t60WohPa=k8vTg% z(ad?*_vY>rMJ(OAgr>|yBm_l?AICl-m~(+dH?>EwsHTL!rz7oI&iDp!3vlRby_>7A7#&o z6ROkSsPX!^1l+&m<;!tBcp6T9pD((-wun+9d!j4upUR|jwG!Qd&&q)5@@y5@N;L0# zYbATZCwYG3>geTuD{3|R?sr+LP0`sx?Y`2S`cB~(3-9l??FJMr!;1FSpN+z9f z^T?^FiHnWPsGl_{)$}zP;aI$7DcKhr-Y5j9vE(2>M3a~+X{S2CPKU*mJLOgy;82N= z7Q>EagKWY@ghngl;9boUFyp&sa3=@ROG3sDW5iZ}Q@*WJ8Fiaeu6s|iNWD>_KFDEs z{#$WyMmiU>?WKvdC8c?ojiK zyYerhPyCn<1oU&hNY*RG-^+8L+qZO1-XzT>n&YUvv0u%}HPF{e=b@>-zC1B^K^rDc6u1f@XSL^^b3mk+Tne3Sy+U%dD0zb=SQ%#&1J$~~b^bG3g(nj6)BiH2%`?c9+ zaQ^m)xgSHhnC`9uGKmn_=yZ@hgPoz0ubfeMoFFTn>_Nnu&CwU#Jn#1szq z=hKxR?-s6*yK#JkoP*ma)`JmQxTCKbBBi=bn9*&ZXbD-U%fMRFQvXo%@|;9nmOTb}xlrcy?uOpNJ7&Uce2y?D#Ma zCb%6Zu}40R-eK2_3eZKO1i8zixz9dqml)4eabh=#@{!GCA#5XBjN{Mb`jk1hLN0A% zf0dR-b*6p`X9kRMuv?zO_lq1d%;JVQVlSZ8OQ~_TlZoaL(^wRH%IYo6&XY5YNwdbo z&KWfwd_0H6X=))TBgnt9u_u?-zh*YlDKC#V-hW89JTNh?tsuzUmpK=IJc}+{IncOq zpKl`4IBeD~vGVoFA~@A#NwrpF5R$ZtlkOjpUi6te=PDT>6Q5Y}$Gs0oNAG$K*yDB+&p)WkvP| z{_O4i-imv-!S*~bV)^0}2g1$Cu{zg?S=3-1_BbyiWN4H2VB9OarhM_mXAw81Hv8>V=n~8~=0vXNLD%h)S8gw2u@6zHAtgLSuWV2`; zWV=g0!=-jXgnCA=`AEon72I*6!3YR=?cM_}&WS3Ytcfwr-v#P?Q2# z_z@rLXex+sai*wC6f1f_|WJ*+7@GB!+#oW`)}g5RC$30Tguq<4oj zxyR3HcFcQLOk~&Za1nLOMwM3y#U6U`E^Kq2@-sQtK zwstp%hf*)0$FGZHsfF@7xF-iC%Rdoj9EmjGr9T-?`OuPxJguh}X@RuaBTAD86)wNh za`l(C?Bg-XCTX0nJ*KaTz-adf%);(yX$xn1WjcFa56nk5p94^r?gwb<60ecwEq`4E z@1;KGE+|TY%yw!J`iuhmzy}PDtlX_;yXrY@Yd+C=ubUK2H;3?EW}+i6cXv83fRuu>lx%Ph6>p28A*KIehud6CT8``hj*4+?;bUnLL|Z_T9BhZ!=*G0@1J zOw*Tz7gOu%804iCo#QZGv`R~IgzfG^#APA#LPU!OkLr=#Oe-UfD)&9iRw})v_wCOC zuHgBalAVYXc9VAN)MyX+lYV8xsvYQz)9Z(-f(JB|Ry>aBrt>N2w#bWn>&e!of~U&} z!|Ch2;-~@w0)r+eYO7sj0~1KwMu+DiMHD_Pz3@hTqhyBSN)TG;$0`-}$&oOM4@^iW zO9Jv4L`xD_Llowte#Cs=(WLQAjZR?jL1;=4sr1iXu7i|rq*lwSeWp}>)$saydhKjq z-1zo0L?1`Jv$G@HCWN#MRm2T$izLC_9H#ZgX~dX_%{p!%Ge`oYDIS^*uf?vLu3ovY z84hzJK6GWcAx(9Yp|$~Hok(a&;36x&7joY^BU}cEKSG)jGkSoQ?9#*wa}yM`(ythq zsY|V)nYG>;PDwJ{F%8I9H>(chp(HFGpKCr_@rBvrEy{Pcv`jm~h~=<$fJmgyDBlz! z=>RykDi8KWBhQ}#tv!v%yxG=$)bWAM&d|v}Zvw;En`{+VmxF5pxu4^hOJ5B8?&2{~ zPP4l$XJMSE`Q8N^K`DbAh%Eia-Tn&HU(&(KF%t7*w4(It0Okz z60W{&^J`h~M28=~Ugk<(Oohz>VPLt(m_ZQ+oR`uZ95+5YjaQn;QXYo+h=Y?rp}h~Sk4?1*r!To+scNbZ}tcotDbL) zO?YdB0$~}%+>OR&Ai$pfa2MNfhJjvkVOq9>+|_V2nvKGmA?b%j${r!{dOsmr6D$1K zDhA_>bCAGt?e+*OsHu7ynAENv)O}7~L#lYAy@+xxj^fH-Qga`8Q4EfaUnLb5QOi*6 zAnLGUEs0l6)04f{T^=EA$u%83AP#}U;+lc4K1$sIXfZk&7Ba7pzV2E;47(c2e*S{r zfUlU~bGVAj%y9kz+U1>Cr#`p}cR27QIVQ%I`N1^0Ed422+-bG^EeY7Ik!<)CNk zZ;dgXd{vn&O4^Bnt?kKVv{kQNJ_|%TV{W(p@q9mDlE0;SCB(~#AhZgih%vfik)^*7 zjl6K;eH5E&HQ8$}p7bfL`D+8x(?;6!ZtSu+C?!8ut*3ZJ$K$rMkx46u#_?(Ll6`>s zDf~I$uz4NJIx-q58@>bC4GwzR3hURby=LTWvJ9BSpU{!#UY_VzxkzLD-FvK*5qN50 z)gPhnRC`dxo>9R$Uv7y^t33U9w6Q)@u1lT%T;p_Vim0uwVP&hTt*>XQvaMyHfQ3Nk zaqhX5#Rg**p@C^+&_;J)o-Li!Gkx{9z{6>p7yM01nNwJLmx7B z!v(-n7Asrb1w1MZb7Xh3G0v8=`pcRs%RvccGa?JCbXJ!g<~}zd z0*lW)*I63@@efvydcd6WqpRNJ0ze>h$A^Kr$J;nH*UqY35YjLmy@;~j#Ie9GVa$+A zK`scuIy~Ss-Fu|XXdE^UJkT_B&*^xXn@Au7;G{4dSSs@Rtk>NbsUBg=buu|j{zzK* zd~FY|yxKDz3Pt#RjRoB_lEr@y$$~AZPAR^)D!_Bh7z;VWn8%ESH_=EX&d=Jm-V2hQZ6!`1Uf!?X#17GzctI|B>p=L}5`ph2b~_*{aU5HGll zUuxdXe((p^eOjGP%v*i z;$RYzv){ZW+*xxeuvXhrpGgdVI>x%DyK+LG;%?02|H60V@DiPf7bMvC7OU!dk{(g| z$CG!3g?8HyhZkrktu9NAoP#}spie*T$*<0w&y&d(C15x^_wKBZWm1k~h_k|OEN1+w za?Oc+z2JV=cpju1Kek z=@cY-qxTW&)(cKNgDA=j-q&4F9j+huG4CZr-`__kx`UoH;X$%hk5o_RR5vF*>udKg zKB9-TTX|#n4fR(8T{C1R4ld8h-|b{&6)>qemZLZ!cK3j03~r($4o}O;p~=O^I)GTm zOu$h^DAsaoG2`H7Sf@S$Z;S7h*q~HMjr~O#sy#vlg<<;wuZO>y&DLc&?sRMWp~SBS zT5g-C?TJ+hBoXO|>jk@PNV<9NL8ACP#$p4ZBG^Oi%lq^ zjwPD)jdZT5GJ^bkq(n6rW(hhi1B;sZXoK z0XAi$U*C&&x%6df$a3Tlj#wg?TZaxVlT{6dUbwXJHe96^3N;U?SlV43bz5I@&1}0L z>+rbR-TR?b^$0sYO|3}B5?0O90h{Nib7ve+Tjz>Bj@uek)__QG9%pwPOtbDsy#jb{ zc_(us2)vu7OJ={U#Q;}&;S4*!w|xSd5O@v)5cMRJTOM@v`vzhy6RPm^YV@3nKmlYR zO!rrxSq=RZt(kY;o!I>vAat}P37OTi#_}&;?5B!q=n^y%Yn39o0Hy7_pJij%Jw*H; z1FE!?nb^u~U26pJDm}$TeP*i`sNPBoFQvFF>_7IPG^q1hmkc|)*Sgzp?kIn$3x&Qa zP!BM^M^nFu?LebWR7sRhFK3^FNN8q7OqTg9I+A|QaovX_R^=G#mRF+2 zYra>{f6x$2EX;qw37DAwfHMA&DcG3)Kq~%)hxiNc@fYob;T2=Tz^qC1ztI6+aSQ*e zF|Q4Hjr_m;UYq`3JiJQqKT}>M_)phfW%y6Af7|>!{BNZB%ldx`^Vj)*Bgt#}f0E-b zt5-2zLuQUwA^sB;f%Q+}|0X89(lP#B?*ADwzEV~G&(!}ug@y4C27vz|L`?ltMI4e|HJyfo-uR$$?=LMc^w#kXd$nR5r$We$6tQ_wEd6$Um7sH zvM&BuF#XH&j|Q(amDfSS#QZ1qU-kb3sd>%&zpL=4fd4z5fSvIb@AAL!1PpAfuN;#9 zf+t9W*HBlyz6H6{!5fgke}sDXga5rck*>Dd2P&8$xesWQ{OW3y%Nl0U307)loJvAm z-)5S_>yJ4VaVLuvN|eetzbW?bu^-Q38*5B7hwIav^4_HTO{(FGJdK<%W%6Q1#6LcG?f?1iAiAAhBa(t$IzxjMO~YU zHs|3$))$-bO})wJ3U%N7jUVxw{s4K5tF(H<(`rVqVKEuUo1)GY-ky%rv!hpC0{aVMY@KMeA8%FYXG;JR^ znD;Pzn8ZPh$&>@gKJ@F}Eh2?lUiU^N=r-KCxOHDPg}=;yuqaX3)pEuCMdCY)lLc+H04EfcUgIzO zU=xrN7RqaRVSz8pL>eeBx2kuCmCsq?UjFD`^MCa+n+S$} zt7S)b(Fr%`6mIV;o_s63YmLp8<<@IGcNty&{m7OQK1Ss%#V-b#qcb6-Zhht>@`OxC zSrUvTJ?=IGPpBb0Z9Gf$R%v3H-od=k;b#ZzmWXAz57)tQ7Z)2HcLBCvPI)-qdT>`V z05j*j%U<&Ra=aUOu$Cs{Z~OwkTYKbU&yD4{_dYm?axECQqFkpOWa>%3Y$`oz!<;F9 zJ@WLZcPZWmnP+ktJE)g5vvz?n*!@tX5>q#Y4YQwujAsSsFT^V8Vf6lR*!~8 zen>iy&ZB;vh=y&GDp8^m5J3BxOi4dbSgQ>|xg#xR}Go85pV194W0ne`o=Ejar%YK1iZpvzA!PG*=`Z z8xG0|hJH##vQweSNmNpCFYQ*_D^aVft*Fj{8a_}i$)78rl`}N@-XRv=VAgt(x6tyS zYDN`nR+mzov3B>)K8Llr zCnE0Z@&(G*jJH?XS(Qj1_DHzv8EUV>0DPwsjVey_%3SGiT3QDZbt?)lIgV6Rmcu4K zBuO8SFP6D$L$j^`ZU?JU#=L|fl-QLc5n8f_~<>8^bxQlO6};D`hUO9EH{<#=fO4 zbwiXgvxS_gD*j3fdSX?+SjJsQ2&k9+(#T~k6FYuL)k;k(Tw@wuB`kM62g~w`FQ;y%ePG3?pJUV1V#|G_J)y6md|nI8+@gqc z^qba{gIst|2<^ffDc1Ls?uW5X>H-e-QaQI`G{SHt!bA;JiTZ2*g@cp_C&=}8Z=GIr zzjP&1u)UTBT1KFF%?C#|SH*(m;s&KFAaa<6$~gGs>=LN#K%4%1xDrfzSi{zkkd#+H zW}<1W)nD=ppGsg-YjqKQ0>G14JbsAfC4eq#|OXBfjD;)p~aWuL`|?_2)X+y4HS)c5o-djipZ zXk@udIeP}HhWJ^3H>WWR^#$-mA10N=1_a#QbB#9ojW!- zFI*xA3Yx&qDNj*FcfS>YRgVaERA_{`wq+ZCk@wjSB3nSd!)6{3{s+c*^;Mj0qI1ySc)`yL5Rc2;&T zxo4z5!~3F+!#S^vqE2*5^~Bfg;T@g>wS2}1&CiA_|3$mpx?pj>*9Cn7!Ir+;N|Q+p zA@Oz5vHZ+)=ij)Ty7);S@M!3)3j^g%(b<~-Y{xIuw z9m*}YF>ze{3k!v3a)&-%Z)eMHimHSL^);{uyjD7MaaJ%M+uo!ONfK`KG9&#)e85>! zb;`+$;isQ308ZPlZ%g0J6jouvFa@6T@Z(eJ6PgM*fmn7OCngx_e+IgjSxO9yR9*x^ zXC~>agrnjv+(#(iZnHBn@kfHq$bj0~h1WgU1KL>&ve}>S~ej6N49Q_ z_CN#C^mJoi|HTV{J&WL733p08#ehh5;ToKC_G*!|irpeW(7Q6>;of@^w@TcSK*+j6 z{V)qZJ-~xdGf23_X8-~ToTMZ1!5 zPoKMb{QzA;eh5_EFn-~F7w{cl(nQ$7)?)%`0(0NlQ*AJGc_0#9*nU92IzJY_89zlo ztuC>y5Bw+)dww?ECSF!TTO3_%h(Z^YUo1Sur-aW5A2CodK4E-revj}z-4D6Tt&5wV zOZS^DvMy`ZD4~3i3E2qo2&ohNS3jdJM1It)=<)AKQiT)}B-5YF;9304x)k`)vtnfU zlKB4zWA6atOYrr1k8RtwZO%4{Qr%VcJyevk6dq7!!O8<ebHDZ0r zE(wp6$nSr#L~}W#x(Ymy3&p5nMAj$k5?WR8$hpNk@=lHP4ZVf5{#*zyE$gBD zQaTFvN#295ICZjqGErUCA1Dl#ghE7pMj{~LlM=rvDS#|H{l^FN3$mM%I4`uXh@jd9 z=_S#ojQEadTUOnlTkioqU()N&OZi?WmVJbQD_;}-eU4ryo_+P+dSIuh9WGF(#+_5) zO)-j%QB&HCO(_aa#r2!fd#^}6$ zR$miTV^l4Dk+$^NlQ>&(-NQIrQQgzH?5MUr!nN4d)3_?}?3=jkpjY_fKa!~@iDTS3 z_@km7za}h`px}Bwi?-atL`cSW^U!IJ3iwM9i~B z5+NTD<_vbkG~UY9_apKKagqE$E6W>?Az$ zOg>S}5%+{RLZnhCONd)RohHjZ*HsnubuSjj@RsM_iI zj(Lh?tz7Y(S?!so)xm6+SFEnqztU^;Y1Zh@v{F}l@zU|yx%jHkh`zKt(_8Iqcp2XY zErV)rcGtM+(RVU5t)=X0wKQG|-Jb9Yk&?yCOFL^@U#>)`)YjTM(5vqrp}iQpK&J3r z8bo+zBCZT$fByXlW!c@++{ zSEfs*mGO?jjsB5gy=QjgNPG9+E+UVU&h_qxmR9eR4s-95e_zjbF3nyR`CqacQ7fI@ z!yA{@_tUG}hjxx~FY=N;-Ide4cHVzlm({MS*YvOKs?1gN)V6=s_XR2-N%ieq2g5^$ zp_rb>zFvFe^L`tC=6lrhUMprhwq%?c&%}1KsW0w{=gCBqAJ3;(GxHiB@|;O5{tk11 z!t8*@g%e5bH}M#AoFxJsa8sOD&l^5S|z?S`~dK7^j_qH9iuKO|Qm9=q|y`Jyp4D-?oTmI2(@Vp zE?H~ZRN(H*m>K|GrcYe%X`5quFKYIwF^Kql*o(aSV|Mi87k2vg03>1$hPBOi>~MRs zJ9A^my9tRnU~)_M3Eg8#bL#)Fr}T;o05j-A)-55P9NpJkuYFGQ!xB*Ffos~=SG@f> zGCI5+4I6Zi0YDKU;ufw&Gbho#m6?+POm985Zjbi@_At?`XJtH}23*Schae;oV9odh zl=}__z(4iJov04~?%@yW#97I6J_<2b1vJ+oO#44MVr0Xg^h>k>F$71=Vp<%04Ld^H z2JQ?LJ7Vi1X!M!4q0|J@JF@G7t_-+3^1t6fv>~@Z%zJ!Fe6Eoc-zR77xwXMwOKgL* z4%j(DZbsbg6u#VqdMiodMD7G-+Bu?HJ4n*E?swq79t8Q`4$7~Fm`L0i+5$ZfeBA;$ zbH*Nv)a@#1iN`XwM&pV)waTWJH4B0SG)h0PZuBSg!K2w>FQ>X zKo8_d(#Y$VYrtF^rrpO}knqo+RU1YyiLlRZNV_&hkMVDR#vFubFvgRFxvm*$D_`oJ zgTi8hC#t908I!JuV=TgN{BL5<&@Rbx$?g&QZBg87GyT8yJzuoP;#L4bfC!nKuu%~N#F>(c`H)HLM7qAudVWB$5dqpo9Lp?ZmCe5btApl zhHtykrl9AO6DhLA>!dar<>)epSy->L?&t!v(qqVDrK7Or>Ww4+kTXjX(f=C9X3bm) z#3*5Iv7(Er{#%*Uo{oFds6{Yg5mJT4o`E&f{|Y8Mk*J9fQwJm;GI);|d{X}@wW;?0 z_JhyaB?16-mqixI!#X$OX}Sca?*wjLg1&6mLr2fgAdWLs1)}vv5SjDg^dK<}T()Is zJfUSk&Vpk%BTj>&SLAqn)=}6q^Yf_p7If)le;v>BJ*5_{_rC2jbi-g>g-a9*g(fD3 z3E`h3KP)A~JUl*5hI#WGdmdsEor(pExqQHbl${M%{OTq83X%oN?bl)$s1M^ zn`K0D0e7&`uN8tL>G{O58!$;ydbTSQl-8(VFUM8FXK5d&RlOKGPFI)rfO+O>5unNBk-OzpY;_Ll# z>(VkQi<{*(bJ9A6CvceUx3vDi$n!K_W4p)mGuzUU47WBPom^5)xW)4FHzldJv+DGb z*XfWm2G3k$jIY_V`_b%FNgq3n_MP`|1-y1gEHb@`7lI6T~xrKsUA+%>iJ;OykX zO|a_a#H8%Rq&zw0Gc_1+eNzSSo7Wf3xiDkcWlUJt{`csC6ascCSJr6dlbBBzs5s-M zhso~Tm76!=Aj60B8i|n4reL;4h%YDCIx|TDm64(Z zPPEbksI)$tMV>hAtQ0fnPPLlT(^X)jy_zE17>N*0L?LBim1qh4FQf@D#5M_ptND!( zt2I#4Fg|r(i}{Dj)EWwR^?!TvrR^F#2D=acHZ(Y@FbfVF6FNIP*JVLMxWKi0`7)y^ zIG-HjIM;8ye04PAv3j^+P~3N-nRDXdEA=FiLs6toIDRAo%DMFLbC0CPBNw0sF~0aVO^$^=6JDAiQm8a8mKxef z{cx9ZlXUVLF-!e8$r>J^r8}4=$*Y?Z23e3th!N%uL1V=H68DLXSh0xoJthmmfZM6tb7v4Yhu%H*aHwDK2g zMXa1GEg&#P0=~?;NQdX$_`*2>)Clc|;*4mZ_i4Lf=abm)(d@PK^&2tj!z8j7_flk&h95Bnl&``kFHGS~6 zP^dVbMNb1?cV~mPncm_k4fXV#u=4mj>9ITMx1Pv3|{gK1yiMsN}$CMjIxt zaHYwRwVP$qd2ZTV-3y=N_HdPmlvTx?)YcPxOHQ2+uUp*5S&?ec(>=9qPGP@QbX>`y)Acb>mRFAbJK386f`hqJ03$ria>I$Xub?VDOHK|-w@{d2 zn_9{)DeXcR=@)&O0C}Q`?d3XaMaAIO`P3%$rVM|QAbj?^`<@aB&u}P~M#trPHgv2E zwm(A1h_+9@Fx}m1Gak7dQE#20TnaN`r>mdDPA|w%>DxaK{-l-Ct+S!)f-6HRdKidR zpjO#fag4#kFJIVcv^O8J(75V=VbDs(IG%`=b=6QbQejulq2gubETPrHYLn=0rt(qZ zrlI*;#58@305=z>GNLgfCbr9ivbeS{gCG5?=hr9fVPIG>xV-rn2-m{Tv(Tcc7@}bVLdkC!hTivHqmh^wk8aa}@fB zK#A0JswhG%?o;T6ypR3Drz(N(y2{iUvp5ver0oaGb2FqXgdCAqu^hqL?rtAnUISQr zi;uIQtI~t>RgGwY={=jl!Vf|Fn5OYpjFjx`TtV~7@hQYhMc^3O^)3<1szPTM7?@$T zgz3jgHqpJ33>A%;@ysT-m2<7omcp?$jZ!Cz`nGGt0`cC*~(maaH25$;JBV5#3c9{LJhu!70MYsD6w>M!Achm}IKc>H1<%y1j)&L72cm zVTqJ5g5wT-6!BWaV_V)+Oq2RgE4@dTER5_u+4o3wxb|956;8ukk~Mqf%yfK-H^dKY zhNKoD9|x}_;`WC#2;_}{`aCn`?JkVcEQnGxzpshLA@LllwMBcXEq}A)c%}|!(Xzr= zobvdvR5vkqEssV2{OacWW>-gnX|*yc$;0q^p(}+>)pn!r%6N=|E!D6%QgKwvh^%Ab zMomw_dy{q;`C0)>=|iIseoes1(F76pj(iP_hm0MAuhj03;u!s-hbnRljjL0n7Dg(; zCaz=7l1K7fv#0XUJyXjBsybsX2B7I7EVH~#mM3hXN$q=+)ZY`s~RXN`LrGlzivLrnozX22`(GwI4UW+T6K_ z_$^RbNm#&K{-Uz<$jWJ}BeHbMrY}=n#6xeG3S#ESQMnzIcx{&;0~5`J@{n4JOawsMkhIfF8BxwC$2P6Z92xV`&y&mCo3>BTUEmz+N<~bnjh_zo*@NkvV70S9-$W0Q)`rYivCU6OEErU)bsAAFVTlC7`GsEhcsj z&)w6Hh9h4E^=8-19kwtbwS00u(T7L{{o53&r z1n8Af5w%DpQQ3mAY?R7&aKhmG(Qq9$CvIu!wY&4{a47DIRLZ4V`(Ne1;8n&=4Td&I zMMOkI;bJ4Ev1wGS0r}pe!#ka?8|k+VolF8tMHN{tb9ia$r7_aL$diLv!&$?E!ql>1 zZ?aHb-t4ChB10tJcJ^1O%>~7&OFbWOJw}%4#~J3Svy%l`S`Q~5F_WgIhKso1f96(| z$b5B_|JYAa?WiyaantS?s8(hTKJI6q@GnE~VC`;F;o3SNGBPCP;CuoH&OK|8?M5EE zEbz9NyV8HWq!3nj7Ja@s3#(867S#UfDx~Ks0bT^Ls#q^9I2B8bmb3>*WPqFu?k3X@ zQR?ak{4V~2h>NHDC!QRkP9wI9%t9^;H#C%0_(&-(e(0*dxSwsmD0bMPpViVa#%**I zyPcDj+6Lc37qy_b+f<6l(B>%N)g6-o|93A8*9K2K_V#c2n0Rb>#F81W2|aS8xJy*2 zg?J>sR?Vq&%b88qpTA6Y%Bo$WQ0Vw7$0^A#)05KoO-CEQU|eKNAYO*1(LMq*&n!Gx z)yAXu94c{5vWHV6Lr)(E@-s5D0{I5)nC{wtBF*Ho6jfR6jG1c=8|#WM4!2h48~UP`tYY8@tE|x%KvX6Sg-&+~ zi&d3eKnRPaEK=Pbrt{v12+IJqYK1Wg8$lZa&BFOZdOgT3klRU>B(M63@$rTGJA(Ff za-LA#si5zL4s=i79qUB_g(rbt3h5Tkc2;WUN^-|d=~jysEWW-34*_b-J>R=Fvh|0@ z2CA#|Un%ma#G!;rV0^~O0-$KJkNFi!`HMql+=-3*OAy{Yq%QWr@6-_=WAU2thnZP~ zzq4pKri|q{%dI&%F>CP%4aX|0P@PhETD48J6kT=hu^Zp|Hg8_8-no#3(=5-1wb~)nKleDr3l2lpG z3mxwjcN-(~3V)KafBrU(@XS;7R7Fh4JDZMJkt9YYHDUmE%vLyNv>6Qx@m(~kGb9;yOHgvus1jxV2 zx&QL*1kU_^bIO$&H6_1*nAW_~(PFdO0=1~RtER#sU^!+>LvKb)FKp2H6{Q1XycWjq z%}_-zXk(~0Gl;n;FJQBqeSgHNYXv`1O2WEO!Z@P;Pv0g5t}gA23AzPLzPJShozRVx zE98Oy7gGhyy&a3Ex}%dRd>v05NBgpFp#xQ_m*QkE5N8Rb+3ylKz`xxPeP4pD(abec z-2G^I;%L9+!-;=+iHrgv7Cb0ZDA3f$PKTtk$%tr2(-hl#HF^v0R4wiehBi@iGkeg; zjoyq-)J!rp^e@HPS1oJl{yVzR|3~`S&CxhJnTMLb!MD)Q^-h|#!8HQ>C$8HjF6z8v z`C~F8gY^a&&kzefHV-P&-x3TRIfhvYu*>>a)yxCh$=}JmPZ)Tt&?@nwnPX+UgoC|A zP9>>n`Iy3L{!w_*zu9`;k|Lf;oQ+vqc1~;{CfTL8dnUt3XnytE%kL#_qRRK(yQ<%Kay?a`k7Y^%l13_dD`CeBv|z zEo{62QF@1ZEZcZ?G1HR61G zH@1py@c^1bs{FIh1qK~bQy>yI#&Sje%{c(oZ9wimdO0ple^HW_<1k%PR+~w`Hd2de z8HbAw&a1eDHJSe763xCNF^=PL|hc6VKK!wK` zuSG~wVi%r|;kN;;Pn8%l-RZ)lMOL1%R^C6sUX3;0@UJnmyWSu9k-;?~l{R}X#!tJ+zXP5~?7E`iS$@V&1r9$Vxj>&Bd6P12H) zA_>`6t-)zyuQf;9xu5Ri(QM)k~og;(LkiUt_V=sp1HH}&ZDjtUavN}EnVr_+kcjz7|C*pGPE30TKu*$3sO#i}=;unT= zz-r);5DZNlAT|*b8Sr2*vNqgQk*HfKri#k*7%iXD$xb&{gVKpksOUkJxOiNQI4hJL z=mZpci8=orIwNKGku)v{X0qYpRKhpeFZ~-AwRjtve%jkz=D0e*o>}H}X;3AAQA-nE zftKZmg8hZtRof+T>0z+;R-w;sf4E=wX8L^DNO^=Rx0}25`n{4M{1ej0Esx2HtRov8 z+lVc(latQn+N5NL$4XC4J!sFi&YGB562t8L0oqC5J7~#V0e%2=5K}Cj;biWjYd#-* zc4zML`P)mN8ddNh=Kv)l$I@W_K5Eo<)lT;mch<#4y=F3_(OP`E#+AEqrD`TaPEvIc zlUhL04mz4jIX^Uz8Rn@{x*`GEJ!C5c`H$2{_~&o20AR2%G(NyB^yGR% z&t1Yq6+ZX*Sxh_!hrvOGZG-X~|BY z?FHr+-B*Glvne2?NtwAOVTjEMiu-XUocqJ(=&EjQkcIB&=4j_9_VPzCg)!7j^Z(8F z542HlePNy-vfdaw61xQ{@}d46P5r%%*!xbgWH@HRHf;{^nr?vy@EJipx>e(=i!)*= zl1_YR1R+s#{xQF9)vHBO#87lo?2&s!TEevv`4n5ov8FR)nj}jCM}lPoMz^lGSM92_ zUuj6m>_R{j!dH#BLE4zMFZ^7>(`fDqnxQlP8NnUQJVh!;6rr=x?gRHcPkq++bd(4B zKR?bqMLoV1t2ITzbZ$aughj&oEDf^HpZs1J(iWm>)EVL}ayJq?3LXYz+uYsz*>k#i zrqfB$N*O7W;R&e+DXw{*#Tiipjdq&9)saq>#+wybt=8)LQ{$Cdp6s->qTfD6Q->kOoJf3aSKbSUSU?nsM%i+Sf=k<9a`_dxPwDVE|}rN2@Zar}F9Rj(ZX zybZ7icKiCmU*?N^VQjLWSkz0)lWpvzD8Hp1H2?5CZbz%<5^oKTmxpBaKM;Fxitt4} z>fe#{LS*a2A17cHc@HH?WeppUs#8+$OYOEsMQV;WLUGjdW@;e8e{B)Hr8O&i6lZIY z6xccIhX6XVHAs6Er(ugS8RH*tSb(*QyHZ!*Ft}?~E@7XGDJ$OyxE+X4lVuLOlBU|dbhkzIU0>1cH{JymQwE=kTC^sx zXm<>6KX`S_IoXb^*yGs9eYg#y(2aeb-L@AtdOxA^))`=wsVO5F-@lhFpU*4QK zZL$G`{HRJpni9X1GZ^@4Zul?B8n2;U1n*Tj3PzpDXW}q*rSoEOFT}B#`|qLcJVCN7 z>F!nR7Z^|7l*tzGDs#buS!AWkH%(rv#Vp6%fqmk|tb>de=aT%;wftYtfU@rLk)k_H z*6-h+i3Xc=IHzjo3GeF&_%*whWU;tMJOrC|Db3!@Fk_-i!i?OS(Oin!0*1N)mJDF1 zkQcp**Mer@Ww}lZ|B`eudpb2YewFONIvEv}$J5Iyukzup z8bns{qrc%`q~K!PV6rXdC2Q9QYXwT&2vr9-^8^*oIl!EEro{+HX5$_*c$nuH+ZtC_RjNH z>p&r@Gvi`_AJl~Nm$K^M2oo*q+7_WZH%WIyYW=d9*>zetnWvKzqdlj_fd}u;2{l%8 zN;=kQRqB22`(>53!ozr=$7MLx?s*x2Zq8JjL5z_{n(&vTx+|c25MOsVYL!R5f0=be zBUZJc(ZpY_SS?RkzF0~6jRwP0t;!5p2ldo4GRVtPjxvkgZ$|W|!gEfLQW+bU2eN33 zDCBKi95A!7ut1^E%*a6dTf>V+rt6uPW~=5`>!6OhR)TTv!SD67G&{N{ugi%j{^9HM z{eom(yy*rI_l)jI6Zh2#+Nj7abho&|0h5u31{Cjz!mddzlO5$_`eyG6n67E#&d!F4 zg0d>(!V&$5itT;prYfoiO!W@h$gLc-50KjKqSd`>XH4(QYvZs5{bO;$kQ~#_(oJB9 z5CqKoCTY)<1)bx-@yLpMV@_+Y$Zpwyk!xp-K+a7C2mZ{G(?Y%qs{S&VnJ87WAd=6f8w{{KUbY;XQ`5_X2YUI@dPgs?|RzY+unr zxzFt>(*;XR@DL`w{NyH)x&jfYh)lgJS5!0%?rofN^@{pmzMD{$ot92UX*|0 zR;bcXZ^_o8BCp)rX=%HQ^=oY;tj|;Fb(F_Juap(}mvjy)Hc#E!e%UC)c9W-|>&NM) z9LwOH`l435JD8zItC-Z@qZPU!6~tX3ycVqL=^sB~V6MShV^#BN&}Rmf+Pi@&psPs> ztSM`&YvRmftTaT5Sg0Xq4!DV%5u~BwD^|8|nw2SrYY(Guqj~4ujKj3C)zgjX>*@>P zK2=sgsS+e2SIP&WAl!RwnT04Hf_aw$qt3D?AxqJTGD7L|@NTjVMbWgXa?#@F{|Rgq zHI78;b2Ku^EWhul=wkAA)iPqPR?)uv4UaQh{Tk>=(p=Uy6krvp>?_B+xe25qQ5$t20dw#Oz9b=gjb(kL4E)LI@5@JcS+8E^#If=j-fGp}u{D3v zv2XU(#HyZ2+qV9?byV*?QNM`83V27pOp9XoU@Uk#+pwgI5V9ths4C`2jA1?D>#E)i zLVf7wim4uc@5r$|Mk~sJC5?09Xvm5ppXnPH9Q?Sw*yNcXQcGOWMduz-OOmgN1@!a( zrM{hZ_?y)Y?{Iz4rqMR$!8kMU@uc@DVo$!Ega7%$6`kY)e>mv*BP}2ZlA9YegS+d3 z2Kd}{0S45#xZ(j5^1o{KQxX7_`z$D4Cn0mqb{h!**}DhAKN}GDN}ue(anJyXfElpc zF|gd?-9`ieVD|y)^%5f2XZL~i))N$v**}6PKo~G{qKiJ_vZRalIuxJ)^EwHV3%=V3 z1Ayr-MFF$~%pB}K_}s2R3d|rL76Mp;fW|P{%g>J^-CTcKmeLc*>55E`WZNt0t{I6 zBnAxhS&+O=g8jRV8aUVb_Ko576AYjaoGZHf!13A?G=qM7cChS3aT@`it9qLerk@rt z<8@mOlxw&9K=leh1mu9{8U)T{?LIKPHU%n-2nl39A_=qx%)s4_f#*8-E5N_Z5jD@VjAkNifHboDTXe2wtl|a$|N?5CwQo-3_D+z;ag-Y#?%9`cFs?1r9K2 z242}CxxT$4$%ZD-IuNW>#R}cN=`gb1xCEt9(5um-U^ipO0sX}Eh8je z%m+P3G2w66v+Z6%gQ?H0t*p*O(5oRLt+Q53Q&-9&Bu=?~yGoBv%Urhz=i?S}m)1#ahQppI(gNEvDXq;q7ZphsuYcKKCKu!-zss4>>%5l> zgFadw&hu&Dlu>iVB%T2ghXhgyg`RN7Snu@s;INk>10+ueNd>$>y&GqUyeqk4w5MMz zo3bVRlDf-D)?32XvKA~wFQ>jlpO-5l)S0m0nv*4~aYE4nBi^{UHqA6jm6MY{UQrY7 zz)2V3+J1$59wtKRzpSzw+yH<~L#sI3tD62$3!^l`I=*T@-Thbe)D;@8YSTBxh05^M zYl*zMk*jkA;loCbn^! zx=bcPCzyEE3a&pwl&SK4yN&0(rw6g`bbmq@&b&S{5f2tNS9mR@7L`SIOIkH7c7Oj{ z48s(thAi*;^X#UL8cehF{M^6c19c@46uWTNIOgWuvnQuD&1p;7h|9$UvwRf-oSFGg za=lv;$J-j7*UKky*lRCK|CqI35`OVu0XAE|@^5M8lQO+lBc}XC^-^WHe#%);KAB8D zq_B#@)n>Sr4)3Uq7kDWmHi=8t-5><>qMc$M|H8;X+L4V`X>*66=MMII;$Jj9z99Px z>q&(RV|$eeTR?^^unPEczWoA{u*<8Xw6uCEx_x02h&}EpC;vm1J}9WEgWyO`?nX`w zcmB!?asnR0`s-BaAUw$#DX8ika%DcL$I3<}r?Z!fx4E}@T5Z%7C}j@c-Qk7;hfY@Y zRf$6 z2_VUPjl2gf1F6lJ`nDXMPnmXXk#OIk@O{b#am!uVzgm5KAW$u!90->LDrhTdD~H$i ziz=laVvq5|;KSe{;Cak#gc=WBlLA<=`iq!*k$+%+34984B>YZb`=tgWK;cuA##WC9 zFLJzI^)3n(NSE}Upij5~Z~Z}_w4y>23Ozz8z118YK+E=@l-^bM*KlCQA- z_Lk}8eR0$kncdO7F0Y$zIfBm)f=O=-2}v#Kp77PLf{_efiJn0+3ewwSj)vJIrvwYF zcMuuGhDWv3@6h5f4)jjiQKi%z(=)47-@bXbRNu*Y`FAs$46-}PB;z}(q zzqgWmIbD7kLZdVJ)Ne|emxf2~R060Tc0axGE#ry+a?e#DNu6zW~b13>`$ z-WPQUoyAYVEsw3f{EKSoVw`iAeaLiw zcg;s?&Ot2B0GvC`HPfcWYGoNS2KJ4{=W^Rto2b)J5t9|#O=b_1PrfDjCaC8k$GOVi zAklH=Q7aRjaNYQ$RiyiJD^u|=drDCzo3goN(II?AA-d)A5kJiM4sp!w+{2dW6EXcnjUDBa6@Og)$0*n8 z*E-GCcrQ>lZ>H^y-09cSh&wHGoGV;%{-C;AAQYX|bZIp!+v(~QX~Uvec7v;6o*OO( zhjcp2$+EblvAzKkj1ydybgxfFkA#0=Bn_Vri$`^0x-()oADS#q=yo`tjf;Cq!CE3H zcPw@{5i3lQaXUaKeRjbR3C^Uw80H|(YW9`;`>l?rz3Le| z{KA`(4=tW1rC{$~uUU(LS}q zfbuVql`zQT=cp!@*(J71EgO|b`>N5>Mx8p}hNX19`ukAEp%xL+n1b2#V&-W_mVl@exhFwB^c@L;0zsP;`H3q!^SAG5R-16h9+h^ssv>TWBj_A{d z^1Dp?3R#lY4k$vGe z^Alh9^^!{7CgT?Z*MgR^yZwbe;P#+{;Wp4Fj%|zY#sHm=bu}_gODsaFcmF6z!D;jD z<;&2Mc2k6$TcNv&NI`Cf?vg=EU`^`HG~4@^6*TWw z9)7oS{?nYuRMSyo=@?rKxBvRs<0qQgC_6oUo&~+vv~l9tFWJZJ;cJ#OjM)?^Ux@q( zF#d#k)Xcy?Q$$Sy+Ow#5*7FORKW}uLtRF0mBb19M6E)Iqqvz&@zy=W~1$-45e_qg3 z(~8`8`MTC}^Ocys(|=1Y>K1w=8qj@58;JizIT{~t?TdfAlSNS79>%rV7`4m$rg$Vc zO8sO}#pf9N4dziYMs6L3uTC8$c}xqdJAt=hB#PC94>@N^(OENyPQiDne1h)fosbrY z>9L;wEvUhEb(J-swALfnw&$Wn7nD<$@Rzs zZ~&#ZC&L!6u%;+K$kHc_`)lO&A-&P9TR35ZOng4ST z-XFj3!UOb&eKrU{NR)^b3xpRh$AQ>hxH2YpQL)b z!8{Ks#rK00p(a4zQ@jbu2ihfLoLuU^(C6(>=s{=+tQ~;pj~Kw(r-f1ogQ}x?wXajr zi&R{J`bI01_L{0KZm&VP#}g8*q%gQd-BLCY0F#GOhB8x83A`!+zfop{`=k!kqVyAJ zT7d}C3(`ZBF#v`_FAK&Ik3~#K1;hbrp9f(HL;z$+YJ_=h6w*zhd1@GQyv{)r#?&B0vBY#*`TpCkJ>Z!%Zh;tzdtc}P}<@5Yx5~#y~gt>F};>WW&ky^0L+et zHp*d**?aiYDE}TDrU#)?_(|)$E9f54E*Lk-R|Td<2I6Ce3D#vS786Qgn-0E@vuGbg z`WfS6dJMnt*CiQRxG#Ckqw2$tL*n`*J~#lX2iPmdE!8d7E!V9>AHr_BN6;rS7eY3W zJctA64UiwmHn==+X~2s=#%|TB8lTJ+9Whw!aWFWrY>`=d_d(t9*V91p}> z&>K*CA=+EuTVh8DE?5A`wxT`=1E?P`PXKLSX`ev=!!C^@{43lm9uTG(A(8R4MEDI9 z_dfidydiNsEFJO;G_8{!c-8R3hyT;Q&HzNc$|xj^znn)4wg%^}xbMHD0M?EMQ8u78 zh(K{fKlDJpNIfwZ47$CbpOE*R0XHB&&;Z2uT#2{1ct4Cc%!D8Cdk3J~1Rz4_|0)P0 zeFm_B1WC^T>^&NAb1p+MzitZ%b1p(xK5sJ#x6eaMJNBpryY|C4KkMG%HNPOL zd_mQFfh%|X)p(7T0pcpPR{Sq4U46=TOyBDNS;GhCaCv> zNx#bb|4n*S^?zfR?!Cf%vd;7$wChK->i*IDU({+bX=vBCYSp!_{m1ClLi(`_|KS+& z!`<(Nzw^WRFYxdD@IP{~|8chyneHGuX&^b-YK+)q_|y15=~J;8qGda0mYB55o_8~T z(hupjX%T;9jf}okCdrWVPO&k=J5#);G+&9()+~@I{%iik=K9!S{HF zVuS^tyagrN(|72uqQ;s~4t%()9rKv_4Mg87d+~j_| z=F^93O7lZ88{l&7$wFu$&id>CI~~dVN!g}9Fm}!|{vDWv9hXWuM*>4Rfz{Di*qvl* zM5q(xvf@J)XD~BuxLVv#hdhb$e<+ZAP7egKSCmb8bF5)x3$Vuo#6xaJ}^U)csN-QWq(y7_;k1;P!<33zNQtE3?U3A*ii^`Q0_iF zLk34kCd4+>bi_^YO?WyW43PFd5<})XFin_CWZpJHAO&FWfYJb;KGwcCe?rh15JBJ^ zP+yo!$Q($0Abl`jh)+B&pidAks819R=vT&Fvt9H%R?VUyZxy}?d=LasN&i-Vie%0x z-)pK{$X%>k$z85#R7(G(zK!%&8|3zjVU_XLp_ybkAy!AUS5QZ|S5ikju7IswvfGwZ zjgTmOnkWx_bZ9Z)Ie+wU7>JS( zn<2O{5H1r67Px;e#3%c1EwJAd77;=?*%6V{Ygk^!TJb47G2yA)RtxDe}i$B!oH<&ZlIU`@NeeB74m@_uq^`cSr z){^1A^ndeX(0H5OhT`K?h_pR~pv!>RiGXl~U{8Vg4Z#M6qI9{CfTMxvgvgM<#X!}G zAnJ$*jE8AA|1)mj{~k5a--X`O5$z-}Ss)6Ku|6^)a4GP4|1lvRCh&BaO$1p`7Jpeo z9wyLqXj9-ue_KP2c+lA=+y8rX97d$I{m&WIy`M+t%WK;O&(1;bbWsvpTB=MtT6`2y zVC1OUzx>S0Tf?|zos}E=T2tJxQo#K(xKP?P=!eTBv&wWL35us??Nnwf=EV|uY>OrN z#8!oJNhPif<}3@+zH)Y&Z#gH?34>m4gx=40Tyb9q!<)VjA3g#%FDDOgz7|r-0DWJB zz8xb9bE6#Hni2RmWX?VF&A_);1p8sTR|dd&`fmlS+(-V+s1HZKH-qL8V?O_Thc(7w zQ4g#*Lu`U!#5*kQTdvdtXub&aIvjcJkbh#keE);Dw~mTq>(l*D1W3>Xw}t}*cMA>) z?gVYzB{c312?V#`4grEg13?;V+@+y$cbCT9F6X@OJHIn?XU&{D_paYsPd)vqXBYiP zQ(e1j?{8HF7968zc10hV2nJ`RY}j1!>37Px6O|jjm_25Aze=`mS@MA zS6+)b$aXzk^W^u#+%*u56nAwR{e)1U*{b?~jzV}rC7Iov?)W0@(Z{5d%UQ=br4oz} zNFrTmn!#Dw7$QC4?yu8wEY$(iqzY-?hH3&Ho?I>`6uh{>EB1pS`S}Rcj-p0|>_7yo ztDj8oPqGM*svz4CYLS_KoZPNMc_<(CW_+@0zVq(RcR8UK$N8OB{dg+F0uNb&mpJ9+ zf$plS3Zb0Tieu&9J-gV;J#BJ(T3TtG4LSL9EsI#DE?%>4;OH0kIO%lM$!JO6t5^$9 z9nZl$ z|J?d?4dyf6Hz+HH^3fnG%(iS^^k5U@sMZ)>)Ya0r7LmMGomx($i=k@{PrvD$@;9OG zS)uNzi-!*=^02Xa5g}apRnegoL{=o$s@O&!Q}ol=JHp@#npplO=OPbd#FV#|b&}@+ zwkJMXDDX&D^d42@Cn8G=DaHJ z&1Q;C?s9v4V}s z8KTRljy$}A5X10{W}6}<)dMK7vMMZ$FsFL%!2 zp~E8<@}(sOihnHLEVkjkICA{+&;LlSxzLm(Trp{YYLG|5$b6 zr|~e{|EP8C*59J~ka2Pt?^kdq&;_TDQgm<*%T*=KSlz~zD&T#(I@MbCan6GWJ0tcg zogu?=a_IdQ3(p$3HKC5d8Q5HZ)lr&eVLtyxAAGAJJ>^4kYA+6XAOU_$IYH` zu$#ZC5@ub>NwW99p>8QB!QNmOzf&db-_T+A>CgfjOjEnQC?WMK?eRKyFDE<9(*Z2( zGAuaRY)>>oJt4rui`@nN${yqBF0ybTd@rU8&Hc)0lmAJOWHC8dkuf_*H-9rZ$Y4<| z#IGmGtp8Xu)l<*j9m#GR!FQ1qb^pa=c!Iu$LrA7zy#L~zi?f@@h12HQlOjK(0p4}K@$#T7}mMZGhCF3btwi0DwUurz86=q`a z>p{%ihh7^orLMQ!=EMOiSslu@QW=Ns6z7Q*Wac*)E>1$b;Lk#-GyT~1%LTBdRsg)j zJ*$S#Lbx3dkG7poiy3VX#d%q#QvUQlu#FG8K5A;C&I! zm61#k=GgZRffd;KVzq_t7{loxEqQOo%4{Zrq&>0okNwcZ_bjTjY$dQ$v}Xb5279Rk zT8Aaqj(lxXD3@#|qh`dRQYeX${{!EpQ0hg#F)?QASKe1BCj5Wt%(BHhurcJgnBW!v zgb5#B>mmV^tyQJtx8AsZL8nJsSA-AG{X$#XudjH8zlLu(yk_YF+W*mO>3(HAR@V(I zIp+2TEVc5mqd398S=lqEI_OQmQ7=l*P$T_e%u>nQl%2R4yi^$H1GlJu<3!=BL+zsD zfU1%1Plc)$g|neIEAq`BFW)ebUegFwBl!tG+$Z0#pPTIVj7JxdtBU0N%KwevN~COA zDQr#kii@Q+@Cscxe0arptL|meDq|gbl>^_?m->nU+&*zd+>ANLOnR5RIS}bPu@f#|Ma(^2lg z9F5{%n2^%>*%Id==v<_V1Y{SKccWC?A{tD_0l5f5m!3ia$p!Y^DCNH!@#l^c<-zD& zB#Ss@Gn98DR4lkWqx;xwIU>^98_Tw8LIunmfO)>+hY!X~$2S2+x;>G5bq)X?@LIRa zd|edDl*1aoZTjR|HCe$qZ&{C}km8<$cJ!F%--)D>;GSP5Ur@rr>jYak8h+13dooq{ zBNm|IQ^Jx7u`kx;s_=9hZU2(>UC)GYYxFZ;^dpm}6Y)F3<(}U}kgwSPUi6_&5a|?m zP?b&TpHMN6LA3B4{@>fR-*ymJ@F=OQ6Wvhu-v;31RgT^cYgkv-sD1FI7e=ew?o z<8U6iC2O+>=JnBgntn=wJZjeptRPaoD(9h5Zn-HYy{ejx8j81`+p}U*WDOT1HNjvZ z=Ywo3EIqHk7mceaE8tE1d)vv(^GZZ$HCX%wa=oGud<|RMnSU4R!@A8DfXuRu5ijGuOeT)&1W%CnJ#{wp0W}%x9N3sADa5@y6mVl# zpF!~Jd}CK*0CF>cFJl0H*m_6MeC&6u}Nx>IEY4ZfY4jYOo zdpAOm<~Nk%WWWF|t=d9gE>B@YLa~q9LGJEhVM9hSQL$~_?kjbOiVGt*+W4RBN9Z#p7zPu#M;oG0=82rRK!n1a->_jX{kSxr`A8Y zY@AW0TpEgfE*sCNQYv1F-6b2(pj<3o^v4~k`c)Z}iUj`(v;5iPin8Z_Y=E678{aS0 zL#+`s6UuGGoi|z1=9f33s@6y2`pvGeiUg;=Lf33qvD2umzgartoI1`(hXXH>X0OAI zF+o@;JynpVLGT)EpH}>Mx_;Xs^66lU;c*NE=Dv zg0rE9ZpSKrKapoT#R2+)vKaLk!9lwI>tXjEqQ%Ow^I9)pQpDmBEMw7Su(Pq&1L${# ziKl+{bWTXDE|XjQSsJgam~Lypb5=2)Vl=EcYloQyB zu_e_-OP@=sw-%!IIxzKAQbHt$uB@H?HHp{fj13^8E{|I1B5grObN$0dFtuk>LH?%& z86pRFJ2xmozPz~Uv;cLFDc=}_UBH5w#ZY9zihAaySM6LC;Pr$$+%DLIJ;OB%YXLR~ z7;>IKifUG7&4aEH0kgJtPn(>`sV`KF%Q>wTtj}heI$ZP%q#<);)@UW^4w0y{vArch z+VWUaG-X9HR-n<;R6*hSSixt9tH&~ASrMxH<*@ZzsRa?%&YbISpM|rxM#mSF7VbS+ z6jtuf4Z`!M`~a>XwPfHU^W|0`QoQDeP^23cg#+mLqTB)W91ZH5wT0+;LB`q^uz301 zNofCqoccA>Um#cT&}d#(pg>s@R@#VD|gli=wvyE z%pH`+e0<*^Q*%dmOmZ3g-7U%pf`qH*h9!%LHssQ^qH#%?Cc+WO^|DB^P+i3szGw6$ z&{t~OdB43YBmF}VQmi&-da1f%iN{B)1>CtIalZfHs9h)G@f&96$7C{?Y8gS%WVqU% z#N_xyA65IW^%#8t)E;raEJ4_TfP;742Wo>KvE@pc+sBO#D#=AT7Bow154ZNRS5{RH zQANK(tr+WTW33p~Z!L!UYWk`GrysrP?s%_hZABuSMCDF&A%0=e-;f$sbJnx!{q*aU zEp$Pd2ri`okrW@jlbr4C^&~a{YZgB#eGvicq88Gp|M+ff5&t?qfI~fDP@URIy>I>| zt;v_OIeg9m1rdf>))L(2qDCBZ+eNvKdcf>?s_X-*Ycn&7?fDi@Nir)$S|qW zGP`4=`tbDs1uH=Tl5?_OHf+dP%|z<;H%q$JS>2q&9uTG7=H}EeH!1)^y|AF z*SJUC@|kcVIYt|{5k=w8*yFbTn6w7rcO~(JUdY|`pU%Ozngm3XU>TO@)^I4n&LY~b zn};IC(~;+fYuv~OzkWoo9CL5N$cGG6(HtT~*XQ-p1o8O3Nxy}B4e^Kx0_zW@pgIwc z>jgAeNe4}l6wfPO=st}x9=nI_D5G&teN<}_AJ&2?oA0P}_sofqy*5^5D_&SB*w#qUO z(0D&jkhpV~Kr9>dkN)E=_d+!YkD&y-3(W#6(pzIr-b;H)I}E3R^=uJ+`M zHfD&ogdVBJEd!s19W(9~GN7_k;K>@B$vMrQhq$PPGDgU5carl8XM=q>`1TvDL7Y}7 z-vlwvE;7k3;L?}TV4BO~{_&hO;|fr)rT%!D@K|skS;2Q>usPuv!vrz5kruRx)W>a(u<4T3+cUT?%-LvX9O%`~q-lg-`es94Szqsg8KY$C=>gl8(Oxp2tNd%U+TLrn z%`VPTad~*#xLX^SSLph&Ol1v}8ItV!APOHb5uJJ~5~}x4>gr!y5iVbfMiJEaN6A>D z*z%dSvC_;&01Hp?K>RjBJ5`xyMRV2Mc}ivZv>N4jyN-bky4m<+ARCDGT-l^+Nm=!* zY)Q$&F38QyMW9XbDf6S?L2(=~!t37U2Zn&o7ZMS(r^de!`; zK(s9Op+@=B6I{QPr=E5}bb=YQDn;WaVkV%l%hKPh(%R{84XJL6XT=c$U& zeASYjaS(q^s$zMHEHq!Gyl5Q6P?IVN&4(k8ZMz_xQqpBW4`V4j{CGT6<7<(TLsif2?fZu_(Ii-ktONLZb}I*QWNa{zSWpgR%xF z5OTSDp}(+LJm=-&RX+gPK4H;Y%o}KQ_DC9T(-K%a$-Eh4Bg@DeFa}H%=Hl-ZO7QRE z2}8D1eZ2KxQyboTU>y!`<|7w8CE&4hLR5&$$H8!X{p#&6CyMnFT|LF#F$@Mj`w5P7 zBocaxo0?ShpH_-Cea^Hc3e<}|$jda~#UD!iix;KJ{bd)WvNq1N6rYT~aMS0hH8OGR zGoOz}(W2%#i%R|NdXsJxYmkomzCMxQ0laYfGAMXrvv&Jc3ZBqzf>z7mjag#iM9Jm{ zN%QjleRX((NCuRl0Vn~)T`0+62rHz^@qK$9UTDB20mqdXV@>siH!+0e(B0&k=vr2v z)SC`YTo}!>9J^igDVtrYIM%QL8Ot?t!5ZKc79fdB%}FtrY`8KIkk?hn7~SAl&Uo42 z$jU6K=QBPbr3amw@X~`0{7Dwy04o$Jc8TZaK$d#rS*F|U(8h_*1yKHdYv%%C9x3V-mT7cNUU8QnWiK5iG;JIZJOFACGosW9~VK;$(tZSobC=;xM(Gx4%SS_V(tB z(Ey(EzGS9u=MR!7rvJ3fCGQiVLH5I=d2-=r@`ms-7vnTy@I_3v06`U7d_9p+mVGxc-(^ER%D7Hbvt zyw;cq*IGbAg9p?x-&CSa#W}~R^tfNCPGDWv3Q)PlthZ0`nL|99!V|r|dp0zy(t7jc zjZe@vN9P8`EV_f6G`dw+g(SLFXGPGM*rQ||m5?y1-^e;|PuB8rsIA}fl@!BL%6hKM zFII`*P`l5@8FMW82OBWFu^-!h%;1j>7-1%#NCS)soewCc$Q%z&Tp*1I*Qo`B=bWBh zqZLMj;x+MHE>8OW>zVQdkG;9cFDDlFHDI;E!MoXhrQLZRWy?86fjPV6Xq+nL?lSPr zw-Vu%Vx_xAr%FMTXeV6{ zq2A8w;$|;F{p5Cz)U#l(_3KJ`rH4WcO5Ub_I$aIZreDWuPV1SqioX3RCjva#(16`D9|MGw`O zu&A4F+rTU?&%4pCxBGGDH@nJ)e!A+$;u0KN!@zaquP(ZKf!;0drs|qBpA!Gbt+`y{?T0J8gosL>X zxm}=IHe(UEBq`&Sr;uPb1w$3cSreSqxt=_6=R~|r$CoT!qnbQ^D;1&D5xid*hO@+h zsTCYt+CeqB5)*1i6wI*1QJd=3@|f??IV)g%0PvXOiKLobc-xqxyodOn0WWm1@8st- zJ|GFrpSIk`=@WCs&+F%@vj{3JN%W&yk--$!x}L1<*8drw&a$b>u!Myu_BL=xbn_Fw zkvl!yF6`%XRfjo%+;i`sCDzwlS08&2Kii#&GVm_c&)nOfqRt^+c_KIYmEW6sVV817 z1rcZ*EKLV#ZS8(XLxw8{SJ&f9FVNY4L*3ymjqk+>y;vuVkDlK#KMq2}6{KEfx>xPch_gb)5<3 zUCi|09jt{#krjDQT`HGn0k4@`xZ@2>Fv+bjll(IIO;|Om2^honJiNd;LO^(C$>(A9 z>K=w!6TGg|rh9exB1lbscy0^#z$xs4Pr@tRSdBTAyxvjwI;e7g*#ms{R96kMfgkHH z$Up$b^DNy5QA~ch4!O2hKPTrJMg4;XIvX;c=+A(U z81Z8TlX&xUGR~i+sb*lz&DO`;2er zN|JNm6vCwwOf;fq!iWp_Pc1dp#~hG_e;Q=67i4xh zA<92m_0Aqf_2!AO033HJS^zOp!GiqjF$rQCm;lG^?_yFLZoC5`HiA^z*m~C3e~iBm z9ho}o)zRMIH%EHZku|oj!ENt|siJ1c@g>)uDmBBF0t4d|QT5^!yS%Gs2@4Hs#9_A#FHyl7dU|+x``Uy-XHt9nF3O1ivuHQtH-aUwK-v<&fSf7g=$`iW zRPpU%nf4ofP9pm0mdPh+wpf)easP9&pmc|O@{HKZbExeq?nq@Q_}J`{)x|4!j&@!+ z6q;=n=A^*K+k|`X4p2g) z_6As^-c8)eTQWJEMmNC9LC;;5TO=TCU)>BIe(K=K(LMZcAZ(BOg&>$n#Uz;?F$elp( zB|ydb6F?~s=KOS0>olJk-O`hEWX84HU!lEGs=-&H4g)1P1^3reQ7^@NtBofn%}xAmcsgP%V;Z~GyYj3*ko;7#8{37Sms0AkRBEOqNI^{1%^9IB-}ZnASWv zA#|W)D3sCOtZpXrpm?32!|h-WEbBXSK$>N`sa+tDYuPuIv(v}otYhYtlN;CA-mq>P z?FYz+mj^x+cO3UE)d9lt)rUf(z^Q-kSMZ3vBWCYE=W7e^0A<&kUEZh04}Rx|pNlS# zihaI<3=Aik%I*{&J{naLar&Kna{hk(YusB4)I6AVC+Y0W@VX{}{}sxbdphZ6!Q$El zSNhuwJ57);6SqiWD*3=*v>AO(d;=zEr)=r`5H;X&>hK`R zkKnQW$X`*XbPRv58p-Y+02aB!0G})^dbXanJl^UQ?BydRw6t+AUu6(}OC94YafUHu zochB&vORhED;mD!teKRThybd8+_^P8wA@EM%soy{&G}9>-+7(YaCWR}drZL4c%~MA z^HD9a1Dz|BH5X0r)ZFA>*fO<>&cC>xTzslD62UiOCu_wP3^_ERCu_$#V%t`2M2}t# zc1LH1M>N<;1pgmTZKYkE?~hi=8+O=!PY;`C0xHr;>8;rg6N;A_O6vFZcCjzS+_{yM3uqoQ+) zlJ;Nb^ER^7d!~*tyg9iZ8*$DX?3*n;{~~Rx)XCKRntaPL%m0AdZex=R)h;|X3-?Qd z8L!iEyY4Sa8a*34Jw09VHKUMpZJR`M7_VWgw*v<8T1_}<7%`lel#z{Lt+JJ6*^#Sapt9oJx6xHx@F?tX>weffGc$9yp`l^- zT1biYOzo{(Nl2r5=K{m3EuI4;tWHN_zRcf4psgt*q=n*`=iNh4=hF8p5^O)QRXgcB zjL^S^?UQRpd&d>$?#g9Wo!S+cr6^ee#1+r1U#7L1zwu|j@koZEo3jSY3>aQ;JfQ|T zQc1M`gjCyZuHm`z=Nt4?;eh<%A3L1?Kj36a&d4s(!zJIyQ;(>F3PfL?4x1ejsMT7FK4Gz#X6p%d@`2jA1fcvkWme z6R-OEB%0Lo3GRyz_9>awc4}4STuN>`A59z6dnW^W@r9^&v^=1`vM`#kAv~GuR5E6Q zovjc@`kZv7_!64_YsWzFyU~QrOg%NzOsD$Hvtfw{x+Kc}ygxS44f{_Km0B+{7Az?P z%>7xSJUT(Q1B!R%mTe&Z_c81pfIqHHY}tqnNggTsi&UFQ14>NQA8IZkT~d!aWS|YZ z5m(Nl+r^Ra$thIAJrB(hRv!OL=xiPWLx-nO@NGS$+TU?u<*$v5_nT0BxWBV(IbbYYHoxO1Mn+$t^7Op53t|;nO zOqYkL1DRI36#k#6j7d!wj2$obx<9)!P)g5zJWy(3@8fI2Qae$F`D&m-YxdO)x-4a6 ztaM{E>XMHJZo}|bf@!~$VV-N<(g9^6%OtDN!=XAj4jqrgWtfGl}e+*%Lb&RB57|-!1Dl@JwtXIc46bzqn8G5CVT-t%(=(3gRD9G*Jt}=@@NrXUN9ph6hQi@YVO8rZ~k|HmR z!sqr-|2<`e;oQ_rDei>q)c#L$xu4|Ll;z9{^OOsz$;-3a_AHKWh?;zn{~mtQvs42T zPb5gXL9pF+(Q@v5YvNF?7f#OnLF7@k<(&cb4Gb^X0oiU$ zh0k|9NiLE=0Vhv&Tz{CzNA@RKT==*zEbb;V zXaC`!e~pFx`|Fcu4x=E{)Ms^_{&Gxzu?~L$rn-M;rQqcc_W9rn&#xlSCu_TAYl8yb zF5}xX627*5k=uH(jCllPBaV2sb|z{inEV?81?vk+n>d>cYc`WtZW*q4zORbBGNY%xz?>{++HT+A-NJ^%Z8nD^?7Lr+9(oSa3ou3DP z>1cbq?N4>xqywzOX)|qh%0%GoI|;LFtvUW-!g8}t%N|FpM;vriP|`u<^5-{*QMXIL z#S+q^(WB6J1kg`mPYVYknR0_WGwK-tq95~aKNnd7hY#2O4p~WQ}d@MexXpc zD%Lp@6rwb?k=5<~4p_|+yK@Th!#p0Qc;M?43BKBT^GN#tJY@4EOFmD8t!h~vm2$gJ z5(`>kWY!>)-@Ft)d+lw3zm(GDW`2;;5F2vwF2=e{ui)v%zvsxOB5C>^ZY-3<%#&J_ z({b)~DuTN7WMEt@U_fw5TZhC0eWai4TGpt0{+nUk)f7=d)esBRV|fa)B3yE{FeUn~ zxcF5H*+05B3QzyfAy|cNDC31<&KdwvCNi`0(h(CnO(>O2E2vh zhDZD{XnX0+JxPwA*nbh0aBoi#pMgRoBQr-*B!YuJj}SXsge;=N)3}eHXGoX`f9>{u zu8<<3Y96rC!144&gD3Pohf>UtR{wVJ!HX^SjA+w5cOK83CudR+(Ut-r40 z5+S?aEf(_&(**P+TTtR)?TDGkzJ>ov9S;ae%o86#%|&rot8PN2u2xJpM9@omgzt!* zdA(9Ut2@5#+bkN5p$U7iHO>^7(qWCEju^5U%r=n-`vpB$X)b$rNm{+^tv3LXZN|u% z_lCyV$#s2g&%PkE|N5LP73~-fjj9-5A$mZ)5!IH8-=Xtav3S zA^J0(FC=XWhIDmA=r20jUfGA!bq^4%&4eHCce$S#3wp9=HW5DRMO?CU+l>*7O*wKc zSa*Y>9^_#rctcaUD8n=NEJYkkw-z>PV$+*@K})dEXe5^3~LIoO`M_fU|3r!mLaDky70COzdR;7^uv`O#au~TUd2DwCCugo# zNoTT#(XN}YX`KMvSa7s;Ht@Q*`OP~Grs81sU2E`=%6*gNfe+N58~9~lW{8yDJPKD} z{DA8>=7#RnFe-KO5rQ)uy@_{hINtr2!yl-BWPxxj=dMa~?HoKcq@o+(X}0NB9}&B6 z^t7JAx%J!9L(OLeZ$zSFifG)P<*F)#K9|Lf6HpZ4VdK!*v641$6JG<#<_+Dg6SF4? zRJ!gZ4`-|!CReCbTaWJzPJzIRXOGpBJ4l;J-Z@r@)JaOR%=cHTuN~_B0954`QS+@g z1_R!jJy(tO7PCNAWZO0L;#U3)yg=jMh3X0KkaX>Q+kQkn{M?aCokya%WYFefi89$U z6n9!msBj<;$&Jz>g8GJtPP7CgrQ z&E#B|anJV@fPxDW0=vB+Km91~(RK{#+!D^R^L>{+Z{8>GsmS!Hp9!77BW*eP8{+`{4)8y?<`4?jn z5Y1*@>I?cTZg1P)(j<5;m$&V*48QYsL9um_z{tvvP4nDgoAOLN7RH;}>M2BTQya1J z&Tjj3!R@+W(HlT))$|#2!vmOf{3w1tn`h5m{KnKG(87@zc` zzcvbY>30|1B2U@F{CuH?(a@cYsPa9)*(*NAK94$jf$&@+6^?NYtN#2A7I#X9#^9MB z^f(0l@fb&j9^Pa>!^Kq{n-v((>qft4PV{aY1Wt|Z+Csx)<><7eO3v%x-^r$U3n@V} zGFYz4W7wda7K|*1JmeJ<604%TL{E@q$c^=^Et8(yj;Ab7ax>2b1&#J6$2UHO@pD8~ z0B?lp-KV~K&f#96(j8=IP^#-_l57uN;JAj2jf-MB-4ZWldP|6a%u|coXn|Kw;mjwQ zNI0R|0J3ou$CkmtyBQH_w74}bCkfXS-AEv{t)m3coIdxqW-lGTp15vl6BU#XrW~ECT>5$sqj4jg zpwf+NOt7q(T;KkzU4*Bw1B}S!Rzy?L_SeV>dC2S463dV{i}w5|&2HF)rkFb{`5Q;0fugF^MU9v+kM%x?a5k&l}|rA}8BY{Sh`&%{=-~>z_W5pX8Jn zOR_#a(e!{38Vzf#?5u@C74OIS+KPR$pyfko8eRf1ca=^7DjAx2w<+YLH4;@>R#BgH zoK$>Q1+$%hPrZXU1!`-HTb!K^5`a79odABL>FgHqca^6>@7;cw?-3`q1}+$qqG$-{ zB0$M#B{eaPB>1huEio7v=M~z`I98g^d0Yb`Ni`4bX&2cDG_2O%5#zVYw>ZQ;wG&%a zth|u?$xRh&Djus?5(FWN*;L#MV(^?uQFb82o1>>R5ICu!ReJiEy)$~JQoQwgrxLtT zIILEAYjDZ-aEb22MxN*HqJ65DC=6TOZWaQSkKDy7*H0*s+ME*Kfdwj*df@GUslGYGZkqZAC+JI~`Wv2wuKkWrM4x zQ)3crg^9%6SUAtIuc|mec-7|_Gx34pj_gTxrykJ+hanrr{=Lh5WH=KVvUeRIlbW{! zWt1gpnnoGs8H&3^lQYH{6FvM&*1uRPSl;NAqLqC$F5&KNkhO*&>%?`j>=`XeOsXv& zluCI(AP=@eHZB#LI^m^?7e=m?F5eawghy}4Z|QF7_ULXQ7Y>u~i^Ki6Qj-JKebv&n z{iQjfvbBS;gR!!>efJOrw&6(^*A3suhlD`Myvpd(C*wXjLPqi?3s4>UJ%nQ6nfzW>c2b)4!z6 zed6xXRHK|pr&RsEFK%6C(%hp#umg2t<`<+!;UeZmX@=wXrr7-QIG$;CK6%V49LH~@ zMktOs>87+BOnd{1eFW=huFc+B&DK0IW{zJM)bck_Z-3LG7lB~KyQs_s3$W7;3(wNq zWByWdjdF>qx#gvXeQqpwDmcyYsW}bfoXT8n+G6@e?v}`JwNIN~6IDB4>^lfa>h#w% zWR2YDNu9;344X!|IGOIBE^vKc%TU`7j!^F^-dC@zsdTy6o!+V(a#gpMvkuq8DT%a! z@N~L%yUwPWoL71ZL>xGnT;K!iJzSw_hnsRc?_JX5dTciEWrh!y$tYA2tfyIp9SzXAT$>Wn6*uybx2#&L&Fjq!!HuW$QyT{e9fXc!MB|7aQ%?gPf`e~SZ^eB5 z1tJ&`?3i;~c^jI(uF<%+A!fUcNQ|b-w!U`DQ}eox*ez}tfQ&2eYSzmG%A=CV3zv$> zPQ+Y_ZvyVb&sCu7AeUNx9kB9Nu}B}oQ&GzAQ^n6fKjsTrRFnFKc2Qk&(I-A}i-KHA zhyb~%*2gWUv@B3 zL4iruI#lRw;SY6dBm2+xj{CVk-0Uq&S?Vb3y4BlUK8B{D2fgHJxNaLUESzH^#GhZm ze`(_HwUA?|%LY5ZmVZTN--wJ8V2NmJTWedhy)-mGin!fdo>@k^gtQH`SzrD%RAlS9 z7inuU%=7{sX&=?jab77^j0-Wki?}Zx;4oov*e)%1EaN~7jR466OdL>GsR<_o$hgyeru3;@sq7R06(Fg7WBjVSY z`*h}u`eOP7=A~jyVlV5WX?ti7-5wLY+4$hh3c~T;z4ua%vW{T_jMvhR4Y$^gk|*?+ zfr0|8!^{I#sZ*mqjO7Z8&k%kmwOa>{1g`~rN#07l>pwNXLkV+TweZ-9KBvtgfyr)D zFL^fUFO^svgU5JI4xal|`bxI+>gVxk7nRKTCJyLaMvlVaAi&APiDny*qs?=OpPf?A z7eBt&6DvK-V$>_(QqQv2nnk3x@2g{gHn6u=@%?*=oRtgPCm{7 z<#yA}LHc=CXYH)oQ`}3R>$@YgBVimj1Yz$ZrrVT|pcy^gR%k-;wiinCx zhAIi_Jn8STy-HeYnCj1vwadr$#JNBcIdQzrm6xPi;3Q5R;n0hVv5Q2 zaWrc9uJu|h>9}$dnq6dG-{3_|?|8|UKi>$75x#TWcpM?9YM8WUY~C>3MVY8T^1d;d z8%oH?y7fM$jrZxaUJ8RfTKEFap*H0>BmNyqTdyv#hkayP^I}%oRAlRtETC+jJ-d-JGI@{=MS`0AUM3^{}n9ei|J3Pi3^ho^J02m{3k zuFh|B9$hFi-+oP|*2hN)opHZ3UR!vSVrp$9rx$K*yzI==$$?BP?XrS^oUHEvmb&=nXEMZ4=1ARGah{&GJ+A&i_4w}B(`%OagG_1YU0mTGtt8j9 z$^=gf`891N$|Kie?5;2Oj3X6+8B$F6uh^&Mgp$B)LyDyzL|ji-qPm__D)tm)Y|5~j zpI-Sqclnp=?^$GT544Z~7+A&9SHJ^X{d0dtd(+&Ccvm zOC5(w9aGfH!|IYd=1+#^Pf~QyWc;L>Sh2?&B7O~c(5BchN@Vti$xco)nCp8fGmB~r z;V%L@H7fO-aRuDnum!rv;96X4tZB&}Gn0dImYZgVn`W&|r0-4+7*jI7rer9jWN5+L zACmcIBlxuGwP#C`i);qvZEVaza-6DZX(`&D%|VS{@2>A-Ze8P*h48bVLmL4 zpQ+adm!ES6=x_!M^?|dViIGaqjhc4Lzy;^IcD)5^U~dji5q`aqkya zOl`!CDJmV~Y@@*?E9>NK#d4|Y7L~h_aTXE8a*b}ko~xF&-bxb{bSs0Jh?O#LC&X1~ zie%1Af2GQ!GOAv|`*Gp@-tj8YMLp74+2)^y<+ zIc~JT{X}syp!ZPiAB#UBc13~X_2TTb6C7REYK-H-;}K&k0=D(jWEMr~BNGf~Ig zuLO*7R>Z9-OG6aIe@jC*5twh0SeHtte3$-9_hl$vXoNJ4u(b8t>$fehh>pWQBej%b z5BX2Dft25rzMc#*{e-6$ivQ8&(-6F-O&iXkNl=PofhW zBS!u^tu&1UNnI%sJyIWj4x2F-{JEsnP_4o*W{u0^<(0TR2hpKEAo(Zq;V0B@s{O^Cj3N*jC=j|MVPndE;%1EX^#%V zthH}n>Fe#!m1e@hOZ3~SPDbki@p_}y>-`qYLz!cmdD@j`Gy4t4O8b{})ql9n@C$eGivX+>5&wcXy|_7k5o@cXxO9;!xb(-KDsDaCZWEc|PCy z&Age+&02fyvvTJClRMexoK1(!T)DhdtDkUA^_Jip(CL344zZ30O`nK822t>!4_%4% z{c@cWqq0S35NR6|uiJ`f6VuEmw@d+J{yH;o&a*zIRSu6a3YXEUd|C+*|J@9D1#%4iDTstW}To$7|}Rc*UXt-DQFq08EM`c`J{RkPRHqBd$eG?;ZdP6M_K zNFA6*D>hv8lt@uO_$L~Itq;h-Kf#o{FI;b24TP5{*xh~z=lgHu?+Ha4yW6Dv1LCg6 zqMr@X@f9qvto`LxL~wdbLq$|V`7-+m*H^dE&M`b{e?rpn7{`E$z2^q6 zCD_snXx`9N+2xz%nkf_q(WVk%C{Rec2npseVvmK9&?MPe2ohKc670AO;0SJDT?A9T zqgB`v*+zxXU4I*|^kKQSY|U*>4!99I@x>mTzn?sVrw(d^PHoj%^$-+_yjEG;! z>qS2MTTkGBX?bU3-Bl%ncJgbb20gEy`&?IUEM8mx5FQ@$Sh;$@#n?bWjYIR>BcE8C z_kyPq>}^MZhjBXtSs~dOU*{>$%v@8!vwLInVKQb}p+9Ly)o)uLS$t7Z8De(eq6dBQ z#}_*B{cZV29?zC7#JGinpUyT5Nj~s?Ecljw!hC##Egwz$Jw6UUdd}ZDhb_s&FY#=^ zGSv^;^e;UZO;5SY?ZliKA38r@r`vljZ0|mtdWsDe?2dtCxyC&=)8-PFM2GENZGXED znu(R4B{8t~45Z(jw$gaPk08#4>VWP7E1Ow;g7RsO}X=!Ex? z!#&@Q!Lpmny^_j$cH22qlM0EesG^9{uo%Yvs3gItCUVcAWD=3#$tvRY(wz8sx7(ZN z8q`{=t5fi3;PWD?>sXlOKKpD&3bsRS~KPv(J!_Co&2GM?H1X{~<>#1G%QCa(CM z9D!SWZsvd)pJ{J?@3M=6!;J}zXWtd7+e`K1%Y;YWiEY1G+9nwGq(?l^7(=mG6YYgr zrbRXH={81jEew9+vVE-IS<^rD*f&Ip%wlj{W6P@N^a!N4c@yhIr2bp)ae`Z#*$)C4AjhTgr z`($-fgKP+b{%p(vFLE$XZ4{`@bvj6GVw6f_Yu{m}=wPokunq}(8 zPAP|vrda`0n-NTo53hG}#FmW#vdiW$av)KpNKHbVrj*0o!>kr+J2~#FOYkyC7hl1z z>#vqQ1)UMZ1u4D3pZO{c>kB9Xmo(05%>70S1dsFK55F&0MDD((un0|<>5xDRH;Wj4 z6JeSe+}!0{2mvT)aOiL@W4rWn3MBG!#e)S{Cf$L@zA# zHfdnT^5A#)$fhECcxk$WjAW_80k&-Wb;k*vhYt_G|WEWIpV zXvl6#4Om*#ZOqD=k6~i(3`V1Z;}|FQTn@iAOI zoW~T~_<3*1$4Q%w!S+Lh9LcA~4-SkuZ7inoRa2bvVL)j4Mt8a8!9FvVByNB>sK)m~ zXZRJ8|Lm>KDdp_lU&|+2Irw%Com){+va(PM8hE1s>UZ@vxx;_#63{>%r*xo<+H|z^>xkfENwGlit zDRzH=j$Q6=lk_1G*v6C68$O=G^ng|uO_08RdtOVQ%P~2-Uuo*j-ko0pE_$9|oIoh8 zOQiz0`!NSP&8V?gYvshZQ{Z%`^%mQGfs6i_ZgYosVjF=&M4@|kXRtE#U6POQaTZd# zg|C&7z3X9TWx-B40h#2RQFOlyE(fB^DUjHA1cz6GP? zB`>k>Enn-*St=e(_HXa^^1ED?wjsQzdiNU4_&!A!>sd?8Ts0oS`51o?8{8}(n&A4x zsDls{jNEnzy84K7W163dRf(?qn#fW0P2M;eW=TfV26bB6&dQKUvCqyU0QT%}UOa_+tqBB;yK<>2s&H7qJ zBE7dQ)UB`y@?)<>?le7cs`eVu#}OB9PvN2v`BV1O^+N~K_N&EW3beQENO#B5vbGPw zN7p|Azjk8h7mvtvtImM_C-M*^i>WI;zDGR`|DL+VfZC8t%j=5uQqAYfVGiw(>eLe5 zm$!e9RwE}iGeq=Avh7@vt6`cjIr2SiA2)hV=QZff2cR{?sUm@50R^|Pp4X|3LWcaq zGy}iOJ^U?HklfpSX# zQCHFGz%s{Y+g6D?sW#3M%))Zf8n;lN+vBd?ktXb>sWlVry5^MWaE$hbE}-Mj;&&7# z6TO#B(y8**vU7sim$xnw~btxo>JUrgDnCcPUpb%x|$K_zQja8pnZW zEGxRkp7{o@{3;joO-+K-dt09AXF$`a6g&5X{733q$p5V{tlT2OasXUeszZ*T@ zIB!+)oFZ8Oy99m-p@godd_#Vmxeeo^RnVi-fwEEBHV`>@Z@?w?&W+nZ^a?iW+Ir2d zDeRbFO;OPsPmD!~484GBMobaf+m6Wo5KGbfJ!kl8?zG|BE{#>U-R;hfa_%qZa{9JM z6vh(qc2DotGxBD>w9#h%m$wjw+0DVpA{zD__K;I))!(tUiI@7EicdP5cB|eh=$>-G zr75GScIeH0Ys_T~WBk?056lq$=v41XGHKb(qRD71*vdF(cK*r?Tz!dQ&vwF>I|lMI4e4u5pDj{ z&5&#f{M7UhKQ;MJ_Qa`iG7j$j&%_U@qMqESbg;8ihsOed8Z{c_PwW zt6Nx`Hp;m8aSo4QM%^UII62<;S)rB zf+<~DNq5oaQOthP>SA*GM7?@h_ei=^SlQNs*lTu;1+>(0lu;B|zeM~4XrnezEx)3B z=%+m6C_!lS<5OO;{{#%n^Jw}9+PwX;pKh8nP0qn-ZK<)>@SkB$M+U-OwNGp7y-)q< zIQf`;mq}Mb(mko-7+{M@o!P7I2W6Nq zwZ_m~oC=~0{`;mbilmTMn`Fk{nq5!s*S9vJ*bkBFu)@5F2mAXtdjSF;^5ua!rh`wd z^i%Vt`DEaTv)$umYS|RP1Jh^5JKd)TnD?q{gMK{UG(%&!m;_0J$$He7bWO1Fd6r1t5?y=}B53 zQ7D0S)cs-oK%VQ>4(k?}t* zzDGWgtSQ@yoGbbrDIO&$9&KgUbXk(dd%C8dg->d+&SP)}vwJX_AQii+jM!WkG;HC0qK zV)M3kkM&V(w3?nb{enCh-s6A`D!Bwsm`%TVGPS=V{`AwZl;TH6S zC(g*uuVi*a*I0uF5qow7Lk0o=UAMnQ_CV5nJQh4>N#3+T?p?7}Ce?~+_RR+aLV%h8 zBTOcOgkxu`a71Ra{_XO|mM|GvNpMYtP`TeHZ6a z+6+Xc{|p3u=nO=!J4@~Z_Ijj^7H1xuCh_DquMB-q*fYu_n?qh}9PW_YkegO=s{x1# zokfg5e9UXli<*am$Qb&@=f;OJDr{(=k}!`)lRl3}3E1kM-GnBDC1ie+E+lBgdsFmG z)9fMxGFVdQXUH|@y1|87f7JzL|A+t%I-PUgAlx8CpLV(vk-x+}6F*}QB3$=i^q7Y1 z`3->!fU=3bYcifRk(e?C6s&|tq>y4bX{K0o60$6l)I&0La!fRd{fQKXrlu{@4k`qv zhSkP4%o*6Prjq<4~Na216fUCcj4IfM?a8r3wyCy1-w|mbA39_* z%C^N$`)m{Ii|CV|l0ECG%hML3XjJTI@ZX;jUjNv{CI@Z3%J?W#X^cy(`>F_G4FDyq z&(u%Uld+{j%Csmj^TR&o4Jl>Bit-ANU@g9}Nwvtfm`u9KxEb{fOZSL^pJXVlyToaS z)W<0hUd!W4>d4Av>gzrd^&E|&Y{v$mr8vIth2Ha7K+7gu7HdZ@(M=6@KT}}7KmQQ& zgq4E0M@vZfdiB@%4ml)&&XD+8lKF| z=gr;Woj_IUQB{eprxm3sb?dMBXVysJE8lTguq|~n+8DKYUrN3h6!#PyAzQ$JT8dhf z0Hybwr{}4zCKOjvSBAg5iv0|;-->+b)jTyk(;ku@W#8uDbs-*5q{C*{-{#-SzzO$g zuRM%7!taVjib`O%6Q>0ps+<9|XVKTM`#el~rWZVUhCDmyKc5{!n=5Nb`(|T{alRv6 zXjOl90~>zD<;CM|u&#}{tn7`qIPMF@uSXPEtqRo-)u%qOIUcZOJHTxRSK`dz>QRD=*brvhrxk1qyrJE5CRw~Q2-3WwOAyY2&k1%uuEUR zSwRFged*KIWCbwLhcx^r$R1Wg32GwH?No*|0V|;%`m}d~nhY8K8xeBoxYYj|(4?u< zBl=n84Cq)%S8kqIEQ5p&YBpr1h6xgpS5u#hGk6?88HGp=nlhv?WGe&Lf|$?fW|DyU znA}Jc5TzEPWBaVrjBQ%JUqA8=gp7114iBxl0X)<^_=EBFu;0hcWV(U<4{MEz9DZdT8l z@h;b<(U#VvTtcm?NmZ;#V}24T%~HoG6QR<7FH^39yj}3$ohld3DIfo}kWnHRWKax3 z>Cmd9RbQy1ab0krMy_t@9u2HsKT(gb57@K_yI_$Q z$XDGW`u;Vl6e=w)v%30pGso$X_MkfkGp%vr6rp;Nan?iJXS!s}vb)M#`X#{{eiYp* zP{zZrC2FhMM<_FfrS76ifIxCu3KF%4ga_0Q!$@IfiJh}?tkisv#A+n39re1V#-aS7 z{K7`H^@zGFtzDsMOFfKFpkx8qXIyZnW88Ov=MM@sYYIio>wsJ%a=!?=5yb!e0G zqrO3YKlhS_s1!WBzLkQY9LB}>lDW`I<;WB=2=YBi5>Erf|H6=!6NMWMVORf;OZ|mm zDf)ltQ=$GpBKp5HM5@Igv?5Pb#lJA*(hr6hScF<6I)*yb!H-ajfwri ze=bE9fVz)Z_NybSUusuEtVy2Fw0EM~u~$hpc{i;zCtl7r2Mu7*{Rl-tF4WIf$Wde; zcoLIMNG!|L%o^TehSfcW7r}hJ2I~ooVp4UKvCg=AQfZ_CpC93yABig$RsE3t1WS1p z$PIOa4*$aE9x-yUa{&Uu4~C6g=xG-+y3HNesn=NPbbva&V1a(3WH97p6M}_+GwKIT zCk*3T_qAaBnV@L`yh4fnuV*3Z7pZ61(I$J|L?ZF_>vDT|L5+}6R6+FVUf>$)W-wDo z)ODMvIMr_ApSsv0^f|4Xe+buY+Tx-53!j3yIAA_nYI)?;M0p;%vyF@8sCzK|4b6n8 z@am7E7!Po&>wznX3vkvE!1YAAwIP{TJQKJr8z%=(&`vx771oXE8_@0lFux5=xtW#j z9NR6F?rir?@=kI;li_T)H|vHLMkGn_%D6YXA1;6bX=nS@&X+*9jltoNVsD&gFy*dr zDS&Ppy1Fw3Q=$v4DG7;en4dy)OqAjWLP#?Gp7fY8yTkE%gcu5iS`^w~5kfc@emKj2 z?+7~la5}08$)UoXzLCK=rT&*2`N255xSbK{!MLQMhCMA3K<_{}1U?zgHM4PVAVmNK ze)t<+_!}kq2;tB3CDcBvq=*S*ax5zntSoVQSDbV!yUO>-24wPPJi0?^kFpG=!$L}6 zH1l#;QJ5x?!_?Qk zv=Eh~g^a;BRcf%x=xt8$ct-?v7 za|Gu1QhEvnt#1meM1p`M$Z&aNc4ro6v!HNQWKsnWE{E~HK@ynnL7iDR2dKvJG@&|3 zEnj(p2xJf)!;RvNP+t!`>EKVQ!i!o8;viz##eXN8mhpQ8+7`TwjEPsfk{|D!(> z|FaTT(NmUk`Ls{jEox^C{H3uc?P5mpIYF|;6h0{zGxqZ8Mymg1{)|5zr~aHW;s4os zea;~P(tjxM#?1^eVjCr~V`5VaP1Bc>F4=2bK&yL0_HydB_qjnimmC=E;g_3D_hcd# z@eUk&afFBmei1t$YlD49Oof4z9BqM=9C!QEGIz_Q42b53<{8Ktg^4^cnCSV*GXn!X zI^@XmQ-wCIz*j0O5&$a}Px{N4E*~*p+w~7j>A5&v%ei^bAzmBwkEb!g=sX}CR5E^1 ze5x9e8EnX{t_Nd05KfFnkvf?;35}RqakLOIU&>d-_xlgU2}P4LejOaq)&9*}wp;kd zJsz3`C8k{{YI;J?lxhPChW`k-I7c@honae5UYY-VF8*boC z=4lj}W=?2|$_Sp!*PA>@AETy;qA__lp*5imP-9UOwu;959ajgb$HGXWu@XTZlEbaC zB25yK^G)Ud*tl>3^~kfCb=ZottJQhgN{1#`)9D*Gvh2Om zI8EAfl?q(R#9bI;GS9vEkztUX#^1gjfk>Di{D4-iay3h3$GknrETD&|#yGmCO71MA zM?XO_f4Fr%j2XgaN?1ym^5;DjNEu0{tn?x95Oq6%>yfnMS3H*S5XBxxwJkx+Z@Epr z#kjUOv>=&5eN_%+{^rVpf&WW6dEsvE6QjF`yNl)>7Up%9#xrEub>r{ z$wbFgm<@zm9shX%*OekaPFcAbiI|Ua2>njYg;RL0wAH_sGtQWNhe)d7A?X3b;bA+g z_)_ZlOaX6@G`hXe->gelILTd!uBS2vQalHhz7cD$ivTT&$)#24j zKGp*0X+dJnAhfY6D+TAo^uTFMpCmG3K#E3_-xE6^+E zE1W9|D?}^4l;0{%C!NFPU|S8@c8EiA{BuHcg7i!)#r?->TW6bPzZ;d;PNPlOqWL|+ zKd2=l(D@?;BgJXP2F8TQ!?x^BjMb{F{K6Sl+q2Yyhe(mr==$Ca{ZW}(AJ5T?H}HX| z>9k^i(Ohh#1EGVY1G5gh{=K>*=d|Iwpm}#Tl$Afne5idychba$V;5-5ZtW_tvYZH@d*=p}eL_Y9edG zi!5dSe%|TQ)X_)X{y;3DX~Egj+a_Oi{x#k?t_q4d!3{3DgD{6|m&lrYibcUl`*Ss4 zz}q)Nt~XOdCNCQ1Wx>VeUY(cXy$JP&nmYH$ruk)E6~mUVFl&0fyN|ft=K7Z!kyGj& zcFJSa9qKbPu%@te7A@tEaJRLViRW*EDUlR2R*46RucqL+P4UJpoeai*F?e zq9B*rx?_eOmR`CUe$btJ>DV{D``aNfJpqFqs$Bx?yvBGd58YdbwtovjZx{=~ZP*Gy zZkP#e2YOwkfnI*V{4E5%M*(%P-&|7&s$*|13br0YWn@Ckh6?8snkuBP870Sire=iug+t&(zVqVo=s+!Ph%y3J%r(S=x*JFUR ztxWOPvBcbYT>G|Dy=KZ0+5#V2zM->j@p!wpxfEpSeIs~=#!-GNYy*95Z-Yhp6t{R( zChdK3t~LZyHR4l2r?_&@tNFS0p)yn7d)!lGDjUnd>MP}dezb zR^-hpCB5>kJ=(`z#;4`yiis(_M4J zOvdYa=wG6LO6yXKd>5^5q6oQU{AW3po(|R{JFsz$F&dEn7~N&zO7$Nr(wF~2N5-vF zmY=94E-wZ~x`k%i;+e3OKNRo(?FtUS@-uc3u$Otz{nO?tSX=K2F{|IDSp}>Dm8d8_ zu=WhGZ<#9tGbva9F1!?Pou>4DF%sC_IOX^}s%go|~yjcmLcPzhYKfHUAqWkF2Alr{3QE%5AUu zK(n)S+R#h5h`nG|a?;FmIzGP{{6;V-w8{RDQ&CUVbCwj1HW=;{@1L9`D~LQ+p?5zP zafe0{i>YPmZiZgqY*b_nO0rw%H~d=W!h_l595FRd=-)GWCu@X7d9z5H{Li1|K$D{O zG4`2eaXr=4a~#O?1DrTtrM*09Zl=bi1yh}BTMmZCDiw`XGj7Tz!_;{Pzj({F4aeKYo}|j);OC?;Aum z^~@dUmE8um5p`|XL($ZEQqimX%aj5gs_QR)J*DsvSk;K@UmB=!Zr1hnG+URLG-Lv_ zt=0>P=n;6E%VFBCwhgtf`TGRjg)gyD zD{hTLAGXbew}i|#4TNfO$qWwg46WJrDXQvm>8@)EWh3%l)}=2zJJIBFozZ4iIpy3i zkL%OrrQ@93d@VcX0InTQ02BDAK4%H-!^X@jyKRRm8~>bs{fhpYBbm?<`5Tc7GRn-3 z*E9d|wt;Iu&v;AMd81RM9p99A*!VOL)wR|b&#GJHd4Wq9xJ=7F^_4Nh4ESsN$7@$M z^9WDX^TqYuV0pCcE0a(I`3rO!0W)aZ<5x$R#I@y&S14`%4 z3TP}n(gl(k1~`?sN6&CKFsc7=SDO?J2R(?Y)w`u;sxOYMf0?}I4Bd0;nk>}y(N#-r z(aOMaacpkuECJ=2k)_Ady?7*1{VZJVQBFsrWT?L@b7#X< z<5~;@ow?k`3OO)^ueTbYOxkUkyA1-FoW`udfGc`B>QE zw>cNFeGDX#tNb@2CwVwIjy&fKNcB5h4YOV|!K->0^K_;*euyUi@k69Z+BgTOuSlc{ zI;@}jk?rzYRl|#uM>>w6wcQJ?x@+3_$C|#daZJYuJB_(6?+H73WLjw%DtokBnHgGm zlvv64s^!Xa-07bA=!_%iWqqX^hv{hUC*ED#bxMhIy?~B&y13&=R&*x(rrbmdEI71Yj89zB1E_O(k**vweb$AGrrsr2Hl)yw};r^UEyVFsPTgQl-{fV z(E&?9y?sH1l8RhS#4YDu>7D1L5*`4f@I9CGvz``VSIkHodZi&35*g)7IL_SLG*VxZ zJTq%LY#Pc2dMSiMF2|4%$a7a8q-1{4>NHFA!k<0ZI_WU2Ykl(9+4CyTQf%#2Iou)+r)y|M!(>2ynrk0QJ-I}8nNSKW z`<-zj7?uFDiG8N7edHe8&XMXtq_t^kaXYwJ)k1$yv1B9aVY#V3@m&$vPMCU_Ya4!w z(Zx`~-*xJ$v*hWB7W3o|fBG0gmTwjWFx(WGFrT?@Cr`D>RdyL+;1e)8Q_y-uh2cKV z@NXkwpHSLBo|;R2&mBv@VOd|wX(HHbs5&ew#b6^WP~QxxPslBI!KSC;Um|J9er#QM zNOj7^b&(XkbJPlz9O~A+pWM^!|MzD}12*@kV5wK8PYh-~VD50WnQXctdBz|Y^E5V6 ze8w`l$a4vT&x=z(mxi|8qxoBLq<-$jwUaYcKN{_kC_zzH+d!Cmz)C;*V zPdV4*v_7&fH>pnn6P+Irh|A3i4AR0(5=aZ=!7S!b?gK@ZbFlP%fLfu#RD{SUH03+n zyZg11FbD=r-0i*7FTMmN!OEv;#Y~|!qJE!&Dv<~a`{c`v2m%Y#~f4>;!y487l2TRa$2A%7o zJF}_@5eiY&iq5`ToCZM|T-k_h%hJOB#)=Y~hJeHf=-aLZFR~RK^75nxiaJ4s)*qsB zZmk9!C*Hc*NH&g%1@OeylVnrEhKD+W)+l135e|wNjwntjb1?HDY4EdVDmSti0SZ>4 zVfeBUPO80%TZJF#ec_@%J-X~@@IFiBvXKw+jRz0$jDzMLkUTbx8+oL@GELGQ`OL&a zP-ySrGX#7l*gGT;a@_uF8xWlledh|6-Fou*t6g<^dirrUh@8zGNhud~wDqR3)4 zQXUh_ObS@rML9dgt@DxjbXE&|KLN&E2qZvkE%?&2mQ4%iKwVH7PJf>L zIhq}~J?Bg7sGf6pV{ri>nX(pwVf%W1CYhb^c$a`SJ?qQDIu2|!hz))LJw`~iutg-( zTle4z&RkjM#YC6i(YqEA9(8(ay&$NDlmkwzU-fp@|9RK14c}hw{@%rBXW{qF zhNOX_o73NLxTv|5(a^tUDw2b8>k}Z5Aki&U%T*t|pFPSdgvuOb5R~C^03ogM(kC3l zYYKh?@H74f45hw#HB^U3% zNE_+n9tRR-A>98|-~XC|S z&37Gm*2LybuByIO6AF-0Kph2PipuPm*UC$wY#_VBYJHv|^=;(ul`gaK)ol(;Mbl9S zEX!X+^&5h!C%unXB;GzQhXc}_gAUJU?wq|W0s4O@g6SPqrChQ6B@Ny!qP$X9@%KbU zZQUvH35?eQ@EONs+w|h+rV4X_>IB(aP~Qfnaxc(?LoRWY8% zsV25$MPmQPS_g?xTmn5NK$z>CyrX_uwE1C9zN2Z*HC_f$lnOvH&<$^A80R-Q0@ zjxiEQy5I^yPv-~6+JA5OmxrYgQ58e;2nhX0It2${DgFT2Gd7GE;4m6KzPg1(;WYHn z>-H}^PYiTq1bz7I!k6^f!D+C%`q``u+kdoQLku6NA}CLR3TTE%1)U*G!CQW#?BK0fSGoYsU;1&0w|Us;Z;Kn^uXbtZYNVczH z(gw_0~GO5O#I$GkePgcE#MlKh^cS% zFL~pdoKuwsw%$5cWg%k4yO_c~hvAoNnEI-oj6`VwgDNfG&lSfZXd7}jqbC{|UUaP} zmF5>9q%>+5ei6;e64NF$hb0M`NO;wmeJ4bMo@>kK>ekv>?`($NXNQ{P@XE?Q2oHhyFa{VfS_@403^P8 zwQHhFmcsW6=k^s_mRXt#yfBmK0gpAAp`pa$V+}@9_JJ{SHH&=^n ziV87zo84=NW`nk^)rz0S=l+h6^CE{!MrqBSVoPejyGC7zM%Ly$RB|2~04aPqrDK(M zr1SY2Wp4{$iSSnrsJt@C1-tm%*Q!`i=uOTX2%BYrQd#kt&vFG*0nml%Ol20Koqe<7 zSVAxL(&avpQR4~jzW!3D-7a5a?{U}%x7fB~YQ9bl5fD?I(!A&3AW#CY^2IZi2{k6yM4?@lF&g*y_rYq*7B}a&MI9q?z z5%ZWalzKS5r#M%_>%9ziWaS_!*d2`0DfuWRo?R~cPC#*)xZFs{j%j zni;_yVj5%`x`+fzfO>|y%qCfK<0@D_EZ?jggxKDP@9_nE_oKwnq|lY2eaW8@o*?4T z)>L6fMR@v8m>T-yndx<(Z+UhTKUdmfl!RFIcm8f{mq=>2130cA#xODP>=VwG$WEm`aw3JfUwY#wT=6H0nL6ZW73lc!{8oG0p;A zg#NuFW{iH!U_19LytBS;_w1E%TfX-Y+D5Vc!MMFtwbYf-g@2XOwbZ4RA?M>Xh?$6) zkRbkX#bGv>GMrK%cZ>DU%AsSw+rNI4k7(6&W_Tq3J>nPZ2~Rc|DWM36#1yVgG(d?W z8MY$?K3}C44u+%(JM)`*{1^Rv`D0YFYrQyoId0PI@6)ir;Jbc_-FjwHT}<SSA{hBWCk6d_ zb&U9m^NKub^&5u*;r+{j%Y6&U>Twteu_PElUihs#@E{Sq{Q}1x_knwu4~9&P`+z!- zzjuoNdjI7eeyuz5gZPzQ8}bFQxNuJyE#*sdP4M~t2YRiKbXoHGK4T$k+43x~e7Ssi z4toqg>d+90;h5pp?~=C6tsMIP$KM1?al0ge&6I=p!FLQvhf%qRm(9il3^~JB0)5>Iztrjp(N6I2Hi#~`}%l-a* zK+G)&sr(Bk1-S%bj!I;+%%q2j*Lx|j`mSk)XO6|TVVOkKeQS#`8)iKqy_#?z`{2&2 z>w5-{+JQ1}tjaKlUEu^MHkgKc+yx?sTTZ zr)w_{HiH4;1AKSBnSjh|d+ z3}hk#V~io!k4!2*is2aSov*a=Bl#vtw5?XL7PhIsK#7VSzL5mhRs=0jRPz|?HP|;E z!bpjmF4{jD-lV^k`Nt%zQ~%e|#9Dg(UNE+e&ORq}_D)BMr(q@X^9%9N)jJ6jYAO|4 zYLArW$9JO_f3OnEOzQ*GCz0kHr){J^OX&|&$^>_nV3c+`tEbnq%T12C&T)H z2?{oVXnXBny8QS3lk6|a4oV@!{Ed2{xZSkCWXl(VjHY1Qcvg?Cuhla?iDzzkSgwL_ z-m&=hC~!mmDt2hlT*pLMk09F})(x#EDBD3F>6H!$PzJt>0otTLo*f+5Q7#7Z$EO3* z*5*d5mv(JOX&cQGM2KdVc~^{EXfffQh1!lYzl~v=BnDv>m$ND%+5vyLt0BZz?%2t=&uwvcqc6qg=R# z+z^JgptCHPjeF0Rv)my-fc^UV@b)!*)qX0#gYfyS!~bmy*%360k4EI>^~{$GQ`D73 za@sjEdLuA%8YaT-sTfXqRZexPc~dD6AgTXu9?sVZ7-YZVf$%^dl)Lgs1iCZXF6N>H z8eUVvMQkOP#-Gb$t8{58k`83yBd~0H@mQ|s)edD=MXzz!&GMl&iR>|6Eo$=BPbaN7 z#Kg)r#*KG2eE!dO*+sNYX)MbaBo86jELYZP-S+o{d8tCH*X5A($ZGYU>M2$8tc!ff<0>L%3-jDSeC-W3k7@>5P!z)(_U-%J1zUI|lQQCK;!rJ< z+WDhdxKFpW_4*B4)O$C-LvIWEI>2F8gFg2mC6c^bVDR&6M|?Q^y?xuMb?|(aC_XKpz2*rT{r8J)O)p1qfIeR-!tN}ULANaL<^2xXTa)g$dAMz{%9eSW zZIepHgSP2W-ji(Wkey;&}-Vm}aMWvs(GgSSfTzyk?!}*D@q;nHJ8I z#de=LXN2W|ixTI>4zj87jMkX5WigLRyLlHL$#znpY|DY@No=QVJ5}1Qt4UUHo``nB zM6qQ3DZbz&w8e$x&rHI&wc?j_R_&~@2HX0Pvzed^dkkXd8kE}7DQE`8d&-@<@I4wn zTr0XdpXjww9Ix<+L{EEM>#RR0nMqwh?aQXqYn+zKM!XxRW`0YKHsv$qmV6GRJSt9E zmC%idstgKWh^^iF%Y!9??{>l)y9zc_R4h;{>~24;NF)9=ruXJ-wol|NYlpt~cmb?< znq4mU)Qu4~i>t5@D+@0Ls+umls$6WHtjL=OE;H5Fd}`H5Sa4Tl-NY)gbgk^vmP{xK z?tZhtm&;Z_`T>u$gBUoAqZ;Y()+J0J*F%vg!-tu*&jZfLTw1jUs@Z#DbkVzr(ndJ( z{DwPwef;y}Z7(Q+_8T}MpZ!4s01;3Q>jf-&a=I6@MrSWfV&?#~drvVCHm%LSSb%X>Nm{1YNqHx5YLJy0N5N=t=n8r{Fcvrk7^lfsJ zmorP>UtQiIyDYnp6iF^Jo~Vqn7QO%F1^OsraF!RDlrY+k%YB;7igVv*ls%ojp)XFpfj%djsJL_F%6|F8ss}ISmARGa-+e-IvXs-or7vyyR$(xq1fZ)O110=Y+26qVV?y>~8CAe#FcXyY?AxLm{m&J8) zyS(qMTlf2_rn{!PW=@?SU2~r4^K>_#cv@evLD1U+UZQYrcP>K#0?}^-BRY&B>8KQI zQ@+&Cv;D-TiYz6m>|?yrlk9kDvI-raQqm9yi$~NglG`TMj2u|qZH7|4$B=HqBr5aV z!WGOCy8rYQFEG^;$S2S#!}M4*c%oFup3Q0gS<15eb@om7-?{O9y+w0~;4oLMTe7Ks z;18z=ZyJ1v@-A< zVZ9W_GrlsACc$+oWti`9)Qp4!ZaPe&h8*o{bY)1FtcIBIe?(G4jD5uB(AJC-;#yCb zuJB<})DYVwugGirFkzW-a>Q1K`2ML3IS8CkD1hOBy|%6=)RF#JCiWq68e);tlhe#o z;HmC_#5m4rVG7&)-?9th!b%I`?g^aJ%pW%9p9E^~bhNhlfOyVnqUx^?l*(}5 zw94>vst@zWI@$6pzM!!=<71ZkKb$H=+E`UIw)q!v^HVxgkc)yEW#L?3KeRub(={LB zK9YXu{lxUjtql8E)gk#R@rtgDb$I)={^a8Dx4+fY=0_@5P81B0UXgq54=;o)Ny`~t z7a?hi&Pb+$(Ia4EaCOm17-aet0wpM&14oc2b;RnGnVoNW$m``VO{Fjkb4IfWo<))g zbitpIjB{W}q~5)=fodciIQw&jPuF@L%c7Ux#RyG03CXn{^({j zB)awGV8}U$EZi*X#nXd{mIbka0` z;vx7##d7eDg3@2`Mn`b#QV;*8g8vBm78v!5Ch3#u3n9Te16y@X0>*gpMgif}&`4Mp zG!~KIgc=nm9cNl_+WnLpI2I(fjoFG}5gs{;D-0hX zW{6z%IJH1ktU%2V)uEFwnNDyG^=J0PuE2f*Ep(OO*WHwYOZ!dg%_oRc#!cc))J^7%z-1GR zWbT0HwC6G}bY=r@O~BYp(!@!SKb(s{pGKjcpalvkJ@^BGf=R%F?LBQUn;u!QJ!M3# z;!J5wJ3p79nF2=-u8E!36sz$Kdy|~JTRX`u`mQjGBQvYE(VS2lqZ^!w!7%Y{P>%R= zi0(lrJ6?J73NhsFnfx*(&Lyl$Z4?fvpdS65YR7~%4g{UiasH>aj2$+dOi^&zQsutv^WqleRJH)_7VGU(2G}7?T2-CYNc8 zfPIxLk+&-OQ*P;HbA|6TkWu^?f7?YcYm1 zq7bAw4b|^8-^(I73Va4T=dBShRk$D;vQoLq0jCCitwjhECuFH+zSRYc&fquu&9rjB zxo5;b74lLd8-XF^Ri;wZPTXTgWt+YVI(-ZBIsxgwM$C`=8|kWe2a6o$oiJ9Dz8;A@ z^lk8$1 zmNBMAK!9TB)Sec$Rz1JeYR0Zszqj)P??H33aLEvB*FI?$f1jYQq87Bit~urv6A6t9 z2b7Y1k0yK6%jYwkgkG+L6E8DO^R&*Bc zGzo7C4_+0s4Z2l`3|084jkG`ZGJxuzN|@Uco@nx^+{HqtuB9RTQOkY8F2Wtc z1ydKu$`DSwp=R3|O;9?33Oc6(c@B;#2+;r4*lZG8OW90ehN)x?}8DwgOQz z$pR|pG#<>G;}JazqO`yG(qlwQ7OawNk;{q}Oq20xa+Kko3SSR^{sSE{W)s(xX;mFT zrG>>`{ROa=-K_vW5(Qy+$5c)QpYZOhmie>cl4#FJ04LChWPV?9lKSa36g?#iVe6Yk zsw4i%3?pZwCM}XP&nV{`w;*|UrfY7%t%dF)iR{mo`k=I(_1A5d&i@jDt?stQT4E%( z54gVe1ytWHI`Gmx_h)7km%V*4`C#@4z~=%aR!%% zXrnHwFa4ZfL)tYR_1h)#(^cw^@N@(B8;`>8^<=0^@ z1(KGPOq~ri4+M$sE&_aLb01)#HqV%06K(fpb1=M{575eB7p?t$E*gw~GwxXgd>*ki z`NB9`y3Zlvw;M=wAMw|>#cl0!d#MI0Amg|e0CUfA7Ye=ZcnSlWEj)OBZgH4I_yPZ^ zxd%gJ5%&;?`HaA2caL?)Wy4(HX6M-7bt?Q^_^Jh#Ic=33qF#}rVg>R)nPn{4%QA2m z@Da~5>ZJ^N>W|PPWM!^PqzzC49VAGWgsc8VH^?P~6r~yex%ElBS2qtSM%#3Ad%Cs_O?^)J=uB#tha_M3 zyN8sTmvbP&7|$W-QCIEVS$r z>cGB9b-240q*H);bMgPXWU70nXH_gu#h07R`);2s+HYB`uM}#Y+)2z<(T(GpzGGd% z82?bDz-Sxj9p?eNgGSWs+QQ+zQ1MGO647o5+6b%my(MembS+M&#$F3teeoUejH$VsZT#wSus>d~O3){JXV=>yfPG*w=+IJHE2G+wQs+)_c&(L|E|ZZPH-& zoN%QX0u(&=>PyjIs8(1%Oel3wceUnS0PWsIr%KIM&~1s&Tch@b(jDH=;dg(Ga(Y5P zSoK+@>(1l!5Kr~)a-+-&qs;Q$_lk2s6<~==L-142+F(8`J~w3CB!YJ%k3s=%K~Ro{ zTx#@&+hywKXDDyW?~&8O9u{(KE2N`B^A_3+FLy5RyAJn;Hc3pCZhN<$izPo

X|5QlK+~XXJ-O8L8rO()hd#>N~Al^(6)|=GHQb~`2Du4 z)26Q-)8Pyy*YF-o(wdcgdK1KT11eoXdaQ?wPIq|$Y{GdyP%+S}DGksBYHK7QB^lt8 z{y_RJ-x~4?sQCNxhPV@Ep^~`MN8a-sZq6V1aV;C}G3&#E+FeTnIB`(c{{Emf_#uqv zUYEqu;(|vPTw)us_sxbEg5ECL8|8+hXQAjZ-d+64INXIF5FvP){AL1CEl^pHVH1=y zE_QF??QXNo9$~0_$!EE(@GN0>ju*Z=>H#m4IHJCm%+yNlB?k0q-a&`S-9@WFw*vM= z#IlvwX4TOfn^V;cJG{WBDN#E{HzKBGM3cZEmwjuQ8(2-TlPa|wN( z8vz>?+|2#`rZ12mO`_>QD?qdEDS{j)J%IykG9_drG7R(2`VzeLYQA+dB%Y z-RNq(gKp^VKY{=$1TP!-)ffW(%rUn1ek|52UH)o)>C$NNhEs&;+iP4IKzLF#vtp(p zIF;Qq`?z9B2y1L?vKCrZ8k>RwZ@eSfdzujZu>r~@XPpcL%AcwpZ5*NsMnsh3oIlgzQ@GG>xY?jYMZB5A{!v7gH5$exZ+?CeJMR zLn(mz5%k${C4DX5VTHj+djzdQf}bMK`Xzjo#ev>`?le*xiKErb1eE)ssWEg%SJk2b z2%UEK{C3Ed4Lk^=dtH#hg*0U8Mp_x!dP<#V+UP4naE@LqRM#E|R;|IYqKpl|{dNjyiao+DwpKTQ8~Bp)4tN9MNf zSR&$pU~37PMx^eGaS+9)$+-%FJw;C=wjO+AP|ojnUn^V8hPw?6Afgm_C`pn>wvvWK zh?&RXb&v$k>c)F!k0(R#LB>!v68QPSxkb-i>J6%Kar>=-s6piRg1P6~gro;S9Dat- z^5Mt%x#cU$@ul(I&fpk|A-BwKu?)G|gWmQVKj(xA^wiy5DaAbrAxN&bKqm8&D;GB? zGuyeAayXCinM!w@pn*JllyUQt)6K|Gj`!m_Pc(S_`>mcojq{GmsS=F1#VYefvmoyt z?dUNrEpE*ajh;(+VYCI%VTZ^>F8L$0h1?a*7rf7XNqSVq%WPd!SuEb$5NtLDfwjc( z+fVMaxJZCKe7oItn?(?v2nkVpGv*8-X$AXiiw!|T70L6|sV)t7_Aqjlc>3cO_NdLZ ztLp|LJ|fmjr&iyj#n~A5k3@YQZN@J3|tmeG!KYjJp$W4OW6TB3YiX;t(4Q8*V5pdNCyA0n%wde+s0pBh+CPOj7 z4$S@4e!6%Wf|1z${);pONv_kle7n=&B@qQeuh}_kxs`7$sF_S;r*OGC4$ol=_TAdE zhCD3Wal%x5bJ|X*s-fuIxa%74{;4fk|I&x0^r6bXa6UH@k+HF(>l1rB&^dOkez9cp zb@!zPIl zFe2xceQQ=&*Q1vq)n5(XqZ;Q=2Bi;KLN@{i{j{pey>S(xhV0;_kMkF8YTkogMPpap zH0L8@=XF?>t6mD4N1f` zW7EJCStyReiOqFlCIu-~!yoJFxZ@I1t*@G6HLYX3v;J_rNrV)BCxN(E#xvzQdYe5J zNBr@T2OCz?Yoc(qVK)*>4Z$o7Z9Lw%j3E@kX-haVkb|zvIanc4c~#uA_jjp^5aP3t zU82zsHoeR`@X$m8N>G>z)!((ZC=NMq`jyI5t&2L`J z`|Gu`tGETL)DP=oN&=6s=bi6zC1Yg1de=-0xB8{Ittc(Q&9L;{*0%_Dxnteg-sUoL<%qH< z@_GLS4V=zV92Y6J$T_C=QAe{{41zlddr!X@uJ_i-*_Q+`wbFg0a#cKO1PmY6@s_6iEpi` zJlf^5J@}Pkfx$iW2^X0 zd-^F)Nq&CY?32KwSUN_A=$vaJehk)D@=DaYvH0l08!j)3k2^8j6eS@+DvZD}0#1u` zE%`bC_%v|#UAD)RTrQLo>M2~euwBIEoM1A>u*lc)DrmKny8P zOPj`fLj%9lG30KWOCtevypt#kklbB28&yeTS!>HOa+d8)SEhy3-7;iOSxL>SqHiwF zOG&FIu;hv7fR(qfFwr;OG~4p|&oO%6g(}81u&~^f7PkeDRRctWH)#j&1LZ1u1J{9j zx#85#y<3_OcmQAea2}Wc`GT9H9ckHkAP=o7I#IXtPQxP%HB#Q`3Zdivt2t%SFJxo?st zUe<6grL3b&W&A!J0+R7Do?Vr%*FFG0pu((72<&ob`QEecq>JmF%AmeQZFM8)rv) zLfy-(sCM|qR7I%YY7Y1&!_|eCF96@Wgr(CELo9qttaIrS6juql?XmP3teS#kn8Fo( zNm-byD0|3XWYlSm0WU=(SE`gnozcyyYt>vp4DlyTM|I`DlK7ODE#D&UbGddss85mp_I5g7^2eH%{B$DTd>p#2qD*6J#pz<7{@!EYE&C) zDui+ynK7FMak2nd|2zqrupB_foFyoVC{j;Tie@^aoCNzgbq-fHq7ScFB*d%7ba(SqZ(f>=_uJq$b^qEN zWMaC)X=psSGP~%3?U|Z5KL3$F;YliEODPg$orsK{-qYdOd=SM>VTP&~U|F~+S9J13 z2S%T(n1in|XyaznW`jF!){SW73PH?vZx$HWhiNh(yd5~NBfreV@nZ6RpE#_)xsQE? zEfLb$J{_wU_Qhn3mm!tz=DyzO41%SU;141>AD;HBAMv2+QYcd%=hPZ%YJ4FTB|ysT zLU8$fI%r^3qF0N|65HXXKvUkg3#Rr@7}r|isAzf6rPo2uu^F0nB( z*!gH@EBzi|^A`J?4?Uu;E|f~6ziU)}#sV2+v%rhD2I4Ud;K8QBl3Z$eTeC9P#zWv$8zP>U9X(o#or4Kc) zsg-<9U2V6=a6x&MUD8bDR3t$KO>3}+@4A)J*AUdlmE9f#aid9tP~LD~Kk!IR2k*m@ zis47fW3emadHhN-+M^$q5wtYQXBKb79c{;4E`EAM_C?Y8FA6^RBk2!QCAm!4g&+DG zHMY8yWY@p*; zbci8&Qdukn4$C#+HbfXs$;QZ>U2Myu#>&)_;eZEM#Y8D=>X-+V4VOLiR1&IgOW*|b zWtN6CvxvIqXOMnUW|)<(QayWQ`Q(V+fqie=jyoijDenaEw7ABj zIF>usfZ@LV?RP_^4TQJ5wKSKHDHRp)H09Ep*8nj@1Tc@KRyy<|pwQdPF|}}kXd=LiKXs+`L?L$Q1j+EfRI8^dS+kUXYkxO4 z35isI&0^nR5hH9-yig~^qh05!C)wLBvq1a&?G0(P{Zxzf8}>iUW|oep-Qpr?Oua5u zL_=&2Pbj^!>ho`lUr2{a{P9-6_gZffR{q1{WY{QbNv;Fi?L)}Zd4P`ztgo-Xo@D*$ zX6fMeBRCdQ;9OmK_OAs&{{NoW>%peZ#eH29on-$26=90qw^j~em7~<($A9?n{^VS- zd&rrzy-jPhYaN5KTc7KxE`l(Xm6bI!#Y=itRu=$U zLwW21)|do*Yu_5s2ZP&BsB@0)t$FOtc^XuX0?-RbF*pg|YgAU+-Kh%}!i9gQTN8yt zlusg@oV;Pv5yB>SNvIS|D-6NHkBx3cStTg=|3&wthG|6y3!ET|V?QuCE8Fy)X9M=U z-2>QkD4{QIk%{$gB%Yo>j1wlgahFpr^uvJD;8YOjAY#ZP5B9BQ+VtC{hp4e@F?+p7 zMX$`NxO`;CMq$)EwT|iB1bla2pS;&=U+6dHgG(#m6e^Or{H<%(cq$i_L-6!y%h~WS zy_EXb%4B7l@8w(K@}J{LJM!2BWdK}-K64cZ^L+0V>B2Uz7A>8W6N1<5Q4InRQbjEhwmxaOOVLXFi z{yMcn$A*$LK{CY3xa_R$U9prNmz4=c;j!Sq=l3y(1^lZl7Bk-bR@O-3VqM)#Q>%fMF6^OaF;d0lW!B$Zp;xEW6N*k zbtYqR)e;ISbJ@N#cytYaU2)4`RZdK3H_zDh2xrLp(@X!cyTK_DER0>lR=n|bRF`L0 zD$-1OvF5Yk=()HN`yPS^TX-gPbez3;sI9OyVXH0eWA>Gi1paRB^UE9}%pHCF%iYC! ztO-ve`(a=IbR#u__k+k}q*?9xk~ERqNqCo-P6X-AbBKG!Cvo!8x7ylrh96-Vb3+%u z%A&#syhCSQ5ASgjoi>V3k1)}B?La&@cM754&liwO}Hc*)*%<7<|ekSFL|G(Ga; zUP6Dl9Q>3q3mKXrwXL*zNj@P18N0rm6Y$~;&QksLFoRP*C&X1gd?ZoX>bgJ7uqpSJF@*P!f?KGBINQ*C*ygGS%cRjPV{J5<&v}xG{+X@ zcYQdQE1J7{If!m5@EOy||2Xu~SoX5jrnfwUWk{(CzTOn$PgCA$`1V93S)V=KT2%Iu zC}w8-YCH$L2*446fim;uNfiap8w#0bx8l1*dtAaYh}qS@qX7SXf;Y{R3yZ7m7#{3Y zFKWR47S1GwE=0A1`W#tX`FQ>xMs6~~^$A<9mbi}$?U9$H(TbPA1aaY{OJD3mr3j$* zfB8f(-a3w1{I-2UrJGVZk^)(SApynxbYZgvdmF28NJjwxrSnn*jVJgI1udPa-tn&ELubYKfkD>%o?+g= zC3zXRM!>+;cHJAF@fXg73tKdlH(0)chm==&a9~=fN;h@1*r>7OEJXhUAWPusc4gXh zu%0TKaE@P7e#v02W#-{MGXRkvZ|D6n(E~5MK}jj3;Ul}c;woRqN1+oqZWtFfjr04i zb4{+&KL>l)Fs)w5e0fZ0DjgU!=@c@O3|+$o*j?lB;FDWZ@CcV%TbjZ;V4qfw>gfYRIs7Y zBHO|&m>k8aAAnGWx5eTcqY$X$u$MmUV!DQznG&J{XXr<# ztcc_96x*PkQUzfDRW-uyPOhiJ)BxO#z%b~%8!10#Fu^cH*yZha>dS=MPtVT6m7Vib z&u>(2?4oyKQA)exbn903`?~)@#BF;n`K{A%*(9_IxFLbGH&hNc-j(2_ZLsL(yxguK z>9TEql4uX$4r!7n3=%3g8a>y-JM%B&-0;fKN63{++EN4uvLB)gB{gDR8}UZjYFd68 zsZrMB=#PeFr-IALJQeWIg@=B+q<80gS5i3?EH5nzeiN zE+J-H5MgYylnmZ8D51ut@dL`7OhLN2xyghui#yGA<7T@Cl+{X0$3OHj26ti zC+(%}H{Z|5_474mk}nQaJX(?h`U_BfkP`-h!6h{>O)M*lczx_jD|5$EnwpxAS&qzv}Lw73-W;#JGkv^^|XmarN_l) zmuqe3RGpU6iu87p7Iv$)u^+E(PiIX;`wi>7t+BtZUOwD5or$bkX@u#m>)j;0sw!_+ zcFLqj$kUt9&xP4j7cDs9u$pb*)9Z;YKGFkw?a(}`Ul=NIVId#-RF0%W>{Nq z7@2~hxt|BxJ-gr&#j$!;E)?;8*YL}?2p|hJEbO6R2HpiVm5$P+)i$SrSM67Re)}6xVXcDM6*Z3ZLudQNrl;D+^95UL_f!mA-LAXA8wQ*a(j4bKGX^D;?Jd3&2EOR^H--+kDQ&-LH-0 z-NL`AP?`F$5ahhwy;~L$eg#al{;lduP*Y3!_lT>6#}LvE<U*n_}MOPM9j`guU)>vS3$-|w!P^+Y029wv>haBDzLk2a);nO zwJ7FO5>RZ-`VQK+k#|l`Z%MEII5y3nJ_99?xTXX^C1ng_c2$W9n>93c=UYXosywFr zOi01T#DWvHog@GDsBFZ(^&t^;>XKuE@%avg6$7uFfsfw+tet*T6<3=6lj^gHJ=xcb zTU_AdBjvN?AeQSgxNzsY;mOEmR&S@5yE#ym++HPy67>?#C7w%kI5YHh<=lD4az_oq zB|Mu9vX}o38(R=mV^CxKh%4*WP400Z6xRd-rq4;~Lov>qx0sbp1(uP@gp)ys`g(e7 z5kmOMeJUl2vW+6qoyZ)~@Vm#HFVJ~$JtzoVu?TSrWWQ_5J@J^Av;#BiB(N|!X!72< zc3{v2Qvt7><>?xBWokKz0x=U$(_ih%mAgXs36~5^JknemLWAq&t+}o{^VzB9KFvv% zHd8tN4*Iq%d!9iy4kjo~7)@JAxS0XJxPP{jkfB>5qB0`AIyc3~yIa?eo0cm!x2>)# zhzaFbyNy$;6gS}H7M0vGP~30J8pKJk+FM;TmztyrmsahaIF-NNQ|;kC zFH%w@8%&fzLPpW`$lAUETPMzsud!)msGYNY&Nv9MZT`4@C+7jKxjgQ?gRJ_nu^+jp zGVCmH=@MfoDif-5osZnzOio7MetfC1UYdo;Y2CP#JT()lcQFO;IOtf4uOWBuJ(Gm| zJ30U_E7-@z`-WMpleIeqfbj5e#sgmOJ4K@B|BBb6Z0ALJq#&)|jaH}^o~SqlGrO9R zh@89?3Rx-lI~6@Ctu#aLDF@VD+)+v`xo4tdYqn4LE3bOvpEO===S?@8{H!z~t7F5P z{&Mo+&6&tUhRv)<2q!Nli(fg{=8d-|qtwbOdHG}}uubfh-9oZB1R#w73IQXbiXOg` z=v1E+@nu-J_6D}gB_x5N)RMkf#wC+kKzW!6y=zkhniR9y@}aT2>q>b0xB`bNzl}W4 zsDsVcKCe%C4Q5N;POWeD2C3E@xcD~EPGN>V0*3d+X9hZ_~-*B5xDBL zDh(4>lo}!c-fKU$17a2A3!xg*JQt6bz?L*c^QXG8U7eycwR&$q8LlO4FKm2e)PI2a z?D2YVjc+h)!SMR{s@2z}#oaM*w#|ICWo%xpA;h`WP`)$`EEo@|~kk#j5K zw*8pqp3>5r;@9PFk15X z@t;^|pG&*|oN#LF)IKhoT`2zS!PKPmQf*%FIx#JNcSvjPV@-etks_2k+rKGxP~yG) zobm^lJYbhp(C#Xd^yZ%BqcZqERsguGf569sb^rP56~i_gNrx+&fBofU7ULRg*q|zT z&ksPiI&T1w{Sr{nAvH%LNSVl+4!)`Q1J53ilOWI|GJwnq1VldM6+vERav4LJaI{C* z@;K;*`R?6Br0cK$X*Dt5eGb5$A2cK=kQ_*geEvyUg2oPE{%7XTha2LSlrIZ|LRz;^dZU`jh8JGl-} zoC!e3x?%;l+TM{w;lmjZs<|L`AYq^ch|jd=_=*Yb1w$$Bn6&1NB-C2&aa<;7pGF2L z0mtbAz{X+Eg9W#iv^K6K~J-;7Z~pV+5?W0YFrMY}$pnfV*^T9jz6p*e4S z^CiHo4k+CdTfigUcfZ}H7R>%K=^48x>1Ycw68^7&w&cx~o1+2hbmX9CKKKbAd^1n_ z&{Y8EALt-8h)X+140zT@;hW8FlMqFNOQ7>q`{wv_94x`5HulN*L=-fkR0RYIfAZ%{ zCvqD@f+azqcDR!i0jSd{(;g^QQw-OxUX?;#xf;KyU?2eUGQUYMqicts15S^W4I%nk;JV_5xn*tBlT$=*i$SANg2gs5L5aZ^bM%FgMn?e z<|5Vb`VyX#jVmwH_SSs0nS}pFAP*C)!4|2R0C3XQul3tLHS(hSXFMp0&%J49CG|q? zyKjDg9nNiIdk{S5We;%~@YI?xMGZ(guf`|TiSI_{-aVV!+ahzaoEp)o4ninZ_U6Qo|u`)6TjE=h~vt;=q*);u4}PjbhHL~3AX3%WPmQZ^(+ zu{etpe1oJtIJf3wz?Wy_-~~$|jxPZ790knN{toIo6;HoqPT9hEh5R{{1Ul$LtL!tc zq#tp>oCHS#dJMP%T>(H*E~=G|m)l76#nTm`*H-%ykw%9z|2Ar4VWUFQmY%f7b4sbV zr!zMSiCp}c4nC+ae0+jG0xAZq9-xHd7e~CXFf-f;_n*o+F=8z^MJ=aqDtNP<`s9Jj z0X0XEy!U>FZbk=C+zV}70L{myHPN3h-F^n=qjYeJdT$ayuZ{v>hIlGsI(U~2#Q2B# zB~sE(-{|U9YgwFO$C8unN4Xdwpen-(`~xoka^6akrh?``1pc?voU7rubWz#cS2e5zUuS+K>J5Ljg0d z1Nt*OF3gPG8nCHs`Ezcf-M)5U1a=M7Tm$q^-#PRnGrMs?Zx%SQA|tPY=z zHw)i*1!ZxtJD=v^kZ`$owQ;f4nH5WZ=I35OAiyZ>DR3_WfaOm}r{Z-omM^EwuUaTw z*Mw(5CQ|+423Yevmw?!@r7HRIm)xM@X${G~!l+kWSB!~mFANR7BxDrcGgcO}Pq7_} zI-MM;YLXiwbtxEvZbiH(n#u*~a_o040xSDsVOJCDm+A{AK;;=Ms*-AAKjRwFA|U;b z8PFc7Fl+3TEIn4nAISU;g8)N1_*0lsOq4q?0N?wV!(3gGpXyo?axm{Np}_>FO1VYc z$3hI3C@B_VtRkuTOX{n~&mrn%V(|qHx;^t#y7~f&i{}aRQyO?5?)i$bXnpgeTnQu43D}`2e0ty^ks>5-t#7=>t;0U-LhFH0ani`rT%&)TYK(b ze;hT{bmXkwyt0}Up_ALb-W|V@Fl>M>B%dCfamGUaRy015b6#!dpAx>m3>06%@z^P$ zZE?g)g4eRpo)J!O$N}OuGbyI9dM0p&+7V@+8?8(3E?Dt>eR4AW-&PaI1UESN-xvyj zw71=f#M55IoQKk2wU7LC^`FPKw;dB0h%411(gT}Z1&{9a>|e?U_shO(0elHDTv-E{ zKAgvZFgGqjx$?5m+;EQlu9y$$eG!T~UyDxT+!fQIq`wD{!|U>0JLdUo_aGi=LemF3 z&htg^9Cg6H6RqN$n|9EAz2@tvKipge-6I`|FQ9xor-2?`p`Wx`c*22&t$&ay2s%wk zrO>hTTm1bQB{i{Klj_z1qW5J5$jQ2_9VC@i(YWjZce_$m1j-^8Xk9vlVZXvJu%Ees zSq*fdjTF4{+Z|lKw)<%29)~c(b5|k97+aEtam3^)~B-<(;*9qLHaU%A$Hn#|5UO-%b*A8DQMXq;< zEp|_?b`99dp@H>}R?J1W1hi4L4oU#CE3B@8*d!T)PRh(^tAz{ifLM{wWFj1I1$EMW+fc2H_PA zIScb5v$yn$t{pqnsfmPU%E}{*;r^*e?I)J%KiUF?RS<}gXzo~icG{^-!{|Fos=r6f zgPZmiPJM7WN*M3(?w>~mkSiK!TyqM|*PYI{?TwUYAQ%?$@qW5yu-3 zTK)#O-VV4PbicW>+aewb+l|*3Saywe37UN@jRYD2&sA2;0L3Wlh3TEGRdu@Y#nXOaXgN3dO|`|YPxEwcDDFJ zItoAq{}5YUupXdpBlA&iEVL>0-8Q0&t9NM^%N8Yi_@^H@@I4C6!`Pm0UOnlg(kazP z%qY{S+o?gHQtpx9I*Nvvcl;g}^m}lr)1`r%+YGTA4@y>BLVxe=d0wv;V$;&U zl~#!_;80ki6je6mi&~YZ=e+=sl7?gv26q2soOT(7$DZJSTnay}r(yFFVs?2d{Ua*v zWWJT?=Y<8Eshi&-wxlOwUHf9iEvp)g$NLioM_$y$DEAM<ddMoQZ}Nyqcqvh;UDTn?gPCY?o~u?N29**fg98F1)IV0 z_=?~H=K+^^cJp#!n7~|mBJu$DsYtdf1Hg?2D1V0w)LUZ=zCjDC7sb-T^Bq#l2VP0^ z^7AnltopBaUSjKW%9=tLE}Bls9#jDE`@j+4G4Acs%#JR%!?B}Y7(a=%iyIUcvp03b znxUACJ&F&fe!J~HsiQLjNF;!7Gkw2JYEbF!f<04J{${^5YF|yDc4d)taD?wcB1YUM zNJVl2NYBsx7PD>=B7E>tI=@W|!l_eX$shi|iGa>EV%h|JU*G>mN1xS!K_C@CYtg@e zHVD*2(N4|xyBc59Y3Jximu`VppB>mFsG_2R9PIuW3%(9aaBmcNC{T3iJSgAq;NLGP z=y=>mD4?(LX(xgI-w?K+Y)X-jO0^OGG(X9hZ5`PEL+}fuR z_P=xR^{IWM17G$60)2XVASUs55ZgiO2XILs(6x&P7>W41*YW>YVx9Zo3Yo&7P^Ev9 zl>F@AGMKVUVeWFS5n>fPsKf=J+=C-L{vM>$E&jz%-1}@ZU2wmji5&g>anLo+1Esz8*9lw~P}DDaY50L=TVfO| zkVqmu@(43bXThB4n4%MSCa_&0-yFQ|biJ1bWTbImsB5$w$>J49o>m!>!BIv515D_y zNA-Y_&um})|7d#)=sKDmVbDx5Gcz+YGc!A8JGNuSm^o%hw`78{v`~N786Cns63?2f56C;!^)uU~vP zX;Txxmut;uQ}oEFO!_)Kn{8NyV;^qT*y#0o0G)10hEDQPxE#M6yj9|Kb^3rG(jKGX z!##!wh#uS^0s-Zq{Kp*;J~W?dbYnMpU0mz2tcRSst^CnpnYd_X2+x6$$j2}D%Dz8Q z)lB5>V&U>Jo7}lKk-VcPnPqn~goZ_G!LW_Svy4LRv927p2mNi7<;;WRf+a#T`qj{g zX-7Y-?H{Nfmk-(pS|hJF;+t}RWkEAp zyWEqdST#gfBbgQOi?>gY!^nPM8fWag-Rr7y*vxa`@`Z4Th2CY|BUpieJKNrTiOR!O zLKqV6`N}gu7KGscl7)$^ZZ(sId0N8tB4Fzes;S*)Nw5}GKM&PWUp1}LEwXmMa6Oa_ z)`2y04b_|Gy*b9o9k||z=)`;X_1SPz2>@e#cQ~=h?9>#mkR8UsXd+Re_oF0$)%Msi zE6zeWD&goiTV4`=#uadYTtQ}|a^F3!+8HJDaA6Aai`*i^6!58b`Yh`-Z_v;#I& z1pxvg{b&9Myojy_$CA5W$uX7STyWNJxhZS+_GEpb;k5O6T|;?=YkHUP7(I2r>>t^7 zi5H-EyJ6pVlAs%u@F>Cngu2c=gRXHbSTJnMEcqPnY^4D=c9dNeA;5v!GUO4Hgnm&g z=xIIcIvAicLjTb#IsCCihDb^d9N_vJ4v{(Myi^?mncrGZ>T1)^@-5mFO^Om4w_ULD zm)NZ%^fza+Ld9;Pq&)#!#EQbFJ5}vx3KU{y>Pz?EmcM&qZ33_57hv&iM;2-oibUV; z2`(vBIG(4^bX#&iu^R&2J{Ej)Y~%jhIE^#Fxf!7`KWS9pNoAdcaRzC{Lw&=5KxGOA zUj$dlNAyRK1tNbHX~1Z~_&HVvWB)0A?3}wR$v&?{9q1bOz(fY!GHGK$^mi7sFO%~` zwk)RgW}YD9FVQsn_mu`U9i60?;>h89eDw)t%ctV)KX^Mt(u^P_K3&jBu4S+oS5^39 z5>trppRRW&KxL^!Mh#XQ|48%rKcva5@3h$1=vqZSg0~J)>d8}L;po0Q?QhGNinhp& zQ=GNm!YXIvTtZY($*jO0Ue5yJ~6O_TN_FLnM2=K^b_(we{#wU~zc6j+mx-=#J zW*rN-jB4>Vl#k3preU*<_ZQB8loBe|`LW)r*J`M#B-Z)L!yjdY!8*MC+4N(G9R?H_QLG9- zjg-`GYg$YRj7#mS9Yr`8G$~8n@}-)uxLLwQ5G{JJM9!`?=*TpVM{O8eKL?CvvnD|^)1J-B+zh}2YHEeBqAh(*L$^Y-@ zW`Gv}*z+-9kHyMAnckKb^sZUKIfP z&(r>&zsqNEI+1j}|2k726Coqvzh&xEG&D11P&9NfwQ(Y322?6DD4ROkIy)GfI`Z-| zh}+sY{rO@dWcynu&PvF{`A><3km)ZxKR<(*tCNI^lcAF-08~PSiJcJe`O^}h%s~kF z0LlO;MF(4B6;mf221QYE231p6Ck82NKec@TmF}X#4W6xOdS}+tpL1< zni|`hm@>$k+L$?+6Ebr${Y7(haxgWthJ$g<=+M@(U6Vxi=Ggk29*$=XS@VhqW5(LE z17V0;8D9?Yf_e~2vXJpL=1FR||9DqtlhPt>b6u{GWvmu;Ueb7+u>$Pz(Bba<^t^HH zK@Kl4QOU4E+Qt8LX!7#H=JEQ0_uAR@_~7Joc@<#7Z2Al1)guo2i9(CG#W9FX_&PAt zdu>zY>@Eu0rcep%71)D6OLB-_Ek!j^k*CT^o&??XYiJI3udmYw2^F;RC)eh z4Dq?DTk3{=3*RU7D*eH$@3JxL=vCQ8v%YV$ZsIbP15i;aeR3Q_*+X_2ra}%nxLraO z?&O=YEK~PL-p?MCL!+d;GTdA?G7Qa#%33aj&8o^c2L=8Lv?FiXZJs`t0$nwhUyJ2} z_|u>&QOn0*6_mdb>eY)1DR({Xa44kWd3g^ltD}x8qN4kolapZ-;r|T#0w#saG5Y1! z*`ZalvJt#{BVAK*J#Fwsruz9^RUzq6g=b{t4v4>U`3x3s_nW)Hd$gs0PCYu+0+jOB ztp5(qRyf=!f`d+6E`;UUB1bn$3sK*?>Snd})WsrUdg^-bWSIvd+P&af{^1JZB60c1e-i`VG-S@(A3%xcF5$y0fsf zN?>5BG&F5%DCvz$xOtjAU1R7hbX$W4OpnUK$TT$GWd&m_@pf;+h=oNY{V-mx=Pv`{ zw@=L5?Q9j<-z0)ggQgVX63W(=-M%P4EOYXa>r+{%nk*=OC_*C_gK0t$_TUF#d%j~2 zIK>IepYJ?xU}mX6+N_M+cKuSuu=4ip7Rlnf?aX@DO$>n_p(VVj?W z5r3}_tfVD9VgAl9=&c&h!~9ETxHOW^Z(Nj2#M{#7C;cmEWcWTACm6bK+lsqe zKm#yASAhxxY6^D^LyFUByQet!npT`ZPDST)VoX8eB+xUAPhPEklEVT}p6jfz$g84$ zoA!L^+Ct0Hv>&sP1H`6d96G1yVvh6v0&}(@h}PlL^Ew8FLdAT?XS?3sM|{Rt*+LK} z9iVu%Ud@SfL8{1~)0TD*#x)rX+*Y>Ce&LoL-pSUE+il>Y zUR}RDri-c9q16CAJ49=%J1%_EQZi~HDt9_JT4}txBDJZq&gzOJPN|CqSjAQ9oOv+} z5rw%@y@K@woNSr+!~MZ`6WdNPXHUo9BeTDhHd^}73*@R+jygP8)Jm-mt(;q#8^zdC zIkYft^RX?%g*HZB)r~V%^9NGsm+jDIAF6wZm(|+v-Iv)s?mHh_%tiZXl`l-1TzH}a zw8yE*7{#2JPboNX7pJN0U^#^udRUrO=I<#Vto`4;DP9Q%t1n^6Gvps)PZhRsC5)eB zaSz(%`ClPW9t(Oze@*kNm0VbRZ`ak?{s@aF;WfLCyfPNDMUP89qj;n8u(fJa|Ds=v zk8@2!+o@RQ$jfbQWoC9YB=_xyKzKa0XAs>1+(M0I3aV44ZEagH7emc`1E^)HOH_I; zBmIDbl1_M{ccWhQf_2nr1_ML2{>aoy{RwT8>s1^A!8P?e zx|>T5WWyCr22NEmu`QZnC9q#54SPVsoK$d_tU!rviX|1Blw$ou%vC_0jiv$tIJoL zjtQpO_nzTO7VIhA7Cjf^^}3Rps2VisX$cXdf|^SYIfF-8M#=#ZoM=~C8H#H30|f03 z(%T&mbov|b461=X4Pglfgu){-6g1VEo`VOtcss)cHvgB1TzCtWN-A>q1|;5EuO#*Y z^K|f=D8(x~c-$Tzq=KMa_{~Jf8UI!RZ{C_-kbcc;s-O>Wji?<`c>n%XdraZA{+^K! zE^_u|3NX(KMXELB>s!+)+$rlMJ@f$}XQlG-v z%tF}=ie}6TkKmB+rdy4p^j<`;TBJ+CnDm72Yi1y382o0eQ@yVIj>2vO^UxJS5hgoB zQH;yLIb@1DNE2b0=0GG+YI)|h-R?+aa^!IdXO;<*BIM9T?xTmV{tT`#*X3I*etBJW z+Bl*C+F!Qi_IfJPaDL4p{Z8%myek#pEaH=Sm)?S%QywP5=csR}Nxzt)^6AC;R+t;# zrM;UNsI^wG;QF&^Kv^bIqbK(+_SjmvQI0xCz#6wR%Zk}cvcwcj7zSD`28!nM<7I8o z;ub1IlQl3OaYV=xRXE5rRFG2tL(JFDP(PNjLn%q@5xKAhE@?n6E_|C2Iynd^+?c=J zhfp#Qli8$|^A(oltpAvZZ98=PqMlssB$Gd)y2W)ndfUuw!je@%oDSxlQK#XORC#GE z8y{47rz}?=6_lvDnF&!m1PjzK&_&5ccmK+9qmP4jTSJMLYQUqrkJQFPc`Ek6RYAFX zieaossJb{ylu-1J6r@MLre}=wNcnf@8`Xue`~H?(*-i?FKZej@I&5O&xfq{BmckYB z>61K86QdyNQvXU8$g-UAku6Cu@NR-+JE{zj)kWaIG~VyIr26|lGsElAYrrzh~omFof#h;yHPP;Icjj7H;7P$XxhV3Zh8L)}E3C%4+~QB8tZ@I%}nEHJhn zYr5anp@WkH{h>bU6-h@Q;V@Wk2%TVYF_n?*K#4mJ<%XIcdJPjKTk;FwHo&t?gMstv z87j?V{DBH-PDZ$caMXeE18rJWjn`~GS?wU%`K0hsMB zsK%eK0YQfPSzq18SBxuL~@K8`A6wNr=+B>@v1cQD<5hC9eJt36&no-m^T^{36JnQSb==*cFP?< z^-89ocPbX%Ecr^pj{iALLV_EX7(;I>d4wz~b3Ybw+W}3~;^{H`XgF{xpB8rV+bu6= zWFYMAJ}Y!c=Vra>7dyejF!28im)NlK!Wac8DvrVUi~ z)P*s)-t5?4O>F}ksK|p^z$CCJVl0ocB4RguizUEsf2C>;96@VC)^$-stX)N^#U-jr zvPgb6tr5p6L~QGG^fCW<9FP~Y_UfOlidlgn^*+oE_;B;FU z$GllFXcg>hZE-v#*772!NLK})dOhY z`4#jjCh^OkYM5Tp<>S6H9_xh-k%?-Cw{pw2TKT^tBW0avd7i!+HK)A?bnbltx0lwI z&nF4-LT#SB3Pyv^tQxAy&!^4s=?Uhaa(%2LQBL0Sj@TGJfiD~=N;vpNs|~jj9;LRH zUa<8t+fX#1-2_`JoI96^ih4COcuURRh^s*y9$7X;DVH{&SuRw@N#&X8+r9aKbru*0 z%9DG{Mp_t)(??U(NJoTog)J%R7zoi36o{m=@mv)Xvd<4?1P@PS>$0%ey2gYdCEoj; ziQs`i&&u+%M|uMO2?4>=n4ZMX<8!9>JsY>~gAAKl+LGX*9Y+wFX{Pu(t|Dxl4OUy| zPL3xonAu@?bn!mHBz1Nv2RVb1uuoCAjm zbAEzZy{u(#99((=G_j#I@=101COH;}Wt9lni&dP6B9JUB@=<6GfOTM=T*Hh(!yq1V zf0zZ^3{j~IY+*Rsa`(M^{;xU8hI{S3BGjXI=qgaZpe@!;a0Y`dt2`r~FG3_KkqvQX za-Pw9aihxoX^ddtsADeCHP^Z~J+DnUp~Cqk^TO4;jBrF`xXLMYG z3HsJ6;^+WHJxoaaxV_ebT26y!$m9Rfh@)ew1ioe!+>yEzfiwc8@ij3>zWc|R*lM#r z!%=%{E(&mK1#$LTbA`?UbsMloj^b)Wva4J|<3&!y&%BHuii1V2jZ3>ZoFMx!e17Lu>=f@M?t>QA~=zvE>J}oya_JRtn0TU~_v2@&yVba-7HRI6T`0U)|)T`Yoa$-^PxOT;Srh zf4IwybwSk0&@?4un1}60l5GH2zE!MS{k{rnIOQ*{DK8^2t%5*7vsB9Fc}BHB zK)h7;Ge+-xpcnqh@|C8-80+nWEYGsn2(vmJna5EJvh5suy!n&~jtE%QUsu!vl4q=w zS_%{kGNnv;t70&Ak3Oi~hlatB+oq(@(f%YP7*-xVXP(=S5CgErArc3xPrR&k?pD*YYKrgJ2!PB;{SElbpB=!kw;ZfxIBzu)v$Rp&E*{Ed>?U z6TLS$xB7{Wx-fz>$)0Zrnx##nKkCr#bC1Lcq*q#j<(>V!z&bGs(Z8gy`;F($l`?H- zv{c7AwQ)Z}uqNX^qQ24-q8s80LuO}#6cfL%-T9g{&||Gfc}k%aa|E3;NEscTcwR!p zTf(B;VligVO2b|$Jm^OJE7BwzZq$(RpwBp9GB8J?r>|fyZ>Uy3SK7$YfR{1fH#Dlh|pY8_h4m2`s zv;gx!_=K=s+({XW&AU||GtgK}k-wTJn#78@oeN8qsGy2Im%)0UE-;OB4i;*$7ze*5 zik*`cb-LhxN6M6FcCG$ZvK6IkP4!z4A1{qqqNsm#G)BZc_2l=bj?9Uoj3}AiE6R=+ zuvDrGikGlhIh(E29Ejg?Hi}#;Y3o-`iaf~c!AJVIcD(40bXstlDu*kw$!tQfUvZAm z4^+LZy0c1E9xW8nT6J{h541LCw@um#^C5-4jWnqjm*4-$pof|UPi42aG8669E??kL zia>=>ZJS*D0m!$BEF=BZs{k)y=eAcM@=lyQ^5^&SBgr~xq6G|Rrifaa;x3dq^i5ww z=PYYy%p^PPA7-+9yEY4uH1vj687sMAGPYXwYQ;AC_V>c8xjWzI%1GxDuDjfWv2>Jb z&Qz_qc%zQNJ9TRkcaT&Vt`1{|OBd9YC~UyjijIWb4F%Rp-2*b(2-wgA6_|!x!O1FN z^hJA>dQL5MHOFbzLzCB38O06or`tk$V1oGYPAd$+Ob{(!JwwcT%W&h1#TW~{FFk8} zoxJ8Crm|I(;#uMMK9*M`>K67K(l!ehuaVS%<8lN94qev^Ei0DOcS;tc&JkwcQrQ>v zOO<>KhhCTku}cK1(sw_m-_lLTlkgM=(}O(S-;=RDA}CFS&2~v7;j=8!Nbv%@{S73< zg$`rA!$;3+wiR4UZmwTIHu^zJZ|INrgK=KqnQ=s*l+l(jbjo|?hGAMi_Fb}CoM|!A z@fWKk%H@4NxO&48+WS+Cgxr2oORYM5vRS)ZBMtd6AkT-W$c)p?)=x(34P7A{$AgO5 z+N)+^$0|$nrn5HuYK~B*4v_M6K4HR?eJm2#dT*;ghHnzzdgj*i zqeSBYZD=J;wO*w;R(>gR)dUjeK7-Fmq)FL=rl%bb;PT`*hu zrL5H>kkPk^7Gzdw$$kHbfA}6l)$h}fp*;mspN7tTUkhRM1Nf~AwDM6tCSQI>L1ps{ z0p+R?JL6pUH1@u(gyrTOdeVJV*X^R77@7&_E?f)AqpXdDArg-OmcipNdH20mCE=C% zEQt8m&T7wNjsSM4`a*>O>K7_azi%-Oar9>@^u$s%g2sZdqoz4Eh7^+Ob7Z+eFDhnq zl9c{)vo@4RDz(0Yh`XoEcsKsk;qG9bC8jy^ATq6W`b^l7kBFHmHN(B9Rfch(HHK3S%8g|QOgHNO9r<_;Sbub|vx zBg&;D$9M)soXR5e!zfEK_J|tXndnvY2&S_thT_`nIqXitgr9t@8MDy~ke=3JJePt7 z>v*0GtRFUfO-{#g34mO3J$gCERte4+-)Bc=rek3$z|FKvGn09(mc}q!-+2#RUCk81 z(tNVNTQ7U3=V{G5agcI^2wfsjcmcIXeHb`o_|D`kvTiI9CV4lK0}qN zX?OOR{v9TEn>8r;M_U5no+)D<%n#;lkrV#Zmqm^z=Ps<0tEz050BqGzzoll|_?S}J z1UyCo;!t3pkO`~IuU^>gPsq=`=3LO@IYFJ%9*a;R&HzB_K9< zxg7!zQA|&lv7R$UC@A4v@Lc*<>Q*!ZhB{!Yq*tpoiY9Y)o{&!CLkoVuH&>`_A1tCc z0e(CUaYA7+aY~Ixa$iLL2tFA5Bbgw4$2y3+HrFBA-Rkk{dMoUjV@e|I3vy+&H9==T zl<1=A!eh#JxR2$!`~f|o5g|kE@J|F3b$t5&+NAwsg#OEf`)ktviH^@;$Y+Y+o{HXKr%8iX#NM* zpEgvSOs&-cD1Tvu|AznQ*qFEo|8xKdHnKAQ=@t+L{39ZO32n*@;QDVc^4|>YKXUjt zuK&L}9{v|6!++(A05~50o2cjiv`gZjaO?k!OM?C1B=x7|e@W{9$tA(e{C{&ve3fxT zkwWg|>HW-&J_)sN%X&{S4Ke73xCHtV-tNKZ$k=FwYG}2HE@QW{*_nDD)7nZ?rb7qG z#MG;-Zswh+_FP<^P}}!oC7vSKHY>Y*czOHucJ0)vv6+waJx0JQ?frVk?O_NI47}3( zmVqH_dRz9+m&NoHZI(!xqNp{HmPcFnjDh)h1Ikc$8vM?eq`Nyd_TEvq(sy#xw0Q%{ z=P}HcU2&1z)RLxq=wo`@b$N*g?18$S>YxX_#6DN2B_3rBQ_)+~)RK|uGcvY9Jch7$ z_Sl|ks&Cub1Gz+qCJGwC@}L3ScNH)IBhm3w;ar5k?Ab5HYus`2n-57p3|&}h9?>@m z+blCJnW~IgONn?>T{L0NsKCW}S{=P_UFjoUKc%|ooql`|Z2Yb}tT^aA*#RR@zkMAI zNHMus&8T+xyjMQ3td;z|0N*rX*N1kz&p5-dS%B*b`~&1L@(lRFYY=84(Y*GOQogCb z<1s=tS!sehLO6rfUmU$wo`e$)sot$bINTS{Ok9P}C9JHq{)~Tb;S9{BZ!Ke~F8PW) z|2bH*WnK)=@OSTv4NkeV*h)in=itVVwA)!A=i(Lg5KFaU)*T<408I6=P+Ijb*GN0B zF^+t%kWYzo?GV5Q8B;xuxVgOo5kKkcslgP4FU$PUBJ6YPK-KMf$OQL6K1NFi-yFM^ zH(wtaR_NdpN`)Z5GF7YLYV`1rqhbc`apq%Vre14wVIJ_wsKgWd*}n5^rYc74n6RO2QT zb#$1Fama;Hw*d0|?W+56|HRQH-O+-egY0Xn39had(4#MI*_XvYW2A{2;aMUXJIPKlcp9 z*_?E_2kjWG`$2B5SR=mRtOTQNW!ra5v{YHlr_l@MY)}>9xWB=pX$HJF0xht)tIhG# z1XyEr=@I`R038Q>F8^Hso9)bHJVyp{s5 zq=mj@!+y1hy1@6`hdx_xS_7hYn<=<V9yTU>F+B-Jz{Qa0W zQd9z*{~UL&{_J~bc23!to>w0$%ADdZL;WMhAeJ{r5V(Aqu|zPy5iL0kgEGaQLm_*T z|7#=IxDH7gRXVt?h4q;rhnlancl?X)m)6|{PEAD4u_DM*SKRU)dt**9{Amw~I$#3) zyVO6S%Z0pUgn2bd4e0{sSr8;+&-hUsYXv9f2aehJmgLb4Kg+Mg1-|hgp*~*BSV6s^ zKfFe4dRu(&F>=KI+hBTm@!wXFlR(^)9;)E!>Es>_@tjS652A31uXgux05>_(vi-@X(%!h3H+ z9Gc}18_WD8&50c;X=n`aeN(Jx3J5Y$BK;vEau&qoiJZc=OoqTTHM99qO%|Jy=8~XE z^?Juiw{0Qot|dI?e_fE~T7Sl#gaW72ySudqs^jBF!2m9VqS|oxqHRdYe8~v2@zBtO z17E1B#FpA&9_}Y394t=auP{xjDeGLw4ED^rYVn}$MMuCkMSDO9jx0ci zLB`xIvHommiP7D8hy`8}UvkqGvrP6-%!YNws_UV$bhi5p)E22y<9HS!yD@$nsy}T! z3D>(2ho+EY#iQdR@uo;{+Ve+CmPC}^ahH9!?{&oxt0Wnw(OhXo=c}Nv9l8*>N%<^=QDqw8L`?~M;@kilhSBA?@e*E#(wsCy?lp`% zIMCnk6)iM&1DsD=R~IKRwJT?d6)B2-L3+2XiE#s(=lzzr7JdgsZgP+l|D0 z9~Evh`4Z8V+(gYA&(80FA?+Mr$R42i`vfyZqVKS$znNlbHU}D_*(4mbx(Ed%kaj|^ z$%zqlCU@;?x)@57-H4tH2)RdY+6MDHZt8NN(yL5kBlZZe9^4%e z2ZDoda0`}!!>oZU2L)XuQzc64mOA6IEhu;!DakAdBN-#YlIzrRt*^qMX!24vlY3VVJK?8=Cd@)b^|z(#J~& z*A6Ps2f*oQY*Ffm)sR5%i&!bR`A=cSc)gCMMmTwt6sc-r<}vQDmiFJ!NqEa6U3&Nr zT(%JI_}F#3t@w3T-~%gW11+x5Qd;o4dV5B%<&zY#5+B3$KU}BS@mbZ^^Ro1_={3h{ z`oC+S1~@a1v$G@8$i+^*ibgcB;+F9?U^>w#=t&f6hHth0^5a}kh|b}@vM-fr%w4UP z8?;hGkHlA!Ko)T>KqcWmVf2NXV%J==wjK&^!Z#EMz$(S0n) zCl~c)o{wu6&}vz} zOB8}zPik6QOhrR2sy!sGhf2s4@v7m84aALL3K0eKRMBdDK}pRvM-hbzP%0xnU&NXR zxu7gfDs6uPL8+?)qob0B^^l__f<@y+W%nfylAt@fFlq(Z#sF%-RzUghev>&%e7Qzr zS<~pJA-0nKj*+?0c4l=P%TS;A`UhL5FAH-{r=}=|{0%Is>dQ|FU>@yoykwDFGf%Q} zDxen_myuayX~HC#LSzpte81Oc?8$!2B##W|p6^TI!55HrrZIlx%SqTVZ!7vN{5zHeZhS@ZbCDwIxF zhSr^LtuAb{{As(3f6>|)9Gld5xkvkjUcK@ynNFRtb-l(5t!uX13j=MTQ`)5}37kd* zJ@i7YMDBrOy@R@#yKsyQmV~dtOHKHxGH4CGPQadP%cu6xkr;OA7ONYR*P3S|^5{81 zm20L@3jTh+NFi_omgDo=ZaUd75Qm94;G7!RWK34C)yd znJBe*Ig!jXaVHt+Qkcbq0*W6p5bCuuO?#@il{yX)4G`aBja$jc3P^}unD0%7y{TVh z_mA#UOD6m6QZ4d9ris20OEg|`%=f#l z)1K%lF_nQF1z7WY~Bq6=(`T|7^+7cqK z{7Ch7qkZn*r1X3*T{t2ifttZp=F)F${zzT0d4nJB=;-*k^H5`-pq0L~8UMBCf$Kk6 zYC_IV=C%%$vW7O6jz3HtoM;IZ4V@e;j4i1E>tg|nQ2|~9%8ySVIUoxlV;~10TOdck z|2H5fph_S@APqp-0muYUVg_OaVgh3P7m|gojVNG|E2StmGb0l#6EibA6B{cd3nvXD z7X>3D1prLW*5v;M0#M#*N|6BL}*&=2AxKZx`mWa9#(e8wP9fWfk7>nErTaS4u zrAUq|yO9~qTMRddEqhBYz{+ArO14CIyW~}}Q@%@xA3Nh!vF93Y7 z74TZ(&P$T0eqHa{e+_{VBK`nYLi`ivm)dcBh|VmH?5x!#9%Ku{N4$T1kB1Ac7IlI& zmvC}@42o0e7?w98g-mYmsj{OVJp-G@(T%d>PkLlmtE&`WLf53A&`uy<*W)z7X|hfj zSY6U9DCJSzRLGc8qqtQOfBK}fIw0wnd2rwUy7{j;GAA%-t*$6JLdkDP zO)x+}H6S`dzTsfHUkj(Ji4;wa;`pP5M7lpX!)kwUa`D1Af0 zJ7M!mLBjLMtOF&$(se}Afw0NlpcD7}D2{)MGV;Ncm#~7t9Dxc;Ax@gt21>#xmnB0K z01*(%=1D@yl3^BL@ClQR=;JFT6!P%(lF1~vUfWU6s^JrsY48)D&gNM?I-w`!~oFNPBP49^IQuLM}%W_F|^{!?B z$%^Ws|MCb;Uf&|I83#WgghJXvR#%n`sUqEm6qK?{fz9lmg|M54Z~ z=&v*(F$J?}d;n>p#{&@1gIr2lLPmh91F^Dzajcpppw8g-Lq{|fVhJ8dqadnp1b)9r12Au%uW@tv2ai{RuM#ZVBH** zb-?_KQ$d(-w=LF&-xWr6NF$K-jt`ZeHhVq3h3t!>D=Mm#fiMUsG#g^Ks2z`A>;PD< z5!g>mx`zHiTXP|>$A-$N$P)t{t2?qR!s%kbltgwSt#LQ&4J?SsApu1V(I52y0m6dd zg~UVSMZgRXC;*2N{yp7Ai2oaiK$JV+)WS^W4pK4%nC-h1qBGKLmI;9Gl!z>Gn7wXF zKTJ?%OyR(vw*`S|DDG%f(MY`W<{W+OSB0v?WPvmo2B7_eIk+I8jGV#U%!bAZFw)&Z z;C24wI=qmgSbiX&+M;M*spXsne2D1-A2!I4EHyCdQf686|m17F?*wQ=Qv zS&Qu?H4V-}OR)wN#ZEVhFQfhFnL>t@EY7haorUv+wJ|M74r$(jGl63OK@;9X>hh}u z6&LD+i`Hg`xX$;2t&I01Zb4s1Rq53=M;UdFG$z56;zsz&;ME^8rrBQ?5fZJ|?uVHa z=bD6cElfOoDcByUhvOx+DU(nyo84^_v8*7-{h|wE+UF>Vv_5EQaO0b#i~|B~ldAK( z`wA#FBkw5;>6*$A)i)(+Fh4M@j(1}H2ADSrQ&#M1{U*)HKLPQ&1V$dqKC4OnOD*gm zZG`0HEH)KUux}(LQ>NcyQa%eymdMR^n6fy(e`1LKu^tssk)!A-(g>HK)2y<#zXDPh z7lmX!@6Wc7&Gq&*WL;Ch?P|yiw5kau7k^7)uN9WX=tn1s`?8#@LoHIyw9~}sj>e=5 zazX6<<;hpaA0?$ZNmQnsQYhHO4NFT%Vo(!~Nte03=8*4L0zyafyZ_P^4g@ajd_zG$ zU3h~%eqI}U25~D*Lyyi_1XiKHN$BtI&@nSQAs5s{WQ9qbNCY7l*d#%2m}lhukj(|; zGb14vVKopzPySWxxPeh|O8!wnbE|Q*jL=DI?8i#5cBB(V)nVqp8NChdhJwxpB<*pU zr6DpTJE5ltKERm2|O1jM%<4-nRMqaX@3fy1vB0VAI+9e6W;#X`{#6?)JLTm#x3? z?sWUSx$%JT<8}d|lJ7QH;O&8fLbP22%SX&y2qE(RZGRuZc5@w1DoIxnYCq3_kL+or zEO_%h8E05Qdp-GaEzHtQD5UZcQXd0)No>bC)=8ICAA@R1>;&W}8zqLOrvap%hWQKP z)fddGFN9ZLD6hUSUeRzu(Fk<_;cEjS(D??VcZ+=4$_2lgCUTWlOlA0R{d}(q*gNif zbtpOw@4~;4>^~P78B+JQr^Gz)pM&jNgu7g$-p%On#}L@;{E)m*+MYO^%uaaTYYT2_ zs_JZc-QWHppLRpP?>T*Uo93qF$a(Rrw88Us(}(-4WYq{^F7LeewQ%zbTNWExR>Jdg z!kz2{07}crXmum$QD%jq;Z#%>HoLws3+-hY(+9T|Bf;Yn_IxOp@t%x)ahrd<>{4UV zk{}_4N5B#}JCU35m~*hwJbG%{8yB4dH*MZet4gd2)c55UbHuC=UY0wmiDvb*)#aq1 zu|%YUc%DWWa6mvjQ7{gC(<%Xtj|#X5bMX#(7{Cn_E8p-7Q>=oz2MwIHh*0FEaW zpVpnp%Fgv-A~4LY;)+4dEr2Qn7Cz<`KhY|QmfMk6=B~Bu?5EA-ftnu{@q#=Ip0y5pV<6U>2YR zV@pZjBJk*n;ldAk8+G!`Mn*=;WK^0h#3-wv647!;+8ZUN3O*D59#f(l(IlGi&ji z3%;6`k{YU-*q?)`Zz*$8DZEBvDgs1xsfgw?yw(KkB5>siqDE(*x=JLd!2(gWXK-Z^ zHsmn%VXU)XRT!~M@c4;TUDY}3`Kv)hIlSRQD#FWfulgcNz-BnM#VJX6BU3GR0^7o} z1iH1ci8H5Vsl9KxJGPdSU!9Yd#OpY(#Y02ppcesbtk_V7*xEQGsL3-??NLfy5%xQf zmUjp(_d$8fAaLy)qL$ORmSd!s31Amcl2cwYD(>>B@%V50YZkvBdoZ;C$leD5z_sQP z<;Ig~-wXa#vcx3}9~}NyBNistZj;JRn%Suo6P+&oIhO%MwatB6thYTtTD+p@KR7Lm zVj+iju4N2^0R#X_f2#qUo6NYG=x)*K0s%a-3Ta;F22z`lf7l5(9g~ z6ja9~DeKev1OF4ib_Ux5ryzQ^xO#K9R;yjE*S9Rz*H!yGz3|@?`J3LaCw8}W@^Q-^ z6&*j9Q)ZakuWQ7jS6Z3n%x)8ti;hRb6m=16?~5#jKd^-PE+fsvdD<3&=MptctYS~% zr0R1*hM2Qw%p0%5@|p?b(M@jpbCjCs@v4r7aXoBIS4>P7Olr*?)|(T>;uG286UpKe z(c+EibFXEen35H}_ilFk@0`frNLE;tU2%^cf4b#Nn|P$!VYu1`Fz{7MIw9xE*OalH zUtS6fsWSeU#EuL?sUksZfWYQJb z5O|NZ!lj}OhnW*J#HT6`hZz$z#LK(J>{W?0#4%@Gv4I&+0(nO%83Nw3hne5FS~Wh9 ztgG@WDqPEpH`@_NNP9N$Eo1CY6o{GtjQ{FhM9mM*+C#vYgfTY3o9k6I#wDc5kWlB2 zrrj8*{AXwlxwX=T0Y)Vz&7>z_EaH-siToXl1OFO}>bS(=fKfS@0x=x+D^?7HlZLuB zkNBShTukC1i9ftqAz<gEBA3=P$iuC---J0v$+!?Xm|&JN}kdJ z8^e}0bMU7b_!zd|trM9Xb*Y2gf{U*3={x}iB>-JTzgD?I&6Q17Pb+D!P=2c+sbzd3$x zXKv3`i70tUrPt!ga}la0Gs<7b_5|mga&fPc{T8M3D!gfo_q0=4?3r0dGj7VdPV*m1 z?lTk2(#+iPrK)vx)Y3p9EgJ8a+{_t6@VZuc=7 z7;g8m8We8#aT*+M_wgDMZqBh91jp(H4{$s0-*uv$DmB-{R_SM5VjIKjbqmgktuZXx zB>(dzKFL-7*@xH$1&`Qz9I4mXdJ-uQWwXV#A2w@h9H@2P)q&2&Os9}CnjDyQ__*KR z;UP~CC>GE2&l>nQ#7AG;pcl^z%CnOV`0U1C8o(AORLaxAQ|s|JSc^fs9xCSFOYbS6 zv=Dgfy!AuN4$$FxDTE#;(%agqE-wjeIy-%wADh;)H~2;Tx7s~6F1Wq2#ZCC*j(0a0 zF1_8J-Y%Ag6eQloPTajd?S9;neZ1bDUT(ho_3dx|{&cwAxo8VcpSrN=>hh>dCNkdd z>h!+9x!(vUu$>WpyBe`9*?!pGf46*po#-3;>_`-TJ@vWRe7jwHef9b6>HfK~mR%rs zp6v7P`s1AgXbuPK7>cYqMrY~HB0nowCS)~O2>-NOC!V5H8 z!~Iy3!29Xt4pJua)nsq?isG^bGn9OtkX5#kb;2zFz{@htrFqo{MfI}S%S&(o_@}<% zGk*omkS54<(n{!?4~grayL%u@c1phnRYuv(FpKRSF>;!*0 z%PY+ISw4B4tW%lt!{08wYadQ)Y&ISZ)?4*F&R+F7f=c_Xh$dq! zjg&?*XpO!Gb1&>GHY)4v*H&{q>{6C0zt{~e=0ez8%v5aHk-p6-K;~mMNC@TLBC*RD zTpm0OT3yyWxL90zJ`^nwz`Z|kd_u0lO&$L?-oF36g&E8oEdTE4(w&+39>|CYwB?aS zJalfz)Y{-86sX>|l`AlR4rgEcp6G2bpAI+qUhA zHL-1;I1_7PPHY<|Ik9cqwyhK6<@>(>z4h*^cdLHY)xG!H-D~yUy{j7Qx3av9?7_CX zt(5g}_JeV*#a))H*X!!*xvdfPf=mI|I#s|O81c5F`bN7qIKJE(?=q%}w}!#A&d6Ic zKl42{4pPh?W#{Bg8^61x{fc+?q2>F#N_?-4%W=e?)>~sTF;o5#D&{K1#u6wgJ)T&SFhjH2ZONwFP;1UUQ7MIFC#LuadELT|Hs>(nTVB{g@gV7a}4Ip3(8GpG4+VM zQSQ>4Y#n=jI`X+hhBT1v1b+^aEbv!eC=D4>sFAU;^=u@3R4ab+zo5)O#^IlX2t(JN zQA7yTTV5|3=E`TuvNz-oF6e`d_qIkcckfQ-;y-rFcgJ5gUOr=;xLzC|+8r{QL;NHS zjJ)d3DF@y^ue4C&79-#8%lzbynpaa@d_CBK(nj*=3qX2%SxMSI|3^7`i|o-8cmylI z&=5j%uhXvhH>H6|I5T+v{5|8m(`%1T_>r%CrPU|L?g+LwTV9BY9O2-@UF&p)>V z9q@$hFCbsPX7VZhDr}s&^%~2P%itFC+pY_5%+1Lib-Ev2_;mxq30MUtx}82*Dz`8Le2@ zJq25T`be-}AktxFC`32z5T}u0hLH*jsl$yd!rc)RFMq_IHY}}-pEF>(x1J&6J(^Qh z!fu-vicMDI%miVH2e25kUZv*{gebB+)B2T)RCd>%CwU8sRnq4?t_OkTzde^7u_uY) z3N~y&Io)1EW!r+ZD>_dWoSLDR7Tr$;8X(Re0rv)fVx5-|>HA##$ z`mR*pwNve*zC`&rZj#XT{1;xmzkt!?9_encLXO7T95*%*^0mKv8y^V1%U@nw`l-F! z>|}^({EVsXgq$RHbLmn3GWmg7efOWI|EG@szjPDp=m-__36{UyA19$ikQnmqD^A;< z-98c&IlHuIDiz^;eqsqMIQO3g>WV+)^v{*(EGKN;`&4X8G4`<`(d806cB$P3ncaqb z-P?ifR7As7mFM&sIL>FNM=wloBEu?cvp2>UA5G-9i0-~4^QgOua37Ab;=i^zgx~SN zLw~J*gyny|4Bpby&bA7rY?Fk`Oy2$xac{ zl6Ju}K|HV7`j2`a23X*$^n_^fk~(8*9rA_vzt>eT&C7V`MT1jB3Jw*@&0Rbyk0|nh z7ysU)tQ&$5K~AOx-yaG$$sU7z)Kl*7E3`XP+g>=bkjj80UZ+QJP-QttXAv`6{7L&E z*WT^F`Y?Ke7bdFo@nF*X!iTaLRaTI=H3Q}E)Wnd; z0AZj^OofZF$-x_)iDXAbf)f(AK>9=?G&^wE1pJ#}?qc)TyV}k9<3Aw*x?LR%)lSBk zv2i7^#jkh`PBOgGwSODZ#Rnl#N1n)1%i;N}3*b%#bMARrk?H^cB&5Wzd*P5x$!8m42JC8`}Q6Z-?kWFKyP%hP@oi{IY=5$^h zY|*7OF*1IEuBpM&MQYx9{L-J%*m2oGB0`Wcio;}MB%6IS(`+Somzm97chRT8^FKm5D=OA5D?@aKAfJhr#fzb=^Zf9^SzxBjrXIdjsnYBQ2F3`)eb^+IA4|6KKclKhc8F)e^B?Re)CS4yW_ z2%dhvRVk3g1mx%Z3#+AEw?4?3SmF))N-$S%MiB5%hH2r)jMfk zw@!$KJkb$su8sucG9dxy%w+%23395{8 zhGmSrK%0mpK*}QIr{;V4({?pB`*r(PUXYCM+D+2!)g;OO8zJJlOfmGsRDI9(g-CAe z1Od$YvNzM8!Q}wr51}(b4Hx^Xty-u}J}#%2)y;O!y34bTn5u`l4fBT?&uhP_^K~fU z#!P-B9G<_?&VBqh=c$WW7K0CVaX}0Yo3=QgzJtAo{WZM^vI$Ntp3yLfrw7uAqpFT&JeF(HW|aaro~uz9#AfLIMrXfmH86ypQ7D~gDmA2PNU zIX5-hjG|co?;&4V>LSVZaG!|Goj!PM$lM2!G*T&D4F@cM&F-C5@hgK(og0jA5p?8E z5tbyP%dh+eET|+Q#my4nYxWG7Wt480EMQ%EbYtkHS1N6ddPyfMMQRQSIv z&)Xb9^j%d71-7FuwBlxpMvM5$|H-WE^8A_iA#%j!fy58Z?>r^pqJyye(2YYmrM7g= zHnuAB?u{#Yn~Jog|25pQFaL{`IJ}TNq&#|d*^F1e)(=567jM-81L+t;t+B%+wbqV~ z$nK$!dtSRvr$RV_c4DNi_r^^h^SFdppLMd=Hg9%X+|zZBV`fXLEKUa_BZ|b!QQD#L zaq7aG+cu-T;JB3=7#Nx3wG4=Gj(#m^>QbM5al&<<-ObWgzWq%1^8WHEDvbd{4%1}H zQ{Kg=ks2Mo@me<8-FR5q_4&8NFu_AMwf63!eJ;>=PNUVYG{QGVHK+DaZm&0l6{Q*q zsvX8rw{XMMQMFoD)+0+z5a+37vsxj`h+DqUIY@)u+0#1cDBWarn3a&ZOapaKQt!__ zd1Yw-EvxTO8r2pawZ58I(F`}A1Nm-K8k=pxGz{iQ!}+swVnOfQrYCZ z?7@*!_4;PKXDQ`iQTm@HXLS!pJcSv2K96IRi6G)D$oq!^aJe7lFp42C+GQ3eEdje%XYB9rQp$SgwG+yxl-a7|~g$E2-tSIHWg?Qyjt(EUz#Qh_> zwWza?)-6~Ot8Ofvg&Ybbz1*dOKm1QWAX?u~oIHn3B{1CodSeZ`(0)3XEj{tbsAXmw zcXHx@f460!&7tFaqHK~Z&bN1|soZSYlkYwvU+yTOrZ_FJrZbPm7Xt>GzG|~7=0l`S zj24J0%KsU{qHf8R{1{19UTm*7^BCI#<5Za*4qw1IS!rr*oSf`6?j%(JUN(5aW#PL# zN=cV`*9K*Khh ziyLo`T{C&0Z2ip^U$NYz`076zmQy8>mZi|S(}H|YW8g}#2Fh$E4M?$&8DL7yO$|nT zy*koOj$RasRn-nf2(V6BC&K-XqM)N-+!l(5>bTleG|xRDF6#FdzequT@f~pJkezMJ zTibfx?Cb3#Zd7+M#+a?);%ab7``~+c!@tQ@mEdvnBHQm1wDG-& zgnw*E^>q&OryA)U<&LPpPcp+wfoho`G7*F?oZ znKOrMoA(xZ9pdr%*NXTCS8kL9^!01gw8h~7s`mMwy|^M+e+DW~+7nfeIRc|M!GjfNPm$tJ@+dwFOepG5^J zG9qGjg(61YlbO*1SN=ELqs*XYzgx~a+l9Um7R+-=GE!nf+!mggvmXft+6i=YSe`V* z(J*v|vTpG5(3P~DYSZ(DYOj80d)xM>Q;Vvg0?%8xoPjuaWd=b90rJPIUCR8@x}9^!_ikHFEl&a$zseZYjz2K)}LNcvZid&XTNfm1NBvrhDUAQEQ3>NKsC(4^dOp;69)V3(EJcfqSWxJs2wu@4I?xi_TzX zt?Li}OpL!nLWf}`@$|x8!X=Wyxf?v>6Ins@L;z3H(6fwm) zs+P6Dw}!Lda+0>_!pztS*j>E);sr=xh376MUxvrLr-BHs9bYdE9eV~c{XnNM^|+}+ z4LJb&(O>pCHu(3Ul7*Bx7C!ut-1VPwnP426vkkX+xNOsF08AObo<1Yzae@;bpR+gZ zcfYUW{_!4n&l69F5|(mIdY#=w>8oU<3JwZZebg;bnJcb4@G8<5;-#FU=M;@ZSj7=2Wj`Vh z&wfRX?^gjFqCKS)b6ID;o^2(^*ozv9eMSR zb2gylWdk0zLiabBZwZ_d(TOPTa|3f0{vea$)8c`qX{em>NLV^)7%IjlV;Q@7%yyIv2DQu3-C#Rl!fH)#&ZggkpozyN~ zG0NaL2}GDM^`sc=dj zbxKZG7O;Y`twHIDX+IW{lvAD~yUjtSFY3UJ2~Tbt#ACd+ zlGTS6RR(=pp-b!rX$Ari(Wd{~Iodt&{IG!Q-AU(yc^N{_uzH$mM{k~l@8j}38@aX$ zu(Ld=i7i44uzr5wWOe@qWxk?XQ=>7KIe0vnCg?h8Z|0tv8*^+v$*zp1RsP`8b zdO2l!qKt;AxZR(?@+PWNWXp$D$AItJsFiQdi;*FFpp%}kCTVaX`EvAItL=$SyBzut zn_4XnJqFL@>8*$Hj^Dp?dw*vbvrg_ZVB^hDM!|cE>Vd_QBBck78fMEaYn<%M{A)Ch z+JHK`0Ov+i`+^NIGG*ATgTs5;$zCb!?fxLk$<9>6%+|mGNj^t=9lQB6p%~Pg#!Hnh zBmxI@lYhodQR+iiHf#w&{g2rZNf%fxbo>qedKqL-(U%+*io4TQh^l*6i z>uce8Kp>&V6hzz$If;ZqP!n`|7Hj071fm|oy?$B?3+~KV^Lz@AjKBd*SXI#_5kat| z!!tr^oT!#Gws#1cuT<<9cw19(eNyDRsE!v|I5t#S9gdeaPMEkZ>JUrrRm1U0hGJ3j zc(gdC$Ia1js=2(n`UU}k#>dXPv>YH-Wn|OYT;?=0^Bv3a(VX<~l8SNtV}^i-KX~fj z=Dl|Xh479q3W_jIwf3q%OGuex>CKSd`V%Cob;OB-$e{!epbjMvt*AP!#m zV6NJD` z-4|Tg_SW4okAWwZCF3wuo*PE5ye9fBMZ@`)~3=w~&+ z4G`%4yT_I?zum7cOExXwVS=}~`H{F3T1+-kUP}V$O#prGwve=YMU)B*FnJxxgtQ*j zp(7NW&`&VVx;529lGKq1q~xl|A@2YzmP;s9*-*POQP*cu-;}jYOvrYMFG=N zDI8TsyM#}R1Y+MMyF7~4ntTp zuE2#zw%_IM*YhS9CS7>gu3Kt%htI@q@O1k3p=aL;23cD=aVm`MN<0HO7_k$H#gkIAsj2_@Y+VX`UyaXX8ZbR>#NYytLlOt|)miEeyf>d)lQDR1D^isf`>U)3S+>EGf5yV+ou> zP%>Q!cYqE>Vv6FePzYtc?Bh@AtL7~KnN4I z>+$QSa^=4#G+jMxR;yu>)|xcu*ER-T(twMJ1Iyu_r+li;G3-J0} zI?DPo&E~Vkrt9tKtI_jp0!$i~Bjt>tnNhnr@Rn4FAjG6-6T;!5d()jkCB5Id1hPKF zsc{i5v2n02esSPiQa)3*mf6W%wv42~45!0l!AT~EcSXAZ8F~^28;7kAV0nQdW4O9=s5CrbcAfRBsDTIX!P&Dtnu_TS8rY9w zxH=7RY*hqN*CWJGt+OiZ}50uV6|@X0F9uu_gc!?Qn$U0s7!X~yG)0qx_@HhFDtXC=S6Lz zb_9hvC`sj149nA5nJOEpv`HBI-1zXNg@E=ARa4m)UY5N!<7a)&^ZSGbQ(LTiI-5)_ zeMOPcUB_4Kg>7t-oq zfs|cv8C|8Iy`8jw__QKM;w|ZXwafJ0d`ZjOXXT=tQx}lc9Y0?vt6E7K5shJV|J9vS zt_yfsr!UVh1Do3vwG#2ak6VA`omX0oY#;wIj%KyMu54Z3oOYv%uBNDySQs8RpS1nW z?q4#Hc?)M(Ls&S<=(mODhHx&%n$ijG==47h4ma^pTxkGH_z7#;nJkLW4A|vvhuI!f z9HR48{&SRtXHB^e$*83*egp+mxgV6sNB2>hxxkf>s}q&8w=y@LRhTJ}_pKIK&EheR zd9;i5Gw^ES9|1>Zo>y@JC?cL#LCu~yky}Xv3C@7xdmqQq3^xRj&cRrP^l+IhYtkJd zAp9o21M@L8U?hP0PZD!PoaU>ZuU|F;(;QZb%2tMBIUFR#kvJ=k(s|Z1R{oG*;O{0V zgv`EdcHdZ5SZu?h%YXL2#<_2_V1e>p8G91AEeLEA$5^J9k1{4-x!ZGY`&{)Qt%g87 zCkFO1Gw)=;P5zyt=S)&Ls|e@LL>{ZI=ws$$!MtJzfJW7J8h6S0ghs1ww2 z=lLs;*Kn(RuJF^W*bb`9kCPWX*=l82u69N8M({ZI=O=;+J2=zm~Fh!NPmMq5zWpq zB03p%FA``4!Gm|H%(hTPi8ZV5h&Vmvv^jHXEm*nPPolNj;m`d~@>p zzVaL3C^k3}6>c(?WCy&p0wE~-XRfUdHt+r(HZ3jfx3p!hFE9@4Y-P~3WI9ctX@|*U z+SsYmh=bKRCO-}fqwWU<+Ha1%sBqqzszeHRlLX0uK98T$DYDU6)RX85g<%`36)coe z*K1|R`PX>}=@;o&n43IDDpm{V@mql=3HC`>+=G7l%1##I4JE$vH^(cfNEv;S1rK7k z3r%Li6OF}I`IBOjCuyVzIp40h*#S!(Wy5Yu#G$ZRec8;y1b2w9r^^JjYQ_#^m_{|Q zWjIstwdym#bBOGU%`UAgB?lW}$GyCGD(Cm5jhr^>C1^+%-`gkSALHI3HBxJG2OMZ`Y9zQR!{{k+VKQ#?ThZ}+ zXQqgj93T^qF>#FItla~ecN7!5n9Nq|Nk_)AfLEhHeMbtlBM5FqfBSXd>k9Ha460>{ zXBG=vt{m_Ma(ah(yaIbYxz2X0Cg?L@VGe{?O>v6S7O`9Lg7V2=_YdbV!MnuKUwl>ruO&*w;#0gwy#m9mat**)N*oc>_14l*?)nc zoFSbWmL68Ay(Y*99h)J!GmM3zdkgKCCZ5<`t*HJjR4)h(;|aIx8kVcGv5YDj&*h`= zEZ*syYTC04p(SM)a^fSK=1!lsQ&&@Nr}RS{JRvNQ<5*jT^OGqn&Tbkcx;Q29Kx%7v zXAE1YSI_DzT1gp&j9S9WBLePXRo(_JEh5AbmYen99gyWxo>)7^T!eMv{Lh36_tBG| z$jQ_9tY?UQmsi#8I(Bjo^YVfy2z|p;)9VfJG}+6XQ)Ch7&9`K2TYGKx-1AorUDMsx z(3SC?eM|17gH=yd7Fl=V=p38LsTn2!Nu%R>p8-|7N`L77k}mMZZtwX#+!swdtzfA~ zx3DvQPZ?`Ik7B39%qJ@BeuwHt-ipW_`;Lz9v7A%4AWqSVoa=v>zgdH8&a5xhG29xh zXeFyv7&SQN&GOxzX@bby3IBL_ILSAz2KuJI#c*n8uBLnens@vas-xS$3U`KNd=a^l z?|Ul2lU9Otuay3yXs5DCm5^utud-RoEXCj6|PDRo)+pv$QoRL@O z!k1I(@>%WtvadGHaRE}HzO-N0=8Tw?+sj9C7O)b^RV!R^BIWo6--i4tvVU!|d!pX# zrqC66!>-PqEInvN*I*=sy$V4|r%EDOFHulcD-{oVj5g`vcufN!(`Olu`jFX*?en5{JQZVl%XHa z!F7gu z`a`9!4o&dM917spy10_jm!4tQU#7~c`Qwt`_1o8JtK^4|hufVeFWw{j8{Ba5hfV`0RVDg6mg?HKH`ewh&{*VI zc{!V@!js4%21GreDjrwNaH=^h+2j^!{`6P~nDayEFQnPHo*dKW zvfh|8ygh(VKbeyA5Vshm0H@BGcWHt!>G9Tael{_jTs!byeyjQPTzpT_?Evq=TP`@H z8oKiAByo6>;Z}FX)QUJfq@vOredvT3&jxM<0E!prGE3ZbqTuvb0t;hPF(DZRY;>mC zZz~wMU=_!9X{TKar!ecRqs#xY~zPYx|X*4#_9)Mzdrm#piKGZC||BV)DWXp zR}z7Kl!Wi+$l8MA?=L|efkD&+*@N46kNnx3hg@<`udJi*AbF1=_p1D>xn);5cefGw zqR+WZ0x#v~@;+reKIe~wbjJiRceu7H1)r+1j%kUwpJGmCjvqyX!y zBp6~pi~S*F;#guPY2e~zSl>x*c=~XTAw!dymC^W0VgHu6*gymO`}Yv_);Z|1h9%#; zrdfuOP)2%Jnvf_AaJfqJ6U4r2RI|j$gXz<}I(l)d#PZqek%fcoQ(R5v4W+9t5Klmh z@33%0mXfaXq2ff*XGPm1sm@Yg@%=4={H;gD{eV#4Yx8C1=2@TN{c{aGEK)g&n$yel ziLuop7B!*qBQ1{mBXIvIiyYu(cTE4WJ33HFCC!rOEi@m6&A zBK9fKUf6h-v@xUYA@hGNU=aJR&(+FPjr7|Rw~c(D$W1Sv2_qysHl&I&#MjK#y?0*h zn^CeDH4x=1Eu<@MtGJ||5AiRQjp)hnFrXg~?VFVyk!IXYg%Iovg<4A#mN!n=Gum9# z@9CN7XW0%fD}C0Iu<^{36am95dCw8LL5Cg7GGYNWtzC?@*OVX-G6V=_!j$=Jk)skJ zms6&qZh{K9>^D|3LB*|fFv1G2bP>0BW~e8ErP_)mp1m5YmfdTT-MjZQWEdGCe^QP) zQeZVkvnJCxvsk`tooFAygFrkxX$>GHp3WG|n#^D#I#QCbpc6a_#$#B#)p=TTa<|3f z)*dlcN=gI7?%%mE@QcPOI>FXtz40V#+GqJ_#dy*WN2x?CJ9?WrUDp1$QFSgR9Qh|` zGR+5$1?&xlj@B~n=)-ucv6@N;_HRlD7WJ^lhNVihrkM%wH?JJa4F?@6%l!fjszx_s z1k@mW{gbAVmSMdE^i=ay^QyiJ) zjp@~FRQl|2Q>BW%XC>(hDpT*KIB;t8m|?w)`!k(Mu4Zt#X|%K^p$x~+?W&1qNE-n2 zGa})$hWUMpE6GFJzq|x|>~I~1qA*AC8R8M{Sz?m9&geR84w6N(|3CuWknhuGGgOvA zYw?2-m)wN&>mt_)w^KA=AE=?D2Hxk<|g68dNxUdpAC$e=3z}Gq268s*KfIehhs3!0q$Yqtro1g5ZLOvyY!sdp0 zl`cAPES5!mM3@?PuZ*`~P2^)Wp`Ao`*$l+w*j$)==ljJH+$nP386m(MtC_JWmYp#+tq=;($OxrMnbRo6N5J)Lps#3`%jR|8{J$F8d+bPC8Pmxo>;wjWIRP@iEsZ6 z`865AB)Wt{+|O5-peE>P`rkN)YOj7Krr;LiL7^2#NJh~WV~CH#3ZY9r{~VL!FtuFy)(?aIKAhqtdgFf(a+z9$L6(WQhYN~24+@lRO+N# zz4W0RPN}Riiu0T*pTmK9Cqk5LWFh$DqhAGH$g>CwR>Fs_fTayId>dmI`bL-me4qEt zqX9ZSm-sPOt=!qkR-S!imrE+Ew9lSC8CJz%bd!E6yt>qP6|(i-Mk-nW;5p{ote$*5 zYXY}rcF{^2*C;3J{DhJ9`oldkgPjL(T|H`?7|mSEit((W9n)oX1Gd%XGHBi9zG>h; z*@lN6+f`4)#`E^7)qA}q8_)k!asp)~*7F6aJ{vuH%IRx9UNl^2^PUko2^}zub>4_Q zOMu913MK-FI)dByZNo!y?{Sgd)JhbEt4_k_o!wC%>reWHbiZ1P7R zP4!o9iMboT03T8#h{3`(9HiR4pTOhGh}~2w36(J?+9T4)I*((Y_is-TSM_aLV*r^w zDw0xU?b|vZRG&46hv;L6k86JQA#8LJm5B`;{lv4@IH!fsa`ln@68Sn8z@7tr*`l{I zv@`l(e`JYph4i~RUwwF)%syTDwZxt-@-j{Qq85L}fpy}mvnN1oak@s_L|0iRT5&=< zzjhEguMuVsXIaJ>xLA^r_%;@^mWk55`nesg$?F!IF=;iS!J{zx#NsZYkp(@XD4~2y zwVgO!b4cS(LFGwjws8M+QLHkYS;GdTU>`v;2kt4K3xM3kJtMn3jQ(XrfTGt|ETY#v zl-OyJ4BqdfwDN1zTScQfg(tW?OghimYqL>ej1dbDOfMH`-1n!EA2MR=txos7@5^bq zCqDdL5R%(fhY2`_oJ(Xi#V5fR3&f|#r+Yw*;(Kzs`flJkrIshYq-6p>u4g1bX;EWE zFZ+algzgL<$Xg@RuOvYSU%_Lhw~nLTBN@JbE2A_ynM{kmABNhmF~XyHQ#gTNcKJko zP9WnMu$IeSQ;g%W)TLQAIPch5p2^p+m~#iQP#&!}y}rp(+Iml88&exSG#@_V9VOXb zcL_a2K!;Bq&srWcd35a1qW=7?8ml!ssfBZG7hStkdfzSTWQ^yj9Hms5(xbxLT34Io zP$|s=*bY^A1I9T{=D5>%z-jKxof}#8PL#5=oVmVj&}(F0*kTyf*K%n+8H$%<15ROj zygvi})IHc%B1*s=qD#K5JgmE8(38jCQM2vYaKhT^hWWF@XwB&Mm;UeYDr8;%#9NeV6`3RxQK*NgZvwsHZljrT3+qHR3~ zyqeY7jowK8{2g{-zd6xL_sqwh%ujbkp4iJeH*skx;*TKyhK2kNOS6z5LF)IzG`7ZG zSJTpG>$OI*KTSc?(qKNgD`N#EpNoY=K?@@Vy`mzD;Mm;AK-{6qNVSQCX|TmtXgO`g zz`;#QlS_Ee&;Rv$SE({Ow$fE!2N@a-DsOvdrUtlUZ<^!bOr)i^VEhNrGhffXa2$66 zOxsZq(IZb6yQyrzdxa#5dLcTzJ1YEskD-#(Lr08fQOyW+!NMCL3G2 z3YaPdzF>kydkQ7R$^B_73KetNQm(2BE*(?BQLUx8n;oX_w6KTC68Y??gHgJTwz@v5 z4=snaYsUGwR=~x;2*3zuBz;%eo9sZ2mUc|WpyPm8UlGrhVo* zHu=L!Hv#F;#u5Jrw(|7#;GmO!GgU1sPmgjzKk0Z3B#lef26nTEW@tWOKi-B^=5BF%iU%7pqsq5iCm==Rc+EgaeIe2GG4M4 zO`kBLnf_(bD3Ojbnj*;65pGpjmU=h6jsy)rZ-6J>&BcYztyp-4CI-WdRsiG)>=NOLroEs zAQWZhXNh`-deEHnsTT9A;LEKlNK6rwMiuZ&&6v zYek`V<|)t0V(a~s&j=XpytqAFp$+)Jmg^Bxs0u?)pMrrFRR@fe2#mY77|8F5ozA%a z6k_#}d*MDe$+c+40TklT{LVEA|1DOMYIQJv7B>4nmWi*~ztX{|4mNJi%GRPSO>u)Pr#h#Y z_&TW}>J_v-_Z9ac%N4dgI2%aEq=6_4+B)GvH-^)SlcdpdHHH&V4st1Tp}pZa=h%~j2Q6I8 zU5IWJt_QVgx8k}-2L}TlEFXvorwD%esJ}4Wc&uIf+ z*826K!TQ12kD@o+8|ZUrld^^I*VKE~Jp%ag>8yn;ae*@a2roHLgr~N9KF90^#3%pz zZ!8u4v5c0C#1DX%SVjONss6N{kc$QWkb1p(Z0Dj+^lvMvJx?69Qv5jt62UnEQJ->e zI`$C~U9T-SO)hDUzyOlZF;%W)4UZuqk{9+m&+fh8{}+q%EiUM5tn0Qv`B#UFwdF%7 z(dnKavmiS0E%uC>==VLw`&be$qrY72&ILR2kXj!htnPbA*hVo^$`W$9VckX+CqqFW z!^p+M?`N#GvE*_ny+`8?iiX=kMo0cK2P|n~ux6}LbL<4ugU=1(1l*$f4lLN&Z{g~9 zsLdum_ljvl7{#HnMk-RW1>z3UsSKt`3EvCwNKCU5f)k#UvWWNlq~l;rfeEaI8KnE) zs2LL-3lj>JDiUkNM|h|!>t?X`aj0FTnzcu~m0YBsO3CLtl%f(GTN1>Sg3D;iXy!pm z9Ma7)BT$82DkJMk4bo3_2`>d}jQeGdn~9x5;hl;_u&1mHfWh^%Y;|#>&5y3zBpZ|0 zb%5+1P`+fc4F3f8gc70BIHuP=L)NQxPVqv6v3&BaC<2tHc!q))F41p0O_PQ3(&uvx zJVLVzL+mRK2NuwJhdsEDNEZG|E%~j^poT#uHbP?xLQy+O1SEi@^J`?>72H*pL3K3p zv@Z#7BW2RXHyDZ^%6T3l)%~fi1{B@u`SZNWx?|vU>xVN6{-)rG~u@Z zU47RiT}}a$ML{g9Mf%BAXYE+sk44*70k>dX!Wk0~*ZE5#Td}UW?`VbmTVI9zrq$vs zVg0G*;wpG%&UruNyyaP`wL);Qf|IfOG?Q@|?9I6fjy78X$CuthsjYy!=iaj6V(Ni( zRRFuLikE~{@D|u56So2IX4y*c4%CfySp{=>dYxe3KhD?sS}evNE`!-V%WZ^9;2z3z zk7bHhJ>xFyTf0>EfBU%I0&sZf7!Jkq`mNaz@atFj=ux@7Uot8h3*4 zShaCilW{Z@2EJzo>+RAm@wIXEAO@Z%-+R-de75V^b%IiC(LI;I;?XtFGQe=WdN4wB zu?%5ULyh{K=>4djAK=j`Q+o@UDQGfGJ<-+nD}n&0!N+8JXhzZ9SPy5G`yy<%G3$Cd zburuhZFzv(dlH+o#$slO+Q|$*3pFFzY53?#p5cZ;tF^?;VPgkhCW+47X1H~9Lt~?5 z=Qi%^{{FsmVjfHT&FhG2V)sbPNEwYbt$vAD*-idPuaGYjrJK0DM-@|3&B-fpUR7P~ zyzHdJgO-g-1*wHi1=E8HtrDX^;c#(okx%bdXB@zut*7YIAE4fb)WQ9#;O0w)v#i=$ zd@=95j|({$UDoNgi^zGg@hBS5+PxXmYDtr7@_02qvMPF>+IO6K)4Jvp^XZ541uk&g zteD9FA~H~sDb|7yy1Y{=<-3z1fzG!eCPIuZVGW1~!!R)XCtm@69-Nx?riI9l@*wG- z!svlHI96LQKeaanwKpk5=;yk5H0-=-0Rw&FO(-}9sB6D59AMW*y#Lwbt|9PlBRmT5 z!3qAA*iw8frRqz@2=}h@{mR%CffSm%N~bpus!s)~4*B-W37L%6+O z4J@eL+%Iw=tXsdiU@5wm?Gb(lN-<#Od`?(nuvgO%DKy~KV^Pgn=O2iG$2SP9y;}LTS{sShumtbLs zI)3QKWLNE#)6(eEVJ`fAH{%$Fa~`(3c~_8Gh(|28vU#uL%294O0T5lM7K4WP=TSBe z>hj5C)1j2x$Zz1J{RMZe>iXn$dY*!J^zOs9$YYA90JAopTx~CNR?DXyB&-J-mIE2u z<4v~|OOUJEW=%g_xo_=`D? zVUFhmZFjZuzq|3rz?sR|M8MToCYM8rtLoH0F5SeB5bqG#J?2;3Ij$4E25IyabhW+n zP|q_1@=aH$46lK(g4;L{0o$Bc*=EJCy!O}Di=Jj>r{1gw&#Z$X+#KTwjbDDK*oURs zHZC9E|4PGlEe;U(L;@RN^{`X+TGoYh+cOyiVmldsx4m29k2wA0lqJ`JO#a@{H?G%m zO>X;1Nv^*$klb`le(_WE>wmKUbyaZ3Y<#`E`Ng)j{|%*zgCOg2I7pf3OYa!Qq&?G^ z+T>3xSx>%0Sc}?+ELe-lAhD{9UGyrHD~BwiH&vmZz+6a@o+~B-dHV7IusyjBB4?Lc zMKko3F~MsJl;A;kwEIPY{J?3q9N!1RBPHVdaDea4RyLpS7Wl(ou1msQFF$&5JNj?* z%~n32o#Q*b+iIj|+!euj^cVfTV;1c;VCo%D7c_%?090EHczR}<*uG*{G$wAkQF_p$a9`e7Ck)| zJsq&a`mbA!9|3vJq|+_27VD3jNTBrpNP+Jwu|d0~|E0jXWS#9R>@<&DUDQM9!gVDw z2-j2e^btA_?DD^G&-mGZ=&5)f7~{X-yer70#rgLAv#m|$|0pP1YOyX{XZuVU`CpO) zpSAq2rkqj#Pp$u#o}ZVg(f?a}c_h%TJ_;zkgG`IlN9=!FCl0uF$^#pHg5(P86Hn?F zrd2D?Wmcz*h2sn)CYZ=I5kHs30?$xz%RB8Uq^o&EhY<|lMgwK5G|@r<+dNGKwtwmE zNv(s@4REbPE{-0d&wCBRzlr_*7GzYz@;|?2^gIPk*u<-hsp}4hHan<|Mv+Wfmiec= zU%Fo+ww0Rjgpp8b+*M5w2%lye?b#ycsWIezo{|!TP>#;}If#=;)dqh}+8oxqlgT3q(di;X$^)yS57H0Yifvv5#Q4#I2A`o&3 zViWTJVeKuT;@Z-6?IZ*U9^4@~!QCym6WrY$f_nnNEkJM!?(R-u72Msa;8p}Ftl%f< z-QB0p-Mep}|DG}CczEkwvudnbtTnafH*YT|t4;}w0{o7uVxgBcT|!s$z=zufL(;oL z(?85r z$kZF1usJa31Tt%OW?SLGcgR5IRtzDe`KL{6*38Pbf`{)Ah0HA(LP*i85Wh)1=#*gA zEW@@!>HiMMymt+&Z(*IRN;*2T^nE7Y%tnT-A%A3s&l9TP+cz0i9{oG@4t=i6xc(^>)dq3Z2BFpl zQ9is=GJoaF_L&D?Gy|DTG2}JSaqk)>Q{I?5Rg^zf)F)Oxhd3Y?q;x@oFP0HS7UMXn z^o5i1jGHf2j8I4lxVvZe+TQH-G0pckOaCQpnZ0&q3**5T&p;+ugqwW#E1^>ag~h$2 z9Q>8hgoNIQkMbf5ouI1#)Z}`f6tg~crpxCq2Xx%OW+eW9F%2o`rQ@+F2NC1VU}b6p zDYf6lm%owG_(J)wc3fw)^txoe(iX(^K1;DL+e@#{k*3FkC>(4p3M4(a79$QQ2BEp# z=P3SA!njEgf1vDC0z&q$g^1USKzFYFH_-xp0oj&3w-1nXuaG%ruhZoyORE8P4iJ9Y z8S-cVfL-f!^Oy1r*{K2}&-paWJ;n-%v1jGrk5AZj6!DEcWgygf%3wImet&F`b3^DE z3|iOB_)cHHg{|Y$US)N1)|q>gJwnd`!cIFw9Q6#gXcuKS$ic6gh|;tg_!rw{h+gX^ z;2gaQED<|#%PAnrPLhKkJK;+n`zGz|6&wkmn*z`CB}}Z*20F4p;3p{-@E_(6m{Zg~oM!aK9t9()?&)z-2;hYla}`9Wy+U!JEWB0O74_rkA6 zP3@mM#r_^(-G-YL%C!LB)!jKD_B?~BHj`PD$p3Basz|X3@ua{De^GS?R_zn&xg4 z60j)2->xcwnJ5m6yQASA{0Lx}sQsVdb;3Y?K5%3{V(<%Vs$^)cc!)&+^J-atq`8wv z?4!_ir;!YH_q5E^7g)s~8{Q+lYfkgMvSwWtpxx=#OMy=oAsY#Wt$wOKO|)JNf16n$ zA2MpVx3I2Tc%>-{V;AUW5qQM&&OPG|zv35Sn(r}~WV|7!Qq>^$GHjJn3B z@E-`vX5F%s&$J>@d+Jo};9Qcs)bSDSY;5nu0hqWk&6*HumtV4SO3Fv0tD2fMB5<0K zyg&SIRmHtLtII>}qZ%M7tklDP(U5&BIM#)hod*Bi9doQ==iRPCHA-Xes1wrBN8KEB zhoEI+nw95})bvb9FANyYuN}b=u>9q-$AM~w8y{Y!>8_~14z#%m zhg#HbzpN3I49R$Nr|<&G#`a2G$StLSj|I0;_Ks(lV zjVW(*-aSTl z``>t^!-oM`YX@Fxn+BG%#yQ7(y#aZ%$yN?;@YMoeE}91N5K;X4_BA6nJD)~={gZQi zvR@r(8;!s4!C9#5&Vs#SsJ8qhi1asW;6+;XM{0&|GIrJeRe>W;zk3M#k8B>h#_@@l zIl!{A*0MCA*=dGeYB&kK*DE5(hu7xUB^K}@H5d*C+Zw*7>V?{eewI3NdY@RSX{l~+ZpW?CGfnV3D zV~LO(!3R?r2Zq6Ds+P0$glYAR;E1~S&ZP|c0ZUh!DZr|;^!H!46Mv2!t@hh|p&1G| z`RUVBt{$&LW$nd0aC+>_T#5F8Be&X#9J=X5wApBCH{Pw?Og@sl{gU3i(buO-$+c^! zV&yS?zB7kkAUe+(Ii}xPD+c8JLa|Rq>r;Yr1KtCgR(OD=y-6^ZhP3e$zL(oH;MKI2 z$7`2S5~t#>_k&7r$|5S%YZ`7#zi9SLmr+zi9ICUn)6MJP*J%utCqAuE9?=-pzw}IL zD{U<-tt=_EE!`=;dQMcXBlxnbOsI9r?{HpP*cB?Zw-x7qdDxh}xyvNXTI?I?Pt55q zvllbEq4IrLL&0V?|1t405nEd;F8JSIX1l&M!`ggIC)FAn27olJwt7_^W>$>p_3LTn z^taxQ9*k6sZF$T(Ygij6;%Hd2=HR3)P`FaB1q;?#fis;vM5Ebr22$UHg^B--e&G{JKdh#66;PIQXB`#dm~TMQY|JoQ6T!L!>+-4T~1F4=s{ z*$ko?fvU~~W3&odH_<~AbZ#y(~|_o^>bZzFUE@}JQxz?}AEX?+&%Z#%P0>B|NQzAnjw+!CDzjpG~#chsO= z_51U@am|Bqe*HlB@Pf1(-kIfr|KfO(>^*{{9GDERXs-$!H(_Rxkg8z8mAd$!iqTfy zvh=!EUQ_F_shw-=98P~K&z?C8YtJvLW2EJYJvwh?x$mDpP~R(Dr)#$`qI&SIFp{3$ z%4ls8D>e$k7Hx4{th;3nAGCZL$K5iy+@MMU6f{SHlG~sOOoj!A*W-}Zwz)&Qqr4og z-Kzz3m@Z6zntR3TOfdhZN6+c!b%g)O@VHss_DEjW_y32mydS&HJmUv>44g)-<9D(9 z|2Ly<{jiB72wO0#$!l%LD}C4ge^=Z|WO;b48H}HEjV~8eA&*s4S=RAcx{V!V%<`7G zXzZ4cX=na2x-=D2SIym%7X=rsIon($J@7JF`7B+>_A(}0UI~(ma{tQ4JbbzR01^J# zE-eT=idw|4W4Evz8B1MN9p)U?L?!nK-OP+28vdEF?Pb3Eg;mhfd+Z`(pLg1&a94gj zHH-Z}GAh>D*6(DUaCF4a;pF`CU>H}bs%Dpb9yTaUJxr@5EHUyI?&@2V?(|%5$0Ouz zZHImJDYs@fLlXaYq^7X5TAGaYWrXu$ zx=`=PkK{e@_#;ahA(Doorv2UfXQrE5bQ^p9)GFM}4ddU@0MG3{gs|8&w5dNas7KUJaqI{a?z&xEwr#HLC_q16|Fr~&sE59d^vUk7u953 zalmyg1?M2-q4WrUel0-e$Agviq1&WSIqCFJt`%%A-aBm0C=-|{GErg>IBloF(!l30 z(Zw7{c;iJO?D*ib(`EUuz`bN215Q-g7J{9L5I}#D<1tvfr~UinO{*Osl7!j2z|)CI zBQZC1e8kschn+n;^=4$m(n5&+JoRtZvPCCUFUkN=^3X)O+kC2bQ8y0Th+D#;4vYL9 z?>);KQ;~s>QO}_ftbY^uFl=yUPe;D6{&D2r8;x8{hmo?T4BxfB)Vwi$mkw)>Q?ET? z@jnxHkbzyuQY-}UP(x`dGY}s|g)eujt~U@9MU2nS=5BWMeIc%f!c=M?hT$L}>#Z-5 z)E2Gpi|L8e+TZ4X$yE^@i!X*4Vun137tcybA5c^8{9QKPh>WY>Vu7eFM8mr20e?{9 zOaB6rk16RdpjKOwn*_xBUhHIlOxp6zIloyY z#^?GnW`LCk2WZS20}SVR+o$1V2Mhdj2)M@VX2c>nkuml38@umejBKbp{VdrTwz3a} z6*?#JTM*1=}XLQitPZXXhvc5#au_s%yA4g+jB1;AZ})-+}4)}6YlpnR`v>b zx)i-?Ug5`5cES;{o3Eg|2;TbHO}>0%eY|8i&L)%8OaTBW_h*fpvK-}3bVEoQx7f?K z0lKcO>)SE&_wRU$S5VlurF!gcSeJ=}A-9i6v7uDkGy;(Q>fC$!Do8qu?%Uvel^SAH z)kK?=k{LbHez+WMe3#V~&4Jzw|7PvfSJvi#w2VUf6BTN-Q!4FZ7^@3*yGB4wA0CI# zq!!?+dKwK*XFV0H)Gk`FJ1WEQBU7BseUd%83Bd!^xj(7zE-jMR1Bp9!6g}zP-Pe~d z_5zNs^ug|lV17G~;7gsw)vL^F%-Gf5hxXxZ!KZeE73wMJ)TWD=$F)E)RtR%j{V928xPrqQZFav=D=(#{xD42zZ?Vi{dcfA)<0~Z@o zvIzt`UL$1776QL^-RpNMM=DQpu(Fz#tSl4nj&ns(V@?!8tH% z>)ZkK!=JOel$^(0!73~>408VZ4pe%n(_m0GXFKa%v9`(T(fY^)S^a&_pFVzpdM)_) z&O=jy(7wy8;jV6w=Zh}n=>{EX+q{KmreW`aJUE}VLSoGKo?r{50G1~%iP}YsR`WK# zs%v08W3vlR?&T}drfIN0vuS^t;k;ZBa<$>#Kp`tR{?Xd-ewmj@Z5h_5`N7gy=D5SS z&|M^@lo2J;CUlX++6PPMlc~NiYEiQ<-Png4JH4%+1&zs@AM`#cwI0(|c{CgoRk~=$ zlnkM{~CFb#u<6|dJ)4;yp`RFENheMU&bkJ1lZ={YGR_?%*vm%H?91vy5uED zG>;_I0ZJ5Rep#mX=%YtGbt~&jF#kFKA$6i$SIo_}_`xf=BKwx8Gt9O(;?}KkltuRu zqtfG1(>0!ZLvlRv?tnWu=-`8){z=*T(Uq=V7j{z)cH!arMZ4p>wX*e-8xv)H1{JS< zx+<-0?D_uORyXx7G)UgD8wofC{>*7_X5O=cw0WfgTI1) z3m_Q(oO*`wqwFlM+NwQ*fXgXekCPBf za$=Sy_^7>`*ILpvGd!3A*(s=@9+fh-Yb=)s-cQRH zTT|b1j%pNavS;?R^1SCHS+4S}RNvGq0=ANsYdjw<`M5LGgzB##sOu2Sx$S5I<`=GVD~h1K z%(!#?f!2KdE}2vmc=#X!JL|S=dfT?L{ZP{v4DqTB5OCfr4N*~lUx_HI{;mYExS+?n z)G3WFxp1gJo45M0i@PU&2)-wN)30|0%<<1E27w2i#u!#{04esTwAsFRlH#Ak>^P2i zf1^0YGC*@dxYo2%=Q&L&p(&;val}Dm<2cD8tL7?t+lHg40aTZvpN%L4m-M*i1QI4t zOcIMZM*?YAYvjd{+Qeef*pW7i5Kode3;)p+#M8xK94uQuB1LYYPO3 zOObC;lRNzHKxLg}WY(h_BW_15r#N87ew?(VrnGXm{E+t$*u1_nr{uKgJ2z?xb#2Pr z9{0~qIl_v7(qFiw;EE_onbwG6rd)H8X2<0=)4;bWj7Fqja78~5B`UEgB zs43;8Q&>1zHoXf44myF``$c#^IkFJWKP(c|2|3PT)@7w!igzB6X3jtAd)&s?wN|Ar zDj6)2o&uj=e_Ix2_}RH^SHYo6KRPE{H^U*PP&dPH`ItP1D1f13QDUB?V_{W*Z1rwEm$7re=eXw|KmQP_*^2plmQGOa^n+I?DZGOjHz!(GQ_rQmU;EKd1A%?VQat9*ln7*VRZAC`w=Vgp!L6n*(JsX zce#pH72Bqnf6Cik{nweQle{>Yrf%kP`im->jpEyCYKpT_jGU%&W-$^wTK|Mvw8X5| zACO~@VvvQJ9*y;B^ANI*0a|#_c0n)7A9eQ)kz-ts=jCAQ5G}CF>EOC7aia0mS!@!& zFTNGdeHg3&JvgS!&+;gt#3<^U6XVXE9mob7tGg+UZY%F?%yQGuaI+tzu^$^ zD>1w@QT*@j%xJY#s`HIx0P%rTuyTk=SPXCf#1Mz(l||9~<>9cEGVzm`%6#r?`$|?U z55&nfM=8zwebNSPmi*U){Cr=sDnY?szAg}ZY>k@2;k1+MB6ulxoT#^Wsw{;@@_-ak zGefG{DvU+V@T0Q6npp(9ql{_iaB08B;_|tx!rm+&&xZ;5`*D9+dJJ1 z9(k*DhAtD&y@8^qT6@GuP?Ma%A@%nyoz)YT*tg}P+3I_Bh#l&Mv2+&-+Sc?w{Em*h z$H(m*nN3aSiQLO=O~_YHYb0aKy*Ge0!AGPtFCQL9wB6&)cEOA$%kwKcgQkq-bT1!v zN5`G{&gJ`!Rd)`dGQ$JnJE;Zyyh_#sg1i+xwxkBCxC_XI#qwo9 z^t8L*aTcn-n`$MI-cscUE9 zjy)q2?yZ)BlM`19&mFr7E#e}9OViph_`^P*9AMn~Xjy>Vs`yCdDPy4cs(AtrF zOwb>&P6x7$F#=*BBJ2DY277*?IHt@;(SFtS^-fk#%`0wEHdi?-)YXXPi5~7Vl>l>3 zr4+A|C^Na5UlS%PA&w>80oHeFDHZLtk8Pd1T?zq{_}y8LaEqQO!a=VsX587y2S>h( zs$Ui^ARm;+F;;JXBh6HHh6GqYZO@#Z1W|{K7T;OS__5QSXk$Z;Hp;c2j$V#?kNy*l z6S$ok>(_jCMOs4Hk;zkvY_w4h-SG*ookqBxZ~4$i<~`eg78{Dfo<` zu4)QAd{O9XIoYJMDiv@uZ`C=aG zkSwUA71+>jI=ckLp_}HWkU3qGGK_5ff zM3t`YTfnzFoGJ5Krve`PI)_P+aTf@DX4A>RgpqkrV)Q3Jw7R1k7r>>x?pUMbqn^_v z(4`Z4)v`vQZmQnk9RO@uGq5}Pu)|bE5LsGdgR%9+qb| z^zg5o>gS763ynKqQ6ZKr?Ui=Jvo85GzU6W)(D{+yiRPqdRoWTtq~DLFwKYa-oe8wgo=x`Kp!U)4O~4-}^wECE(wWGJlp zIlB8Ev?ZuivpM;;)QrOVQ8ge49Xv-baD?qyfxk~MPlB@Haq zspoUf9f&-AT$z>jIZCFqPI^d;K27|A_|#H34^pcsv2-bnjN6+MR7z|L0=_S5yK!?4 zfvi)0`K_^Pkhq7rMQT@>Evd3XxzhdkzPN!UcDee#_z*>^*^+#|M75?b2RJILqNTdh zZb&5#WV4L4P4(D$(j4LKp7)z5E@boJHs z)vygazOo4$G<3FVOF5J=91em~V0 z0c?2IU>7&v)AzDeMMkvyi_s@cC%Sz zZB8+b(J$)1_fO`i`ljR{IcgWv@J3LoM$-+<5v9KUrH#bQND3g^CwO;l-izGzA;sM!1Kdz>=`x| zmO9=oh7vVo=PhrjSL;X_qO@43k>J-knzA=z)mEWEPEqo;n4gON`mQgJ$W`p>1SU+P1#Em)JO7p&HwQtCzI zb>2`jzD^LYv!1lm;YiO~=-}Y0k+L@1(qF)g1Pe7W{;ew`+;kcX0X@4fSVjfpR7=tb zsSyzJedAzgivE}3&zD?%mA8AVvIzy#`a*x3mc`rM(8~xtcmCDcYMyjSm>|CAzD5jT z4WzTd>xaV=`&~#Ano!t9DSVS7nxaCr|J!8goF}Y7xILK8E>aW3>B(pi`Vf${j&=uv z@;v+9lYPsBU9{<%@rm6TXG}6G(iy?R=`B<5cJm8O)Cd20x>MF`i#qi+Qh3zPS-Zq> z=k=CmBQSTH#!U!dQo7=&X{$kY%ND!3Z(+o^+9GNd@Tt-~`jp=L4qM-E81pk6I~!ZJ_MMC!T01cy4CCwrv=iGvv7P5H(EJ?&kR;)eudy7tq@Pj@X=h zjp7I%N$53Yk}|exKDlyE#`Rq3%;99XMJ4?|o(ZMklRq1B?02);l4~Y09MCk959vZ2 zLw2#aruIcK1deJ2J8s~t{Hl+kS9#I!Z*-r2nG|a58`>3gy5(~%H1~P#yRVfxeKk($ zoT!_rU7&r9pnD$^kFaZ*knZem>C$5<^r;{!^{ZMsErnJ-U>-TnK4={OhUKik#%XtE zGm-~Izo6$UG*H`jFy;jqNg##>EGK~9%6a&W>$z=?1>?-MGRXJXd;yUeIJN*Q2fr@c zWFxhS8RVF++n@@+E)MDPa+s|gSlJ-lncLd}C{sh%yWN4Pp}?r8pDK)mXk4sKM6bce zMqc%-Ex^ycH$#ztIu^FPb|%{r?F;^XC$YxNhhic@sUiMv;L3U=WhP91hyKSSGX7d0 zTgQ#Hq!XsyW7TKA!(+95#!GouA`{omU?$pUwRt}JuGxzO_k5tg-PzXde(1p~N!0dJ zbCbx5?wb?F*ASdAAIvt8pH@^yHTTu0G@q^4M2NQDTVh+f1s}SwZ$4t*7+Duh6&d{W zNiOQ|{#%=?FXC~1oaqroz^Bhb$dz9Mgt~(NbGK7!GbW;{Z0j&7vbylzOsj4UV&K)^ zsd;p_A>F6jBfm|8z0zT_7-ZZZ*{M1hs=C6?BPXU=Fsp9u7O<;5KJOR$^T>nB>(T%# z$PjL)VSe)_ulr{jM3c--T~uFPL6dVD8sMIEj27zKaVpeW8d`afQ|7%_O7a&n=v1(h zFk_IfYW-;vLwIX99H8yN2SVyiJ5#8^XClp*{8mP{SBls=o>_9+Ydq>mtS~LCD&3OX zTTy%}i$o`54H;7S*-y9Z__dJ(*CkO`PFK@`oz&Xe@VwS>+aJ=PzJgXt>XlB()JE7LIpiE!r)dX01*8Q-n7S z1wKekl_XIhYB5MsBVlV*ePo=__ms}Tl+Kc$?_vd-FXD#C8bg;z95T#Hhgc2H5$l|& z;wSFbXEG5oX2jRJ=w&>nT-l~!qE^0rc;y+GTfE`j)@smv==UaaqcwvBhVKOkfJmN8 zAK`i7%}(MOHAKrrN5WWa1zLKey*k;TwuO$R5e+Q%%9e#7v-fTwo}N6eK0bwurA$zq znsvKBxKk*io0;)1&J3>c>)Tl9G-2U2Y#$o6L@9Jvd%rX;UQo+&%h9Hl6&%l>=^-fs z+W5!S1L>_o=hw%IIin%%ly|Yv- zWA{8GmCkuXe-OoYs3XbZ9O&bHNt%v4r;o85mK`e^d(ixFqVTg=hA)cqD3hVEeN%6H zvISAFIX9XJv^MYl)M_WRcpSojv&`DPq=Lk@}VN-0Z*N~8{Y#n@|zi!X)O!h57G_H zi6`7%j@S)eoWOSMIn|K1rv$uiUr>4-;eY0ClHx{ytXU`Wv?r-{04e1ci$kPFzkas& zb@V;_@8M4YcOn9{!Y{Vspa`!ckKDSQuiz%fZ&Z+7I#ueZMB(?oLm1yC>4-hR`qugX zFz)6)#GNe`C83UNVT$I=72uIRGff=Xs0A<$XD1quUf^jO$y*qaAv6k2dO!5F-!$!Z zpZ(Qixy&(h{XmFoNgn0C&MB8$a4U1){!GLkdc7=$8Z)2LC$AZ9%EV?(Bk~SVkTtfq_$fFx(~Bo#%!jv^~>LG z_ot~Sdi#Aa_4vs=#IAz7aoUMMf93-{^C`k#2i+WK&q}*9(v^h9Hz^keSmx-QhQiQ{d{#t7*{cF=8Gt;VrW;(N!#w# zf){381`IxRhNMaSBI{0${Pb-N3}X~v(+wKPM&H0Y2jXy%K+8Q)q~xk9W=5 zPuy(c#X|ox{O=!F>~@l~ExHc$a0|~Ot?x|;x>5!b3eL>-_cTd5xz`w?x#hU;3U)0X zG?g4$80ER|mxAVHK@C%$6&wci(ZA&Tx4N8#V3XV}tQ5rQZ-`A(ES<K>5l=C5M&UY%-MWiVuVmjPKR{*^DTh`a+tWV#BGNEd(hilJCpW79IauiYQE3h06> zzE9#*3^6y-b+Kv^eyB57#L-c&BVuSQjc!?JSGSKhz2@Nzm||OEJ0VJ>Q0B!5rsyBk z{jlnjaM*c3P!&tgw%?y{AoEJsy`pxJvm?7D3liWZSSkM50d(1LtiAqjw7M(R*0w@l zY}%C*)NxA~wjQ?}zmoK$k+P}ay}8H{CfyY}{Gh#zgB&Xj0XxHQ^+8u(Ir+A2vVA*V zFX=}uWinL@!=SkgliUaG_~AdS*+kWUHU7v`R+jbGZ~BwZ`D?3;J|&(=Lz9t;mwr%N zW=!^jMtog-M&gfhO3U9C{vITvS~k&)Jq5;XMsYx6@B4_%DiXatI3aAV7DM7(W?^Wl#k0cXl}LyE zdcT$-dO1<3^>#RsuArfHmsP(o2%0B@r{6@mrf)~M7OO$j2trZ-25v;ZT$A>FksbI` zN@$~}Z}%f6=AkhR)`^z&aX3i(OmKoGoODBqeB9c&LkLkah(MPu#Qx&PZS&s4tv3`& z3(XJ*826OBBzBXL@u1pj7TJbm2$iW>@p1?*a=-e7@q~R zatpdBqOJWkQQ|kg);d_+ykdAh)RW7=@C#h{;q@#3z|i$s-)v53LlA*b4!7Th?~9Q1!maYHa?d3F1)_4U(i}~s z3e*H@5;s+}KP{drq~E1dKWlkdCn4n*BP8WIRW)0Moq0)kK`4$3m4r%8sv8zEppmKf~AULxX zBghU1J)Iu3&$`LbK`l(c?S>8Ec>kLJ!^xQ4Lqx)6%~JcsHh<3PvJ{8xZHBTubfNb z`UruaTV)Zf$i6nj)?O*k2@NehrqamXU7L|+AAu75d~3VZ$820oO_|Ba^%0W++agMm zGhf9OWd4T`)z{90;JEn?w1G+PVbdFfS*v(G2Fwo;JD?qms&t@579T$TtInR3A8|b_3>Rb%@J&nvEu^#RWKO~)>V)p z;KAt`(JOcW!08ncVkn^M(}Ql_z3Jhatj$dc=18-0LZl!oq*g|4%74Sq3>KTjUK-rN<(QMG}$+^ z2X1NcP-vyRXNfv&VhlK?s_62Z7g5-26=Qa4T)9($?*)}iaF(kAd7Yxu5~7bQ#ybxV ztsMM>9&s&|d!e_@>mr6DjYUQvJ8plD6Cd94H-atSvE}@*f#nuZMiHgSLpg81l7N2R z&KUo$%S*?NWh>Xrq50dNOK+?}#zH4{+g#+GB$t&R`+bH6Y-Q$CDKP z6tv;@FQzW9X*6LQ;mouQt_bHJ0VEhc!*7y#;*oqJ@Wdhs0ve;w^q6=evQ@wQy%J0d zaU5_Ce$oC)+lr0kslU@QF8*Ydj^|rAJ$uGcBn;QwCuZDus zessvJr9UAn{YOiSKr1egQ?uI^%=g2Hs+i_(qAR5=60+Ss+St0+NyOdC9LmP>7AAp> zWj68CJmDVJjJc-t1@hQ4F#w9)BF8y_&i|XThz(H1oo+uhS0*uLPcuWRq z5kl!e6x6RGZ}XqUCR-sLe-r#>h_RRa@|Nn8zl>|(*aU2=DEAvf%pbOaz6xKe!jE%k z-g9Gix(sb*eBdb}8v7*|Z5)u% zgq{--{C@RxKv8>-zpr3V=I8FuN3Tgo%q;d`D!)+G*?Yt`7yAps;N5Q$8OvI^s(E)q zR>G*>Jzi>pZLyaj+8>iXS7BK~orz6a#pFH0_Q&LmGwYDUI8kc`$mZ(tfV=zwAOSZb zW@G&eJ>Br(gy!~)AW65*$bnH=qU^pi8KP{49Q&^mT(VY#RK$@kh8KbO#uGfcO2$b_ zRb~bpP3^jDq!H|XIN9O!&XE{RDZPw4PLVBBq}SP<-!5og<@rRiy=6>e?^RN6QjzNU zTai_|i{`*49MXzAsFd03Ey2M>pPlxpaW0rbB^SABM&V+!3)74DHtW`)c`*1^j2yd- zgG;rZ9b}>B$~ru1FRoeFw5aRKjmCk7Ef|j!j}~DtMm1JoLX*?rqu9b^UvW0a?CrO* zG+fSAww#YNoK(eSeL1#cFjiL4fhd*OOlZhBt<0rKtnaS6SrGHqr*VW)SNBSNQByeE z-_8BfrmU&LS~o97EqkWg!FQ#xaMf{%xa;P$b-&3j>&m^CyK~_#dE2Hg`Syfv94nZk zWZX`R-q-*9IM^|#Gn7xZgRAhwaNGAhgQ(tm92Z)j~+*k(A4P@=oYwiKl$k z7;S;Q6-3>t2@k)uC89?ZM#vlXlcihmWpn5=$mHl zKIWXd`c+nPx`N7IXHC+VvwMqWKW)D;v-ho^fuMHtp|r5h>V00&=&F=rG-~l=a4MHU z_z4A?e3K`$mxqlF+5%2v5b-x=yYfX8B`*|)p}AZ;#-St~5-eLUBW3r;MxRmZ#F>ka zX(aEbVQjob6wr$IpK}U+D}?`d<}3p_$*)XhEz}3a#|Dw9;$MX-#IonGv!4-ithsdV zV;aHKY;|?cJ*E=46ORNRZo+NoT66c@(-uA&HbvZ9=t!Jf5<1#p6Ix;O>PU<&xFtMo zTNNVC`VcTpZZ<z`1Q90HIHVSg`+hY{U_ureoV{_Wt zXXy<}fwXoc1kKM`>9B*F<5WC61?~+=`5h1hO@gHCz+osPH2?}O&px==g$;Bhk8lmg!P);g1ZrA87s(8^B!yL86f7zO5 zIuv&GwjGzF6PK9E{Wev5z}MuHVTO76w?v&(b2}tUyt3sHWK)#Zja^H;<(!lyqLR_L zzeCN%M;)`GRK`3;ZAaRiNp`zrQ}3Xh06T@EfLEn-r(-;BN-yDSY0K&?(Hh+g^@OF5 zU*YmOq-0(4IdBW=8?X!tD`h1pxP@MCPwI48RU}+x(9S3I4ucWf5$R|2-dFPrqX7DnjQpFJ^9S`6DtLG8^>!Dwj%@_Dw!=$+XEHzObO2Z06M#;VN3$HE6 ztuNGqRi$bYH+=He#IFV~&+>xGq`XtjkZ$0x>Yyqd;a1kKfJe!&pbBG`Fh-f2iG>d@ zvyU<_a#BLi?1IZXQZ}z@(ooOt$nJ=t5WkI}ErQN8j8$CEXa()Cj0_-Q;F*&zBD{PtZRV-&sP95%BAJH65+_HB`Y|**z z)ibR`pSl=P>WANfJGb3TT~8B!wO(6(WfC+yctGu63#SFc(Mw>4GG#L7Kj*I_FezM< zXF=^QcT`A)Aw?N8u|ydoOH@FW(3{Z9$vdv-hT!2!iwu^~xCCDqSk4vs`v~&+B(Hmot{@aWnWc z`0H^qVaHxD9tvzS%o%*h@<_5~=5MdhI8Uon(bZ-vHLFizPE}=-($)VUHi)vMOLZ>i zFgKSUQs`gMk;%v7R;`ho7GFBGrZ6f!I$>s`Vbgf^X#ztmugwq@lluYEUaut1Pj2QT z@*ENC+utz%%KPm*W-50zWvr_LLDWwbEu`LRJfcxgL)mB-FLu8fgT+mv(vS$A{`?w* zc4Eqa-|dApjxPTA6zGoWbL7TWwW$235*CzFBe@-bx9kNb{zB_bHC=xw7~O6$Gi-l! zCA@iXMVq!*0Ff>>a47HF&;K_WPfJS*yPfyV7wc2bc?A22E3Z>OVoM1*R~Q~pbqf36zD{9PkRi4 z!GL6YvArqk2fI5Q>@wr`^VTNG5kQk`769I=U2mdz2(k<(gZZUZ=GyBzc>@zp;>xS%W+;^ zYO}hQoh)a^_Ov57gy?QORqBQtjaK#Y5=W@bm|&KRgLngdhuL=&1a~LF8ka_1lfCyn=iUF@@!tR5&*<^3TD8`kEEu!rtg2b7zJ@@&nV#85B3nPn zyJGb|>6S!T=#6Vqj+ie_oY}I~>`qc}<(T^Yk&Q4;UKf2sy7b!YgsXB_lXI9bHDia& zbB^>LqJ8flzXogioTp5u%_h@p1R{wr!jG_AI@kSOWfdLC+cUiI}2ceh-7< zl6-V|dF7DN?(1dS2gG^vqo$z^zohVQoBHijo@Zx+4lPrjO1mG+>sL_Gdoo9tYz)%N zT{p8EY^%NvZDco0Ge3yM024OG3$D-pH$=<2lNTyGwMqe`+Vs;EYLC%32S0fU`(!q) zyDwBSX5(Xx(tg%VO&UV!$ z#U?SEMkA!E<~)`jkA3Gd%95|v7%kZK8-46$>XT86u@R{@KJ(s~niTWp&9`Fx$rtyr zlW6cmGvvbSEP(awxDW?-_j5$}{LfM|{ZY;YrV?2XB{50%vPP+o++lSkS ze3^FncKMXPh~9|kHx;y=(af>4{rj?lQ(PAL>dSoDKZGpIUn^cO=|$_iS(kP-Be; zKMj7%_u|QJk;iiObiI5A6`IO=>7xF7;AhfC;!o~Ui=I5GeLjvKFR6Nr+wUw>qe$FGSY7V+ebW@I@`#$* z$EJ{NtaP#!mZ~tlbxIea`+NHaBW$-d@-|p<$*wcYLIM8a>*&i88Q(Yg;x8wuKbixM zmyrYu^c;f?^weM@T%d^xRy%T?qlw}u7+GCKr~gG_I@F6i{=UFff5t}Xf&PrkTnbS zf^%T_ct@lMMA#1=7C^pBcJo)r@k2I|hFk4uoNO7*Txw?vprtZvdP9&KOs#E$((@eW zUHVJ~M3o(HY<3~ct)70--Z>XZF^`S1;A^<&1oe;^#U3109)WuV$GUqZt9$6tWHKA; zR|hlExf};^y~_<=pSl%P&$Y)k35p48L~;j-0&Hv1ZjKt(0~AEl=La~x9na?oE<-wN z1P>6QUC&4{pq%yx$6|B zrrCBo_?_ABgtN+xP~BM0x~9Z-ZO_)^(s2coE)AqeRF3iojrhLBGI~vJabzsXCO2EV z{%g00M02zSoM@>lEjuGntHV*|!*hfTe8VN92UQ>kWx*qH013x*LL`AM zFlk%CnI{XOxC>TOBtT@C*HkDAoo?>xicP+Yd4&ess_p?*i0M1cl7kBn^br7m55PMN zd|LaG$1rn4>Xi}Ba{^vK4GG_!E2ek({zUdCKQ@wD;0%Y=-$@_41fB@%)MRyX*L6kT zYH?*c=$t)L&QzoCZYa3kg6AJa(lKYdu|Hc<-@I;06RTY9*~Ra_@SW2J`IKesnwCBg zigg3V5iIlCC02;!hRaVXEZjH1s&`Y-fg&er)uCR(SH5hI@W=Awvn7+jwRBv)N3@v` zR2szZuO3sjt=8(=;;#D7&=fobxsJl_84 zG&ZMI`i|F~3&P(6q#F}Csb2pimSm+EGU~ZO^T1-2avBihU^zj&AnD7D%Npm9E3Iqe z9;P}WT*3X_Ij5>+^=VgFY^I^c=$wAmwt(q;qiJO#^4<$J$|pFptj{B<^j4qZ$z9xi zRqIQP)K$c|I1V=yw8YyX9!}*Q5*HcC$*bz=PKSh>MNeSzapyL)O{eP(dxXV zPsbwZl2u11L0q91AS#k1GDOe`*SoVIeoXHLzB@_y&!R2PVA;3nckeR-u0e2&BR~^2%i|@c$WqUCnu6* zO?IG5$#3_cxk(qkhy2ct{oyO|qdtW%FD1cn_e))Dr%v+R_dO3NPTisquaZ!&?n3T` zS8)RP1@C+4{ov}8NFC_qD559jAiY}G8!!D_h}xPkObo+0tGY;Z)?>^6yV~=lm!oa2 zm!$dHoW$f{Bi6{TcF{gdLZOMz7{fuD#Oa`KG19|@&yI4GT)wVvvf@N_f^4S4w}u$d z4V;zF(HjNpndK*qf^=PTfzGQxv|-cc$&ruGi5m%lW1q2 zt?f+o3N~Nw=%3* zrEPcC4bran2ZwWu9nBVSFvHy=pIEo|i7BJU@Mp(Q<8|Yh5Zbq9!u=Xx<@(}pA@?R0 z;JE!Rs4B(UnEf>WQOu{J`Jf1<|xifN?Q9}yqMx>ohBMawmXW`AQDA;D#MC`Q{Hb!|x zCs)`Zv|DmrV}GLNhX`9mZ9w<8_?_0xIZrXATc`aL>ya?K>`q_XksdvJ3heXo8JceH z8PZhPEKLcGi$v$b8w)=JJ^D307n>|I1uJlUy61fBjb}J=`zCctSNmzF1!{tlRtKPZ zK+@^Jy39n^`2xVK+PJGT!`YvOqaOYqzq#|JCFg!Gvl6!9TH-<>c(O9;H@>L1QCtzu zcA_vN9i;XpDv%g3==1kx0s>&Li%IW%o7n%`$6$sm67bvgWH!GK;c8zX3NvRxI$t1) z#KwbNta=~@%<8x6AK6+yT)eCZnqBi4=u`wD{_Cn8|Kgt$SNKZPJR*I6{8QjS!j&Y# ze{YPwea+%0=MAmlP&NR|kMj=d?F)12cS^D9n#hfJxw5x>AWty&mk!9oWjhbPpv%R@ z-wO$&en;@MM)y=9)v_kRZRmttf2`>Y#($p5prMZ90G|Nv*kl@#7Ocf~4~m~a7eV~~ ze3IxpyaTOd=Bo)t{QBsg%LxJ>NvA!;=CCP(b7*vM4at6F_;hqZS9CP5x0<*K@-esv z%5-wCz`weuXJ+a8hR@N`+?7%pjr9XT_iy?P9$^+ADR-?e_(dIs>p$o{c!UwFEZV<0 zi+?r~-@WA^pVe@ncor&@E)iD~jVHj}#V9w|gO*8ZMnHF zUnkfB1eXcu?PFa4$x>8XZxT7QaCY0iZN6aw--x-Dm6w$_?`Pe%tu~f_Ux5Gy z=%$Gzz$H1b(%HzZ&uM%zWy^3U9Jd-!CPHUEHMC#;Sh7M}t? znqxS)+kuNTqC*{4l+X+*QHj|VU6vzHt}|O5sUX-;Y8l(Ylr1jwrnTUeS_9#T=KdpdlNHb23;PH6~NuE|SyH&c$0(3={#3C^$2sJS`I<<0Q! z@B@%z;Z-yXA*5nBY908@p-k&6Pi9GB&?QT~TAsfxS*}0Ep{6xh3QD+8JOK#*OZ`Ws zkNzLk|KZL*D(%eZ-{KPgbW{4Z2Ir|esxhb3pW3%}6uB0P-8k38o?RRz!OJzMmm%B= zIzh++GS4xD*MhF zaw1I` zSV%axt8fCHzApLG0D=@7>LNU55CUfI2MC+N5Rsl2SG)~cy?lVB-q2=~+GS=7Ob{>viBlR*qxdAnc*bogSkdBVuD5qUa_c8sEZRDp~D@v zGmqHnl?cY9-hw}7t!Cj1-I+kpm+D?k`N};gcDmI9^8rLUl4=$ScMpSGO_f~?(_@;5 zR@_>d0|KrM>heLjd+0h{T8U1?y_54oA{57%_ann62pz}0)#&@cqRo4o>PU)_#OwE5 za2V^1Xk(H~eRkMImiGOTU0kG&LmPBK*JPYL+b8Jtf5!4rD0KAnnts6?1jpD-IFqet zfH1WtnQk)_#{QXaimRZONK;VNw&)EgWCsnSn@-Qvjw=XjW9=ago;rgy?j(} z{S&&HJK!gn0PnRXvug)D`nL%r^V|+(+|%3#F&X`OII)mpbdMS}2iLW+Ba;hK+U>RUSzWMwdOgLQ=e&`tPP(#Ic zfX14Z7M&eeY^09ZY=(P)Z1E!%4%1%KT6RP^mfLW6v)2usc(# zN5p12Am@e&uI)#cj{dbGrisluE4yD|cy&GGBk}*Nv_cdv^>}hy5N}F7U>p?7YvxTz z0pvgFLyw%v?yxu_S#wd(!&ui}?)CbPN3Oi9n2v1VJm2Ic?3i}OHpCQ+A*hscsq#op zcUWfg(QAwfo{?}V^(bfg62Sv*=^)4U>RjeR>FW|ohr6obWbArM-WqRFuy0KFhr&Va zc+QGC-Y^H-uz@>IQEjZc*fed$WuRRC0u=b?$CT;A=VIx&m}_{+_0-|A5LR8R_6UvV zE4m4YZJqiEmJoU|WVLSI8o~g?_HZjRvNf8D-8JuPsus9mZ_f5eUPCrZ5+W znCW85i*w*&Zz0BRk#{N9O$&vkw=ha_pV62$C)*UKBVWELD*kkI>7L%{MuvK+Tx2x~ z=xLx4AUK>)3=-x_vpiGA^#wp};14;KYg?b?tlf*lR)OY*nN`hiM~2cOVzUr(=n3{t zyF*#G8;;#vqs=9HhE;*Lz!O|DL0A@{qKCjW-jWS(aNRv;`U8Gj2v!9N-2ryXcp%R` z|Mk1itx1;@b3JW~Skua|CfdnPPQ1h204KIFiPkDW_mj3}@PLarA%= zz6XFSMwaa^HZ4|M71QA%Cx06oOM4wQ0JmUf?@I{YW~k#cC5r%80^5R)&foDk8x=17WYVMYnFxSes8!+h5vW5R@TG^l+R?&v9<$q+&@ z?C}nbYwSDX9RB5k;pga2IX0po_|)#FVcD&C{m-a`y)X7>MDEr-Ag=`d8Idr*Z~d!l zv^9oyq{mLP467M-MYsp#g|ndyFr>X}b zGjhVnr&t3+_^)g5+Tj1XgS??bdk$q$#pTUE)&cyTKOyI{UQC%21mPT(;X%x*UIHq& zj8AXXhxv*b5)3-=Cdd~g46YL|_Q(0(x(b|Tk!$Muw&hK9%HIj@Qeb2gt9!NO5lo?i z?U>zF1#EVe7ihYLl^@l{`LPJ7ve&r~`U#QbIl3=Ot!^UMA?^e=9}|~N=?w8Ma0I6+LzLu z?nmnB%Ji%-?Vl#)30bR1GWtT65C654DSMGc7ENGH2t+pwrcPkQ2hB|M z5e_v>;4Da^KG#X1T4xp_pAd@f8-zK=6GGlCde7B@2u5kW@$cYNBQ%wza)tz8YLTqL zvvG64Eo1X(dRy9V2eN&E0f^~`pEt`e$F7Uol=Kd7bu~+3kFED%n@_Xlsa$eu;{*=E zMh&I?_kkDd9x2GK=`5)*Gc_)3aUCZ$Aw*QgO0UOLzT2oGP;fsX*hN{*lv=o$em7++ z>l854PBS3P@b{@J#=aV|tE$2nOL5&jnZydq;Qn@ZOXIv4XXiQPOy)l;t8PQ$__y@b zrB@t<47*9~$gb4i;w-nsPK7}*W?aq=*XO%QTVfxwQbqAr0f1iCgd*w=fgOPak z>Xcexg>KN7-aCQ*IB84#LyLSH^7YFb7-t5HF7`3}ztmNh)PGKFIuKup1>I%paR5>N zZj4iAbcYPxRl3F)c4rZpfB-O_pp1?ZSsw8=cLFsWz6o3YL9*(L3gcnN`S!C1Led3PF!X@c|WfHrG#;)UE zvlwD5uk&1!89IJ1XAOE#7hhLw!tjv4rsQ4N>pceVX7M!{F7? z{`Qf2ZJ#Y+03#Poxv+xsg0xxc74x((DmAP>en})o z>S2s(B*2x7wMng{*&t(1-aom9j%XwwS0>dyjtkyZW*hs&sN4g1{FnqX?eJlsuhgw zcheI{I2;jNZbg<@IZnFrrL0@AFq_`zIYu|Oi)MjQqksRGN0o4$F7G!&2iU=*IRlw^ zS1OAfqgi7+D8Du~utx0(6El~h=6>PSNcO4m$?>Jz>`LjK7d&xOF}s7U+wCC@e;Kkc zcgk0qW)Jf|7Y-75Vz(xe9CKCNO6|yH1k22TV-Cw)d$+R+bF2hnH>6FO6LM&&gqz$~{(3k}Kx<-w~psWTy% z%qrT_78VA~f7ryL6CCu2bnW@pHAF#_W0L;PqXb&V>2SbVOke!jQQvdxIM%dm(B^k* zuGX>Tv^J6WINE$O7S)so>5AhM2E(&Aqn~hiVXi8A-P((i%Ge3#_nHa+=89O^6?5PD1yY3kZNS-oJh$B=-MH8R?NWyF2)ZG7OEe_BQs%)Cc{>@U}>wpGs9WkYM2ftJSDRVa+0jW_L=|4Ge#$eHh2h5=l% zMexxt|AX3_(`dzj?z%-vhH@cAZI_ga4Q4%}pFdylT+5(<2i6G4{Ai_}<$uQUsRQcO*Lm&S zV=HHuYjOLWYSG%3)P+Azi0U`7zP?UqtntkGm!dTO){0-2Dx7vcdQ-z0|59zQU476p zJLCXlilXM=mgghs6YuH17i9R!t%7Ug^Qxbdi~j_3opul9W`g2Y!sPP!6I3hC`m>bi zf`+EA*W>NWUAp+SsfN9$1MtVWCUAI2n&l zGJM#3T8){ilbJ75K}tP{-iK%LgvpzNy-xTHT|>Vp-fis0C_Lr>%lEy?7>FZ_oCPvm zaNG%M?`?6ClcH!z{|*pETtsPt7714b!W&iA9W*zLX}A2JEpa>H`;kzUk2Cx840Wtt zqrQt+H`-YV_IiO_K3Sd{psBO8kP!Wu7dRUEO9Hp+}>vUS`nZ_?1G zF%&?Y%H2xY3Z=PugxLGQ0F!BwJkqO7>}DwvE-F!wq#ezbT+UL8SJs8&R8WRP!U)a^vJl}#yNvDtLWm0+GG zL7V$~bhYrQwR6ZrfloUqar8qS_lr!1{d@B+xgCE*>^hTr-~b4>;zBCtLku$6ZaX)} zLAjB}D*@lBw%bJ(FHkxn@>SemlUIk4nM!hsXwI+i8I0%61|wp9wW4$_fyy663EqYC ztMY8Ab@JayQe8gxz3hfIzB}I6^%~b!xioC$j6j-q^A(El?w3|~dTX1`B1jJG`u>9C znJ6rAFPFmbU8MT>s)EVL%hruNt68`n##Q>`Dp5!$tw)jRr(V)r0DB0!b|3!ahebo%|*b`8-+1>|=CY=P_MJ%u!jJNBUGVhc#`MlPT8I`r1#- z5g{S7W0Mimgf8aTb(C;~6DGOd7+!e2i1Z*3+^#Z5sg}1>pmK@glKOsT-a4$6|Gc^I zdYLdlFnm=7<)RevuyNw&`_Xd?;!q=muhmmG#PCvx&0dxtdkfy|b!4uNu zm@4@K*lSX2URNfexYk;Pl`*Hr`7LS8K18zB`37bbNUIXobMV)YJ=Km_c{@|D>q8j? z-0Ti%CdfqLX)z<6uhc3;G*jcw9UqvTDD4enMHZuk+_=&&QO}SL4@?HhDe>v6n)+a{ z_qSw?osyYVa+{2WdvgKrI9*yP|dGytLQe&tK^(I{l!}`@TbUzOSlWd_^XCY3{ocdVb6V%Blojjxb z{-JCTkA zJgUF@Ur?;W-&*!d%g7f@PD6D*DG8>YIj<MSE?_PnKNm;c{Xl1Ik{27vEGKWnjm zKS!aHn0?3rURO<8(OdhNOhKO-_&IY*{oTIv3SROUdLA(GPfr(;?ZVa299K<{0R8(m zq$`AQ2qHB zLW_`ueIq6d$iy=y3H;LZ!i(PIv1nNv?vFO-PWCfzNLO=AcDf=SJqYjwPIhtBW6COtIuy&YLN%e9E@4KNI?*$i zz{6@;3g7Zpt@=8<1MR=bp8Qa!YmJb?$_x2ungQt6{RW}1!5DGzV6SVf zkP*j6rCu`EPlk+RDWY3AE~!iGUa=gtu%G;L^6H`(nzDJ@yuF=(qX3R7=XTF_Jn<#= zBjU;7<@Es8)8*D9%4oM-;xi*>R<&fmiM9hy1#vpe6sy*IvJW1mp;V4rk>Ug%rO z7DwLvC`FxZeQbNEU|jt*6fRBG{r+2Jce%lFtXgm_gE~X!HGYZ4p%&hIBex%W-eR>R zag#9b?GC4WT?=o1VJke(clf1ew_5;A&M=gZ)RF&L-sHp^aV3h|H1+dm4(55cTdhCJHAtvsVFo%T96|oUBkW?A3UyX4@;fWT?`1P1hpk&yrr)&v-Rr`L?MeEB zA}#smW})RT5tawP_ap8zLO+Z%+!%fUd_1=aW##x?wO9%~j+Rs8({P;kx{t4FU648^ zdH;~DV|=%N+Z^dNCNME@aHCJ-a6Z|0Th4=Hv^ax1zU+xnJv8yv=ToJD?_N3Y1JteM zy-D_ZdQz2td8VExzF7pYCPWzd31lI{PU!p`(R~b)P4whxGMgW)4K*enH# zS1RRuDAaQ(yqo_p@`WKIP3G)_wK4vvQogqWA7}Iq!(o1@aeaX+mM;&Q_2h~il5G|@)7v5~_p;xw z% zJtj)ta3qv&AV^=DLP#--R5<=Z?d>hS(8ulKx+AiQ8i2G;D)QAC*3qUn{8SoObs$7k zkJNG~|E7phgbEk%SDbYYbu!XSfZh~m1hyE{$)b zK;rCDg7Dmtk>bAYlTJB#R*7cU&tI{aNT13Sy{%yG{XsY9KZ|i+oC*#WnV|whZSRl5 zo_4Og_hWwt@-DEo7z=znd+|09H)CktLIXSC>XWPav%8}@YzG4&ocKtBH5nnYvEYMa zQB9n0alEiBh21_cN5s2O>7%VgQDNMSmsUlk_UiDJLpS^hY3cRdwOjP>J?9c|pp!S^ zXOA5gm)YHIZgW;R&=K#@8>gu@#A7Mg9@w;Nc@{sL0cMZJZuJN>%*HQqbILKy$&|o8 z0`?XLy!)8sE~Wbz`k2;s(riy2EbStc^^4XJL68fR8iw7K*0i>X((Fv|t0AQms2}&Tc~2vf#gRK++6UmO=(j<#XhEhm(gIwjp7g2 zrEjk@yTj{;O&OliLDUt*-r(bYwEro6A9@JO1(1kK>_JnAOFVCmS_b90CY)@}TeZIUHn*_O|9A8_Uf++MopOf93BWWaLi}5}}%>(?+oT2PlQ@d(h0n z$A`r`6H;RLchouyWFhW$c{>9P;b3X66WAOPN^tF!q^xD4hA5A{OW8rf8ngS<)vDh$ zRUXSl*?324z6D`&uwJyTIWfnNak(Jlm`JliD%C6bwK=SIAZC!V|)GiX_Lj zb7=smh5H9?F6~|m4bld*AHgrAMQkGmM4e5 zl)nBdW@|)suUpkGdJc-DcKWe7%0D)EV=zPIOR4sJ`1>|hUHgv}B`B1C=y;$yXd$B& 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

kmh@Ls7_wHVx|j*6EjUkC+&x)m8iEi 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∨!yng-O=Y7B5_oW-0J%Ft9 zI-umdVTACvTC6pybGXHBtq|?THEWf~89gj0vkxPKM(L zavIKJomD~t@3xAfMY zlI<=1;bZHdIB6`_7RVey`52324e-3|1H2#y0L$bKzzVqwuuAT28LYL+{VgNV&Wy2A zYnKO&6*!&+91-WChnze@a143{CD6|?amlz_E6bBFA}((ktJUP0mdRS5JZqe`PKv9> zW^F*8H#YHc%ZznWUV`Hpah=@JD#7=TbL4w~9r8oKE_oZUSAGK6FYmz|^~eWs@9+WT@tsAN7hyG3Fd$+j$mR0YbRYPz=3sf&v;xr z<4QlqSyvX|yeqe5wsuJEGb>%~Rf@6cF+I82N=FZxCuCss-UByQpd=>k_mi5|g z*Tv?A+9$3{%?rd6-K*VmRbsE?s&3w@JrEXK9@x0OX*O)tu7&2Ht;V(NPlP&aP=|JH_)~0x>wZguO>u1*JvQC7<4?C4uBXj?wxDaj zdB@i2I`n7Rx)rlO*Vd<;Y#z4_DDnP$+mMpvKV!S8q&6?u#+3~JS=*G7?Ju_7Qu6#4 z!|{ggj&j<6$+n;r`YUln(NbnxR?hjWZEH#io&}}UUlaE1whg5m@V;^xa7(%3r)@im z%`e!VDy(0z?JJUBw;d{~->5Syjs9TWNyYE)49B$JsZ>HR`y_S>M=5pj$~FIS+^F<4 z_thmS*TGW*H~f9ySx|2H`|47aVgEo~hBE3Os>@a;{7PLOsd-wNZoX4jsNDA7tUIU7 z!EuSQ*sRo*Dl35H%H8J9y35KY;1%UT^H7~lc?8HRkDC|jBxM&+Rh~63*EPBkpxp6RZyCWO}x0VnrC0PEQEq7P* zvOU?|3z&uxN3E@w30|>hy8FYCYOBqj;~s3@u%B{|075yG6u8I2QEMwpP$H<}Ro~i3 z&>u#7k$bXv$9`UzZVlNlxM!N5+RKF7t=H@o?%C#jdzE`0(CS`lKD682s}NhlytMWZ zyl&^*>;AY}yBn;cU3Ncgy#qGC_O|wiY7KZg zuv)FpYA>jC>ofbdDg==IiK-aW_B~Z^eGvA`wVA2`_i~^HaV(*B8X<>C?Z!S`?Q8CK z#Ha%iZ|jIthp_)rZyJk^M0FfWQq(EHboExmQ#i8JI{}L$S6zVPe04bx>o}vX1rqSx z1(F?S)r})dD?5tS`_Rrsb;}rbTvB%eX^u+uX&@6uW)ZlL0-^aWvvE#16m75%gq-j{_Y9yRa_^^kSmU0HGX8?s(X+mk-PnTq3xN{ZwF`U>CuAjs=edz8gGv ztIe_OQNdG#9}hfqta%!ZM~)4T-*{9r=LrEfW<1x7$7Ia62|gj?FzLAO=`l7PTb}F2 z1ILc%2KaOmg*u*khKWaV?a~*&8>S$2qR? zKB=<>b>zk!huNd)E%Y|Uhc0scO-Z3k++b6x zagG~l$_Q0*V@=tiYHqSA5B%m#)9FwRH``R$yu-~moeR<7-2u1MRAQ8Ht4*aLfm>=! zZ(rrso6189cdzL(_Nq-+Li$l0{;wP$zfLB=ntDP*;T>pwUek5hbA@+0WKY2-Hr)u_4Da&zl%`?8^rlhR5nx|GULR_j z2#s@=rs>cWpVf3b6y$T8=0ctI@uX&c(_(OfKhv}lx)t7MvExm!=jG2fZNh%`Y10EE zl`n331pCUorpLx<{$kT^+nEPyq>*wCH&3}1qg$J4&# z&;l>`(we*R2!xh-#g`e5RoW+c-IoKc8NO47pAY&9LTh}duPC$;-VgHKzVo5`e4p<^ zXbZ0_X>O1tEK$1FA(0bUJc`Ag0Qdjb-;+N`MM&A_n0jQ7_Zv+4PS3~UwM_~@B8`< zmf!LX0zx^I?D$5)drY`G#&ZP8PV*|+GhS5*Hu6t>W3Y3C{o_?XzweubeIo24uZH+T z-;8liF#Bc!Px|H|#3I#e$B21J2?7^mf3cOwrM$SXK7YD)mBVPT0z@ITGfh- zIgD+Wu$^qHJlb0kq#L#K&HJ=poNTM6L)wM58v2@6)<)AkT1A^cU)QSI6#9l{1-!1= z+jM$Z!zo*jNAO=m*+l+a3CmHq*R8Kh|c!242+W+ZO0uZK-WJ?4dBW zty$OAJ8c`*b#1lnemHWgTh!Luw&-Wty|x_&X%E|;e*2oX-Mqk9v?p!*Osuxo7Q-ZH z2W^K;ve)FVWYWAbK{J!-jSHS+a=eMbc;=KhC7ASlYfOPRJ(voZ70h6Yyt%<_=DasQ zn8#f3o(Z02%DiWTg-nIFICze!@?H#f&k;@xk)4|oW;r<;R!nFIY~aFaFZ@xcddjGh#H#K!5V z!N+W(o)O$-Q}pcMGd5k%GgvlDKi!VlT)oh^%jWCn+V!J2jfY;hj zS;zFA_5!v>ziwn$*Yz9iMJ%lkx1VPPeYE`otLPK$Wvs4Gw^uNO`fV5`!1k)}uAepZ zxppfX)EC=H-lmdKAKvw|H}yyD zgJjpahfL^A>IwC~5u$!Z!B5mP>gUKz{lY{ci|K^Pf?hFw$P|k{WQsSvhF&$jVM;(8f?hLanBGFKo3c%xL~oe>#PlcV&8Q1eUq;C%N=|$UrJRsYxKQeeAD;LjN{a(Q zAB#(mdk3Y*U5cwlWpUq*YeV0RdpGW{kUwrAZU_B&+~c@CbQgN_HDo65ug0MdqgT*t zr~-WmRiYa7Rb)foMb+rvqiZODy3mhM5dA&+FBnus1VgdU7-4?KcT)({TJ%*sBcDnKkECGYF5l{%40Une#&bO znZHXln%_0QOBv=rGXF8vV*XR}pHTtxn0cJKYMwIxfa)~=mHDrzF7tmk|26e4dHb)& zylVat^+)D==KItio43qAq591~HUE^lVg8x9X{je%JD+mSNLH{2qX*+%jhQThs4ZmMzOBr)9;mZjvpV zmQ7QG<-X;{M{}mxXjgQ%X(##*qyI1pKkL&U^=kC@qQ|0M$Nvv5>dolCh@Os0jh>1A zVN@D^UMDIm`tPIHqfSR}L~li%iT+9SzeIg8CM#wlsv_o}U-@{{kK=wG_j5CTp)6tW%d9XWj0uxp9u;PUSz%sS5>|zEG3INE7$+u*DPNls z)5R*%8WkE^g-KXTJq^KnH z8&Szo$tZ<9vH6jx?5J$?QSx3>T2xU~5lSa-F?~GhT-4`L26@LLlRUHW3Fv<;l|V)g zBN9>(#1BG-kS*j1r-ee{oKPZ^3gyCOz$=1HULl2{Lh>BOq$>MiOm^ab+9Vli05OX!Q_|J;>O-=eJOOH>V2gT6wZ=`JPjC%!{*6o<+v zkrL5YDL18}OH>o(N9ABUgXl6?&#UP7sqa#q=$lj*)rG!A-cP&&mUJ3@o0_3!P%Sk} z{SeuxdFro`o%$Q4fDOgynA$mS+-{e}b?)i?IA{!tzg|C6FA#^-mG5=Mt{x5w8Cx;rc1U_0JHl{}$o; zZv)p&sDSYMvxMLOj`}E-2E512E+WkSUBc|MJMN&U{05k_Y~eCY%U{gzCS?UpkTNEm|JN1Q;chCE+_*9$TzF6M z&)k$UE0lp&sD<1uWnQTI*Ok<n%93DLmbe9FmFTjvE^wf-T0)LBwN&t_<=mQb zkK0fl3W4{O{M?~l=I$%oLf5a+UiAuTV@r8LbVu3ao+<}Ie^~J`x9>IygYPN+nLBjH z2qW$o{E3w}yW@nhU$3|xf6|@E$GcO6$rqJRa;NjD?kr*EMddTxxx(yw%4fUtKZv?| z^d&yeeTF~nKKo0x&|QqxbzNV@%Aa#z{6JdbzQmWhD}R-`Zs_ZLxx4ytJ=Qg{5o|_=-aMo{R!Xb4ifdd zJNb~i`vtw`?t7p1xCdU)>+YcstT)^@`C<3?`*hSj#ZS0zy-!~r>uL9$52C`nYU6La z7x+2%@-J05CoHL~u&PR=-lBW$1L=x;;@PgVK5?)x7^g@&|H%E6^!FtdO==H0e(c`=bt=ZF*Tp#X#tUuix({E_XR7&S z6%*BAF-08}ka|)~S0~74mOA~*`tz$)u&D7uteW&bO;A&XWHsY`nx{TeV`vi`0RQFpKu-VqPi(wQXhzw>LamQeJs|fyV$>owE7H} zlY0XnAqpOZeTk@eETZm-6%9{<81y8Iot`wY+mnfHJHBVJ&yyn#curyaEDm`J#G9TX zaolsB*k!Qkcr3&z&joBd#ao^-+^%@XQz0&Rs>EfFRb2Df#SIT9-uKAjmPaE#68j+R z6Yv=BsCnX3j}QAXaUc9oWSkE@Ws=zwz-{1j(n(K;6z}OGz9-^qpPQrOHnAT0l!!0D z{ldOcO7iqdsh)l*!!vk1&$vF!9iDqB+cP5NdB&vEo=K_DGegSGfe-HvEB4peZ@-{J zVZSVuD3in=!*wFQ7=IE4{*Zfn$;aYPtWv3R4=eVM5x*Kysa$!2_1H&ZpLygPpZAr| z`^bo&jHq-O{2=&3;`_iKN>|+JSP5^jpUViVWb@2oUP`QIUXnaZ@~M7r+T!|PVM;W@zTiQLz)W|Bs=7->R_BkLlv4vy?1wx!av zmWb_~bQ^5b(HfEFv=nT&@b@D&@O^9RrFC^|UyjxmZUfs*X;IykR(h)wvQ1T`J6q(bxAw84z^7&2F?U^ z)b+T*gy-0`+Yp2A)Ag(&PC*Tcilre1mlK;M=_5*PLpq6HfOojAlF*Pv;thy9l;nn7 z5>tRpQ_>ppNt|{R6DXMtXOx_Vv)KPDry7c}ty2mbh%Ho#8ZKeQYg9SkP^nyKs8-4v zYOozvDjH~|szD$z8Q4q3+Mtl{+8gxam!=NUPT?91SGnFn`W1=oBC$dF zdp4M8B!)SPJ#bs34Y?sGr+CZBcOu`%^|6h{KVx3tF~IkxHFT0P95+VvC{BDqKS(Ty z`xc4mo{Q^_6~}WCeL1d+#Av@HHdB0I{k5?fj=i3bzi`YIiMyVUv2b7UcX6G_m>jJw zXR>yQe5PrY&P=VEa23Zqk#&`$)i_USG|>W0a29Eb^Sq`zFKC9dObZgN&^nz}TKDsO zcUrYRqIPWnuP-O34LN1)rc=|#ojz^qm##P1A2%7QljFQ4a-z2s z^HEOsUY4`GSL9r;P0shSI4+RScqQBp9zXf4SCxysjU={(`Ij$x{qiMmh-jtv8Xj{z zc5=11N3QW+muc?}S?~^H+bt{JQBq&`PRNFLS`K<|;}}rx^v*?Wv)t`njQAzF&$}WI zc<8%1`wid0#&zAL<1zvtHynsh`LG9iMZ>>lg5vBlV!)t|Yz8m8w^`GW06kcUQJ< zb>-=HJm;>{I_E0XWqe<*bGqg#(S5E`JwR;2kv?lxL{ltLjV6aDE|-r24x35eed@G zOex|RiBXwG#?OS9YfKMwow>mbGoyeL%rsMaBr4I{%p6mGB#X=nbC=m<9x#t8Z!wRV zUFI2!SWD#=8_OnqBZ*C}yw9dFwy;1AP&SjzVc4)#E_@@NJ;fGOPO(ModG-QZ##XRZ ztd+I194oUL>th4V<%mFy4z`Q!W&4>cVPOZ^5q1pfO_KiM9^sn!9KIr40q6N&y$Rg@ z^1n$Q^c`3mUj=!Mo^6 zNKW)iBqw@-*MEBRY_HRfsa50DMk^*pkhADMrGXjs2{2+yB} zeD86UPDJ^1BAr5~(^+&bNIrdrK1&zV7wJoMC0$LVo9?3r=pp(h$T&Sk-=go(3-mI* zMsEo6*G)~KClOK z#X`6e4NUnWa0utjUjcSh0f#U@K1BEtOY-Ee!hO{PlQ0|NfeY^fpD+&+fCa2D}OLKL@IsXS>7@qZykXcV9Iq;9d%x|MKGRNsuJk0UO$?Rs3 zd3}q_XeRY-%8EWgX7p{CQ3+*JD$HmO$#Q>+>V#R$CA0YHqrW4GbK1X2{RK6RP9Z9$ zAg1WO`EXR4UvpHxEVQ2vIjS8sj?S>q*BsS!4;Bagve4HZfoM7g`Ok02zcxLLa#XPI2Mj2XrGVB zam&G%MVzg_=2&*DMMRu;Y#hn`mqlEHUTuX%Ty^X?cIcB(@{)+_;yuSx@u6cMD2f7`CN|=>|Jz5L>&8c zc0{1XaNBwG-IrvOegM}weJqdYLM-;K_un=B*pWh?I~H6oi7t6bc0r%fr9{ft|pH^uV zGet6y@fea~q&PgPQX(FGDFu%-GsuiEW6UHo!^}FWnR)o$612U_tUDCu9`lgdb_AIx z(7yp@k2zpXYz!O6CbB7PI-AAjItJ{sY(9I2J^^%~Z-&*1rLX>EeSCcq;W%8WKGiW*pMh6n zeKu%b{ptF``g8Rq^`(wG_2rI*`pdW#yz=U=)Z4;LrBBzh^-{fB-$<9&`yEPssQwyl zqf_g9>aW8nH`d>%AFdy*p8&p=zzh`DPuJhBp99X7*Dr#s(53Zv2?O)!yzpF+dRH)G z@LbhzfJ~1ROQ274$?O1^#$|Fjjy3KSSAf646>;ae3m|2L z9L7?}1-K5b3wmvH7+f#cPp5K&n5WzbH^xnJGu$jU z&n`Q0BQp8JVnTJv_tmQTPymV1m5mxZJb`(pO=xnJ{s+MZli%gmr3!^=RSqat* z+oyeeS*Qgy;HL#i0854K9bs^|CblqSUWy$%l49?Ybl|uF<=Ieg4eV8_guk&YbxPgP z$3AI58j@~G>UWMFaRB~L*`l!quoPj}Bai!2~AI6NCcSx`VgRuNf6Q5RTckvrE1 z%OW5mDlZig5Z{Q1h>9$7QE+^rB9G=~{^|fDVyqiCzKAd4-ss4GCs|opRaseCRi}^R zyj0Cp&60T%D|1tIQVldG4d|C@GCtSdHkck2GstN{~;Jd~P~dNegZwK%mbH7m6;wI;P8^=4{wYTKYt zYKPG7)V|cWsROC>Ff+K(u*_kV2h2}x8?tA>%3;++yVrmnL#9x|J2?YJ>RUNOmJFJw zZ{`e`bNt<$KEwJC*fDG{Z|4N><_t*dyE&=NgLVb)=S&;0=9KT~>={;;+B|H(thED! zD(PD~gDTzNOPnSpUSl%ziwBOnp{nG@h9&Dxyty+-c8eQY53GDcjUknTw|0WJbq4mo zp>SA};7y&{ysLBK&75Oz>QXWj_6m<(<)6}Y)n5g- zUsB#-`A+_8>YfqU=n;_G?|%{vJ_QXwiAMb!G)`#JDQJq&v{TT7C(%Q{jgr26&lP(7 zS7?EyWF<@8mi$I~PH6S7Q?jajul;S5(Ae1+(AxoRv6QS~zY{V)$=bqi7uxwtN@$$z z`PY=p5y}<5ETH{D2Y*g^p;M555>@&)NPLl3;}j(0$;Yp z-}hfr_c1~fPqI;R5)J(&b)PJBx9~Sg-sx|@yU#jxe}0v278-vFx?O1MDd@hRQ};P1 za`(^j?Xi4$ERQ{UBENK>|MUEDJWk5b>#=z`=A*^se7o%DeL9{~%E#uhHGFJssjVR9 zlZ7Y6wa({Cp*2Dqgx)Nfl&^h|{iXXhE7vjU9?^YA342M2Asa` z#~YKqDyDmt%u7t_#-vV6^T6;Rr;8tA4Q;-RHL-SMvY(Vlc}(_?nBXvhHFF0v%J1DxZQ*-j^Gmf|`_^*k8--vB#-PIXZcdJ+@!|Pxi@i zB|qN_r<9!71Iz7qu`M<(W0L=4I|E)~E>;%Ati)SPa(V2a{dayS_?BFqU&*f9{Hk_6 z>A3PG|K>~n&Cdze#j$k||>drS*^Jz?0Y3N$cu(ehJoAevpeb z{_`)leLP;juU&8XQa@kYk+$C*|PdXP9Go zcwt~;SIMOK-9epW_4nA^%)cMEK45HL1hTp1Xu&Dyx10snmYg`#y)sml|ziO8pKX?6XFIyedt#QI9$JSQ<)Zkm!-HehGXP#hPfGYE@zVXGMkTe{^N3nh_4A~gY~)kF0S=93&~j`zQgA3`0hYo&Jb}qL&Oi*GhjSj zay&OD%!z#|A?JxiWqTh<)UtPqgzS+C*&`EjZb-DVeoS<*_YvK@6M5D~B5CJ2(ZjB* zgxnz$vL7a7|4XQC+3OPH?EX&KB)jI6*M28tUK6tCB_6bWPe}YF=Gr+=sNMoQu7u_= zS#OEeHYXgOJJWWX?-JUdG8?<aZ9Ho%B*d@DkoBX!jd9wV z(_Z<%w=w=VJu5T0X086B>TC=x3WXwdgc=An5^64Vp-}sB-<^W*tAyf0MMAxV`Uwpb z8YVPSXpGQAp~*sb3*9d?OK6VJqXEqqS}e3oXr<5^p$$TB3T+PB+9tF^Xm`2qedYfB ztXD6PhG6MQEDPgF+7p%@ulFXo1iYq348F3#}E}DD<|_7CWwt?Ls?)?>*(dkLj0L zpYpves5h`&`F^2;{4c&k6?`FCuNA7E_*VZ^s3BCl+;@&pZn^JfLak4HYo9AzEOdEL zzw5t8%vpK5%96JKGkY~oqL@%&@E!Z5oeDjL`dWWiC=nW3?)yfen?s8dQxo?kW+Y}O zN)z*x{F@UC6H61z6E7y#C0<>-sN_>&{I`Ko|aMDR;$S0c2O4dx)Nj69} zN;Xekm~5Zyl)Ne#hl-ND_;;M?s&0{sn^zh6|0-ItAkjCKXI6m{#y$!9xXe3mz|6P_P7gu3&Y+T4-az+t8MR z?ain&R>}Z|n1);N|Eux)5jibfUfuT#IL!%=?oueb8w}iSy$44iG64BeEcZ3R})1xaw zS4USxSBEA>H$?Y_Ch^x79{>NiXW?+w@NnK&Sspq+6sor+AX(}4b_TR3pt5qjlC17} z2Lpbm{*T)&pW_EqDIi(tIkJLsWOe6=QckYb&1n|stE_doe_tGYUmj4`6K&?i?7wpg zL+2-a`BX|&P1H!#mQPM1mrt`q>%_&0%M)D_u|y%Co{7GRlEl!&jftB@IzDl`a8sp5 zZm=5ddeoIznpiG#bvl1(BgEg>aQGV=ZnSx{dB{XNN4tc)=#|m#p$LC(qf+$RXg`^U zLD3wHNTMwuIU@j8u z=?xaF2%ibx622vT3-}96OwpSNKT@!{HxvFM_`&e!!*`=rBf%ztwF0b-*HZL*nTCp9 zQr~*=#t5HfaumHk3NAtC5v_X!{>UoqOhP`y_A2OGdo14s-xWE$cb%d?6Zs`bip9>S z+QTC|ydLznJtMMp&qwDE^tKf?i{abC52EKC8QnnYDu01{6iH+FPq9#u(yqu;Snh~? z1pMjnm!i{z)_c*)>9lewd`Ebz-x~cA!DjHy;G3IvU~4QO0b3w%gO}QPLujQPI?A_j zXHjb%nj^7X3O^VAP58UvS85;99nf!&ycKx6U{kOK^VPz12HR4rKkW_zpAUtdq24sX z_TCi1J3MLK83kV*biu9OLxPi4Gh79Hh+56TkfJ*Q%~J2rf=j)J1?#FLyi57;AxdYX z-y8k8@GZeCY<`YTJ@cAiE%Sm7<%2W-;=V z>W9-gX({bTN{xNG2os4~>Ly73BpTMYSNf8A*NkBgBKm zr_&$(anx;&Bm^Jwc7iHt2$mu*Wh_hKms*}4E~SS{>CaMMvWNQ?2U04@R#gPU}g(fpob0UVFO!A z{~MSx8R@k)lD+*J!?ZGsx);*(!C+l~6gnHgMc`rDZKbiT`mSdYe|`qe#M(?ewozA> zWTaA}dNr|XkqCreY7xt`;j_@sV&1b$$pYf1EqEn4 zFxz`V@N+*;a2oRO6vLpbjwhJqzw2s6vK7tVtb#1CC3c!Cy3^oGy&3deYPqeje=l`A zp#Ld+6YzN(&t%SL$)caI3L+}^4{B`q^VDzN*;>~OQSbSmDDTIVcb_BjyAaRsDMpNr z*MHFL(B2YVx8t{)v_G;QWB9x&n2pbyg4uY!DVUA_n}XS_$EIL5bI}x3{qO1jbS&3m z>_f>dOTjFgyZrOXR4oN-Yfr+5ln=ke%(jo5rx^@=7k(?XCfgiE&nL5fo7+62rS1gQ z^#pWE!Mfn3tms`9BhM(xU0qw$(%wW)Z!*JNmB`+t_PbKr(q;+jejfQf5hAO=X$rP8 zACR3?=Mp6K%_pqE9|b$GUcU8Z=XG9IxvYpE$^5b+!o~1UX@>W9vo1oa?-h~HUzRh*)k1590FCr%>XM!EI<{YtnrH)7cz1B~}g(DA;P5oLJ8+27Sp zOHL^{_^K1FybHdL{%crx&1OzokAvUqT!b5vIeU}OUxB|LEcWDt>GZ&U5wlhYJG+pO z`NP}5vFI<*QHKwjn;7F*!CbRN^9eeSF`~WN&+r^9%+;}bt<+0i14VbH#-!vWvF3iI zycrEYT6^v$nB{CT)sI1@(zrT9t-0rD4`nyhQCDSLADQjKUtnGpele2P^yC}xR{F4w zakYalq;6-kM6i?5o%%uLW#3U>ZAY_#d#3PTV(kz(A9+VCv@w$fzX7{>vc?@l-_EAR zXVG71)@!_B^B_1G`S)08hqX=c*CAi$eN3M<^6${onw-i;3(n9?F7i%d|Mz|i(H~)S zO$}C*^P$%2jDH^YUS-{lB?1*+(bKzA&;LDm5ts{Rg4cl41?^ckiDpYM={M4hr+oOG z0CT}i@ETBcO376mp{)z%f|=kopz60lvk#i9EOM4B#!fLkPr;`G zJ{QacuK|n5GkwHMmvZ(_V>6AlXRS>$Un3klMc66AP7!vBuv3ILiqx9hSvB2!@EUr) z8#}w<*Tb);|MmQL@rFe^(s$_<=vBhzyVSi1RQXs>ZhTG@JX7xUnh!gYgn? z7%vs$rDD8P%uE&ICFNhCKi8q}!q>ykDMj%f(d*@Fl3t>{!w!5 z?XIlHbjgaveoXfsE1^pM8*$))GN6~4ays4?0?p9v(?( zNa|B6JB!~2|EJKb1h(~W5quE~cY|MAR11Qek*I~I(0rI$hgD(@BjM!f{e}JUFPuo% zf@8sLoG{?7Qu(|W3uSke>nZdxn^pV3U~Wn(j2>w070$5>wN2yR9qcDz67 zO*!H)F4wCj*d04x(9dqV-p!L(hz6*3qS%SzpC=j1lj`Y9hvJ%Xm;`B#^KHM&k<{v=uOjIrgBr=qFNAK z1Re%sIyy?ZLA&cz;+9f(kFLt_cFxJSf-}H1oF^x8C%uz9>1~{srg1jlo*pjK6QDB} z%QfKN)?2gN-b?G+LEb{`n4Q{x!`a(hZxQ+R^!9psdp*6KroA#Z>D}3XgIXa@jI|g$ z_incUe2#O%(~M{aH|Xh{#9qgKV~e!Xm{uCoN@Mh2SFf5owJpD;HxAsulMStPrbQ(A zc;g2=cEJ0Dwa|{Jwy5#hMDNZLZzA!Bd&CC(AVzcxYw8yC-}gReMl7m_YwJDQ7?pVa z%u0Hw{6zRO>HnEXsuGQ}z#d+fSlgv{Vec}3nn>PNxi_2A&Wi2|`0rH5RN?Nt7M;zi z?`5)f&H=CCF8n07;I9?EY(1xWW3-mvo>n?w^Hui8kFfj{)+T{by>Xjmls?94$^y^O z(h58&%IL|>>!@aFuUPY2GwVHfyG zdnlgQ**T*3XvtUE%u7>H@7Hs3jJET z$C0nrgSU`Fa`Yx{KGoZ|S)wTWphnk5|1siR*Z5la!;In)>h2&nKBE$UljaJ42=bS} z{^W-p)V&(~GI9Yp+zV$rrsnCc?zJ@C1XJ9RW6DM~Pt-vP2gtD(b4uN8oIaW%(&aY|klwFU)IKiMAfG=00-8QHm4H^Nns6SIpr5X|Wcwop~=<~k-RKX+fsI`N8ff5duJ$g~otiEGBX-3>zU`y!8t zr)h52^;!<{8U%GTsMMT9n!A-tT>Gcvy;DzgH3t4$5TtuLIQ*&TB%NI z**n#!uk??_-?`#{FGM4g(5D1qrYDRKUhBra^1RxY1qN&%p}9fFf+5F}J}IlpPrg*$ zr0mL{X0Kx*`3qaLAD8T?&#Jb&B5)tl9)1d{W(;+5n$)+f+;^Tw(@rQi*u-t&kL=!} zvNA4x1qp+nw@1D(9%{@|YnG3JP>$F3ct+3r1n^GEraB(E{0WsDv-9}-U4hgP4QJY`YauivyhQctFrs#bDz&}4 zKih|HhaKhhnRR*?_27FO+iUr^8IYG@R0}q+b4)=~Goi+-h$s!iyHUGMw(YR(tZy8i z#@&N)biaEv*XrAu)h`vN-g9QYTRf}r-DWCTr&{VdL4I5TF@XI1Jt%nH#qguXXW0?n znivniRDKm+eqpjZ^>yz^|CGSP*SV_uV+Q;j_h;FEkLf;D>q&n>{}YT56P7`lhC=Xh z9);FT)h;~m{x*HDE4r(hUp`(jeDGZ|k6n^x+%9aU;1Mq+J>=oiNbH#h@NDH4>>;!q z;>M97D~+h|#>a^@R^{2?iWw-PvgacFZR+iX(5kP^NVEMbPcD6~ zky+w$w5={e9K=Bzb+SMpZdT2&Cepx3j3ZQFgr$@)NMtt8|Euk$DC4t2b??|b*gcNK z4tOa)&yDKZJ0e8jy{p&G!;Wl>8 z=8pX6{SIR9`%O&m%=}N!>pyw`jD#x6R#eW!tR2vj1V1ePI%-7^cy@$|d3(%o`D4$W zoQplp3*pl7&1coju809uD{Gb2E8V$MN-!Z9q9Ql$yYyx2PQz}R!dc+dg~rZ+E3F16 zA6Ce?K-2!O9%78@Az|n{*vpeyyWDC(qVFk*xT5Gx)QKT7pW>wO7pk|em_-ZJgjnOB zmDJ|y!8|j=Z=PE6sufOR(+!IqkLU{YrYmrs;zMtgW*=J+end40Kx6_=z9=xC>&UqDkr#?p3GcUWHTH1b!Nvz4h6$9*gAH%)9)gSSamHM96K zKcBEV_6Owz;VP6qau1bUiL+xnP-QrUDuKjSwifY=La+J)TX->RFLM48wV+ad;tlr$4kwdrF#}om7FGvRpo3-fDgp?O8U&7Z~dL58qn=#^juEN zh0+sI#~0um*;&I2tA()nf#&>QqhYob7yk*<*zWvZKo_A?kjEb9AHnuV&4~TP$O`yI zjK*o4PmJls4es zDoCK?L9v@5=R_WmQeL$THou9sA*zL^uZVcA*XRA}Jvn7hH4eo3Eb02SkTD`hamA9$ zO*lF?n`Xc+J&ci-^gu6j-2uE5VKQ(wa_k=`F0 z+xYlvwE#Gi^~JmQG2_ELwBGGS-9CPDf*)N<&mb?`4iLV9Zee#Xf9iAGR7QsGvuBds z`2GC?cshJK08>0zk1wCjd@a)iAH!<{Jz7p6cU|K=so&G*m0U5~dJT`RNS0TPsJ`W; z^3__ILY^ZW-&C!N9>+FC*GaUB&OL0Ngd3Ha1)Gt(0Sjm4Csk^!{40Ye%6-)u(ne+k zGvaH;$F*lKAq%o=uIM>71{6P3lm0vy$;vI-AObKRh+=N7?{(uTh&D=a9EHwVg=rzv zmpdTO1VWIoIWp;WW!`Y%Y<8hG$RAkQQ1lLu7M9h8_e9?KHKjKl$%xm>9Fc#*90B$; ze@PqrQnHNAI|>_=4h!JRuU!gk*{p;P{-#At^VY(7fQltl zgrr7p>3F&TSwqUH@W{pG&lD1}N19d?W`SYOiY!CZoGItTgI;sS{_3xwI?P4i8q@yw z&KjEYH?t<2$3-XhtAtnL^~No>yR>C!&TPVsXCIt`Coyk8RYiao)EmkfeG^)P(&Y+8 z=gd5K+2!%F2;oXMQ%n_wKX}?&>q55bztW`?BF_90rMX3OdJ|kCW=nJWxE<7ldWiJ1 z-(f|lPRxClnZUiceeb5OovJxTfo4*B&VVP1 zQ*ATP2O=L&2yS?>?+ffMN7!!{9@YN0qk;hIX59Pq0X+M3CgN#p{DRAB zS7CTtfb)z^G9k*x-k#LbGv5B@c8!?#BQcQ8Y z`WX29q;!t%Tpxd3V$0`V+4jEE(Ypo9+odvP7@5k<8VwGD79Qw0;4A7-!m-h9L64Qr3}2u;-SO`(R#fWbPONRV*duJ8T^vo zLEWKs9u1q;vGfswOCvU<#~U`v1<`CcVrESXybge^Tf+MCa)#;Kk{qq$f8%eXyn}og zs~8R|MbGQBdWex`93KZp?*{$e$6cV8g}+041AWWL6BJ_=wj-3-|FH{bc9%C3*z^ZSB^r*tmCrbcQhR-UFek2bu97@pUhv$8qm>dyb9G)xTp^xN|eI1 zLT&_hKbqOpa?|ZO#cg@I(w_u*05$Tx#w+1UZ}o zarO*Y2CTvos!kfPvxHNA^PZK|hRTt~f_V(nNY||j2 zVHMRPcf)46^|y$8k!42HIKp;{RFS+Sn1A7a;XM$BjI1LVKmQk?t2xyI#)23iA_N&A z39d7|YvG%!L$5*gLZ(gaA^(U7(tP8OMmmLi-y`1qy66Gp2c8xVyV#xlvxFJB%S`$* zTQGA(6%WOcR?vp#ji?jeG<>sNqzv^WE-ZdG_pI5LAdoMQ!OYKF^@j>P@ncdX*y?^o5l z$kYyx>eouS09~n5ycyV2)MDB`OIFhik9gT-~9h#-OJN>_myC)O&Um z$WLZ_0^^^jL&l^ygcntN=ZoSegVVmmqijKn#N(I=qEFy%XO(v=vbX#%p1zu&$m@vn zaKM6=^~LU~8?-aB@cesn@+!y6?HPd>EWALH0hkyXsoWn*5*0}yz67bgAk079UlKC` z6Zn*9elR=|D%}5JD|puHx=V6m%I#=lF-`Q_&qKfG+UslP+au5CE~}lz$=B;Bdv&!7 zms(fC?6TC|yq0a83qM_q>urOwe<_)8mTeU{_DH42Wrw2czU1CeUhsNvDW9D};Z%@&x%5>cO5(jRnI*JZlDA2p zf-!D5|GZ`1p<6Ld2W`<|;dFitcV2VR86lSkUb+-Kl}Npq*jiKYI+lLnk9o&YLZ?=t zq~$KFMq^k{uyy`dj%ls|!y6qGUKPPB$T%X!5ld2Zhf9_zp`||fuyM|iikXa{l`p%c zvf`;$zd0W@JJ)D#YAifi^xUIIK(FPQTSYfF_q4h~Cs08e<1fHdQ{Z03-x_Q!#J?kb zNF~RyS7|l=aGqv~SRHbF?D-!J!MLZ?GsO*w=GGL@G)b-r^cgmk6#3^-`+wgogr62F z!rjWIUJMxe&c*J}19&D_SpZb@Y-e_U1ukTC%%P}ibKE--i+_%Q`5+p6&j3H#3CQGg zG7HD1u(6^e3D{GMT?^8U+&B^}$!}!U_2*V2q4O){N^*tWuHK}#?0I{KAn0rY0j?^g z_$dhFR1oJ+%C-vAVxCte+V)TtXLx!V0;^2pNCV4MX2$t7OL}y$9Wu*%q>IleM~Eji zNa+u}=H&!gP_W)YJ}yPr36*)sv*rQf>45w^m?r5(I}mrNVLK_yyd@g7DCede)7}?$ z_b%saYfXg?XIaEktY0meyd6i3gsU0hrckfp5I610566f;G7UF5*C*i)UsYKAgA+Z07~{?J?!Tyt{171OK8&rwG%)-?TAp0W- zOL6L}I6#=>Yf4msF5XQZ-HGCXG4ChlX%vrcDfM`r#D*&i;DTc^c^02bckw3iBwcVa z0%SX8nP=dIr0EP2bUR>dN|x z*%j=L*;@lxlUEx_%^&pA*UxKPJbjAtp6EBT&zo-*yUnL6!0t;9>{FGJIB@E;ggU+Q z?8)k%M+Fy2)x0VCLQQo96r=mN;Q5lpH77Z~DSn!`iBlxZz^r{>*{Dhq;!Sbkk+o?- z)bPKaul6a`SG-%e1}CB8OJd1$0pG=GnxiYmdXH0&6KC1c6TwFilfTdZ`w*Sqy*NNN zZz8wg3nIu~LSImCJ^Dr3v6d^dWDLD3NJJHw%A0ZFKb)#!=3>BnV)n3UuCg}GT8wd~ zl=E6VfKOQpw77j`#L-T_DY>2`HE&D0iE`K9U_P0S>YnbI$yxwBwhnIPi~W%9tcK{O zilNhH!M7oJj1ZiSr7z1&UwWH2ixs|9^=E5&yIyWf3g7UP?xKzmt~gLGD=OZts&te)5*FyB&#RE36tceTzYAyIG2zg@ei3L1Ea|FvcBZM+vF5(0<43K z%AR;~yAz5DW}02l9|bP1O<%_99@~K1uw;3Cfh2vUPM9H{lk4J)tOvLGKxWVBv$rh; z{4|V3Z{Z?3q07cXZe$g$paW`=m-u1=**`RtU;cNn3e$4JpW3HbcD9xcAdg!Sxe*k~ z*~&SHe-E$2|CpR5C|?68yOXEsO1H%k3JC-p-Ib2L(1#`zVf#L?a0b@V7^H8X7W%2m z^8$uNB=;krV@FtGha1%VR-=pQFMsIu-sE47;)bEA~I8}}p) zx%xvoD|u33MaD~>!d}oS)TINE3ssbZrXH$5rIgbUhUr&SImX-7E6@1#I>&l+$ZFc| z`tX!5*(P^8A8dD`r^J57RD4nR0v!{u6f8@1Tv(k^ufcM0^i0wS&7#bcLG?voXu)m8 zmE#h+mqnTPB9$TJ^C|hd?#$c!7rcG%3d>eGXWv=vYDd|*cE$esH}l z=;yvRnR9^H8Yr8!0vTq$u8eHRdNy@(!Eh>-%!YZY8mK2u{ayI#=q4rq8#>@2!x zA7e{5A?bm?cRX~Y2yOEn%0ejlEQ*&6(5C@XV}RT&Jc=Rb=l9wU7fh$Q!(EYBoN$jC zLAfBlJL(n)0{pJe3({IY&n&*@0MsZ*q3P!vTfSP5XU$RIQVh<*G&t(tl*$Lbv*WoE z%wCKl2eKRHPLLX5Wp`XK&lmAoLI@F_@Gyc|Nbz|t{!wu7x+yGoATSVI!S?^d;2Xd}v9tp2g! z253wa`Y5Z#hAIu|)(m?JL*`w>{v-#7oQ{b5U^h0LY{pan%0QU>hhNWLJO;>BVxjLOSk9R)#{%L=7D~G zzF7H_WvIpwrsj+Yq~x7uIFH4?q#qS6e0=%1+TPwn_0~gA0G$wH7frc zC09Y3!sEqaRVf@GnrKo?!@ri&PzHpVY63}(wDOlmR4xB5Zm{QZXwfC~JEm~JJuj}w zcZ*RpfBmPQ1nNU~8suf+a}V8b1!^p_n-9X-?`X=|>D33m?;ccR^R90^kvwcJUF6uR zGc>2qWbyM1rhOLUSOJ4k7GrvxzxnZeAzFc@_Y3-kg7PWg{og|xYLN~P@*ZD*7#V!N zURMV`6n6BXus!E{hI@{J3n0I(CU0c0Vk%<59^Up1*l9x_#SagejuTdq^m|oN| z_Y8h2?RP@SN9KgWK`0oNgmAFnWE={|_4!rQJ4aWp0|U11OYnAInwO)Awi+ZQk}DcMbe#w#b= zH21e)sbbNR?#O+G%@zK9(}W|SZvBGY-ZgF$v_MaZA)r7{jiG3J;jLGUt)K?;xPX`C z$Y5Le^cG4WR}=1^=8bJJq)bSRJqke`BVG`u1o}}Y#KzxUR>8_sR?&s|kbK$c5I0yw z_Zej&U9dh8dzm!Kjj|iLD6`=QbQq5E&t4`MB!?pI=vHjF`B|vZBDp;cb>ma2pRIpb z)k6>1FdY1<_m$fB+1mG=+V_Fl_bsD?B<=_Nn>>0`Cnx3w)0~Q~geh&mhpF$@s)9g_wV-1Taa;AIhw;=4 z_Y1lC5TaZpk});FHUNq;;4&cktU2hbq_RQ~(cnFY8#w(2#F=brf_M*#*C*USXN{8g zVYx0C8&t&AW}}1;`v|x?`jdHr!e>W*i@S7{V}2 z!Vahq44n_K=JtB^QEz2Ehc23bzW3vN@n0iay&CXiE!`V>V_EO)zi_UM3hd|gk@IH} z`cL)8Y2Aw^qmdC4m4}zdQ(H!6Mn_o~;h>5K-g2=_a8 z=$rCO(%}$YFGc$h16xHeMLoFegSuz545mDgL{4E!;0v@)_{k0dHm zZH}aZ`tPqud-MvUA*b?aY5<7}m#UnJGP(+Qg089xx)_40rYZ)PD!Qr|Z%ui5IZ0Z1 zfo1qc`5#NFyE69jn9+*0zpf;CXZhUWALR{av@m7W9YKBO_1NXE`I+yFq`Iioq@toMP);c3@|g4{)mfv@CfNm5o&^L&`Aek^QJ=@CH?hu= zr}D1CfVI-6h|n{CZX%q&B4_dLy7-C`gScnG+{8E)R%e;!g|_8cd$KOtn;5c-x-ROh z%Fl~6g?z zi5jT$VFWQ$CD8*bsg=ZpTdB(<`<=?usUeW5e~Ha~3sM2Es#2-KIF`+qvmU7YR@HR> zfyyCqnx|qHRGTW9Ds)v!bC1W^*O78fnL1I=PY=8xFnZ};e!gYJnlSOAUQ<{@I08Y_iF3E^4y* zsrYKLDRwPN@zK2$qInPfB~G)haVe2ECyFnccU!_8&0qAFyE;~cWhvW#Fp4gpppipaHXyv?m3;TXj+u?)oCI z_Dp#Be!bKUHQz1SwPu9RC-GHe{5@CqO^$DDN})3oR?FL2TxQD}aG`)uE=Xq%Bzx;y zfLgu%zBlej8XYpm2#e86qJdy#NOKV|V2?vTV574Nde1nr3>jQg%Fy>rAJXORLnZUj zC1Gf{{f`s-3^TPbO&F|IQI-3(&a;Fv;un$U&7eO5!|oWU4TaZ7OJ?i&H*wY zTFH^v54J7wV;ocXW6bnpoM*6tdmdB3*!PSGbX&HGsrfRK|mChNOKc8-x7{y6TXrc$4>xeIPL|fZq zuO2Yhul_cPniy3}OR%8_Y@-0AC6(1s0l44f03IE2*Y@ZON9@&0=DQygy|e_Av;-e| zz`L$ELTfahBR1Csv*X}mN)bKFh>mG&$7HsB2G=RG)A;X$=!sFyv;-%5z_G44eQUHe zh4>Q^08&a>?ps!zzAakE6}xSZ*>UmrLFU9Ld|E;lJ)lKL+_ocn!vVYPnAvgr_kns^ z0wg^EQCFOxBbwI%Tgm|&y0twK$7DE=hy??d+4z=-CDlHoO)^@CLi`E^5Z738@(o-$ zBHLjho6opDU>43@m}^e47A3cbKd1bF(lykv=fk8EjRY8yFiL*Gx(<|&V%e+Yq?nF^ z-79P*rH`W7D{m#Qj>6q5X(h9b;@PWiJ&s%aE{eM}?WhYneQS9wY%YV>SwMFY3TH2* z!zv6qfg+d_c>t=BM1tNyjUYi*2k{XltQ8ZOL&TfY_lELi5|as#F=|@@HvCfhQfiz) z0!~f%=e{-i`+)rp%Ol2H+_%VIQ9(Ks&@Rz&-uL*+)y=LjoPNM5&}&&{@LR7aUc0Dl zD+}dT14KN%pl4ruloISo`562io`o4#GrCf|^)?&X(1fMlc+>A`f|$^RQ8-2>)WRLk z!W}-(5W9I7%U1*&I~qyk+6|j>9SE`%nKe}FD4`IQLj!qOT;ibFRR)E_<&I=E3uG^8WyZTm)+cC?lkZ(BQk;IFlZ#3aC#fy}0WZse4 zi>7aE-ZAEjm~Vvsk@}0O;jPt2d+jT{Z_@T&%PYQb+V=kQYt09+-zeej$Op9iE^uxn zx#Ty72$V>AKcM&qCeK}#6$xGpFsIXqWEZ7Y*lCmV@kh^nYlQRrLV9jQ|TVMq=1_KO(^hEL!ECUFdk43Hob&C3VHv*&Vv3$Wn5XiH)X2H}(0r zXMMM~EPFisZ@_E2w+MTx>_JxjUu*KL35@zb-qPK4+G9)12yxBsjUz=x7o^(>xAhGd zBpu_n^&J<)UgKb^(&Xb?^>Nf@?+W^G#4308;PZF;uxxQFCznzjkrhwN>- zSMfZD^ljQ-B+sK=%$iq8?}xx13IvH^hsYi(1W6-@&>l*;iKU0w9%{Ks$A{n^ih7A@ zhv*)vdP&QN@E*!ri7khquL}H$afhfGB%sWTuzKXjqiv44*$h3&um|`a>RU-r z1cq@x4LTC5gzH6@@)t}`CSH+zi@B!qEoLh$mot}|Pnb{EUa@@3xn?shJ&l+v`m6fu zu$Oihc9+)|Vo%RcM(>dCW?oHQ!+KUV4a@7e7coz2URhlOTNc;#ZtFcOUKd@i^<6Vt zc7%=ct7aEYPvGx~K11Dx+x6EgZkJw9KJV)90iUzJCIZcQKR0v{IE-rpId(Tac7$s` z+hv;TI0trG>^RYBwQWzwrJ8Fw2X|WbIMr#rZGXe%it9N?KL>JJ@Mt;<-Osh;ceh^<`wX<`my@S z^}+Qy^X~NO^nU+x|91a+{|@_7`cnE<`da#K_G0!X@WU41x0`pFx1V>Ocbq3LpJ!p0 z_p}0egN;W=d714;Z&~2CO`#|D?JLNNKD85XPPG*XIFOBtur0*JlZbl;&PFmG(%=M; zM@HDE^1gH3X&;Z-=@Rw0Bz!E9)rr!EOdJqbV8{Y+f8{YN#+z!du4AI$|3l)~#3K9;- z&sUFl>irJ2$NrABhwu)zNB^G5ul#$7uAH`AEJd|N(&mpsMGs%mt)XR5JrV~MkE|2~ zHFQB@w8gLfzXx2@5&0+x{GFDH?w8~CpSd0$dIX#`(-lEGY#y?V?tFTPGUv+Y$~PL) zRey-8vX*46Q?LX&0@zy5*pU+RA8--q^i@jOJK&iM&k zqU-lBhUs~MsS|i^DiW#_Aa1&h80)xnM$p8bHXfx1(8NlVHQD8tbpLt0N?L?=%XK2jww80H2uu3su{Cyh;CjdDk>f4rTk5YoOLc(eO7gw1 zj_~T_SK&Rb^u*$^SuF6Tn<5la7VUS_opmwwgmKrm{=EQ8C@A1P%5Oy2Apda`r;3r1 z;(gcjU8FAeTBNVGd&Y%+Yv*yy+Py0Es(&->f^C*@tHvIP9>}Pc#}?T6FxiD>7mN5b6OXB;dfjk2@1ERK(bf7so?v?7!USFO&mAiT2GUGeryEN}K>J;2{$aTck zr?tOE6w>rqytif$ADwcz%KTbbIjH6V>jhZFu~W2jXr9Ksj4{pXtlQFPUe#XGPPLhv znORY@`)&8Tc}jaoJH+N$?ODx?r<1LVZB@<=-wwZdVtsTy{PKzYiQTlvJpE&_GgLRArds^JGeA=-g)gRGib_1U%s)22QH)KyW>2~(Cv zX27JisVhrZ#y{_^$=^rpKdj?Z-lo0{{+hG2CK&91DH2n~d+>&I&5da0qA9Efu=R<= zRsQBYd;`c;V%KzhLy1);*X$eviXWNt%p60rRW8?DT?5QjGS>`ULv?sVtiA3RRbC{- zA;7H$FESMgkku8A-jRzGD#Hoc&+T0-#eouXJf%74h0wAxv zt~e)8FkIk}RS9b}(RwCpIJ6;bUTnQy><>^htM|lTm-z zTCU-g=CiWe8`=OO|4hYm` zKAXNEnp`*gAOb$RpTr!V zaeeXfUJ#Vgxw}r3g_oRY5#;SK}zO*@`AK$H!KP`moHqDLCq zL40oGbqb`1xnZYBo>`JU(wwASiP${+qH;GYBr6}|X_MDK-}$f>K|x<;u7_Z~-hIZ) z?~<;OligX>{ z4tl~PSyt$Vy~Fmog~8gm?Nr_;$4dd3C2GeN>8FRBuP?T@nY+~fCa;@N_OmuG_KUbU zawwCLpBeD284=P@u3BBWx3prhTo=(kXE>Voakb}dvmjNpy~gv3cyXhp$^D7mk>c@< zOv1ociGwcUrCdivTqP6n?|w!Ce*GxIs!14Ly-4JR0z|zCu}PTl7{YH79yD=RN|x1v zN|Ue$OqQiWFoYW7Q~;{qBVH&=RLCCXeXS(Mz<3??PbB4EWHrTIXG@E`Odqsj&z>1G zpl4R!MjJtAG_gY6oNM#DBO$A3bU@5CXY+U5?2A|HfQSd@%-H>{qzOl=Sm8rRd=w_7 zb>xvTKCYn@(X)~pdrl@Nl2BZ7|gx~8O-|5IZ5Vbq^MW^gZ|j#+@li z!*ULluvX78QNurQ(Ql`NFhyje{=T`!<&;LsKW%uI{!c)EezHW^MabKxOyN};(1S~G z%gB`4RDCsIN_TbvV&KZ7)FR{kPggV=nm8s zQJh0?ps{zR;yRXRIdLO;os5)JmTcn|MAZ*_o}j-UPFgZLQJ8ifNlH9@dKKAqKHX`A z46{|I=C+56@-89Yo}c#(s3${7HQ;Dw<7~oAI3wM@)E#U)X6_Y|`W2V&3+Tn_G}M5b z{to*!xe+KRl4=uPpBX~2h#-gNA7ne{n*j-dlSv|x0m1`+A^bvuE-drkGZNHA7edAp zL_G2LT=uMu;wCe z)?sSafo|5JYF-t$ZeX?^l3j7ksyiI7J8YhPLP{F|(8o#W0LQhG5ZnU04?^xCtM>z{ zqa}2}<2Z>#i=n*LIY6zz1I)PN3wsKM1V+~3x0US#p%iGpyvboG4fK@<`I-H{tUVbF zc9zvhFQpovNcc2^e89g;YvO?|iWR`(As=dH|NRm*@+mN012RI!g8c9oz(VvEBDLa; z&|%J+{9S2mZFmt(Xo&a$=9SQmQ6H&+t0An$R1vH?z83zYb#~5p4s}j> zj&;s?4t7p@5lm_#h&&oxr~nt)(5|sriC7s|Nw7qr#(+CU@UH&!>xufw(v{u|o+mD6 zMsMOPrYlQ#WNTn+qT1}*_}YxnVB2WhkfZ*(A!}voV&nqjiRH=Z3D%XTBM2~zd@O0N zfyW*;kZ>Rvi)Myo#uzrjbd+vSiI4}_Nq3y&Jjy1Q{V{6CWieaBxu^bnNGx4j^Vs9(!L^i8?d z5O`s0DOl<#q73CRt|yH8Xl@X^Ut~a;i$VU%SSE!=&rKqkVzC5b4`uhs7?lXhmchFe z@UsR75g}#@^0NksqEUk;{~1R zgK$UI3sv8B`6)#ReKx?g4#U5J_kP~?qW|`qIsBgIOCu$YNf*c-3n5gPBz!HsqLN@i z7LD3Eb%U(s^r@LV?y&qirE)setsv48hcY5k(GmZ!G8S{|33H@qvIEte0|^hZV22PaRZN;fBua^znv=LM~Pe}`Yjakt!e1@)}3GW z=!5+tGWXW)eWkyByT|wOyfH|aodqNch|E)?T;c(YKlRNBz1}^bzDZF=MW7GjB!4C& z9S*uCe_xP&3E@d#&ywvy;0VCzpMSc2Ykx_6Z+<6z3-Eo`TL}_a9)rHUrixMCll0Nwpfs)b(InS66R`nPYITcT%FTut zA3-jBLGc&3GDv-YAxTBf&PbDrDQd%g2O?&PzH(4W{o1t?F2u`9COa)17)ydFtCF0b z!BZwlQPd7u5VfI0`E6T_@HcJ^qL|nccUK=4M-)N$vhToP;V6N3ft~!+ECf9sysRr% zCvGjogxC_3Df_0uTLKj>6gEj(fGH*7Z9=8cPax`a)R_cJ#>^DS5|X7zfhY5e%oD9b zS;33k3E0w%sX@Vu_@3~gp(Z0t;k}kq$3hXhZ15Phb3Hsm5v~VAD@pm2M1~haB&SG!ksjIg;+?6i~uP6Mz8Z|#p;m`L!JG?#(PF0ua?O$U7*M3Ex!^0NyRG958YQ+2p~n=74OPfz&jkAYr5KqLeib~@GNS_RIq#naD4kh( zvruf;qUs>Wy;j{2hON)jw#0B$WoPaxrd5r>Y$S|mGwlu{@8=lT1e3;Ix4Bs-%z!_w z=03ujDAD|4Yci6#wzFGka?m&>$0p%7j~LQ*t2^Nlho47HeFw+Ta-#{2AK8~!uxgU6 zyh6LM$?axndj8BP^#!1s30$Qo9dT?G@1fB4Wcd6O_eoE+NeU*Q;(eEV{+JJcea721 zYa?hwuXZ&W-q>v#i_97i?jLkGj4Oewg>U9XK5CT}CEj?}TrOd8g%98_AjiJOrG=(C z{fl^ndmL@=%fGgK_}X5^VOCr$5T4NnCJ)M0N5P7bjnIl!uV$mU;&?DibNy67g_rm(6*^9g$FJpma>h)Xh)>w!PfW(>z#SF1_QhONsVF`H|t z>R2vwUmdxdaTBJU5%DmR3uO9dmT=;JH$!Cx64`vLA&fk>nqzp9^ zwfXsgF#B?9)YE;%SHKXI6K7*{_AZuP6CyMwL%NrZn{j^zwtd-Xm%^)>%m z-~T^+y<>2u!MEs}nb@{%+s-?&ZQFJxb~3RuNhY>!+cw|W=FQ&c{_no$d^q)dSiM%S z>aObQ>gwuet>3a7SXm*y&M?7Wm4s_FEc=NJVWvTY6%`eU zz6DR5pOGXpe|?FJ2y|!NKr()%_AS(r{uL9w?G#=UI6C)CX4Fcgh3fzywA->4o28!^ zcmFZXxiu3og>RH@il%G!=()3CRd?_{;W^{r z42(O)!L?v|$E zP{vbObS8f=eg|nx$H2-A1MM{%B1R>&t zo)Cnu6c7@9iJa&x50(%k{9MYv&uA$<&>v(oF(M=@@;?FZ+|chqzLcLbSI^7FF(w}} ztW_8U_7^yArb*=y`IMJ(wnWQU(y??}iXAz=CVHcD>Q&y(VSe!)Uw?OG|HdXc z$u+&#G^{5Bt>t9bd0lGy@$j(;`K6TVmQS!n&lR0Lc6L@n%C!HrtCpegZWI(@*v@J? zl-tH!Z$-y279`UQfnjz^y@hS?0iCOO0j`bOm65gWvk8wHiW*4R)P^(SN1aKA=P}o1 zeD@7zLq*cWK%EQ;wr;nx6Z$TFd8aT)E4El%%{Jc<_-&R^gM<-`;k03U^TM@rb;0F5 z2Ul<9o$zK!N`kO38E$Xa%|Lx8my)SeGfWYc@(U83owT6-o$+m_Fxw`ZC0*(+YF<1; zTxY_$_84EUVHlQ0<-UfYFU2DY;|BxDiUsY4GGhlStdbrf&}qV7)PBuMd*!;%d{zp% z497n6;MFZ$WC$Y)io1%$!V!izO_C9R9HA8>N;M{s0@826e|{<`|3G2w1&aUpCVZZr zcPrIoLx27NEu9G}J1erVSgDkK%;6Au(b`yLt@iu`xdsewGR8Z23~93nlz$?y=bPuV4BI8kfe@MuVb4!Srfg@ zkBRjcnV{yjJ0*R+Nptt|o6E_%9eAJ50y)+d;Gsk3AhamyHY!4Xo}mLH>BZ}RZuqdm zN2djD8dtT4@wE=X`W+g4{1eIY0BY#CIPNL&U!`bj>+;~?(pAt!StxDJuimaO@=f2Dc^WOQx9%IyTrxsdeBxo%b25oNbuM(c4f)(T!wOLKIFy? z#E;N$^*=fQZ5weCh#Fh1pOd)MaRT(XvfPRYBHnoyeSiG*#=Gp~gsNnvk<^%T{b-J4 zh!ro3jZ(f4MrKimy6mgFml;uzK1Bf&^UfQyIOfXqE9jdrvPRyf^L;Jn+$+oo0&mK-t2r7!(ng_?c9X=_5^+k<;i=yNR14d3!Z zgGKdE3Q(VSRC4)7q{Me;8 z3qSWjw^LwQm*JqeOskk)E@>8L$2}lvCM8Nc;#1T~eqLqBFYx91i|mPG=$sOOw%RRO zhEAQKGIZs*z0TY{D|ILPIjaGolC!ZvBR@lf~N&Wo}Lw zwq|LF3VX)YE+!`d$_({fzGMYm<<&fL|1nLx#ljp33#_Q4}mw8 z%>cW!c;}J@FGx$&OLyr>|r$d#W5Y->arOse*>mAyC3|doK^0%Hk%#;Y&N{hRZ)a zoedvH8&i@(;&~dkMM`zQdn?oSRrxT;|1>!kT^A z;IW;!`dpK80q;FEEuUZOZ!U7pqCo>8lDrHms}V^qwi!({du_e=fUB|)Oag2!oHKPg z7ee5mr5W5OQl}9(`rEj*e_4(9Wn)JM#$-q96{Dkm)YW6`O_{4kZEw1RBTVWnCmiFn zbr)U6uF_niL49;$me^4!xb41~-_J7@{(*WZ%duKp_kt$l55=76P<$&^+ZSqc*h~1_ z?lP|MjY1mDkJ@?zO0H`5q2lH!&x0C>w>bUrvG!h#*Rd$r|KK-``lcr1xL;T^~E5sxuD9oqnZmd{TsO%AK~n(Tx<*`WU9J@ zokDG=7yHV`;JE7DbiR`@Esv%7=0YaFhla>Jtx)(`&uuFDV{`1zB}L6Qb*g}6GO*0)_YWO zQ#~?k0=f~te^+OO!vJoV2du^U8e62lrEHa-(Xe!|G<-1 zdh))fF0)$;tf{*4{BtWpyo;=?1q_~+)updn1zRU1*;T!VWd1WHp~8$qm(wZpR(N*m zwVbrBw7M)_>csNxMhzaMH=5?gcD;2xub=b;zJzvOuM7m>R*emEw#i0H;KV7Xc|~fk z^-rS-D{GjrLW6`9t#1#H3kuraUXax>?Nh~A=YFUM_5$w(MPm?l)=@GMOFy*_EwSEj zC6EPB3McC^7cz7m?OXoVT_pJEN&2-J&Wg}9Y-@A*=#K#`lI(<9P!z?W{s;~1CT{GC zk>m+KBbAErX+;X11u4)b{GwlyUViBx%}B!`#QcMVMwni9BdUNr3O10Wa_0`XY@04RVKvdWx2mon*n$hd_0Xknw`FKVaQt0 zdM~d0inMGxx1;q@oL%0As}CDT-b_BB#5uLb)2iH9_|bHT(GKuSg^8tLNX)iz3P7L2 zNC8}B(s+0rCblg{ncPg!5>&f|=r<(j}L|Mzn5txk<;R(J4QvtezAC z`*B#`gXB525VL7*vNq4IO=8n4i-hvzCVy3rdj*l7+}p_|%fGH0*((kM`j+ZkQKwy- zJZ!Bs1YCd?r!)NXDIF_?UYna!drFn+~*4rhBZa{*&y zu3f9Yl5!=-3RGEEXj4CI(XQ`kQ9gWF;&EoS$yc|lDnRac^_!Vqlzh!spD}!3ou!q> zp}X%!YWf{>D$R;{DDBd<3efg2Dvg-wFCaUMd`(5>=VDNCK3-BQ^=VIsU^3lvoxFT~ zg3%2VnS3sc$K91bOcx*3H%8~N*^4Ki-kpGNS$Cb85DZ%H2fweH`bGg1uKX~K>iRsu zqlvb>F@`xmXXO^~u%`tGwG%8ArheW`G0;YuA%!r^#b5+VR5KN1Qur}XN(4X#9Jl*} zU0m%3L3J{R5q?NBz6=DaXA@~IUCro}GaT32e!ac!ypJTQ|6Z+5?3 zng7`H{m$iNz^O{(Aa9m>PDz_R3X}GrnfVn#RAbd|?~N^TaJuQnZD)7c(++*QiyVQj zmRo4jF=cffJ@>uJkJ#plppGRw+ia9)I$;O%`GbYHX5du&YtA#_Ynb*FJdCNGiL;B7 zsiEzEH|>qA;9;0qIGKrnHt-hm@>+k+L^mp5V3M`u`~a_3NsNm3o|#1fB-zqf0o@N>pTlqM@99s z#~--miO7U#U}oSk!SwSd3F9I8*kO#kkkAiV;cL|ltfKUcls};vXKHrUvfeh0i%U!y zhH09HSE-rS>z8V4#_MjWIZGM6*I(IhnZj(=<)hXi2S3O-R8)%p$+w-RK?H1ub#ibp+FI#;xSi;N)TXKNEp#}A7~d~v_=1S9 zgt1r%pY;{Sw(no_)FKF3>#Qs+!EiY2enhWqwK$BPf}eIDY5o|~@8?jb%h+CU+6&sG ztoc&Z$Z3UQZTNGl&a@eLf*h4n)p8z}acc(h!`0zJudbq1@*JTR$H1Cg$YOJ@Xk1IQ ziW%JaV^U+=(Q$t61@^gl-rE-L0?f@o}F&-YLIB`KsrS{Ar($ zQpYn072M&+P6-w4A66~RK8PPe50_Ge6Z zQwUs?l+!w_m}7LgV6V4hVM){duf8LHsH~EF^!*5=@~^xG{Jr4%4Y}aLcA5Tb0xX38 zR{ROBD+qk#c)&uwTR zhuJsaLleT536?4e)zW|~-*H-*oC9mF0eG<0Q8^hMER2keocwY9Q%_E6W!Qe*?{M92@ErPUK{&S?RV!S*4(<*u-EXCJ=Wt8M3-2n zdEIQE21uUm&Iv2w0+t}?Bq%3s%Jnp$zWc+I^LkS#z#TN{&DUS>@JpiQo>FV!yqV4# zt!#yEi6|DeDKOHP9O&nIsc&hhb^Rfm3bIYOlI|B~Qbp**kIS3xpA%XFp3>qg`HD-& zZXpEA(*YAd55W`&-3Tl`Qm8Soc|+jm=v$mYSni=%fm;@VwCU}zb-=d?%k4$rGu1`p z?1`yC_51P7Om>P|{~R6pTo-=-{Xh_ONjQ53+i!gg(6F}P`oj5H>T;O{Yc_3FQe9qI znxm(x$!vR?G@3|}lA4@?hKY{x>jiZP7&AUOIyHuu$-?8gFw(MuT$N^_9X@ISwQ$ye z(S)EAGL7dWh%cv=dlA6=uA4g$wFH*a1|Gc zu^0AcOdO8{bsQ+hqNMhJIMt5N4&s!ZUVCZRmT&D|CRZ1aEk|;3BZos5qiSPpsbo>ZjX{rz=0UPr7{b14MrM~&@B_PdEz`M(}HATIxXcuD4Tin#mLfFcqwqJsJZp5EUKjDyM zbU-uF|C3ZMHS2&?D-Bp;>~^i*-~McMU0(m%8;qr`G8HAZ)ljl=S>dkqOptsokeyU( zHyPg*oyJ^(x(Vb}Em+gZ0|Sh{?-9e~ESAm{|E+GmJEL~cezuFIXY=71{}4B#tJ0Z3 zt-uQ zK+?(9y#ZC^Qb$jEOrztFGXl!%;96x>JbudnK2G1F1_3Z0K?I=D;n;Chy zcq0#hcPbT`il3jV}q8(0?Cf=64Vd)X6kJnOpf@+Mx2foiku}?1$ev^H)aneWUe4qTjzcGM-q@) z+CL^2kAdH}g!3d;!Y5Jj4IfPxH+|x3!-(2fp=@nl9Nqy!ze>W%?DA6k%66i&L==BQ<3RpSoYyHex)rL`;gSiH5+?tWI) z!+7dV-L;|iNM8Dc{7L0Uq=-W8QMK&4pigaTykWryiVUA7JF(D@AIB>S+m3dj-fBv> zRFkc(zn$CwVHDTz@FRK|J;Fw2!Z{A`4Nw;zd!W(yR47uUV-QK3RACCS1v{GhE8(uy zLv7WD6HHw&(p7!QwfM#m?ZLFnb_caJKdh^UGf;*qsh-UO9ciRUBdIFx8qgNppw&HK zAo5|&psZ_NwKO9dH7x1Xw4wl~YSHcm9Tde%OgT{`J>^)4BkJahm}*LF?KSRXh%iUrJGwlG`K62@DnTXYcnfE zQ@^Sz`Bla_7P{1E7s%9?yR;@Z7Hz!QS=E}=U`HgTPDWK5lSk1TW6 z7o>Fi1_>(jT)Jz-T1FBHVostS4PF(RXF}Vg`fm9xH4D?)H&A!!E>I}E@v4p)3{eb8 z@-|TM!>CA;P^9=2p~HP#};$=rjOi+eUhLBjGPJ-D) zXoy3Y)=<+!e^Eq}kRhW$Lw^$+JVfw_Qi3JK7fW`MhKF1uOQer7y#uB?F~gB zLfI?pv4W}>>=AyA+ZPlJ3H5~PC)*O|z_?4$R}JNkdP%Y&*%DNfSrg^JyPF!k4%Lie zN4z1^5^)XNC)XDfj0?4l>URlED{)Tr9$k~|fNzLvNNWh27vw;1$ZCkXizC9jYt<(q zuYs^fBc*#%>u5t%L8&9G0nm`v5N*k-$#B3nOdjR|uT5~EHU!U$aey}D{w|6g?Z9kE zZ3w+f(iaju7%Uzf5)2;v5{x0jYDkbbYHTUQhH`{*gv3BJK`}wXhI9(;8k`=C9jql1 zL)n0>D4Ql%LZad&a_u-o12qq&%->rZPEFv9V#M;_TO~_Df{Hu|DH2+o0QK^<;=eWu z-w>aez&A33k2sDgHePy!*aWo>D*c<@!5j=H!b2PrFZGK!nt}{f0yzOHA{eaimk1wm zERr;qumiFYlw4pCl59AM7zzoLn+O+iv;nCGG=>NjaWIk$6RHdtX|E6z2^h*xD6haN zV=8eAXq>=|za&)9FoD02prS$MKoX)b3keGm4{?*`sq_o7L|!1r)T#9Iv&3G09y%vY zD+q|cfE^kq=_Pd+yu%+>QxWF9gCB|}2^RPS+zO0&Q(fg}3312XB8+|4Db0I_K8&OC z7xF|se4?`dizoVmKc<+ptmqfz1a{c?H}Y6rQBT+t`;a^dQ&CUIli-j$$y_l2wxEWRU^$T1EV z8M_!+af$@spBPkV_;L6Jaytn@tU^_Dz599Y3izm997FQC8LUKGj}kSXEu6$n1lDRc zR(d7YNuU&M-%%)Za+5?R2uJfpysS+_= z&Ak41{v#?rf8*9s8+b-nEajL4MX>$pXb~hv_M*6CX-X{A1ZntCiy#HVG;0krEG8m z1E=1D@XXHlgHnTO{2QG@u>!^^#K{Lf-IIAu09S*gHifggD0uTE5F~5~?Ea1ST>d0t z|0Wc8>wE>dwMugqAoUV@3wnc=OubILvd(dhyyWRjBz#lm{s>Zn0Y?VsLvs)?x*cQ$ zui=q%D`MI{SKyaZdsu@of5w#h^?4`p!kOFL zr|ZC}1KHezu@brQquJ1hwa9+ZtvkSbN1);GwO|(^UTs1mgMc&XqmI)=%NAIMJ0O%j4hu*K~Y{j6G4;C>?OsJ>@IFAFbz1 zQ#1AE$>+&et^U_lpME(w=O?YsuU_!6J!jXvToCp>SB_m@ApXIEz1r6t9iZO{uTx); z*XGZ#@8|-d^1H0hKjp^gV~udF97U>b-1X%FzP{P(^WHO2pQaL$M#hRP8W>*M2;=4` z+5=0qvNo(00B!r;Y4~gDl~|7MAC=yeL+v-O>K4`Bvw9|tkTZJj1&i;GX9Eq}k#T?F zpI6!)C)i#;>N;ECbHt+@c^zQC!`V$}b83fSgVX^#&2^?zO^7k0_KmC@-mrjYfp_?e znWz*Vie(=_({`9eXSeZdwD@)^{UfnYu-ZfOPSXco|W0j$ve3ErpTBv3ElzaD8`BgRk0Nlig z%MB`EpmSEpa;r@sUw=qNIC?z`UHVYj zic1q7up_zBAhqu5v$+NMqAwWic}~8o(yh+l61DrS=Ik%=U5pO{?1pR!jE|-n0|h7Fm^5jxCsFexkoTEVIu1l zYc{LCMaWedB%)yYqc1|}@Y5`|3)i~(vpWAXUyFDbuj>fsgZ zDM`=4XE#P^&+?}WJ>xIdqO7E?f=}R|2TzJ+6mKxbN2n61t^N(7 z5QgCHpCBeZ+B2x6b-jpr@L9Vl>hPk%008EcD}H~}T1&p{q;>wyVqu3Rlgbo@dwjZ6 z!{B}J;dSD;IIs$aE-Xn(@_cq9mo^5LAfqEBD-}S`oHf`>%OsX5!UUEmVU#R_UkCCvAq|~1?)&e4y3Lbz4qDGaEjNkKzh8U^% zT3WIg#!p@s={D!z-c$eQony*DYpwK}J^F6v;eRCqa}i2;mdS8gMmCJL%Y6*Br`m3K z8UanNO4G_F@0RI34+0$CWQz%M${XanF6MnPx8_rp-4Cx`^q*XIq4dSF?`tC2ywD)& zPlZY^jP#{{{N+QyF+*j?QMksWQ~P@uZ=it4HoU=&`M2nUf2i4uX>f7zYsQQ#5-yQ- z;UtlPx#dgr2WCrv-&aQSoA^~s^-CjPfR z?`QgJh<_?^6?3H9x>4FnUEQ$8M}~ynlf{lpl-}-LGhfJMzn|o>pMT{k7YXy({Cjf` z-En+vjvHXbKqj1}r<(C=dHS^$k3`E$Kv-QjcGVCfhajoSXR^>qp;@~{K*k`bV*3?m zHP(oK##XA*fH#?*j(vh*ZK0DzOYsW|KBDiCTX=*8n*02hsQmg7r+ryjXZcf6D5MqT zMLN6p`bI;`nl(-(v!Yv2{I!w4=H5ugH=XK^f#N(J75_7YR#WR`Cqev4k4IR=GRX!f z)`#*dx7FmUoB`G41ZPTPbGH#TntUAuUUfqSpui9JJr5F zU~vzV{IM3rX=nUXc)rt2VMeca(@&LtH{y<{Rt{L~&q(YFeO$R0=psfZ-w^?uw_u}FjO1M;=#&rn9_qUu|A)Kdn&5?<@x%mO`?Fmc!ySh*t zH6Wb08@9|` ze;v4%>Mz}^5Gn6%N={gC8|G7TA-bxnpE|k_;i0AfR#96RZ@+k^LTe$G!xm9BEP&fM zl4E<$oWmd6-!BI7KN-*<(+*tsKsbh)W$1j8sbI?7`8p@g9v&TUK|`ADFI-LO!4=P% zk|$I1gU|T&uK1H}C}{7Pc5|ezKDHpgZa-V3FLg(ge$SIz`p^XP`uE2h&bF4vZnqZ=9UpR_S9 z&_K~ZouU}T$>Nuu_7%sA+tS0t!k{liZUe+iNw<>OzGFB&$>C{232etkQ#qFlZUs^p zc*TwpZK%9iFV#OCL-vRkF{0ShrV(P~;Z9(>i3AU6o9rUIZ58*D22qu00R%T&o-c>e zT22g9c)gcXxZ7Vja|FBv1%(}rG`hv*)i-h|_LdblcFlz;dDYXn&%e$^bH{$;3+Tti z#Rb?AqXZJmDtI>_JI2*IgcEW#aE|B@2*Pki1Lgvgr$l5qop+rn!od+=mA-1Xd|b{y zjU~Bkr~l5U9{{8{2R?!c-s^EtF$FoK4uS@aQ^x$O>Ox~Nd~sW)&dXb>%m@2Koh6zl z>?NtQIf+Ti^K4bMMb#cnA=mb;%ZqvNl*@{SG1v}5%_pt2H#umdY+H{XLr$8)8KaT& zel!i}s9OoYj?A{Qsx8V~XmIIOa$3lN1!J-0)uvAcJ5obad$KYd$}gw4e8L@L8;Z)2 zpG&(W3Hi~?hM*tAP7F`eRlKtnC)lII$0Fp)w%q&1k#?wHMJ`>~b{g4Rzp5`~VT12m z*O7J^Q7-ZOg^=k!?uZ*XZwH0Ij!B56(xubL?Ma(cPi<#L5@G$Ybm+8)=i)?fA&Zzs3a zlI!oErxd7lc*%~Mm*3(tlrYmUl^hxjxnSmwSel(zPfF3(OBE0h@K2&Aemogz`G>7O zb(}kp(?D(}E>D%F(sxmBx??O(_Qmm&{$Shl{?BHh-j-)Y4w9?}rgUOMsFZDEfxOZy zAVJUsxQb{9tY#SiIHD}FQ5D)pQ^4Bh{6Swwpx1vKm`H4^IK$+y$<7o2X*viTfF8di zwFVqc(c=(<+4@>4|7I0g-PwH8S&hDZ9Ohi8$l9|?-=$xIEL^GtOj{E^YxpST{lKg! zV)oD}sh4Ps)k% z)Agf80zV!E*4LVis0Ze~8Z8SNCfKBjM_-K!Wxp%D1nwTf0+Q@59s8Oe(tCdU*0vDrRH5{x2I)P5};~+k|c2L^9lO#>=H6%PF1K2)PDDUsMw^21z6>)i|h0WkHpvg1BAU{CA zcW_x0*h9D!8@C2b%IjKAs+IeCX9@9LIDP*onLcaN?*5{_#i{Azx1LQOQqI!#B2>#r zwUQyges&r3;o9d5X|L&IeP^K@;Ew;*45{2vk6s%If`yno1LglXsaGaY&=u8L3&119 zSePUTBr7o*CbJzHi6(n*aj=9CrItaGnWIuyo^-}>KE_Nel9?-xG{T8I`VJT&f`ujxqKJ6ZaUj+Nzn93$A01|HxUGy28ipC!vD zxKZEeyJ6Z%M3FBvSC^{zglJbP8Xd=1bJXqag$Ar+ZbO~aj5I%c=;-u*lF=7ELY=il z+1X&N8?diN&q_W{mvKyu##iw*_{joqW$wZ!RvO@(O>``5)}F~Zm&nzJYli%QW#r_} zcYXZ{!^2(3*tlhKY1)}OY-1v|8mAdNb&q9j2Qx&=BrUPhd!74rUAf1!znojZn~)tmPXSssIw3syTw)i#Y+dcXu(ywy%uw z0U$U^kb@%po(@ewD+)0rkrFh&P?B{>Mw^*lZ^hGoJo?jh%=h9UoRc6DnsO8x0i$2O9+!qaY@}P9ncv4yS8Vhi0K5K?|N) z0>@3SNizb!b=1z=8KE_csdTNYEl|&Q+n)i?Km6Q;Ii#<2sIIyjOi#^8VWyKXnZm|E zLBTnC^s(VB0%ct5+pdwvGLoK&hLMtV=5iDZ1B;t{wn%vHeY7L&H`j*jp6HVWick00 z=?r0^iqnYmjG03d8iqSc7xA}zPNjraMMgy>N>zwMB6SJ~VDy1MyV|WzXyJX{8i3o@ z)%U|rEEfHYh3Qz%;Tz4+%xDh5H}TaAsq4IA@*c@t`hu_mEZGm&TZ3CRt0OgVty_2o zNtG|2ps&rJ(s0p3FMc*kWUh^W@ORAH*3}}VoQtN4ebk^qOQ-tE3R?8Qcs9V# zfv>ODszxmM7umD=DtsTuDcSHa)+P^2-pw@<#QK+u-UhOG06m#br2hwUh^dO#RQQ@# zGCjHRMz|>^jQ76NUZC~S6C=Mfc}^R#rWDh%`t|ct=Ij0kElO@KMw;tXBpmv^x3F<3 z${}l(NyUP71A4>C1b5dJk3+ylliT!@DzCS!*0g3qb$NbN5xWVZX2Krz=W+8323ggJ zlg|(!FSges80XfG0EQUpcP&B%-KKF#(ih(01hUge`^(GtbbZ%?d3PoN-QL4y(P?_E zFM*b@{T^j{?dMe)x{_#>Z-3nl{3>$bUY&V$rdrF*_0Zz?nXcvXFu%OfMeBPM*{AFN zZ&HUkH?Gq*^4Dt9&1ZcCrNaKs(c%s0EvXuQPRBE`)LiB_&#+Bvd4{y+9qz`~dn4rW zeSS=Idcs`BcT3cHBgvxsr2B27V%}pt>EhPL=j|XGC}ofPDhIN1eZF`gsIGORV`(_W zY3>n8ENmkoDoyDI5;k_)$Q_=2^rJ{zv^L=qAOni~vXlz}Glx~k}mFw)L6!z-tl*U8SJ@4+VPE8^Wc zBaPkg(;onZH@22Vpf9uG41F{RXfzrLUj~yoCMp@}0G2UWJr?TQ%da4oGNn7Laqx>C zVo6*Rnq`Rh{wtIBDA3oRzxCX_4(<~8sDSd9X2+b!8~lgcPXlon(_X0g#!5+41nF&` zu^CI9$moYNZL!Dl zGn;i5?Gg@8lTQ`f?%wG_e1JJ=MSAHHGIMQ8P1fzI4-n|46dT6$MYCxQGmkUzo^A|3 zb9#+xx11pl364c$Ks3R^bdS!kZ|e2AbGNxNfAv+jdhNRy)^T;C+(0e;xwrk4GqK1fD!=R)8(CS8*dWd!)FweS(QS4vD- z27Z{71!-c51E5`(*XtrAzB}jP&pt`tr7WEq&#y_KAGPR@MCT zsY`r(oq8&D%N;a&WN&h-$Ry&m}vY~#AbBFDJveyLbDhNN6InJkdYOX zI(SW!NfL($%wl}bENxB%w&4)2a0Udt=ptC-#s8^`a@|p6T;@%XwV1MX_DO)h)BWm7 z`|7sppgd(^Y37}NskwqtpTB8s@YD0?HnvKL)A_;@J-gGBLvMZP{6`W;c!8TxsfeNH zgrQ=YhQvTPa4|4e{s|xz`VC0YVQ3ZHHfjin3v50Yml6AEFz&unxIf4=l^`4QkpDe$JFPOVD zWtIeDiQbp5h~h+~Mja+1=POX35og7g&}DlFFAb}BZjL7=1rvcC=jBX5S<#b{)p9i& zPs#~C@k=H@$eVbFt(zfMtE~(sV}+<Za=0s1gM0H!X(?oWhiY4R;FNFu*EiRj-dF*E0^2Iw= zmoi!8+-P9|LOp6oEq*ni&koZSM8j*}^JG6HBFc!mKvU_(R?|HA26PI1uqXgnlQA)C zZES39b@Kj!HC|x#@vg`Yrf|VcdU}VLwOY1{4IYe?Drwv3q-0Dqj^g;(!o@nry+3*4 zc0t{VM3`$7ItAekJ}~{yWe8h7UHCk4u<xGUJfD_7*{u|!ob4?Lphc1T}} zByW@qp+_%$uCfqh;QD~!5R*6H)b)6d3|p^WC`F&^6J`56R($X3xc^J(VaV5tcHK53 z4ynt)OirmumVvYfRtO{I78@eeIJjySEiy*UJepRdR68Wcwm7q%=KJ*;42)Ccqmn(@v@_r-ov;%BJ`UJ}M>?{fF+b@6}IX~?5Ll@v$+^-BDUl2@e~VB3!t z_Lj0VrnjDvv6|xxtIDDr%W|4V%=);FGH}v|gE7Wke18~;tfK@s%b4|oSF`Srb(T`d zF|4V@cPC2dG!~Le;M-xQ*RUFF`jTPL-`A|IXX`SYY}>dF0u_IMD5fvmY&;n~DzJ(Y zzQAvF)|CN$Z=NpyJsknT^YvvJ@IqGf!-KUT&NATL7oP#4VoxYr9x8Cma6wZg;2gRW zK}v)~hRW*ukuTak9unffT_{OU_8n&*c%;_pAVqs9bGxx~;6^%uYUBx7H*@DymEshg zU?ziAm0Yy?ZxUNaXLk@gnO}Djdxc4v*B5HLO6OrAW-3KysgRw_I|V3K9!Fr>#LqtK z_(ues>nd!hz~xAp-xBE;N3CU}TbR%_wjSF$!oF2qBOEPa+VZh>V*_d?B5V=lV7;VH z#^A3w2OAqU*OR)o0UAOB?uWLY3jY=s)duSWm#h?!$y~re44}N&Z}#0rmc)#~OFaFB zg_U$D6x9>d@~B+SP$DuC6lh9Dvr40lHQ#V{lc4e1iQE~?7cy)IYSP?Fk^{~vz+}zd znfKSmrq@REvl<_qYOelBUe&djgm6qdeF*Y;N_sM9=UlwusUheAr_(ENymIedDwg6Fy_CQ-%X-8yvD zGw8;6#s|T7k9)sUe3V6;0;vU>hZ-$hHRtAV_1mD`%@#4q$>>mTS!e^DBHR^F0G^_m9kH(B%SG0hbyhDER9?5 zoFS#0CphRX(kU2{D;v&@2XYl6y^W4O`U}((- z{shHe@kQUopFGu` zJnA}SVQjm|%F)Kp45L!EJ2!f=7EycgbCNiQEJFQzHWA^uNkT2A>3ChnNoH(%WHp~vh(WXv*&C`2p|&|F;~ zEdKx{1-wrKeYY{A@GMh3c#+t^xUA3HIJ_S?qW6yfZrJPe#3&U=XVRRVb@%TH{-X-~ytv z2gTcWo@{Zp)cteyh^(B!+~)4cUSmEg+EJSArR<1zQ)HtOEtn>y86D0VVGm0PZ4S0X zq(c)7#-Zu}s}5U1#04YZ@|fz+1vE_6LH-Wia=)t$QOX^5=?+y%qfv{;rRf=V!hfPu z=ph9~r9~@h%DJe=R#`SGu z^9kcl=kuWLkW#md?ba4Mc3iKQFx6{2%)_a+8eLAl5!_uq{Ij>+S)TE}5Q5TgVD0J( zb!k8Z+7(hP2x5~1mn=8ITf8jaqkI3Fh=UN-F!L<|u#Z$;E7Rt>NfXMMByr=cp|DOX z#%kn14CD|6+rWKO@5+5s8+Xcyjz>Oxj5)vt2fuYpRC8_YNH6|_sy3p(>t-nK(xI#% zK_kZ2>+_v2ZcfIUZtXC;!-H*Q+(&81>HEa+xgLk?9QP|WQ8z)hng1lmU_33>0CfQ$ zs`%ZXMEWi)z2$mbIl%!t13NA^y0(`UW|p@1By4lQi_!7fxB*3Yb>^H^<@_^G^{81r z@7`|AO}mstMD1MM@uN4EHD)`%(zb?-1U82Jd1=_LS?W#!>N1@DbZfQ>`{x^Hbu$8XV7rPB6>N zF?D(3{{ewOe!nq0-RfF(tD04-ITg<%Zko9sAbH$mIgoBXazi+q$m(Dv{4ZLBT~4Lb z;;~@X!@T7BB>P)$9)B}>vH=%jl}r?X7s zt|ye1ol0fgP6ci0q=#;l0SZ-1TS8|Yl5YBEyYtrX^nd@&u4}sU9x&%NmDN{X=I1x9 z-f?jev)k3WZ9_?0WlFU1ax&go4{atwn;KNo_%At2hiXTs9R) zw&8b8xm-!pxZA7OAgJ4zwo75#Wi&$dH_+;5@q38dKm+r(&!2zKS1D75)t-^M)!Wt< z7F}}VT2D_=j^E>HElso*uJCBgdYy`QjYRLZTJyTD>gc#`eUVXjo!ORF)miFkuS#WD zmfa0Vn?M68RMVyV6$+N+hysinHB7BEym}`%8NgM=v`}m$E09D7z(|^aumSVZ*(7el zuibZFH1|G5T__Y?Ix+&u3*#PWArD&MQR)=OfiAiaVs zd;Rsk+oQKKyZ2w-duS#=><9Z&EYMxjt6UdBP1BnaSm zlD29kTC>^qmE&uFxR z5}#06cIkA9yLjqC=R{w6Yx~tmX4gF?XKBXL#&nO<%>SZf zoj2n(W_MC~YqdQm$@m{8F(0rj1}y6U3)v%HGs#0#b?sLnn@vx`%V@FNRTh3{aw*1A;#6sKn zzb&aP_aqmkn>p)iiHXtAnBA8AMo$I|S9rcK?``~Afos3kkwLs87i?D!wyQ)95dMh# z$cV+V2oB!3B(*xJG)-^gUHQAR($duWT`I|t9-3mv8U%f~PXaBL629b)?DB%PPDUyzJ$rsT{B3wkZS^Cm0VK)R}Xe@piHt!w`}WFu@D8K5trD&AKvtINFg` z;xrr6%d_yqq&KoK$Jus%HA;rD?L|+bBpleU!zn50(-^8yTP$jeal)3et4QnBuF#Jp1OOi3+mbos6@UX+yZ zEmLAbNn2U83mX>YCZwl`M4~w62W+3B44Gi^QBESfZ=cz0hv{G7fZA@I&>9Xg+mMo=8x;JFIqyMSW81tI}9ZU2L=*S-K#Z$>T;V=$B=*Qu{ z11QOMht6;W0BJ#;1Yxpx2SK<^MkqrhX%8UE{TNwwbW!D&ODU#&a__DRlxKAdHT*(T?Or;DNCVDlT=u4o!=dkjl5LBY#+l!TU70<61{ab_R{NWx_5Ns57dJrXq}*jN<#%jpt{-1llCx?!y}r7k3Pz@%;Mdq4{3=v}8c-|x z>b{Z^1l?p{U-8P7aYTlinv|u}pm0}iZc3ew{Gd=qMk#Ull(dvI@2>SGTx)7IF^tJ2 zD0ekBx+~DG;^LNFZV+**VwYo@`3jvffLvsSbEdfXtxLh@Np_*Rh4hCfft;j?rr2aSNwB4rFDff0FYYB*F$`Bkjb3Ba zm_$a&HMixhu5vmGmt^JCCD=U4S>?&e-n`I7s;lK>MIHhd zOFIH;B_}04S~1->gymIgGQ~K1Jw4tgKb2rvqux@G{6MPOYEL#lcpFY=%P(J|x3{}H zR|4`M#aqjkMQ^|_=4z6QGNU&!V{7xuOLAT18!wA4A+hye5L?3_ivgl5n`S8(huFX? z_o>ViI^t;w6H;=LCZ`_v>|A?pBr<;>GMw8!-ZF7-Zrk|kJMMez*6gx0ebch+@-#iC zU%7Q{(L?vF0Q#K=r&Bx)85=eLrMVLS5+ZyxOo`KwcS@&DBH2hFXr8cIg+%*=&Ugg0 zrvdE=%vbg&rJj{BrFa#`YDj-LgEvZQpYbpLc0h)kW1QByldw zwYhBV-CSJf_KqBe`-JVU&ri#18(R&DvphPZ(yS+=*7um_VU(gk@u+T}!2nr?sNI)b0D@Efa{H#VAi9vAdYK9Gy%8Q29{=d9+_n=QDBislz(=+T3ft zv3KttY>&RTC3%g9`K49}hOz0E`<>6;^2cEf*#U$dV7V5)0d!XSB;@VDKE`6vejoIv z0T0_wbhY1Xm|%F)FXGvLu@+1D09tp(Iz!TNOZ$A-mb>|^R!`~Ln)E$uUG?G~=9MK` z>B&{=s_`As8@J?o@HasRZ-D>b0xc_0(E$a|FywpI{ZlN9$?w4-Msb+@W-9%$(^`;R zavGB~E{A!k#eXo3g!URk(02B|T&>^o$hWyT`qDdrQgXMPT56Mzpd3= zQ*}$!kMFsqvGy{rXeOEw0n>8OH_T?eI##Jvs~DJYDLE3D+xIc537BzREj=QXnTBYAT!Ns&Ecy;-wXN718gqH6M5Q z`>&AO4e)s|$}E{=?4(@>OtgCU>2wY|NOQoZGfyzeL(n<`^+KC7&wFa;TD8pXCw9s! zW6*x|0Y0_7v|NONTf)P}#H@JRqQY$bqkLjdYJQ?NrLKR4vmik*q~s+4VS*=zpv>JxYVPPhw)hbjR&nwAti~-#d zayOZe(%>@DnJCHW9uu9Mka?k#h5y9&Ef)6GHLu)s?F()HTKJXQZq4HpXZGQW=nt5d zXa`v6X*?wcnl>PPi|AjPowZzvOncmGl`n*UeJ z<;D}HMdy^uO>ZtNW|v$x&MObkE2pJmsgui|zfXz7aV>FM<+AT@D!+#Ey9?$2aB(guSBO688WXzxr)1G zUX4VhDDwi}KHHWCbt}CxuSL1a37OY1cPgKjc|95u*3JGE?PB4$%wwbyVt-wmL7Z-1 z?C)ix6y1F?&mo;|kIeH(tNXspE8zSOWnPJP=w6d~6|(BhGOtEPeW%O|%ph!Jxjc#XNi~eEb)?_A3-82MnzC6fNMd6$dAG(ght`jhazyU0k|+4 zq0|Rw$S>pvQ6YR%hlZets2$GrqXGDAl)ekVF#uO@2HFc(HqbjrjYCiaxn_`39~_72 zH6pY{>KD-%y_Z}O1Uf>o^wXAyp^&rva6SOX&G0TvYaXWWBXXTVT3-m>4^R{$NJOsm zL*2u0O@v=YG+Kz;b)Z(Mq35r3egPhNYcSG=Q6FpBf)=Tf$N?RO6 zWsqVda`eN!A$l)C6QXtv%+vFTTnCZMM^VQ#*F$YUY9tyOr8SUy!u0(Jy`y(lheYm9 zSsr3d$zq#jy{)D7^un2OTGN~!d#NTzs7Gw2trOjm>!dq<^qK%g(ocP1oJuz^>lKnm z#{5yjIYccdSv>;0NNpLWS{kC~0%!|uKSJ#hq#UtSFRguWo<9DvCybtDC*t8_)HbB; zm`-9|9+PZzp8kjFF(7MqSUyjDvj?sw8X=!bxFp+>cob#)0jkx2>>DweLR6kn8o>d2 z4MEaMZ5;$ek`ECK0UF6;vQ4FEBib9IwTiNC`scMBmgNo3o(s}=3Q+A0K`qs^Z7ISB zD7JiRLlTLRS*uDucD7Znq_u?PI%3z5&m>O|%6VtA95n>ph>Sd@Pv0z}9@+kqzG6N_ z;@>CdmLZ^#*(jRt!9z4^HqG8Wr(3`5Ej@AskJ0$(o%OSG<0(Shi_q(Ps6{u^tgv-f zgRwktKHNR@+W8r6T+SZ^@ws`rO7_CD^K8AGL8@l6d@1Udkq*lKQVR7ILs@ut!R*~% zl)nRVLVqnej1UpYVW)V3s8%PW&OtPIsd19|E=CA)?dUl+C}{|=5-y^77^KF zBz?MN1ZVdXA!^r%9LYq}&2Yw#vZ>rTa!wLaBSj_MOFU@=H0*{lPD>%}sm?}TD95>5 z&gHRQZ3JrA3TH`AF_&A;t~GYPk7kE3%{sCAE~1#Feqigo{xdS0f97(oWIM@IhpB#I z8j}1oroCmLzh>yo=AtY1iIjPJsZJuZS|6uv`Dt!GU%P|n$uV=0b8b%{`TGc!G$==( zRF~AxlZag?H~C!3o7r$z4)sncrh2~+Rq&jezr2p-YM;x{QZ|*m$A4DObgt}k{(3g9 z`5BN%BFPe=?Zv#F)Gx^@^{hdfw|rkHsibG$Svrm7nuReyv`Rd0Ozx!vbe!dveJVuz zh5)oT@>eYM_lk?Tm~c}xBnHN4&rnEhHG;N0A{G}FRfsKv{%~kC)E5yOLgA56*cTZL z1q;Qxp&_w-uzw&jDz*nk1L4hq-ol1Za5OaJ8x;pfMc?3XpjYe*g~hSafH)WwN5Y~0 zuy1&HFxW2!f}01!q2O>J2)Fx!y<#Xb5D1I@!LWa9cr@Y*`U9ilIGhTIK5;k{42_QX z{It4Ygj7B{67Uc94MLL?hkw8q_W2`$@TfT8+Z+&~GI7*591zC`dm{t+;?UrxfEXI; z6(d_m0^{L9a%H|a?At`J3`U@h{!pkFstFDH0~GTJToDTThA6n6vC+X`V02XUhr;2& z=twBoOAr={ozTwUFbD?1i)#miy`k|@31jcz=*W<7tLPgV3XQ{uKCw42I@lisM3Dia z3Q#1`Bh)z*0_};BkQfYwhoQwtU`qrf@CC(4*w;Hqu7a}*lrSpE)DRjA4+g>n2~jy| zY?R_34uR_Yp<&=7zMi42VmJVGfwZAM5$X>Fd!ZuQQYa{n`on<$n6z~y5bOjEiG2ZI zWDFz)v-yX{dIO-we!r3b-xz&xV^zL9{0(?=@m0r>$J(Nx&)18*4$M2Lwb1rLQno5;r$tsm6V0|p)o z68xb#J4Jk>k$~8+#x=MGv3Lny0(>p51>TFjz}MkA;OlWc@C|q=@XPQr z;Fsg&z&GMX^8G&C1pErT0{E49CGe~8D&U)OGw?0A1^Cr?HSn!?4e)Ka4fuB44txjh z0KOA<0pE?gfnUosA5hz zB7Y9(3(N~Zf5`k0=!?vYKwoBF2Kr;>$3RaoCxE`nybAQE%ulI|hkzboj{rT&9tHX| z`!vvF>@lFnSK>VP(I4M3N1;DOu<4m8ZI;=t3m77l!jYvo#jwsCDhJGc&@ z-CVb9cgf)#q4LUH}!z$R2YcT&2S(&LoAF}!Jb6Z)9aQ-orUQaz=1O4BLL zr)#uCM$#@%ey$SU3;##X5}jy>4*mvChmueR$_G6!MoVD^)`>R2n3s%ox65%qARTRg zl#cd)myQYD(lN0~I_4xu$J{vi_yO|VhSwH&?SR*H@cJ6OcEM``F&FQmrIcl9$`5Ip#WYJXA|gh_ zNHM0EQVb;QIp6mZBGsRD`{%daAKcIRzBA{Zd+xda&b{wFGIMaqwS}n7(rve{Cx}j2 zwg;|faFxqXT67vDV~7$=y}KshYS!CL zbe`yv5PsQe+j-L;l$k^{h4P}%cfvn{h}NcmERo%^H*K(t@J}R~Y_`>(X63sFN%);a zw72FTB|1*B8I~^t<+F%4(l|!!cuKK)?Xz>SJ=Y2^2GNP4(SNX1N%jZ=@ zYlzknZ6w-Ew3VoVXa~_QqP>Gx`L0~kcYl-BzC#ur{+M*+DmrG-Nz1R(7M*-QVNMO9 ztL(^k718x9(K(_EMEyeKs#mVL(WX3i6ww%S-t*YzCRp}pymKd*fu3Sr9Z^$5ii#5trdte)Kw*#LYsmJM-oZ(Od{z z3|t0W3H?>%VIa^6?7E5%26_m~1HFTiIr+kD3-!sie4Qj!`7t!>7UahgRspN?o|Ij=P`lfIMRME!nKi=cv+}Uqg24@;4CH=hs@j-9xz)TXGun zDW2r)%x{Dy&t%4qoIUw_Let6Ge%KsD^mb3q{``X`A4(>93v%0l?Z6Z8ilR-vqTJq0_QmAh)v7|sIYk`6&@aAl(fFur*u|T^y;vplat$^lCPJ6**!V?8))*R^Z zb{06HnR&(AA$+hPi#;ju4N6WG6b$%-R#5*Jl%muX3>H*?uY^DIfC~wO1&hHiL+(n# zNCD5WGX-lxGZ7oTIo$>8tk}goMbw=01r$+<-)co3FGpvl3Yx4r!~7xmaJa04c#5UI5j5^zUNy+2i0X?gIBB(!B@|bEV@cA*t0NTf z*$d91?76`<(wyO_Sa5;kYC%6^A;s8PdkZPX`X&~R3I$0*5!E-Du#@-%=umX^r4>$s z<`hV#h000a4SkBJK4)QeXb$ldIenRhMbHTWXNRhMS%nlQeZIo^u(=5GC7}i0eTB=x zKZrQL&BRc(ub_~krLVM*JZkQ?6d!sEk8|WK zr0C~cSJ+ARHx_n$=FHHyT*PHOIV=1ynUYwk^E?Kz@IAKVK> zQOtlp#K&?E6ve|DMIK*PQ8JBMYEg>W1EKnyW2%?vgA8j8H3 zo!)�Z4+O#+*P=d1w#j?S9gqgR<3_pVhEXg`H>xNf-^_L0}7Nv5+(=7WsA*Ra4I= z7cGUI4OFVDXobZaz!uE^mchNO9(C0tw=vX4-bM(Sj|H}qh1I;v6x9sq6K|f8cB1S~ zl-EwpD*Bp=DE{~k6`iLwV(va|MHCf% zhl}OVDc_Oes8C%_Tk(j2z0!BAn4%)d$CmZ@P8Qp#pWBKjVvnQU(097P89GCf$-Lf+ z(?Z?m-sd}8OtH~dS)3Uk2`|B^Z92X;eiH)$CX;W_q}7n{4Pop+^TUr6{a6c?B~ zGR24T;!=*8#T8+hu#$57i|2*T5AI@fhU~MQL-xUxAvF%I7ijGQQSaYza%zhghNHY) z#f!P$ikF2)P>n0$$*OQ%PNaC16%P&K*TD02yo(iY43D6`+8iF?R|}ls5hU4)o@prS z@kbZ$2sL6)39ud7#p;T8g@k`p@m}t?+)LrHbYd}2DKd>6qv0QuXO6`PNJh{MAq?BW zx3CZ4iSVSwpHSRX)=QooBAXMg*zr#)K5X#@umwAH3!*N~-r^(3O@sY3=s3fZ{ZopM zg(rhg13IY(_?#RmK5d?tXzoRd&kn?SpaECANoEAcm^&=#Ga5i{X;wJXv_DWwfq4>J$esif%##>+K6M9!lVEcS?=rz@ z=Gei9RaQS3{_LQe_vPRWU^Z!<3R2AU=LU;-&Id!l*}%Dj=ge(EI#K(Jf{VggIW@s0 zp+HVsa5;1y96*04_%N@g;95v1=J;m^HF{Z}HF$I=h64TvgU7=K zl-mJ29aycI;W+f6g(UA}-}tQSe>m7x*6Cjx&!x0}bK^_n!bf~ZO8IPATWaUtE1d{_@(@e|I)Rzt$%I+peZT@> zDX;<-DtTU&&MWK6O)RB5k=*1`idVTQrOS}J5}FjL{A)`oM&+iKuDeoK$xaJ9NwN`g zzWWZ9ZUxe5!5>|^1M_D$a(4mgOz1ye+C()PrH4X^Wce`UM}Wtm-+Bd0PXak&w3eO) zp5yzn(hGcFR*J}AVwuXbv@9C@DBzeYcUxt&x^t(OO$Z;GWiO+3ojbE+4vpi6vMJ$R zIkjcexR$bM19xr2yCHF#YnJ9b$ILjs9}J%yydO-1+=&%2baj~beHGv_pUY;1Pm>SX zkSqhPVx)*oSe9GXlj{vGhdeGEmm4T6;`LHW^W2p12|0Y0_^9w=tc7!^i&jBdD0~6Y z*lQwU@`s|3#f^CPCGghEeBUKoZ@Ty$mxi}nI^Jv9@J1^N@3MyBEmkz%Uk%5bs~Ehe zx=z`n92IuuCFKoqhtjRQCwzD}6;xx?apH68ZE8q-1#gy~z&oWwcuVl>=ubs|N*w3k z85F9xMF?@Lm?S2M6mhpm#{b1F7x##*;`3sgcvAd8JSBcAekk^e*ToL;hIm`Fi+7|b z@tS${CoNLk|tl2`y^da6kQsoT(8_9U8mfnBuJx_ z3CaX1PMM^nNTZchC0&YFeyIFVN>IaUL>i}lM{SUD)Th;_r7x*JR(DGC)qhj>ON-Pd z^`Nv^{iWJ0eO+x)|5N&g`Wv-F`j+~pdPe%LdRDz4{gZl8Q>8j>q!uS_*T!f!NzZBt zTC%iDyH%Sk{kt|*OO^hQmZ4=x&udQY)6yaBGn!Xw)%==YYS#i7rJn)kuBX_q6Xz z{aUS7D{I;o?Fm`ewrShsXzeNODS5cIUE40lXg}7TldseEXnW;2ZNIi(zEL}*9g^d< z7VSm(CheH^mVAr$2YsZRp~vd6azG!gKP2bthxGGuQ*K0?Ct>NT3WnQhc*K=mtVosiJ^J=Dy37+$O<@Y!=FQy0)eS7rnLXLLO98pLb zC!Lf|(p-H*dV}U_r}P%h)h?+^sM5RAyEIoXN*8Ia_DPq8P1a>yM9U-Pkz%+UC&$tJ zyh*-ETqh^UTtl5dr771zsC<*6c8zFkfiH^^?;Eyl=q%6Ezzd1OTVu=|JI zFK(jtwTlyICH_yoXOgJ&O!7?eO!K%sGd$UzTu+fFzVIaMEnxZa-s)44|~>n z)_XR2ws^LYbdhJf=ULBg&pyuqPqU|$J{|QO_jGtVJzbt2Pp_vpTV(5=j_eppvDxw2 ziG<0dHJGwfsHB;W4yN8KDLWNq&GNC?hUZzfm_0pvX13tEv%Q|9*#XiEl16#<9BPYX zqZKa_Xza$(y8D)RT#TiawpF-jr9CO!;u-O;;#1-|N|~Zb91x!t2Pw@I&6MsGFN;@2 z7OlhAMGmdRH-u00i1WfPE>H?cilm5qNs}~DfZi6)&Ius&QLF3R`LDWgq zMbtyoOQS;#@#q%CfTm|PQ|bgZXLSL4vU)wj{Or+*Vk|k5Cl>N}PogK8D8-ZNF+9^f zGd*5Uz!Rj;1F4*7j;D&!0!r0HrhEbAEcLA5H<-$4Dn>|Sm2 z&uQnM+NKZl<9{msxqkj7%KyLWtG`vfA2$E4ZvThP%|EAIJN_H({%iHihuQt8we~^t z)I@a>?lP`DL;3rAhO$*OTzR_SNDy8}f@6YXl4D8+ z-TXQxP3xhnAZ{9QhQm#HOfwwW8AirTM{b7KQAFhCL=sAlkYl!EZpIwP{EP*TMf7Qj zV|m7Y$AgZC9rGP)DW}dc*Rh@?n;cs*_GBD%Y;i0nIj2oXmZbp+KPiZI((D>x-NTmQ z9=4oP0{&)poVbtDc-+<6#mjU*>lP;{O&2}l_u>xm2TGroyX1Go44Ork#7yO8B|&7- zoViV8ll738eWeGC1~I{qjRs=}h&dV89YfMCk~XAOTXLqoL`@_g$lnF8UF7v>@><2W zE$H|k#ZkB$=kG9xp`=o)MhZ<_Pqo`fH(m@AcT&0zf6G0B+Vm|kN_?Br_2MB)vEmU* zH;C_0iW85DwN$1?d{^8k){Do)P2v~g0QE;JrSa7E^VA=buIkZO+LzHKU&!dn=*j3c zgrOTTMywG}*F+=PNHJ0k!%gv zzT}7^>t>3emLbV8f+&va<(iWR<(HrdZO2&hqu zCdVQ8!?~%LC&`Y(lp0vWh;bt}%`EQUcI^(!G+sHV9GjgX;%Ae5r*p1zzH^atiF3KJ!ug={VY1N3 zv)#Fte2T#9_2l;^=N5D3ljk(ooZF}!1HG`F(zDLp)(SJrMAMq6H)5ElIhTo+H_HPhv#{%AM6&ZDk?D@du_ zsCRa`=8$%kYXSA)DM|}m)keEB*R|BO!WD6?rW&TZYFry!wWL+&ighe=x?L-1o>sZ) z4U)PVT{~(1t}xYxQ?4_vZbyM* zv+F!rzhtyK);K$j>27|cA4OcdQSGX7k8rGU$5EMxdo0OxnkNxsHPsd2J|2iXZo7M; zdos;K?uB}Hn%n8lbZ5DJL7odyRXY zd!u`^dn>PBGf^~X!(QaRc0T*NJfF>@a{xbiAH#o}ly*)?>C;49S{J3Bw4SNWQ=6wW zOle5#P3vVoT~N}~^(m{StV)kbkAWc{~r^-kNAuK zuj}`O9skpM4!-~A%lPJ>J@}v2Kg0jDK8f$`c?(hF0^SzxlHP&?<(MHSe zz;*MG>sF!$q8&uLEc*>s{$9)PCZa<`hl!31$v;MP(yHe)(OIH%L-H>W^>X-54a|LNd6R}X;-f7Pn4Tz22nOqE>RIth-fy^T%!3zi>_SR=cpw_ z%Po5FW75M{(OQevTmEdaX#M*MeK&;u$j%m`ZA9CNo+a8nVS$9IhH)Hjar8s9U%*Dmb3J;ojjijPXQC)$(k zDfUz%!#@N&$NiRBoSRuZl|5o9qkh)%K;fZ2Jnn+9USW_8QXNV6U~;+3W3% zblpki_Ym#3AGEjF+wAScpRk{@pRsq_&yzOOr6f5iDrrPgT+-Mid(uSWCfjS0(vqA> znVg@LmE=n*NGb(YM5Tf%ljbEYOj?|@ENNxZs-!hZ>ykDmZD!({Z2UD;lgyN~HEHWm zKB>V)r(KY(!U!jZm3ACp|k;5lUPfi>k{h|YZDte&rFFs zV`E9Shot)x8;LuZ*h0E(bZtjEk$5WcOky{2=lTB)V80Ubi?m-!N{jM>kd-#&sL=7Z zLc^7AW6*g_ zdlHiG0vn-o3(y70zkt6Jyb7EONdoX&ki>ys3BDBkNbn1Q--cuc_#c2D4&-m?E2Lgw zd;vHdXv#-GXEg8yUDR?1H=>@=K8SLw*Tm520)`umO@Kz-hoL zLRw?sp95YG^Z;)|sjo09uYpIOtLq6zqYv+}dV2@(VOTRI_dF@8q-GzAGiELgjBIY)dv{mpJEN7ht=)CHK>LCnZt7B z=VokFKSy3Y!s}FeL|aJm^}th%>S*x41$F>WLOv0g0?Aq64eB}Nfk*$a4zba!D)LZ;(zy{#UEayl?zHuvV zf#&Pb9IgK&;W$Wk0MA+20OYbAtfQE<7%U-V$puJOV^!`!sY@2V25bPn45am?x}k|U zsl0@;NgQX?H1KKgc`Eq(EPM^v0OWej*4@jIQ=MatyoWMzF^S88yF&3Y|is%BK&>j_%W<$GD zA?ZfhGz(t@)&ogXErmQAd>l&UU|v1Xdo;}-&b-mQEC`^V;I`K$@6L_ z`v$(=mJa_@Fv>im&M>Mmn0wLixm|x0K7SPw)_E2DKk%-nyo=H7hU9fOBv6 zKJSTY0DKxSgZql&(u2Haq5pH>8(76o=zNp+O?5i&n`*uGOgWc)5SmN*3`QO@KZ^ZSeq(9AjMeut*3`?Wopx1qB60=% zS6HH~N1Ty?^{BC*_hoG~qw+Re)+T{}1buP}tM9kKZj_pcQYqlwSn0okD8IVt~ z;u7OefX|y~s{(H3{)FaM#DROjR|0F`^G4{Ohy4b4(hls!SU<`qf7*$7R!_v3p2g1f z3!G2B1Nn6`hNWu6TAtfGFFPbn0CxKsn5 zQq(V@)nDSX3eCfBBdR>g*09QOu27DHPk{VMV4pq?_!C~;`j04gF?8+#-h(xp56%C8 z&!6Bk53TW6;PWep*u3_=w(EISqW2V_Kr0T@eKySyU_V>XMxwW0KyCnd5%{mbXMwMx z{~trYMWY8KmZ*0_@+m$?sfe5uV|jE&fj47Ls>a{a9f0Poz^TBS>0X~#-?w3Z3)c9n zsGW1;QSa-(?*o4Yc?NJ4e4c{3bnw66QyKZjxy7*d8lTXVpF)xh4D;zoor~NTF%wRL z{{ia#D)2VoF|@Z2(e+jA00Y zUa4P$WCU;y-Gxi)jleId2Jj}r3YG3wR6A<fm3+? zs}a=oJK#@%KeOfxpP%1=q!VR70~A0Nv+g=;m*k$2(GR`olM%q-ko*dG5t33q<R^Ow$H4Ip5Nkfqb9!BTI5W-+?kO754udB)EI+*ZE$+lJj$hYUn@FFClj$P*DF= zK;F-&B(M)k7Whi|a}gFc0lxxI()&LFJO|&-@jaU5Ki_2!@53E;e;#t#lP`cz?_b3C zVwTTQ@Ps^67MZnMZT~zlAJ%Z6)sLq!eY=5dxe(T7!SXEh&n(M+5s>d9dtvkCe!dTF zLJv2w9YXHCdl;oA(|#ZB#QR?Y;z>wf7vI6b!lULW^j+rrHS~!W7{`7RzQ+iicD6|p zJ`J9=+Q?6$9=Cet5|1)`C}jKOv*{1+So<#Wy{-B^JlnzCQ-28rujBq&KY;r|%qWd= zrJ&5cy_ug%DT`E!|4KyV-(Fa&uH!L1v@{QoDfMbAOMkxq>t);mRc6P7@m47K> zn#MEa8RXUh_XC^FdVv+nE-nQu!tX^aLOfrl(2k&N2Or^IjgTwx+YvI*Zc3253#F=n zYf);Eat{11@T^}4JOV5NR#+0&Z?;M?dVv+djrjG62&`?l^!ZuYX4IZ8JAqgW{0;ep zh!WD<;MaoR2YxZ|pMd-%+pGCxaPFVTIyR4q@0q>1c70<79 zvPpMgTN!N&INmZ(vFI?6<78DoKLc5%@ahO*Ol7qLGob@KX-YG!nZ`3@n##YC5`p9d za651sMlciT1=@iTTKPWnLF61;&Muzn_S3G9>lD z%FEOn>S*xm`MZSVW8mG)E6boi8j`oQk_h+(;A4PmAxQup<48p_64to4$y>CAqoT4Fv2h;Dl}m_e2^^7>I>h$= zem-e$hlNG3oMLL4eS+Av7o}oRs><|V@QBz^>Ig6f^`635PiC9ad(g)(h)BDE#${d+ zmHqtODF=4Gff_S`&8THF`nevM3c20tH}3Na@NeRGD|+E)Gc4m5gp?DPE8rXRWBSWc zil2+VdASRcn~atp{Nwsqir1MD8h)472V`XhK`w$jRVP4tH zwT2eC!LNk8S$q-vC%8q@X^vFZoScgh;j_vi)Hn|qMA=r%D7(B4vx3|5s5x`YzU5k! z{pQ>N-wE_GQg1whes}~c;t|XN?!%eD#ps77@H%ilBt5_uNZP^gM!lylcc7)^h$?C5 zlR9`vu~8k%eL{#;kKAUI{UIb+M^X=4Q0Mc0O;}3nE}D5l<^`htSiEPMX}xX1nMdyd zVt2Fg+loRn*M?DpJj(VubP6HI({jBXh;xYT58!c5w!xYWJC1D@$ zz+-r_{g_o(4sZ;kb{Ra*=Qg}k)8oNMfClhx;4h%R20HHm?}GeuKszMZVQr{aGd)ZN z;yk9$2aoq<`a|H&-E%qjgKZ9D)L8V1DKWs`2mX`bzYabf*bNJuy>pbL!P73-m{zrI zO?!IU)3)tt+qO|{+qP}nw%yaV?d|X0{q1+}-u-J&owwe|Cn6)`&2y?wR#xN_eE2qc zme?`FptaL!S3z2i_@`f>AyQz+b+_jP=+h47qa#QE?Je(}mh%%5=qSRfULbS?6ANL~!LCw^+h z{NpJ>Jeupu2A}l+@`7hU?gEtw&CmPS+q$?tujZp)B++PS>a<+9ZT`~q+x)d6e2@G^ z;U)bGp{{QKSW;v?)c9c_sAdRkxT9;gy%Bj^K&G)N^Shl8_EmCyH3p#C8JRBg6EkbF>7kaU}GB?v1C zdBFo9GjKDIGoUl*Gt^ecK7YhYV#)i}$ekz3%%MkgNc=zF8plkBIu;#zA z<}VS}z+_~DhU4biYDG4e0>N26BuVeB^Y7@?v-bdM$k z-Ti4@oAFEQFkPu~kZEYlL!Unjd2><{E~i;r2-wQAHkSLP)GFF1z3e{3Rg8vAW3jcso7=l5`dIB(uyk*~W;2*myu9d^)aJT;c zlkMJ1;_jTK9o;kmgPa-}K_EDNDlq%FN04>+yYh%E1cAzJ&3kXOnA?6OAI{@1?p17~ z&&D|s>)TN4D4uRK$+>(FL6UYexmBfc!_oB2?b6+=-$7vW81@Ngn>D2>0keb|Y0)1H z#k3GA>A?hrG8>MDY%@X0vmj4brm;BGO&eO(v@Jh%lQwHARc+U9Ey_^x1R-1rfs$=N zZH#=rYQ2y#Sv`h*&W63cN-H%tqF^g?E*$GdI}$eqKe8NbiF}1FSgjv+2>OITg)V|V zgd~x24Vpg09TK(bcQ*XN_YFoLf?BXb7d-^M0#NI>_^s!7_JMr%As+xN`Kk7B zcar;np;;riv3yCEG`?iKveEcs0==rr+VA6N5kvU^N1sb}@nrF1IF4ZQd``#IsH{Al z88}y7PmB&i9^5TNI-jThqn@`NhnAjncixDIry;qET#xf5LZm$=|$~NR8E7-o)qWFv z-chsYZqeJ+esgP zXySe}=B&Z5LB##u6H~TC!VLhf>at)p8w;)=Z3Mv^3EF9}WWWz!tU$AXy}`)O+IbKY za6DrE%-ur}fOFi4HF1S>*=5h_&vc`r8wBl$NZ#So4pr&n?*LT$wO^Ze;2<0_yTWfI zF7GzlLT?Ay__g1(bh=*h6D$O$Q? zya}hMAmsjP(-n!H6%5emq2Ys@h?xG&PyI4ACYgLc=Xd|dZ%j{{)>rtxNAdM6PQu%( z$)$whWGSMVieM?rp>QW~VS4qbA;QC(2SxwLuj-drsAbw+8{bg>2g}l@fqI3{40?sg zjIuHF#9L37Q?kDoQmow{KH(7rm-Is13Pkz|e`RV;TNk{bvlmk0%?Cd2F`p%-=#9YA z#LT+}bWW_scMeq7zhHI&a@LXI+kwHi11LZE1O%{e2O@9P-<)u0-~~V`NQrz($PcK9 z0l`sDaj5VK(vS(#unE%83DWS1f{+L}WNdMCY;jC%>|czGQii00hK4O8BVw_!@;^yZ zf0E=2i_{5;)Cr5&3yIhZiwuQDM4)1a<{w;la zWn>gKG%P!&o)C=WRf&AZWzh<$7<`cD#SVG-r8AHR) zkr9#DSm~c6>B2gzKN;(l42%968mEs;ILD^q|0LlQ7I6-ZILE+VC1I>nF*L-cuLEGM zf@CQ?5;E4w8X9(why{*}fX2r9|0D?(7KsXpz(dDoCudZkVpO1EwAVB&5HZ{j7#R_d zjh+8VVj?6m6&CSM^g6~Kn|k+?2~)_JHf%x@C6x+F1Ob#psb_?$S23WKJ>V>e!opb$ z);k*NA67<$qAiZhaQ}^1MxcW&EkX3%wGbDK4w+uv{I%qeSDyzF8wzZ9KR&S8(R z&=;5^qo#4fLot?dg7%}Tj8PF3Zhi5nD1!ROMhHLq;&C}RL^&cwjt=|kk+}X+B64e| zM8^11cxEfA{#g@s=od6I7s7}`pMgT2YLEH-Gh7^5O&}@Gs30XF=D?ecF86bH{I^jO z!=MyQeTG_Zg`qM-c`EaSx-ouz)@qNXAqzu#D$Rs)QNrqwrHM1W(S(d~vSDa}(5-r% zW}U#TOr3~15p!Hce1%B|87`Sd;ZU5yD2sUNf~GmKl?Zw4sLr0xemsof&x!nJhR;P( z_f5rPw)u!CQj=K}jF~~mNnuzyhXy1XfybUU5^RAWB8oT}##kmb(Ipa_x>QS%N>gnD zvE<)GfrfxoiK5sOL&#Kd#pNW^#rdC6ORK#hyfDB|?K}y#9OOTgxzE5dlZ~TzO zLZR20yW;p_tC z`26)TbWkt1G1Y+m@*%`S)L4w{iQ?QMTLd6mFmZQ`PK4A8nJ0`nwRJ6>Ch&YfoM zUC!MY$_t{K-~oNb{|F?cd1v!j$thO@-MbE55ckz3N-l?d`*Pf`*eCnvwIad$Uj(l* zfL9r$R~cCpw5u51J4)t^`~gAO{J#!V)5wnyPdN-D2b4`^zGy0u@>!9F$f8OKI*tw6LZmiJVx_^VTFpm@xYbee%)oDBPV1?X5L%|%~3gDAN$#tbM(k(7pv43C<9 z@$ty>ghov~u(^|EaEnIotj&CJIDn%0v#m)Uw%O(4T|hW&wi5Jd+-)Geiszs8x4>Dm zNi)Z%3)jZv17WQhRD|r;+Mmd2b~!kA2!=P{}h(72&MA(qhp|>&k{cE<0KyNLh~9zHM0kU}-&fFp7GQ6ox}5 z_H82>^?T02e4@NpZW} zm33%mX|qg$wz(`fQ^@O@{;5HEiH%hbfm4jTJo8h`Yh)4^;pK0_PNTYGnjck(pf-BF zvVZ@zG55-*@m;V6uGv5~R)aTI!#-3&Jyan&nS(f)Lpz!Oa59H;G6!=q2NW{<&!q{P z(d0BF$rUTh6)(vZv&a=sn!z`SR#ApNvINh58e?4W@B4;L<^fbg!b;*Q3xLy+4NtB9 zWve{yAEIV3GGSrPnU6wOGhN51_h6mE4=Hk5il6>MP&iC*BSu9*Ov-WELaswNnVGW6tdI&IO1ga^-0?%5Qi}1fE2>H>$6&rj0 zQqe2HNHK#c2KMxEYUUtdd}VR)Rh|h{p7B?n30C6rrLzXKvHG>KLSC_eUalcJtbl3dNH8;E^R3q%Fk6@BjH;6UV|%5ENysPUGn!Fo>oYNTEAq zu=j5mT{0o24u3Cf$-Y;#K`)VR)1JC&%6+%r$BBo`YbI5-mSULoCRHVu(i)8}RH2l6 z0kSols)*lx$ z@^1QdTSsF?yyO96D~ffX#$Hnkc;_bUiTl`UuK5H6;`i*ez8UBn_e}8Ob2%9 z!e|e!&p%YtzPsqq-j~oNw|Z+n-_v2bCsor4cWWd8T)ya%l)kY89onxYHn3jG{drD_ zSF;84e&qsQ)!1@gxu5luX9-W`fTXy>)>rP6B3r-O_&5Rb9rY4Mp=iM{vCxjdAN6d@ znYzwqDS7FARkIlW`uUdNYq^+7Ri+>kf}@n6gE@|`H|Q9FX89AU7q_eBqEZVSi?v%K z?eCthx*20h1$~9B(pKoL6-7UjJG91-q(X2we8}IPrDoXn-hO?vzq0@mWmUq=(v=F> z8s+{Z({HMg(J*!ICm@&FfkPFhuLv=-+TGqevYwz|CZ=U1;iX&eCTFDW{xd9~Hx=91 zALkw|jXkj&6_+Uj80hil7v8yfo7&sAiLd9L_{S;k&52S*q?Nk1QDRty2$-7cF!!WPW zSxz>WJ0Fj=fr0)N7#WXs-(-ZH#f!cOE(cu%4i`%+u2o(OZkFxqdkc?f3|H6-GK<*rsY&Bclfa+FDRpKc zs~G~qQyrEMTg8f5LxmWrF5`1sYes9qd*cdUS7&rjbe7N>#oc#tKMVJ|HYQ-^%R4SpmOfAz)~(;>q7uQgy4qFuE;cP9HC#12h4s(M(i)dr zCoE(XHE85zL$?*HSCuHLb~nws*Ksq-|_6UA7%w&}{)v8m+ zvQ-)ThP3FecIFy?9Se67k%{)bPj-5Z{c426r9E5Zvw>spv8M3Y(en)4WRrZ;vb?p; zsKe_$F{yb9yN0*&(S+Kg)s@tVK@MAvoG$CO|K)lKUk1xjC)Hkfp4$6yhOB&wwyptiR&k$m7L~WkE1(|Q(#$*d>I*hWT=dkOxUNZ-YsuCy+fc`f8Yu879qX? z3I;2E=%G2v?(!p@Qm*B|F)UE>gIlG&%B2iwuv+IJGH5d-Jp3Na#XY~X)k+l%2^EOo zTI+*%YG3N$mmg>|@fm+;B#}8b1lM_})8*V|K7u@s;UsxgmV%pYW^v=(; zMaL$8YU)hc!^8Aqk4kbym35l6JeJ-a^3XIqMR;1tS-FwrbBFoSWI*h>O zwQ|^;@{3a>pcWirt)D{dDsl}}|IUCdQkv@O7>3Cz$J5lYa#$fH4}!}sY5iDg~>G6^Ql_;~H^va4BURf|p$ z?uR4ECN@p&3}v57l@AZq))^{P(yjDo&dc}&gQ<^4>RNV6IR9jl_6O2sJr^m=Uk|lC zxac0U=YSbm&T)`hc=drgb>5RxjA8b0uZ7*rM4K# zS^-MJuU}(@p>L_Yt6$0Lik`we4-38EnV4CsX9sP)@9n)RD37UWiRgcMR$9J}-OBx^ zaN?hq9vj~#D}&|ZF>s5^HRox?>tJx^8=Tf36xS_J==l%qWqO0$;^vVrf*;(j&ofV> z4dx^@ql&-Y@16JSeiu!A^}Fdz-ldnnm1YnqsT397R(W?!KIbZqv7F<3SFbiF| zp`4#@N_t@vWA2-xp4h@&=X*0*r#U(n?^N5-LxGN9OVZtJRuxyaZo`t}%~4Fe_Xe9K zD>R@d2g+99n8M~yh{}Htd3Y-m;$8|ok|XLppY+)CmO7O8JAPckF9u*p;^r3Q$@>GX z*NoMTo0oTd@4T&@8N4c}k93``&gMvu19I8R^G(w}9*noN#dIf{6kMsflH2I4QjZuZ zxw!|&XBmDm_Y&V2;ByF(QE(K&MWHrv6cvz*B1THcI^4tNM;-F9QgHye$S#7PDLc>z z2$#`Gr)4JSNl5lAu!jm*#;87A;Gq|aq=oEPdVa>&R;fP7)bnM-Bhnp2xaBea@@Pq#WHNZfzs7}TgjP>n#wJSt6`0$ zm#0$?#g&wo!gU@Ewfq%60Q?7aacNyvDX!CgnN7fSf zx2IBRS518>b$3I334=yEMOThistonE9@XF|j{qf;z?!lVwU=&tt0lmA5N@G-oQ~#L zPRif-N4-z-PrY943+^@dwKu2hyLy|G%abPt;(Vifia_Xaar|#mth;2eM*16b?Piau ztxIhOn&vDCFO=5K3pM;J?eJj4jgPfw#%-MW)q}}5Yq}cE*5%uq zLBb*}H~FNJZMBmr#NgZbEXNX@JFc6Z&03N2evXE!rjfRIHKV6>Xe->Wuqtc+{(I$v z#4Vu9Sx=mG9kqwbd1>`ja_29HrA-&=ob|2F)U%7jfoVyP7@S(m+5HYl*m3Y}wRXJk z8hYLiF;j)4bWlv)Og2TlUO_byj>1Z#%#9|APyOZ0Jev4h8_Tx9=`d>6CGAbD{ICAq zPHp0TeQngzHakRwC*)q?UmcJ z^Ix%#1;vFz!k^Km)595a-9Jo6E!SI#^*_1~F!6Iu2k zFUNJPG(4Qr(?{RUXj2ikx8bnSPwq8k&t6+@q3j^JnIs=fws$KX-d!>zOP6Thyj%u8 z96n?`-YRJZUG;P4%c;9_Nk{s<2Z4p;i^hU)epMzKHnt4x1FK6 z;!Ru3?^l8Q{dWZ$M=vMAdtO_K3aD6$KdoAefU_;LS>g|CnyuO)C(hes(@bzhgugZM zzSBe}!z^Q*t@XX2KolkBUNqEWjKF-IZ==Sz@MhgNat z`jlI=@$$@AZ8T7e*2Ou^sNTT%UV1Oat{o9F3%kG5i^Fky-=KWjCPFe4-x}Y;Ms#)l zrd@_h?M>UEbG-<}Bh2XtN3(5zAnifxI((%9Por%I9-R*kl;8nf{Dv#QWB1*zS~AW7~2$J?(nHK6mMC?-X;mylVtM z>CoA6YGgO`YhNFCEM#z5 ziq5-yB$|a;652C10e>R|e_~{hSx< zjd~R-%ah>l+A15}S7xpr`dXDHQ@AwqRI{t{D9+Ye#5WFji+X*Ri2L>v={{$TQm^L< zwBoJCH%i|-=`z!4G;{P1M366MWTJ;0SMRNpvo*>G7UbI9m}fi>fvX$B%;`*h?QU9P zR^5y5iHfxCp zQNA1wrJl z1(tP4Cw@ChKw+MtDRz)k@!e%jD1JC*3^^GSPl_gU;jp=B3=L1y=a~MU z^o|fCJEB{e{dH<{KY57c9Yvk1U6t)$#sS$hvcq<}IxBZl`}TuV=3!}elkfxVnpxe@ zrn7)$a(!~<$_vnmKnz$V=8n%GUfuQGv1&CSKiwKLuHs={%R_0&27AAvE7wuZuYO~x zM%TmfN?fDEl4Wa!kbbp$R1k`>@XvytYInAG=#YIQe;QPs->NbHAaxJOsjRpL>nd6O0# z{d1-<4DB2V-Kku46|-=t2)Ikq-@}Sb3dvMYYb(cDPOHaPzY&^Frqj+M@`TQe(^m4n zyBk@Lw#t-L2A9tf&CWPK^S~G3=q%uR*92RFlg86|f52cf7^D)NUFl!qy{oA0bK@(KO?a#Sx`pljYQGQEL;L%|F2TjkWyc_r+1&#U-E z2++!`O~cEK^7XoRpx=7=oYh9}MkKLx$kI-tZ2qvv$y1bd*YTjghiFpuq-NXOadh+g zM3as@b__DB=<4-CR@}sx=42CHmBisFqs-M-X^Ncn{L!0N(81B(NYCnjh&KA)5CbDC6A?Yp|By9^ zn3?In8~^L;zmWf2|117~%Kz#6pZovp_usw$-}rxP{=cOEea!#v`(NY!&(?px|F`Xb zr2kX*|3jli^uJBhpZ`n~7Z;s~nWdwVJ)MZ9o}-bFk%5h&5uKFL_xGYH5fd8&3;X}w zU?5^+XQuzd!vhca&$PQ{oO{CP{#|VSVt<;-1ZIy;kj5JtGfJUg#lc{UG5#K%ln{Vk zC5BlyBtAzHi;?~j04*Xf&wm=EY+fmx@?(LBR&`b#z1ArgI9;}qcTui-Ch$R>>bBi_ zBoks9*fjn6>dijt;%&ma{W9g!b(e_>p%)N?%!9K3yNo7Xv#=&pq@^b)2Kct0w;PwX zZqkPQI;tG7azCn+*x2lH>5ZNH5sa+vXl-u=>}9^1%2 z>4elsW^ws#a48`&a)$zUEp~>kHD%!4`6UrRz8Q*SVs@3%z0gYcg4GcCiT?UBnTbyc z8hg{0)9LjY*Lcwgo8c7z(Cyf8!I-eH_ITRw)X4domCI@bVf_1ayyfGFTOj&db*=Gm zc3!cXKO~l9pQp>v&Ejr}MvD_^&68SyAv}qt`hm& zbjp$B;vC2;#Hshrp|DkJuRVOvOOxgsL%2qL5Hb=rUYh!$Q?8v>p8kxj&_j7j=DMDi%{1&oS0d34IoWaDi1I z$|FWxDvpIoqC6L6BY+p@(Ck2je4aD%iPG3F2M{4sqK^<76_X($@5{eKK33*`ttxTi z5Wkwjr9`Y#gF_W^y;?8Md4S5uoJhDQcu}2`X(fg}0qS!>lR}tdk1-TT1`RaxeP9kg zljc}5X#XgH;DGq+F8}5+WBaUwt!rf*+TuUpyEfPWMG126ladAIh_Ljj$j}YgB@8p7 z;j`k~p=y9APe6 zbW(o&D|CHUfvVY`?;^HYdg=}Tu52}8#-fY!FRVIQQ3KvpwSw*ivz`qvsJ~kaWSun2 z#dYy%a@+;G#5-8fhwvTT3OJ)I<2iU0(p+?vx4m=yr31o!@43zOt^vlRrSK$7Lkn{uTE+{!cj z5=1WnEar>+!DP;NGbKLdE1z|DL?q}BND-9s7SIz=6A%_q5|9=U?3)PSM2+HL<**46 z3Xo?W2~`;E0_0YgmY^(#02}jOOc~Temk=HwDDRa3KqUd4`N6I#M{Pvl&WH)vGOe-I zerhi7GoCH(2Y>9+2qLN0{!z3Q<`>a@RqPagVotRiI%Z&m4Naqb=q?cxxXnQNwbLmFNx#3+bTFcL!47RO6pTIA_@E?#sj~>h+tT=Jex5pr+z)M2p`2DLJ1yVtK zhDwYsj)LH7*}8F)I*fuYWX*TYKOZcVFRJsKsQ6I1vqCXW7^O! z1lnhRWHy=yu0z>tJn(ZX+>vHQp<{LEn%$98F{~*O%7jc2zYMwUybc z4=&tN85PD$hJ^!QZ(lk##8D|C5cdsDBJT=|BW0u?BWx+yEsg!Pi{+`%?Nbxtze$ht z!#BzJO(@y1;z-*iCFjM~HsP=*1sVN_DGU=m8)ZhmX>{1T)#HQHE-)AO&7{3*$d@=N z@GY73rj)h{^SEJL*aEZF|M>db)GSPR@1vKM+lm3aZZOsX+Uunu2!S3TXu`AgR zgWw+Q{druiQux~ub4sx&QlwJ?T}TNDwy=%U-OijA18RX_( z7l5=eEoi6wW50Q2MStLyJA0Y88?y|bnYavx;3JqJdgc7+8RX;kw2Ii3HvjujjQe#O zDKw4>Aq-|L-|j~TXfQo*^7p^hTD;NfM96D@H~Hpe7WA(KJEqsM^!*C)bW{H41%i!H|mvFVCy-7=Ug)5-4`{GC)pt}qzVugr@b^YwLoO|dt{lJb~f?fMBl~b z_l&#@a*H%f+<2WCanWTMxUq>5fz>YiJYsL_nrCiM(!(IW%yYcvJo zDolHYOu(D+O_{NTEBN(wPM}aKifa%zJ0vSK{NblgX<_CurY zSk>|yVFXDs2k*jy=${j1*kk!?n{5u`iR+M{f-vmsG74vZE`f7m-eMh#jQlJ&bqJD6 ztncNX-aLlH-z~=(*$Al!e4wdzN>*WIhAyWu7vEG-Xy7ubk%|aR5s>Raspf7g5^%4J zA&^Sa{;P>Wo215ETei11p-;nmczs%_QTV{D_sN z;qK(xo|nhdq|dtFp|v=(TV|1JfUQ{kV_8#8B8V-|PFqbah6^85oUS3kW zkIXGFb>RdLgfj;CLqv9xYK&t!FUnhxOzM5oa0CE!SYA_15U0}QXaVP=xzd%B0f>LM`PRm`j4C5@>Sqyh zCDg<~xhV$-azsLBf{uUwF%N9?g+N=g@e?vtG$@&sgtSs!p**hR36R*_(_1ym)?~yU zSza-4Gy&kEKKjnpNBV%d3O2(38AcGts)z-M7eP*GY|1U*IQlh^l{8}9XW%FlW*$y} zdr*pJQN+xBe})-pmh$H)1;ZSVk-Wq;6J;Jrj$)Zv6b=IySZcu{DiKS4^7o1J&~SYm zb4ntv!MfLdloTG!=A@l?%j~K_>jhFU+~fG|#P+BxAjf6b%ZY|FQLTPcKnjpO+GQM$ zjZ7>OxhyFz6TZ}XR9c9M;a-qafXho6@`8m$;&{+bK~LTnMJDNFlq1)9xbLUgSo0l_ zEyMjZJe1XUm&0|Sd5(qdN@;~u*c2$kRnQ=6L{~s~*5Bd8G^Lwa=R>(iaA4lwhTiVv zgX0*n4042eVNB1t5HZz&*p}vlo9j=8It9^Bg$G)_JbX+j0bh_sy&&re%5-2BovtUr z)e!~+f>rwDQ~;6H0W!-1l}>UNw4U3L`ZL+7%=G)xeJ-uni}7?05DS{{%n#R2jO8zr z6A~F$s#AxYNenMhfo8C$N5zfH(~=hDHqsWQHdAm*Z+>q4#@2@!?xORG(o&-HoYE8b z4X>{T4{X(+L+(Yil}$X=7=-169)a6w4X3YV4P&oS66fUu_(tht*1rs%l6IpMJS))X z=mtHhXvL|k=p?8s=)}gWkKR&^fB>ygWMi267P@)Rlfhu3k1_co)Rx0k^xz@GWWLL= zE>{(C-mT5#l>Ou3_E!`IQ0qcl*uZqE^8#DcKwPQ~K0Q&L4$Obhi2a*FK(Qqgya_BP!xC1!=jliW*5N5P8s=x9j1@w^u5P_v=V^mVPaw542eTD!s zv@j|(dCCGgKH_XJS>k8`+CXtMa)lH=JJh{AuxG2(h~fp7pG zzzNzMWkk`xLi#egA_!g5z`p=0v^c5_>BKAAGGZ5n+AaRo&dkSKaDa!Y|2n1X>x3a^ zWX`{$m<5wtkQPd|w+KTGHcC%KnmC{iBCWuA2{EUZ`Y4ku;VXK zAi}*$jsssdC=hTDGc(NR4f+awJk3W4mI?6+axBaD1#vH$^Zi=^@t$A?J7*jG1L0UJ zXP)m0q!a!gW5&jJ>&L5X&KJll{7kj43}`3lJ;#g%Up3f=gvQ=8*$g!wg|9Xw2k1S@ zOgJAM$OqW5TTV7OH`M*_8M_=4A1}!JKSF%@9WiGz`CLFY5$?frxcNRNoV~h+4qBu;H)?TBF=s0Inn5<<8c>hPb8wZoqi}tk zL9`GHqWkgf(sxs$R-|hqrjty{8)^~Cr_)S~p41W5vA4`!5*$-lQ*{`+4U#MwcRcP} zctWr#o*>^lBjFTI z3K)=-Fh^h%e9Aktw0ve66-wiOJUhq!#gvW%WNPCI)R9>_Kkt6gRX{f8%Pjai=fBOK zsYZRYfX!_l6F7o!M{4sC>QTw`DAL^+yQulrlaL6+BKCXy)DaP}Ck&nrFcGgrrgHhE zZ_Jxxq{*rfyiRh|huhyB8j-+-nuX3k_c$^#A_^D1KTAM*7K?n#bF|hvxdFaGr>9La z3SHO!1=@r&qxl!qUNvCktCRzGlHUr6#HNy(4@D)1*_1{-cqt#=G&QDPU5o~NBdm&l zeOBqea`T&VEoL8fsaak7V;mZvA!T%W=n`h*tY&W2M=0DH48!G;JEFJ!tOFm2Z1$SN z=?@#@tMljirt{*D>5dg=V8~c@+0cfxXAlTf{+XGwj~Epa1()ka83rwbL;Xc?teS29 z)S|!KJk~z`;`w(kNhaoub4afEIwjJ$5$xru;HJ!jf!w51Kx4{#|_je z-)0xy(R*)>#$O${6an7DtJB-#c=(j$-n{T4JaH8V9V4Mj^Q-vw91oBAt~7Ce5~c*R z*fl}SDWQ^8RD7bf0CRGm^r?E`9zM;%9$b?<$St4QY5nchJy61Hul*}a=y&%5g|-3| z@1nt9k}}Q|W@HTRD#pqz?UkQfLED*k)@!bTH{L|&S4-F%}Xld4z`3xN*ri+ zFjLL%iK2mEvL<)B7}c2%$QJ>j*J0J@;MHE|V+lSe5}T@WG8p%Ne?b)I-gAkJxq45c zKXuJbPCUqTyT5MfR9LkFAMV9R85pO$PB#~*o37gQ6zO|dl&UG6GNZ+-HD?-)Uo=$% zF=A!WPtlxyiHXU}BQBN4z@l-X23Z|JHtjYv0zn*q8{ zbsM9u%cuAL48KI9+NBkEJYC)uaeMeA)6}rKfYITl5#8p2q7K@oj3&dSQaxr~&q4t2 zEyx@ny;59`d}iSgUKx+A0rq6bm# zu|a*|dY^uzP63G*58AW@NW%G!roq>9x&2f3mV9PCD^8ara09{YW}9S09qt@|wfz_C zJAG437Z9D{on9Y2`LrF)>$AxO^FGBw`<-)xiLQXn74@eDJ2e)y`C5YI(ZR^~$bkS| zYlYiHhm-m|qZ%Dla^oLH@C6C7Gveyup%7$K%#Uo>&lhB)acj4Vy(1q<8*V?9m0{LH zC7VoMvVL>KKcNhJsVYaEpPo8T4NqRoR}VV(PAWBLVM$7^#TA`BTnmS~?1rAGg_RUY@v5(k{oLBEv$@nW>jGRwnDC43(ghWQnUA_Z2rk}wiv zDFL1uMkQk=?m0R%b}$wo>#EdMCnpz0neN-O3X&RM^YyPIaPO&no=LNenOk{IEoI}M zC3fndK67N@ozcon?Ey}+je>+0W~z(yU8KVtqlvcG0pdW5&L(eXySpF|=TlE4OO*E- z%S1Mdi?>_1A%-1p(>96sMR`IT}e9ZD*xzi?xeTX-6& ztLtIxt4vU*by=7Z#LiO9M8^C}L<>pN1EC8^tUHOmsY6-#R_9 z45bJHp&a8P{w?4VNU+&Le|e7fJ_Np(0q<50j-Heqr6o6;!^w_Lxc^Z|`kIiXQQhKI z_ec!rD)&k5E6C7_5>c?T{S`uc@hbv{3fNTD(->I2r}zP-^iTZ(-U+6<=1O{@$$ri^ z(g9%_CY#G``}x5Y*;Vyp=Z|L?4S)il(}(xxn;XUmLm+&Al(e8l-ccfnIE+{0-#i%! z9OU(A%p2pokb;C~7bj+ODg`CUGKH)|`9w;RyeKzADA+2Db6qx;yx(cG`Ph2c8|9YD z<6|4E0|yc&Ap{0Y@)qLGED!A|oOjhDZ61L_xh!Q*gBZN)YHcl~rSFG|J9iL@9rG4r zS)rWd?}hRMKQsJ#t*2sVb5oi*IFzIm6ybYT1lq ztIJwS32=E}#z{>VJ~gjWRyY#}rkMmbB4;?2Nx3qayVx9$zYyV~}v(pI;&G}Nfj zHZ~Pj=AR*OIkkqDFa3L)PSzeeWh}ub{R#2mOhl+oTU9NP3q|#tGs3eX_+mKREq?0> zD?G+{A)Y~LESsvp<~A*j--0^hj~^oF7yv+BQFjvuKeAD%U`JyRR8jA0A{DwtqBm%? zGH9n_W8+#<@@{(Fh*@;?a`5_ksfHcj=G_>s)>Y3lx|^O6+wJ;I$ij=AY^}D2ZqhP~ z_coB5B}=FUhdM=jQ6}9!l*KcPottV5#6Usq9r#*1NePJNF)Bqp2-21m6c6xZ*-FoI{~tco_ZH+(gQk| zA+dVSl7Of|*AuI8N?*A0{-vw-XEp@3OqOItT9|3N~l)%ADUs6%6c008TwA>^U1+8NDT05oTj`;0|fw zN2A89-pZ=E(|k;owpLTCuEy1Zy{3K)G4SLt61EwL&!#^PMpRI;OSGf@be3Q=WWvQ- zmJ2SAMaBjXY>o|7@f(*_8>b$?_5(H9@zZ863hdqLVK%Q@+OQ+k5box>!}DJsTR+Kl z>?r8V1CbBe$GM&0RcE8S=sX_D&PdC!C&HEgM&67(iHSLZBs@ z@_HSwx0dQgR+-OakA0K3Uf2fUp^%3ZJ;V)09PmB&+FAVxnC5e2YTAFWC$g)C?jleO zOwCHRDT{0-scc+U7AcmoQnN+ae2l}AGBzxoE~-s^^|>451H;a5N*^d+yCw!1r5Tv?4TjKphco5&G!9gc>k8( z#pybS&&h9GDkxOkf$E(2X>%3@_|_tK@zQIH7^%XWS2@}?%3-=lxjaR40_7`f$Era- z=OQ1oJ3u}rR3DX(QlT)ZWoj9#tX0&a_e}bCE*zB9M}W&HSQlY_x^Jr&JxxU~O-k3E z-4T4MZO)pBjP2)r$BhchxY1J{US5>qO<(xndiK=$k&P=0;zp&zz4}ww#kF8B18A?v zTh0h)hEkpEvDp*sPPIX+a~hb$>;UW)oo@UD>6_!KV&3GvRoNNIjKQh4%M(47iPgG6 zQIi8uxMB**f1K>;;|BV~C_FOy0ix@6`JIskGi7B_V+X7Cm3S_j?WY#NB8^%CR=Pta zXEiGGxbfrt$?~du29pyqlND8amq-*Eqk30t{KWhzqx^*qi8+1(#M+9TJD4Z4i;}hJ zQ(G4=Obf5LDCH1N-#_@9ic?dIX8H-lg7aWO{aNfm9$dy`$c!x?;|UoNkt_{$oTC|Kq_?dWb0c5u|$pH{i07%^32M; z-N~DW+QsM`)^0v_bYQ~;!w4%}1zv*@<`9EMUU*~B;U&m|oOlU&V|ZIx<$jAt(c^3A z8^gs#L*E$aZJb=jg*OHZePTHL3wKf5)pyNm+R;1~Vw>;AIV+duE~?M>T2?O2TS(A& zYTM}0XtTcm*Ee??Sj8UJis4Q&W|8<PiV$ zpL*=Vg#6+uZ50fXaB25@g&Vt;_=vDzUN5+am)QrEPD)gLsqq%>tW-!cnT1N}=Vh(l zx&u#wz8ci~Y{kdBN*4(yJeK4WA92dWH1HAI;4Gg3XSrIf4mYt!q6<8xVFMiLPb^~| z2reQn;uRB4k`ugZ%?c#Ga~6Tj;!%gFu}Z5fHrCEz9IqGrLtVT~ieuyTdTD%h%xPXd zME}SWS0G>(sJ3*ky0gY6N7eSEsJ8B!magI-UFGf7*~fWGx32)b4Gr$S znMJ8DKT{l>V4txg)ChWuQ5&4%FTza5q1)(8`jQ=R+$=j})Nt~C&|I_En#g8IyhivL z7bkaRSjYVyk^dq=Z?u&n_RWl{xU=@ew}zg+1H$ne2#B|4auA=*%p?S}eB|%yf}Gxi z4-*Viv6qN3row~Y!U3I)POrS#hqlb`T1%7X=|!S>5UI2#8=f>Jgy{@F)gn? zr?7MS7!WS`_qV&@=I7%-x zSK4hCZgbD&`TazZGc%tHh)){Ez|i}Wp2mgC@MZNf^c-_#yG+@_3%K~|z^=+$pV7Xv zF2*`5{C)zq<@6WeXA;7>bF|V?Rk@yy0&P76PEbJ$zloExvx!)#}Q zO&iI609w9QoNcltmc#KFRNY|E=(Jk92F$Dm$4aI4_)4v=(gdcVMp_+JTk@VuUn2y| z4BrcH5iyt1lD?ye_rPS~l%~Er#2$}c{hsNJn(1n9eKooGfxmGgdeuAj7_)WYs- zfj~|UoHuc?Co(f_uK}yVI~@D%4am0jo2+E#N*P8fbMJe6xvimlZjS0%{j42Fmp{OM zFtFgks-K-Y({+9LzryGLFo(QX0hb$r%UJYlQTlo*XEw*Gj0TMyvvRo__2YJ4AFI^q zG-@8Q;k+?Q^^ZkfL8izne7u&|n)GHJr;_t>gWRA|s-#j?wOXTz6`1o2e{%DYs~6~C z4t;f>J7>1Rk9~0`h*5g2f;f+JXM@)P21u|`kN(e%B3yR`X|O5e00u8ITa=Pyqau6u z#_C%NT)lTH33h2IGvUJSieqoQ z*9m^v?r>1z0=c=-O;m2ZtfL=a$r}?*R%?veY%}T;Ri+W3JOK?dZMSdm2{OLSDK zv}btP^uZk_FzY8Tj-bMsnVH1Ji1qnxdh*<8fB5h0gKSeRH)y+ZnQWHKmdo~QS>|NJ z%^Q}sw~dQSPqdFu$f&Px9Q)$qTVl%=SB!D!xu?`4r>_3RRZsLZX2r1V-5eL6*EX5x z%>IQ3Z{66rG|+PB=&y)oPXe9M!rT>ue}9XWGpvlk5}85*KT<5y%UH>8rIm69j`oKc z#ap~^MI>)9IphylnK`0Sg57EyyeB9x-AwokRJQO(FYIF5&!38Ao*npYJo81|z+|R$ z1M}OPw-5LTkHWnXP8>J#^LBS^Y`oGSGoCSM-;~8GVa+YK2x|RLW#2skVOX z;LSLdw)|G?#I_te@mo$D$BykJM3!Y+i7h#@ z9LFII5Fk)W1Efi7poPE>Eu>t^4N00pF3-TFkWk9IJW?)w@%Iug?QOYykSPC|*_G@# z;s4vO_rI?%nar89quDd(oH^&r%g=$!!D`rLHwN(7;AL7i^v%gNo%f7pC%g*-iJ$wIcw{cq*Y|Dua zQckI#l)4fzMhcaT1AdW8#j80Lu!!EHY=LFdK_o*czV&s?=V>7i?7(fLOX>YGdn4>z zRVdeGAgWN2^9~A;_%rNkkvI|9QB}22R%TD+trYx=bGRV&?7OMBmHX_LFEt|FAA|R7 z2OZnca#xm3VdYa43A_SQ)*{1vFY3l~Zgl!gDfOe%qBP_M()09*z=^-apSFwcBQxw< z=uh8L8|M2H^Q-y()-S&Vh2RVtO7 z*ZfAlGVxtR6@Tt|m~!ffYKWFjMzuusB(8ofCUNPjASx>}*qls7Mee}xL~YqX_F8Y# zH?Q1~=l}(tbEm#_%Udbz#~(FZu_RfpyxZW~ab)X1-+C)^@>cR)GT^KlqEQ-J>PolB zlaq038m!{u(~_}*)ugRTU8Oq{A8-0SU5(e(ovCu1iM?VG8KR5#d8=}Zsfd;K*Dvu2 z@fz8E)-2D~n>s4D6sI;WTWWS+<#ShM@okSVs*-E2-&yogGrocf?jqvGssgPQ{- zurLSC4#HZq4LB=B^)4I3EmCk6g+*h8y-e88ETYTX#>uKHfqv7gJeH!&Xl{%~QssZfTsneZ5Q$2I&ui?4B5od6JM}~ zVHfblx_^KBBi~Lb$~2JZoa%rwyHs}lmtS!5FSnR%j-=F*ER!j-C@HmckqNr9M%Hm! z*(sEOtdAxns94y59o8zxQ4b>TAkREc!%sGl*6WeeLRL>Equ#=-*gxBH55$J<2Y-2e zWq4;~-TgTH;$EDC7vao3o4*J>Hxf(Q%RleFcA)s?fBM%Q*Xm@B7SH0y z;i{ghRL}=H968B#%C#W>4Mcv-F%_H*>?{Gb{}@(gI+PFx z!jHoRgIIk15hQ0g1Ok+vf>3_${WH2Z&%7@=40&bGd~5rC^^Et*`|4%aM+(Sk68r|} z>@AozySYyo1#=gAfOUgaJ%XpXW%BEx=5DbDeT=8suhE(Vqz3wPoIk`qgbz@TQd}CW zfG{qTy`f;=z{qjtbo2y8bhd?j%h}(iu*rjGf0N24;ka)_^xpz4U}Yqay@Pc^l(If* zFsOCM@OKZ(_y7uuUP52pV)4m?)1qZfMze((@7vv1*tY+d`)g+oZ(DNJ&5^vE$(!zQ zZ~5@#!KxcdZ@TyJy4|lefb};<@|ZU$?c^x!BQiA~L;*^i1QbGDeAuDLArITLbMThF z>qY7{+kpDcn_1_D)Q_y&{qsi9KtImstgLl`22Ly3(?kPrUP1$B&)%29uJ@k3FO^-# z?EY3Hfofn8GtIsu%Y`|+$YqL)S0pCILrO`Gw^|KP@Nzj1BUlZi%kO4?6PLeY%>BKt-fOOkbmB*rm6xya zm!BuTBb_&30$MqbH&j%tw`T>*@m$tf)Qf{(mBwaB8^Bm$QME7|lds#wrt znXo|-AEQ>3=fLvEKre`n37_miqs6dd>h}J+fui)HFqYrEKVkW(`X`HQM>!{>r|F5_WA; zt3Bt6>AoU!Qeu_OE!Qfiwq&pLxeGFDddigvB~_KBR!ehEZnMj2PF+!=EnD@qeh07I zb5>qkm6%_XX_jqN#Myh9_ucE#7k9Rp-0L!{`-t~Va3=Po{1JMlx8%pX5^*w&*kjC% zk3y(a{R49YINsNhjDBCZuCz`%4+i5!AFN?pPKLsU%hU{eGNg}u(lLX5cR8~k;!Jz@ zGIvJS;x&;U5<7U7i{ltMY=ThXqp7L!u=klgtcZ_S7@lBmL>lHMlmsQi?3U(hViMvq zSw85T(K>C`Nk#vcW!a%<425o zXaAP!hpc*#c9t`7Ngyo`b93=efV1zoR2q#uL7~vg69_K~5LOSRoQNy(LSrO3+D4A! z*bKxXE2C#!8TM@4lEK@2Cw4#mcYE%L(-e0)+cvJK-LSk+c17#9UeT*k|I7Rwk0tBBUYCuC1hWqcj+P-2M@N$+&2sJr2* zr>MIS|1)GLq{MEC3|@y17$Ps)aGoLZRxU2*Ow66@kFGx@j)93iPy5b23ganP%lRjv z0~K^2gKoqw>!c&9;!7fIgPk}CN*2e=n+FW|sNtR~po3Q9-SXAz*GGg68wlkWf%3IL zS%wz5R4hm$lW~|i4&=Bw2?$L`bdzErr%Wdz{ky}HxRfw??pdI-1x6g zluCt04J!zYV?2!T0+yDY7fwUrOlCZd!lvC!AUT;a=z*@@2lBYrj=j9hkS=j z=2~9Z;>_V?vicQ;&6U}*4gJ@2n*d{!b-eWvM*d!qcA4hERL%1?ssasisKdPo|fd4IE`wl zt3SW5sgpCkWX&)rBLBqPnOe3Yw`rADTatqfm3cp}CKh~%*=aK+1IGFFK>j^$w-SmtpWy2$TZfbr12>6-x}3Sj~(Y)-b! zVsSdTm60D5Z7O;+>`SRRA%7&Y`jb!b4)&Jn9!#XQUYz03tRTY$P;nhYH>oB1@I zPC$zu$G1brnaqtYEp}+@w4GX3tCbsOlb&F%M7dOxR|AQwh$gA^ZlOoEPL`IEXVngR zmmY0k>U=~eCd8oBm+dv1~Qwe6L`8cX3+eT}C! zQQg^oW&avES5REuU&*|@IyuX%5}eJs{Tni?DlF!3d}6Y*dvRn8CstS53hj1~tc`h= zac$JDgRX>JrKVs3!l4l`2T#e#D02MQRC~H=B4CDe)XrQ3st&AS4 zs-g?BGVxFyYl})G7au{3hoBhTm$2Nky(zsRx#F4~+1nGcTs2FC#cg@=?^qVqr8YNI zs)eM63}M+42m9yMJ67c?m6$#EMC60(?284pebq$!#1%OW0~Pz#ys5McxZecha#&W2 z(vTgs9kt^ul?q$QxBj!TU|%pxevc3aMqOv`v|nLo?RHttV=y9S=E_5|SkP+BxmYvnTZ88%p@?5HjIB zFAa&fK$hm6OP)~6G0qvv4`6kAW*T;~)R#)B`Bl-4se`;Uq7QPb#Kn&|gf=#|*jA8(NduK&WoxTsGc%fEU+EW?%5dTz2O{wl(0@(gn!?u#NxYi}E<-G$D z7g*g|@S*2Hngo=AvdQ;VZby2Qgl~UTW|{@#y7Ex!EQ-1cc*%QoGK(#^i8>ACbEkuA z8K$rLiiSnS8*c2I*dM4+pQCg_?G&*(p5tx zb*+`%BfyIpzs9}>yqHinYWN8rN+~U!;x=v)F;*WTF((Z z?FZj~2Y87?S;vta?2S0p?S~K>_c-(}2M^yt7wu7ND>GOs_2l&>Y$Nwy->4bc8n>HY z+#71VR#p-5_ie3+h#IY%Q`EZ9mQrF@X`u$9tSy9sKBKm??qX;62mS9rqCUaGRj$ej3_(0n>tk* zdt4HIySe7vpLMX>Ic&y%Fhs7vUgqUq{J+LGM0`Zjl|cO^xf({a-eu6Kv}$c!oLXaH zS@=w&Lo%{)GcjKSPuWI(pLZ^5(ye)!vI@j%eKbqBDb&dmu$_a*QS?eo3@QeJpEL*2&cT=Y47Sd6Aj^WFFQ;|g{^Wfn&Vqp zxq?@W>nxRZZH3)l)lOx$y{LP6F>k+;i_{K6R%E0N}bLSA1_xE!y`)CNevH}fXIv;rP4xGVav&(nqd{ulLH$S`Avha zDTlh?-~)x*ZK_W^RodJddy-6+?7shd-zfd0vF=})j>tqG?umTqF50qlH+dp=62HZ9 z(0?j;VL}2n8T2NTUYV4ftTZJg>5oJA8XC{8p@E^QD*6ce4n2nhxo6F_0-E-BbwPBzplfTC3XP5bJ?#^VGAj`&QROT?Pk?otBuiGA4 zy#06NOY-~0gk_Mz_ys0aN?w}wvIa;Y_Eq*(&dq%wGs`BV^w|HTBwqsQ9!0+5`-<-? z2b52!HbVN8ujPNGUar1ZvlP-jaf{=Aq)pZa;(16n#=rCbFX`<6>FJvnrGHFFxhQo= zX=Yw}eJ<%Uq!f_SJO5tEkQ+;*e^a`{aMJL);k{@wc0*bR>EPw`UoJfb>68E9^lv6) zQhjAAG!2+;`YY1Im(wNEAOBmYFU(h6kPbom%u;CyOX(h(o=fB)^(Wq+c)yjgZnEyP z{!C0s=yJN8E~m@sa{3>T#$)MZa+#DKOnxv$krIG(SWKygR8Q&;XnNy6JEbN6O{q1O z_R;ifF{NjvPh3uy)8%wIT~3$N+Y*P_b!v*fQ) zaw-exTt3l7xgUSqMk)u)U$|-dKPg}&mu1BS;R#>i@2y~5f}9=;-a2K zT-5V}NI<2i7}8?EI*=cEQ3wUmB;;WfhPnp8LTG|Q57hV(InrAMpVXre zpxy`NR=5gL%H#ApEYS>5dO^4zrCbOg5ozfK+T+kBOxt)VmjarWTKVX`0<<6$iTo4v z?-I^&7oge@IVYd`C|&Z)+@h3o`tSlx59Qel_Ymsj9#XfJ_9JpesCX#vgbP2=AoX^* z8iT9Nw4P{eh~6RJ{$AC~I8k(dO$UPx?Jwfjnis_KZ-7U#OMpGQIt&-k)DV-sxnWmKH^f*K{IYBLA zhW1W$N7{*ZdT1LT7-*F0FFc(B0Tu0Cr?RZDta5y-V~)O zNV*xB*LO&gHxR1}P=E4K?TrDICA4qR!$&D^b~=W{6T`7l6>aRoQQ1zZ1SJ~LHsmwW z(gRZ5*(!Mr;ci0WJgQGmjH5wm{6&35ZHoB6M~W?D0K+jans32l)N3}!?w-@FSF)Bt z$%Ch;e+|%ck)BeJ={U9CDtu!jk#55R<1DE1^khYy4(Wa&NK{&oRPFG7-cwwAv zpN6a~H}@J{RL>F5HzztyA=^p|9jB za1rIdTt{=%=OVQjRYmLZUNA#lEc=|jUdY${NJu0RWeL;%qE=7ni?WI{Y=Fiu&sRz+ z>e+LFPNOkrp$`zP63d&CW@{f^Z+Rt~3eq{k2mMX_KSt=^%P;19!a=zqJ}^aRh$1>x z6KLCmLTPdFVxhzD4FxBI!(pKz7@7!%JYjz@P$blkjR{@;k5l0Qt(d-9{;#+NEi-=gsDlN;138Bq2Nf!Gd}JQj0nEKR(~iM821I>c28hP2!=;} zA;Iepd8fuF!=8ZGHz`a*l~3>pC=K;#EAZ>710Q$bb z5D=n01p~sQH{|odkakY^0^Oh?Vc6#hPl2Q`Y~Hb{As=WpFhcJRLB9cl1*XP*Af1E7@o;d&xB9p(?bXig8aZ2(NxIm z0c#oag~g^mGVBuuXN0Yu&PtDc?+8yyj{~^K@ z44QA;6WT0L@#b9)U)q(3ZxCkJ1pGvOtHYkKkMimO0+L?@rvhOZ=*gn?DQ~W4G7qdt zXbJ`4({OmA+Toatg00SPH@`efP)1!Xx=)8OVF{_~i6mta7{Y1zQ z4ZP3_{Juzt_8km>edhY}1Rspn(0o#XXyZ$AM4MBi22%y~ctwYb^-lFF(Gra?*AKmf zed9#+AwTpA4jUK?dggZuJbOe=iRDB`AUGACm;$%&yc4ekoc!=7i@R_a;H&X!z`OApzR2iu!5@q=;WLLtGFtFOSmNfYq%PKbzB|5dafQ|1J?j>IR_TPHF01YTnh(Q!L@N< z4_pTamcXszRsmeitp>P;gK_72xn6*MTpz#zZUEp0ZUY@hkWtAgK}Mxq2{J0-A3$CS zBdgRXH2}3rEkK=82T-rn12if@YNc5TQY#acAhj|{nFKIJnF3Hyg6zs7CCJEYc%Z;* zd7!}Sc%Z=Rc|En0I>|y9$uf9!BYpz0-kH!CGLD3Nn^EbQCmcX7_yn)+S|%VPBHtos z=<`ew!$?UjOT1!`3YihxvT|iJ61qA&1eD+1)h3{F>2u zsE5Ka3U^UBOX0&5o}loZ@y+9#(WexCK_KQR)KZv8VJ3xk`ka->NcxpQKMJ_!|BKWT zov4Wp{st@#rJyWi2R$!Ejj(&_M(bd`O4g}6B)=aOOUq|snfSU`CiRGAaNME4BNo@&U*XOXcAO*AD}&-B3Oz<)j||eJt`4yT1qWx_RXwRNt?#Dw{k{7D-$-kQDIB9PMB%o1 z_)ZG1qwppPKL9jurTDig{4Ry}QuqLc4^w!U!pA6l3i|z1M=OOZDeM9GMaQ~mO$+K6 z1Sszq1*qu=(7P&okG1GK!o5$lBzA1?-3Rb$3JIRpu^Xf#GM;G3>bRN8*i7$grZo3b zIC~L3OZ&Qu_H`e?{Emb4E;sa**zpKZF77x==^v-``+Hx6yPkoTl^rio3NKUmdJO-f z!o6jZP9soQ7ZI-$@N#_SzmH~W4)PM7z+-$8rdMaI#6W0VJKA;$pULu)RE z`=Tuu;CDn}OTPO6;IFhl5AeK1K}3r1Ach!95&3i9 zpQ^F=9)X7ucsw2tLJT#A8nuS1F~(YJ4Kcwrd2uBr05-uo=Vfn&%;4okcFr8ZjT~WxfWq;u)@N=xO-H~5gm3-^HD2c0%>4uW$S*lNvqM}A{rTiN;i&4njPW?SJI z%LmrwoiDrq$xD5#{eZ40yuy|g$-SJaqR{L1pcgd$MFW`A2P=xAK*zE@MX;(UnXsZL z6?6tl9XyXkhL(dy2eP>|&bZYIhOERiZ1c$kWXcJ1B_5(RE+Z6l*22 z{0x&5)Dfk-sqSpcC%f|x7R|GKhUtZ{VKL#sqGi^+cVpFXDMi=(!$tLFtId1ML%z#cmwILEN%)K`7w~3RJ=9lr=IQzR$SjTig#b%Nv-`3JDs&dVQ(^9&)19h z_U;9G@qykLt{1mpG>$?WMIIWr4w^Ni__Q?w>+(~I&s)CNL3Afa{$h$b-YGs2tn$wA z>A~vz8hjDpL_SqC^QUmdLL-OFYM*JJ19(z(G#?>t{luo1iMUT`*( zhCJS7d=soax|?Xfx%0x#1*p4#b#hx&S^=yw_t4-r?4&drKJ!df7Zl!wK8kqW#lD%4 ztfrNi;xo@zYl3UAt9F29Yu5*N0!_LuuiIyyz8Zsjs8+3YvSO>2^1S#~KxZB3HP*az z13PH65f6PF2@M~e$GppY+h~oLyHBH!PG#PezCFQx-g@7@U}z?S|e>g%^SciNjH`#djfi*xdWPTYMA=z1w|Pg00?NtE%93Mu!HC#SRUYL zR#F)}fI*ZcS^RH=Oyyqxh31J zy^Q03XmBpDjwE+c@8*^?1NWOdEa~TcmPhQ6xwi)Q6oi#f6e<{4atxXe5huE&-P&Qh zfgOxwCu`nm>c8Gfk$Ec1fF-A_lUO&=XL%wib-_&!KZsi+_Gu6Y=SUT#)NuQf@04?_bUy=wC(l zG;)iKyvqE1?#21)I{MeKfBMPW3w-_!<;hG3BMO54rt(xO-3pnlIFZWb89Z*+5&FqC zKI;}t^zSHJRWRAV8`}1gZBzXe{|jpT6#0ohTAo3@I9~1mjv?$ozfME{d0;2@_vG@7 zf;s-~a<_%^OGUXCbWy>gQr(={@<4uVX$03QjU@d`N@GCB11a(sEH6y~oqm1AF_u@- zI?5=Y#K?16Y6PbjtSTK{JJ*-)gKY~l;0d+tEt<^}9BrPl0pFT(ji!M+0XGI|3KW8+z{tuP~n?TgDBm z!@TdafrdW^y2>|koB?MH&<%_=v25LV-Ji=eMdOU|5rH0FFM+7*9FDi34_m9laeWQa zNUlRPUOzsvObxC_O#XA+W}=YAU_7%Dcv@vXr;@EFRQzm8!&508&!a-{Bq|iop!(tI zQy88*g-Zb`AR_QgslU>!vC`A2C-3mSA1XmNc@x7 zCEgWV#CzhLXcfPeLd84sBl08SvfL)05Le_g@>$U%UzGnKN%Cd+vZN`JqDZ>ZPl=HF zDT9?EQhy~uNsMQCi(xd7R z)m_q5_2=q-sYX4Z9+GCOzfuoNPpU`Mx1=wtZ>wjdr_|r77o~5iotluor72p3v|bym z#Ys(Cyp||!)rM)Q(spfxmL>f}vuh6N=h|p(wDhVrR=ZEyujOk+Qj1oil}N2xKnqH5 zYL!~0bX=>_rbusV)3j;QDea5et1Xi*YRk2i(k1O%TAg%R ztJmtKtJ-(87o{GpL2HmTtx*oVb9CI6O!mp3P zO}$;tts*yF|1+P97%) z^UR2te$VuKMhv0;wTd?MGLoN9xSPc!ce8uH`;hyH`xvEm_bK;T_eFP?yT_w?!aM^# z(UjvnNuJ^EQ=T+WmdE88OF7pw-sAHGJrg~XJySh3o;jZRo<*J|p5>lZ#G6Rvt3B&H z8z?n-w&J>jy|X**KcJp|tLv5-*BaT4@c!Nh@umaEX`2zlzU_S164U&0?>(SL~ydBMwj+ zC*Be#gqzmkyCR=f;(Nj?I>jYXAi5|`kZ8$?LjFA*QH0SfCSQ_-PgitBlx0Dudb}PlD)oEx6!D-wS|1}G(#Ps!DHcey=67Ny41T)h zUP5^};yz0G zfcv<+!+qL)-rec$_6YiHC67)y!V_sGq9ZMSq(}F}c;fj9rgC2SBc6+gS)&}J6iZ{h zMtn;A3#Dv|eaERkXDQkFH^7BM&(Jf3Q@87O;nH*UT$%$ZA}%7C|KEaUC0t1E71T37 zO0|6Ow6Bl6AUiaw(JX7V3a|C88I^dbBY)BQ>G z-l+30>F3Ao)6MMo-|6h&O->co5`QMHGznO3TCH<=WAN2cgH7+;P`%!D{ z!~EovuHBD{b00QOAEzH5CHHaK`|tX6Gr5n7p&z#opS0fJGyg5@_)B$u*n0Y;ZQl5~ z@?*&SPy71U9>c$dowxF>{C_0#U51*hrsFQ-)^{lXc;BHkh)o}SyI>p=dB!2*h;htl zH%?JHmbHZNEai(?OR}1bE-K^PV^_19vW{jQwX60pyGlGt#Gzy#Xphe7w8z<#?8BM1 zr`fXzUG}lW$)!AyN~5#aWanj9*vA8X#HU0wrR$ombNHKru(9M_1FU=4GTg&fP>RF< zy$%&$qLhHUTAO%_?q^-1jnXL5DgGcvi$7AjSMHSmAjXmx$s$KdRFZ_7d}f5m#alin z_8Eank(9mJs5B;VW{NUjC-q5FsH`$$f-$4FY&PY2#GgTl%csEV&ym%G1peS#=t9R| z6o=w&JdFREl#)ulx=m=}c4|F@WMf1>F^*Dy{6F>p>eEwVpm7SWb0Th;NF)VwHG73=uyQducpcC?!zeFVT2Nx~hkL(7)^ra#!|-?56Ck**mg# zXYb8EkljMpquIx^JF-t_pU>{h?ly#>8xcmN5o5$>cNoKrNRrv`r^%=_hLH{=V=3v{ z0eydxj1{Dvl2J$XJN~S64b?Tqtf;S@9>y*lcVgyL6-oq@BhdV;|+1KT8LD z^&B=6wT@(@80m!RhGC2{a*RA_wzAKpHCTlW30D(@5^lK5m}^A8N7Bu+O&7voACb+ZWUP zu_v{RePfU=L6Gg(wr$(Cb;q`C+xo`lotZnfZS#(8+rBe9yRjQ@-;WpZepGawtjz2a zQ61G?U6qxq>1!J1j3fa#=C!T0&77;8{R9m75Q^OPJ0e!tvZjP}4y`vNdVaRyly#7E zbQ{^yJN_TUAIP$!MjiGgcLKJ8BVTrkEv?CMrI%OFjn6U93_gIP3-#Z#Y@pBX5i-|j3m53BHw?%rC#Mybrt?$z=4-g1T3Ydc?Br|&~ zW*{b&Ne~SQq*b{n)=#)8e!{?CVe#1Gx#QpB#pB5r2b@P~=IgS$x9a0Z3c{-0Z3~c3 zo!R;yXz~7DBF0xg6G$er!|+mFxnJ%ob`e;9m6tYARK#V*cgKSsx{Tj;ncjCS3KStp z=d>TvcC_o4ne)bp@_Z1)jRBE{um7B0;k5Zz_|Zz{%eCvYKQ9#?^upGoO>ZRJn;Ze{H}1KXD;(#>Ok!%XZMkpHb-s7`owkA>O<>9PR1n{ z_VOWTut6uMd8Q=%TGuGwSd8bwb126q=c2s(C(G}p!U@NT!U=)3UH(Hs;z_I%fxGK3 z-s)%S8U7iL^KJz{U8tz!8P>zuQR(yG2NWLxuXXDabkZ;hE6z8|80DiRy}}yc8Y+z{ zzr0C_e|p1-u_WfDw3#Y2;$`h?_%(3pKg((C;dB*a`r>!w5w1;G5XOq^UdQ_Jd=g=k zSN9#!4T>gk6?(uLC8BQf&hk#vj??bbq`Fd@!!>4)R^)dVdN$PTZ5-__Z7rSd?OFJ; zx*t(4k;h{rHmiB(Jo`Ms-Bc&bZDv4b8qwaF;P-PGn`BbZ5Hz5xCy+}?X2xA=AWena|LsS^}r@zU5BAQ zWY7hSUnJOHJNQST^YPzW73eYJl4+48t`b@jrLcNcXge5tt{vKX$ZN;ny{bHpAb(0O`DpoNll^DTA}9jJ-&dWo&CdCJL^V#G`#%u zeqxrQq3wN9eW87^F64!JM4!_7YuoHDyZXX^B7%yrzGjrF^_PHIYJQ3D-}g=NcF9Pk zr;z(OrU}pw-6HByKPbU73TICJWP25X9B1u(8w@kdqxuvVYC!2_qX1;}EGo6)AHJoo zhUr4~loL&_FUqMH`!U(7uAF+r7gaNnXl_>}CaH@GbsFUkB1`w1Uv!q)U zM4Bk~EJy$QWvQxBrAWFS?{C5{D-m6kqrSug4%^cJ2CoFqL5ne?IDsB zCxlg%1X@%|as}y}L@r(@0zJ%mH>drEq132J+v=#N_phPmD0uaCv2w=lVVMooR-2;7 zf5cA2PEnoqQqw8Vzj#tShg#_GG>v)h%ZD2OL6GSeFQ%?0dooMQ!^q-fpxIR_L>IlH zeH7kV<)G)Q4pGA2NlW^|2>Zf_`<_R5e2eK1eMhnVt8G6GVDdEE2(^on1kmQF}b^^QmpgzzdL&kN#s31{AFF@inNNegAu^;CHD#5p)Zn|Swl7k zT}ZZ&#zgd`B4R0`Dq4YwFz!*&&d9 z%RWmzJ!}nP!pN}NvnKlfvqdx)!uF-tZJdHI-y@AxF=MpYBZ^fcpqO_{L7I!d0%Twc z?;WuJty~@0aueuJ@F+3hquJ;h&lmqj!P8HiB5Ct2M|F2InAjEV{^kL>V}>AI1JaA| z_^Yn}kPc`xr9NZ<>XU=Zr0~suZcmJ|Oc0VE>XA_xF|Y+~k;X{uCQrkF^s{87m--cI z;T~2Fl``p+GHCDIX^{trpQ0NI$1pn!yo#a=kZ7te8o*4!2NGHf%zx^`oKADocMQLq z;g>UfrET(s_E;5^SC2*bYr`cJaQ8Z=yBO36?zUDjD%1<~ZYObOW`}xw;kL^wl>C4} znwzAV_rwSBlP=Jp(OmXxWmibW2QP=}x@fINAn%qud07Ey2WSTYHuE7c?4}3}3k4>7 zr9P~0DnaU++V(5&i(Co;{43nC)IHv(|B6OAVI1yFKpPvbD$Ep1f)uV~Ht2z^Nv$76 zv!>oO*6bubXtn_Dp==s>K7%%O)1xGb9G!4Q4Wog4f^ROafN%gyAW&JR?l2vgb!`1@ zIpY)KJt!fdAMY)JzmK6s=|b`zSH5zw`ZN*pp$*%2tg>l81!t8N(&RqUA03Y%&e&e> zy`Eg!FOlN>rARODpG$(5;GwW*1NYbMNP=h66WHm7SEwkPBLXr5TqcBF9k6;Br~%7~ z><6-pOVGuhmF>4q8l;GXU*<`SRaP_VDYX^@`{0+H9kZ!nqdN?NCkX8fUPP_viNoAA z&mwuR$~_Z^GM`PTuJ>}*G|Qqka1Qt->mFE{8t3OfcP+|!*ROw0`R8w>4e@Ls~#9mo^=G>y@~@BBW5 zU8i55=OaPeP`>c@VY{;s@etqe679);im7|waTxy)98nVjpqmp(W8c*@{V~aQ!VZc4 z;f9L#uYq(~?okk}Tp3~y+YTEd5W95rX+=M^p*GiOzW!L<(i4d@ErCl9aURJp${%|E zHV>Q$oF)|t7$5Km%nsbFS?e6-+Ao)_YX3m{n-B7BZ|RTtC{%#W*&z&QxW(V4xLs?p zkDW?)ix#(LH^uAQJ3UZbYgHQ_;0%nLIytRKGhw(MisnMJU7)(QB0kmN;lfnn9Q@B# zp(It%-IL&Wk!s)9`O2SARExGpgwr?7U0ltOZ#djM;8Ma`dAC>z(ki+m%Yv?0ZG=Bd zyj&HPvPiA$uX*JzRCI`-`~=<#ptYKhxI!&1;HIwIu&RVz*GwCKy!!zmpK3(=rT4Ig zppp>m01x;l;-)Vgl99@?CB%a{#BNV?QZ3lr=3T_FDbYR=*vx=zb`XmD$o9V%BMBnU zD!byZ+gjV%s+rv9K3$^a{)s;=_X<={OKGmFHG1@UA9O6qkzqpAC$; zMyjN{Zbo(OY5@owf(QtcIY9rgx6i0>_}~c*XF3yX1E+ABe4sxQyAUf-g)D#?y{f2S z==Yak-ts|q2H)L;j%m9zDvCU7RdJDVv+GG_fCGRtZ~BroOyC6LI>2v(&I(RKwj-a+ zgq+D7!PG~==U9ojHT=LE`yPc_)V;Qnd|@kZ=&Ptd_ZuWE_}H;aK)RJOimF6%5`*F_ z>mxi&?U0IaX0n?1zkN{5FC$|jTHpzu{M@s zcccf+`6t@F+Cw#s#ox0T8ZcoYIW4m{|{a}@J zd#I^iypzsb27iz&zr3RNjaJeSIbo^lFZ8`Hh3a!D-V>__zA)xAO$$bpF2SblCcLBr z?d?TR-yTJH6;Ov?!4K~EhThPw^C&K;e)45e?s3R_fAtmdJ7o4vP^3VMX}hKn$SeaG zgAp7(Kzki8L^93RD^ztV&jsMQ;=SSqX*?D75#D>R82p}JOTdQD30KpF8V`s#^0?=Y zQ2)14_h~2Q5D($yi=pBlmZ%yC;>TV5zBY($b(IWp#S#1YKotk35Aj9oNP7!*ybpfe z>`r-10(amQ|8_2lwKRJVEhA1>QZ~uM7|da!-0^Hh04cSN_=)x{!cje1TA0s$z(kQQ zJX)~j5wrvG1@dXTt9q&k`V~8CXo~nCJGam4OYlpke;nBRHMUqm;>_bOjDqC^f1knmCfmv*IWqmFXFm~m0dXS69mWS;1GZ6(p8!#=((+3jdEd2Ltj<)Kv5{# zJDbzyIaaj$-oeag58t0~UhONEnd45uC*WttB#RllgaG_klS#t1YoFau7#7f=d{CGI zm|hl*Wlkm*maY=qqCN0!$QeeV9SFGFadr5mXs8vEc>Y-R8W9U@lB)-ye01`%(g~>t zg>#%8+PIz;B(|B66@MUKR8PcP^4&=x0cFGv3ZVc{PlUEiWjL@cAnad=3R^4N$7%s~ zl&9Z;rg%Hqy1cLmJK_QmaFFKDVvbgTxU9L^JbY_svC#W(%FBy7<~x!c|q(!wSJsefuT{WnIc`>Qm=@ZKm3 z^VXIb;65xq3SSnJm&#qP}BSmTgY>Ix>lBFqL=SJecYI!|T3 zH{o7ZEtYwSR>`Ymt%W^Wt244o15__?A!+aDoOfX74f-{P*|__ zTT8;)LR;U)$#Y6W^bdqvQILRTaw@4UDA_~cMG$r0(VPKdN)WZKti6%80Q3x&WpW`s ztY%yXhao+k6EN!$+cPA#z-+IHB3qAaqGufDfp(u^Ud&aE4&vWmWO;AtMpTSJVyV z(S0rvW}^$BtPLDccC3=L6R&mr7TqV;UaMz5iy1i>t3r9IAv79jZ>pMRP;{pZ8PpgZ z04gN_u|CZ96n!)r>_TwAAxs$}08$0155`gGN^K1f)Lj|zuMz$cuK>3VgDXmTxD)a4 zYz`@?gSIWLD}@yCDeY~^T#vx6!3a&qer@W;Y<1R2aojisZtO%@k>;?LD9!!3YrF`i zqdh`#>!F}`C=53`uM8IB{ANCP^P5Nzq=+ ztC@bNPOZicuue_Pn}J21SqJis0{g%t$~|;;K4TTcQ_EfV0z{T^euL3h)_?q(yuhzS zbiUDcX%L##`Gc{W5WU^-1R4D&qKkH5f(V{)jV*|*^Y+@o^;tl+n?CFPPq-@yix3%-^h_RM$KFXsO)SoCt1?FPvF^tf}wo_kou%og-3S1>C?xy0GUA zN;E$$nj+_b8)GezuLEICKFBn$o+p%o7;yj?VW--d^6mvyce>R-y8Qjeo8X;D3tGy) zy%YNv$If}~2OrPvkFrNjp>4IcavQ@w)<0!IS1i2E*{Qcb(bK!WhTK~`t!JR6^6OuB^e%SDAd#cw$Y<(Z28 zj(^~>;T0(N{Eioxzw9HJz$^=zQb*(R9p<4{etW#_?p{k901JG0wQ-Yvc1Ju?1O$k% zU4whdS>{Zi;AlAFjC$TjWnE)#1M_2Rg3e$Yf^sPWz4;%?H!d$(1PTJT0JS=mm!F(Z z_K6BT*JIXR1O20Lq!a`$^no|(d6CJ&uJ|7JsXgB7){yVM>2}_QS5x*}`D=*GNHU~H zA|8vDkD8DE67?Y-MTLnNB{{@)M}8Oj8ci-=L}@G*e9D+KTxvyrG&eDUiW-`)uAf?l zu`n#htU-6`7od*zb>kOV7X`d;pGdKplr)|@T&(mE)f zH3q?m(;JE@*>R258sjqrWdv1v8|fn+M1^6tFWeQ9x3lzacE?`1*o()cC5O G}665mid?_4&9agT{ow1(yLc1rooHsY_#DfT;-v2Sgi` zOyK_-!#;twi)TphNbZR5$m+Oqcn0tnUPI&q;{)O2@ES2OP+boy4YUZt4ASc(kWj16 zdwYvmVlpKAnW2Np0he0viG(3h4qp5p@(W|^E=Yl z0k=W7fw$!{>1=@8LR>=)=3xt6l>Hq~2b) zeG{->@VgXxK5QDCB)?sEC|&5ehu8;$3Q$aVdTdel-fswiZ&O8V^uY$Io$dLLs(cnuu zLN)SothO#8J^Sr7xyyHv7~R8NiX3@7BE>ePVJx6&UazEeg2e19-t{Oe{=+qqgdWzN z`7%E*|9G#%xEyt2G7SHY=dJ6|X<==0 zGNg-d;>Hdw$_)uzKcQvztrT*XS%9cHYF+LV5DoMjrkrE|y0M>cARPo+7MeLmGt2Cb z3lSK?rkau=&P&ZJ~ zqz){Vu7X3*Qb&mRT}ur^CLUGndX__CBrnrQT(aiQAU_aayqb&#nIv+cO}(2|GkXpi zeI&z1lw<~9Uwqe$oM>B`GvYf__XW#V~iPkcl zET!*Oh*X*yIlD3?`(HA4;nf-L?}>tBLR~T=2BZGez(fl%esTUgKdRUUhGj^t&iD)MgnZ!SqdVe&7!ao*!e^gWG6ALzq&?N1ZIgQ9aR(uFhPj+WQC;o{giz+z6 z@&oC9pd_7Go@OM-ok^9{Cl)QT;K;-fzzOrmI_#BMo!mcmDU#5{t)V&<;zvXJ6U*jD zWBtbz;RnioVqN^e_a6v+XJY$fkNX2he(W{&M^{5%nXe^2u{5Xe7NdxBM`!{%OVifj>N3Nd054ejwxzOnhZ_|7p#QB0R|Zamn~2`k{0! z|B3ZN>>sNa_4SVOul?tK*FU%aaeVnh?&Zh4JCg9=>qo?SXTlfw%1rRX3h~E{-;cQe zN6hGTvI2Nze*R$v`XdtBAN7RtYV@IM3D?3phx^G6@G1qa^(qDGa+ip3d_Wp<3Ce-1 z8hmAlPzD*{IDzdu1v#Cuff?BOItHxR&srDS)tM)|t!E&ytv5@0Q^QDkQ*)B+v7(Xi zQ<8p4;!pX(D?b=^7o`oqDvZ|%oeRoiaI1hoebCww>N@13-$)bIre9eT@uHu36$rP_ z$rC0IgmRa@7zzif)>nvP49r)|eGK7eKCWzVi|s{(C?}~u1}kzH<4Y_eUk0sm3daL# z<%*CS0%t8uuN25o0IL+qP$-)qt}%yB6{M|9i&n_72ti&>x`<3Aj$afnY;_Li1~Q=( zr%IYqqM%$_fajL=b9z8|XZ+z6RPwR0NPKY1#OMwsW^Pk0qdSE{_K zCHl&>1vpRP-k?k6fJMnNVZT2DqVhN%$x1PQEMcq{;HHJ}wWVMS8R*4jh55C^(}Lcc z@aQ4oEzPvCapq~7VAy^yS+ZNoUCi;+(N;@d2&1k?as+Q#qOOCvm)-%(pAonsT1x25 zVbnp|iR%cvtcSM*VKm{}K@M+9sLdt0|IRHy-%7rQuC~Hl2VbA_I~ABqyOwY}jMvM5-lw1>f6_9F5UWiFMEi?F4MMn$Ut>vXo zfMAHOCC-(gW}do7q#mXgBv6G@2?5!NQw8y8)~rc?I(lC3J(u5XNN*S@rA-D8D&9b% z#U)0@m=qx@9!(-X6TxRBV&BVyI}rJ9YJg)u%L{~a*Y8JJ1dH@*2n{&;a$WIzGV|Nn zoO0&VT=;w_7;dc0ia7bPHuuwpGWQaUB{4(mut1=pknfC$578CG@9uP&FczrLQ;Y!7 zeD}*uU<|xcn0Xb(9b|JdD7gT{Ao>#<@Deh&89Ru3qA^{Ea50TeqNE<>VO(_9V=zuW> zf<%5kk|jP8A1|G?QPReI$zvdZ96Ugd9xx?Lkmya2D9T3?;UyM-8;SShhCI@iH1d)n zP347<#5qUu5DXv%3XmcNj7bwDQV=9A@R3+}ip|_d<{Thf?ICl|k~#-T9+CjY$O#f@ z`A9Up#I(J{YVKO*M@U_AC66HhQ}P6vI(#gnP$Z>LB-3DtlQ|`hAK{L(^2>))fh2gK zqDEY?VNQ-Pa)Hv05OP6hOrSGCT8;!ch#PZ`QM88|X+`Z0IYv-$z)0~S2SCApks7gb z;0}O6QH@BD2F@IL4EN}`V5Rz0Ga$qqIi|o=m~dx?$#p|k0`Xu(goX5f7T?VH7x4%Cg=j*y6UqLIp&BgncUf=~)5yoEP^L`9npRCB z^%uG-d2`&l!c~F0irONBHD_}~#h+)DkFtM@z!l*YB?u~Rs{C$Jb>d1CV8PD9VF?(Q zNH{QY;A+8oDV2r*!``~e-M|6~B}z8*ENHhml%_{XtO9XM<_Tijc>`aU>CxG4q*>Od zJ2@6ilY|IF)C5HJAbUf2Dj4f}gE)wd!HJd{`2lA$-eQi8I-U5a zp;*^SrG}0-EEfiCP0XF*ROGr)__}b|-jEZR-yK#b{O=9c7Q&FlC{8hSy9b3p?yFDs zt(V;G)=BWN!2!}LT$-=m0VG-Ou%gDuN;-uirQww(ukH@fD<{avv>3W*aVKW*aopSOwh~1ko1t zp&Ooq;4!pXO7Ac4T!77xE$aC)3Jk=0Nvq zN;VLz0wgv;NHkCxnI4&bxPybd(gMgPPp8Nr7BN~AM*iIt;^LL9CCg{JtWl;S83FH1Db75pbgP7F_pn?fPp6z*lqkhl%SOrea_+$i{G$sm5HM- z;cWB~R3et~05-Ngw@65XA`%*eVsl2h05>`Gq;#u&>vteEYfL8iR9knU5MslO(aaS* zI9&$IAGpZ&?!rLwR!+3K{pWCyv3L{oFznZUB&vJ(65bTftX5aBK9!f8Tee60UF!pxZ;1#TtLB~WL!i7 z-y^keqoB+!)@EfPc58UF71)e}E_OlT3ZYv4@Hf{>9BI@0t91}st-&|5QlS)<+w9gwEH;;&oi6SNu4oc= zf5qxdIBmkrFww7Wvx~`&ahBvF@6{DRVX*a!WEBv}(&+>l7E0AAk)&0~)t!pasfB4) z(DaMM85Sy>*9xE4N}rdDpO?#@my4d4%UYL7T9+wWk5%_yjvhn_^x=E%ZBJr?1rs5` zjRZRxl0lLh@D2g9#2LsE#>c`_SW~=_(u203?fi^PokCOeNUX3!T_DV* zLiV-r*Xfa)jF?;)z%+bWG17|tg;A00%3zXdyHwJbQqe?I@^#6?tK%ryNu(U)ikDJB ztBEA__~gdC6GQGDNE^z;85JmUOHhB#!G6IT^Jaavdj7TKS>a*6A-iW*&WPw8W(!0* zjLDkAc136|fIUU&2-a4{bqnQ@$SuGr|Fvj!PPZhNTUw){Sbn0)`xO0?2&`COVYBuW zOIu3zFG~|%wOr+#brV9hB<^1dSC0-zJ7Jx_98LIFLcD+ZtuQ+fx6<89`K=h&vk9a= z=Du8s_)`#mOV0H_Vx<{ltB=XlB~`J}PEIsN|K!OUsHn%O!l)e8jx7H9O7u!3xditS z)i{m%m zoy7MOp~(T)w@pHg>Pc`p?jh9cmkwB#6o?bBJJ6?ygkE^-p1NC2Rr=K+^TM)rxMEt& z!R*65)+C4^5odV zr2?A)$72@4K?ze=@S}OGyoCY6$KTPVi-r+nWHGVhygsbn`rw!HmoY9n$Ue|(sb{cl z*vs2*+RhXwO4%V=dS07}WLYizj$bQGlFdVLbmz~#L@|!HX9cxaOg_(-P~$XmU05oU z*YQn##~$*=hKYBo7KiE&mA}{gZcHZ#H1XNViup*}Eo}iqL5S*CI451}8VgD6s@ewL z4&~+NTl%zvDI*Zfdl$`@{~C8}y|NVJfYc;Z$~-kry)>+)2vcu7UuD5=JFHI+8lFnQY779!G0~F zy25LEeJKC^`tA46>@zIxR}Mn@PI{HWVvoqu^PRq>C%JMDzh~9byIWGJZbpfV3r_C! zdABErZRXnbfIobpqM)w5vpa#ZH73^GI8%p*$-*+O+`ZeRc=z(;usFeMF_R|y@2^4b z)}P=IS4cs)+;+Q4?U3?rWkATDILt$w=^#fJ^x~&{?Ol>{XMk61cIvH3_{4?*g_!h5 zca7h5!0+d61pQdV89KOgkoq{#m#R^_d5x_qI9-{tzu%Z ze(29;!xJaz##hwSjoWhWZN_KQ+QU~^m?Q=KBcfkB3_iANNkB?ip{(Z?c8Ilf?fGK) z3cq#h@z^T?D~q49r{cO$>Dtn*-f2anH9>Zo*F_bNo>^hQP^YBxrJ9-DNm#sd{EAIy zH{Q)AsJ7qN;*!n7HC2Y*t^fB--D2!cFzf>B3ElRWvBP$FBSN;{Ntx^Pb321SymvR> zmrm_th!&s-uQg+%Yul_xo{iSkYW_7i^;dCYOE=egO{YWM!0)GrA`plMsaZ`ka-dG6 zt^5xB=Z)*LTfQMatE}~8>2$ISZP;dR);ysm=4onwJaK!uejOw$;VrTkek@j00n9)j zlKKiDDFf8(Vz?-Nty&memt5~k`wyPSWciSzcJd%!ACQ!F}dIo2aat6S5*Q`l}uNOU?B|<#tLq;6g5<2zW-LHm;vMf~_aM#jJCD0Hw7EDxiST2+| zsBiJR88>rx$jooqd>V9Y;CeUZ#uo)6aBZ6 zvwd#*%ZSN$zPT*K`+dm^9+CDU-hfTOmb|y%k6X%`PiNu!#Gh2|`IS_Tp`Vq9tND#) zU*&xKJeQK%KPPHcNIAI20`#wY4~Q&+B^0)G0;#u?3%tbQ)T+&+Cov2#n63GE^nUio zG1lT|h$f`+$8vg_ddjRPJrgzLkOppRs66NOpYo-Y-lUkevf0i<2Q&9xQ6?*!l~R1B zy<^(rB6r%BCMDiyyQ!!&45vKNlsno#JJU-KvKUMJP<83AS;G^(liwX?`8yWw#CGKW z_E&71ai?R>x=W)xbv8Iz{OM23*Pp`c9po)sUUd@^j-1ydbP|>L;2v)~q!fi9Z>bag zQ}Uqupq}#;ZCFb_*{rz<1^$$aW80~pKRoX5018?4DSqU9Xp1|t`T7MYk2-*+=i^29 zkp6ID^*CWUo$DT&F&-895ZR!+h=PW8Qoz74x>G*>Yv5{0fPrg=%t;*_(;OKCz~^MA zGl~w=0pehD!6Scucb4TtIHPt);q`6DD57KS=^GjvB1Fd`*eNd#-C-vh;P49{hLF=N z<=udo*i^%wYusO3eu%U8-S;wHK>Y9Dw;qzz`H;RyqmGBa4w=PI^yr!rRL(u~JxbG0Z z)<`eX&vY{miW_A^&0OD3@}0Z|`MhIomgd%5W|iV3FF&h8>M@hH=}^hdweWKqJE)iV zU|7l9O0soCiT(Qi!sGAXhRqj>rNQue>ne8dZ(RZ#OfFZoJ~*%gDIhIsRsP=X*S1E= zYxl{la*fmHin{-h#G9A7Rrwqc)PE&b2e`1WYOhDp+f|S2LeBcM$UZLjdRdQ6Man!k%t zfcNeeNCpPJlM0r_TFu_JTAf=wCOFr{l?iR?tIUdA=R75wZLsty{U~y1OuL8?~~eZVl<+^Rcu@mYz)y&}BX{ z`mFmM46dcIyom5RxAd;mr1n-FRiR;=GxfBU6)@@bi6?aC^c06%Gb!NUiR7vB<)Wj) ziCKML@NUD|+M*V2lVhO6TF5HwM_Sxp@o?Ol113F62%nzzFT?jS!GAsOrj7EsNAU*z z!*&9~^k@-{kIuv0jo1HLa6d1U+R2Fc+o0`4RvKE+Sm_y&?h`b);ilrBwNbuK?O>eV z2)>@mfwRSG&V~KF9}6Yk6vNr}ddsAO$C2@c=>v1CuSK|KOC|00Sd|}EA$E#xN&O|q z2K$!DY*<^e%#z77qK~7|Bez9s^-}jsQ#f6Q@AE)a46DhxdoCWazIUS0%96i;Ey^p0&XU_}E%BDcd#1$HXTJPD ze^Th5vjyVXS@v>I0*@`L=^M2Xe$QSpV_&U7OOpDpVXm+d`G(B3Ec)pk(~V{*%E(oB z)Nb3SKV3y-aYty>;=A)2s}KEKvrxA6_y_vDtZ;Y35Y?Qf-u0~Zt#%i_P=CI=ptggW zqFa1e(f`y}Cij&Up)eN}PKJ_LJn8roTj^LtuMlgZ&x}m(zbZ zCioWJQ>5~qt?X2%Vs!wz&gxa!bgX|q443BW)i1QoKQhiC6(2Pn2T6X-c$_$NE@6uE zGiw*UKBsIRakDV8{*kZe?eUdxTF~q#HTOw#d)nwq%&f^2cDXlhxybNhAI50gitfs{ z?($TD+%XkGjg8y`=$w8>ou%gp1sedVg>UA-xEjwACKau(AW{))%jkfC^r<4jYzAJu z{Av`Oy6_iL@(MYmN2L59NHEYvBMD`JJ>bLO&qdMP&HQsl_u-$lXkkp^r^<2gI9*ABbSmOoK51dg zZSQIOa@TuV7zg0cRx_C2@S?jf)@Z5K+ONZ(EUDrAT0WcZZm>xg*&Rp+j~MLM$i~8q z&1Jm!*=)x*e$lrUy`~V-8Ue9|BD`;kLV#SBWs$@^K5i}u65=G88)lc`&+>QQZnVopVh`LLRB z2FBA&Mk!4tH+|`D!M8K1DFxX>K@9`f_k+kT%I@+hzCg8>8+e45zM1C8v?Xo2>tjLh zu1$e3u>p?;f$lQT90Vc=3JGFgm`*E`5D_Ji0SatE7_TQQ@Idr70JZ;-zFAepTu?cB^uf}A)3s=3Am~i!){LZdNy}j&T+T|hf_^3Rcdfm?w`~e{+YLvkHevR)vU0i> z_Pv`sPdU#Y>mz?td-bfhC#a7_G?VV~*+f+BmCp$>H zO55bE(p&XBZqJJX$QmZ(FXH{wd1%|pe;wsozI<(u;_ea4K6FRK`|!Wa&5){VSg7?8!ES z@aa4j=v;INk@Ft-{`kBjgJQF=PPX9Sl45zEM43NorbFKij`xAQf+X- z_IS%|QWQ2Y^L%Vp?>zU_kv%o{GwEKwo$9Ve03vIpR>0`J-R#IPJmC!_0lZKBm8j`& z@%g$y@6rB^@SE*9Z!~JUo{GYc6QA6J1=meUD>(;8!i=^lHIwMA zL=?cOn0&c_4Jlty{$x7X_;sTO?2aV=glnNh7hjIcuGr$&{pW^s;vXN#%Qg##9NzQk zx*Eb<6TUyGe}W|dPS2d%t@twlh;PJLV8$eP7&CiQ7guL9BfI~qIv88S!!WaOvJ){8 z{a2ljk5R(P*450JQNq^9)lAIH#KF{zQO?ZX!qt+9m6Jt403POl>^*b*ROB5(nBck} zXq_(+(4luykyK=Lq6P)nS{9l>!54_*0zvq1Z_-z*uC%QZgCF-_K5b2Sr&}^@CCq!v zYNm`#-AHM{MLkr=>p<~vt)c?el=VXDoK6v{5gng2XbpPP$D4c5zmXD83f;}445o*T zKUoF6Szw(aKIbuH{@ zT==rGdnKC+(XP`HBrQGc9Q<3?esYzhQkFd8?49p_WlUR<<+OI*co(s}KwkXYD*k_U zAjkh#2ePqqF?0NPZ!!}x|NOpU<@mpQ^fCupS8aHI)MBRn!>s+1hy=4X5GFFP>~O#= zLU&b+F&YLYvR%3DFfAoBy4@@@tt2zE{OssAgm!sJ%lff;w?>qCXGu59ulCOXm*aSy z?w9Z0tDTQ;K?L8~8%~$wsm!Y>?g#}G8K}Dv3Gu13Fm5f%9f6jZIbI87lrAD#e$of4 zljZ49-%n!V`^BoRO_7N2YrRn4EJ>*)Uac_ka!Q((0Ab6t%!CTR;N;t`F0{}TT8&*!6XR*!1vjdY4T;SJf_!(p&mfCX@(3R09k;L-Bg)|^sO)l>}(?uVs=l%yKib*MDsRgnoM1ZuI7 zL<$sH8Yrg+^%>cys*2*t$gI;vKsl z&AtKTenawioc7Ux4(gfZ(&FzL{qOj|2Y*C{!Z<*X7hl}DuI;~@_;1J=jR(O=$)cch z9(ssl8=2)0)|E3t=c{d)A6CY@FK8WvQn%g(@0h7Jo$+sm;GNGxXpU|7a!&jnso$V) zYY&@Nj=*jfv!;>-H9l-+UbS@=ofqeg$Y&fYJkJh-7_VRWe(X0qv)9x&-;MtQXg|N< zGEDRXT=DJ0a6xNU444?i`#`({?-*hWXg56Q8TCLmh54AG{N@sgAY8%fS5p13bw5eh z-Do#|2vs}&?@Ju;?0FC8FfTCTi2PYULvwU5ecxm+e;QtBOJ|xy&%c+YuWt#V0I_Yf zl`qDhSDVK?i0*n=_uy6=;9qql-iJZO_WyDCSqix(uJZ+s+#QHzwsVJs{tpXUG%B@B z8kfssKF^gRs+e({*sC}aE!oJF3tRe6Vx}pFmSi3!d~wu>G(TDAA`yFdaoAxf9Mm{0 zHB@~V9IO^<1A{4G%~XL?BfB)CH2WkIGb>#;Os`3$k3s0>&n?z}dXkwGX zEu-R3qk^!aaJ_P>3Li?sRC1f7uF3hS=+n}qWJ}EEoqzXJH9GDc*Nz~i>+WPoA38vK zSN{h9Q$Vc0uC9cuHHQD4I-|&&YK@fNt2Yat#6-M^H}Qe@BmN|S1S;vln5Tr!1^46V zT%^n;_mg?(@%dx{SxD;0BJv4!{QvfPCf2O-kt2qe3>#W(D;iW-ke`=3a6tclx94PMWoD$O zrKVVu`}XPG>$aqxJ-R2xc8Q7Z7!lsV(mpiM*URMTZZzn1T8&yIOO!-sSTak^_J~ru zD#DVT9mC?5G9;8;mr!aqBPsL7Ja%)blFfW$PAhU&-jvhIb6T(Fq$YE3(mN*FoMAEB z52stqjdWA`3^CE9-e80^!r41os_SXTzEm+%$Bf(RC8Bd@r?t!B8D-`6ynI_mdT>}+v64p8 zl(OuaG`m(Q%RH9VnJhBbNAIh9u+cAZrh zEK9zvi6pe1tnX$HZb%^ANHMF2-9HV35|L47E3dSNmIjw&epZ@o!C`i5F}knVVyh@- zqhvAJJDtSo!jv;AN1<&u*G?z*x}NVr-jexAQtHJ+PQ zsFOLPBK^7w-cYF8RY6y2zh6&@^@Z!iI6}vUGh6JE!*S&zO+qnB5*x)pvz_FbZI%j4 zu?2I;nrCBeV|}fRZ@)rIzx<&#Wwc$hWY7&UzQ5sa5u>lmsO{x{(qk zO()VQ8Qm!HG?Pe^kf!2kRwa!Ej8I?|`WI_$hPj-L&8*_8y3%5HWf6ajBYvr!TKW>Z zWa(Q^C5@ZiV5vy88!f3UJ(;B^^K=bM*J4&se~Qjw3sPOF1&b7BlZ^yZJ`ZJ9q`9%R zb&xIWaPZmUFwCh%7mF zJxb8KN>anNXt4F*s-z7`RCZLz&Lik;Lpwpf|VCOgTt+=gN2WvV0CiDHZE zye;v{g^BCH5I&!Y9(5yyHl7lUC{9+)J4x$?nvb?%*XU9+dRs+C7h<0Ch13wtQ!20? zsv;^B48g9Qgf&YJH@X|_`YtFCzswuEu~3@blB-iQ=SPjRr0Ef7Xm83%Z( zmbKgs{VsDoZqH;Fdv}h*^?%=mY8P=0-^ph6+PmhPDdh6sAR(%feg|=2u}Z3iFFF7lip) zn4g6Ci!eV5b6%Kp!u%l2_rjbN<~w1&73LdZz82;yVZIdR3t`R(^SLmmg*hcmvoI%x z`AnEkh51C7KMV6GVLle-BVj%i=7ccEg*hh7QDKe<^MNq$3-g{Z?+WvdFo%VCTbQ?m zc~h7-gn3<<*MvDF%t2ue2=l5iuL!eWn0>B8JC%rs%93Nu-l8e#4dW|A-yg_$7Ccwxo~bB8cv zg{cx|j4+kLR0vZp%xGao2~#FasW2mj86nJYVM>G^*ELiN$sj*bZdmxDRRPlx-}w+ku4by@*${ ztyGJn=iul(Y-@o;OxRjMHISv*j`EbEM(G|$N^5A7G*g=8C=c~aiI!%OWH1THC~p?| z46tKoq2!U$48&(3K2n+vHy!Q=>2B;A5j!Kbnj59dg#fa(%_h)qU0hv zD5kI|xsdKFq-&Mmf|&fGyqMgg>RcL|OV?)8>TJ3%n@-B6)@+&?lTnl&lU9@(lTu`D zlqNd#o|#S3cxjv?J{0kBO1yQSRN0_+%Y1K-RD&v8r8^tqdSqhvosPC)nT?X{XxBaz zPYqnCBcvmQC_-DgIJvZNxx(eLqiq!A5|>}OT;%c#mkV5e=JJyxI2Q63El zA9MML%ZFS}a5>K97?-15jyQsPK|bK}K9~2nyvyYsE{D0i&E+jFZ*qBq%j;ZT<8p}0 zK`sZlyvpSjF8jIcWfzy7Ty}72;Nsv?&&AGV zJC|)-p69Za%N8!1xje^Z6PIVXY~=C`mknH==CYp4Q(V?@SCb-!{u=!2$zSstl;txm*rfRaaqb`375rO9^|r!OPwPi3$l>Q0xt8pJiuihm;1TQ z<#HdFd%4tdnZxBCF0;AJ;xd!V3@+2T+|6Ygm#JK)aGA`dhRa=C?&MOJw#wEewmj{XG62}v}a*5^Ag-eXX7fU*g<`U)b z35Rs%(#he?*5r;{BDq9x3Fp#*i-k*jE@52E4zEN=D3^9zLL8=aNLwz!T-tC6;u6Ru zfQvsDKQ6vpe7JaX@#13Q;>pE>i#r!Lhi5;Ck&A(go{Nr)mWzgqnv05y%thitxe#kB zl;H#|;0m}5E`eXcMeqx_0DcBPfxmzs!Fg~F`~bcOXTf*iTks9|8hi!51YdwN;B#;q zoC3|@B=`(`3O)gU27dw{gO9+6-~>1hj(HS>9tB6h2jG419(WhL0}g|?!CT->@CJAt zyao<|gWv#o6}$rW1M8}N*zN@{gO|XIU=P?0nm{9X0qg=h!4A*>9H8EPRHz+n2iw5& zU@O?-o)@|q`W)BUiLowpF?bM|+R*AYwQZ#8pxPiQHZVCbH&6}@hz&>%kk@^+8C z9@1WqcRfDykgXnlQ#0k4sPfO35K5PkK~eo0wXFsH?7F;RcDleGUdXoA{GoQu0y`-h zI?Ps2>5}4lDy0pwd$GUDD)D)X7n6|Ge)f<;n?qi=E+n%oAiOj;fhF zrDjT0R836{jjEY4xu#|^iTckE^pCEi{KY<0sIVp0)GKNg7e@U_yK$m z&Vuj2x8NJ_HTVjA3BCYlz~|sJI0c%)N$?r?6np~y4E_W@1|NYB!3l6290Nze5%2+c zAG`I^U!E;~}cou8~&wveJJ$MSN18cz(U=4U2JO);SRp3#u5bq4Q8dV?MyHo+zqAyyl&FT zpa$FpCV`1y0vHd*fjhuhPzA<-N>BmH!DuiFlz~z(5{v-DK?xWJih&Ib0fRvi7z7GH zKF9;PU?3O(ZU;Fa6QqI^Uw^8cIO0tn0qdJ;^@vkBC$U3r(>?d!Mb5uh^X#aoU zOOoFNbujTJr1g8}oYu>&ozy=%&p1mo0j(PKiB@0vJHAgnkGMH2TQ4~0I6rFbqUyt({uWNmim0C8%Z+Z=_vRSE}c!H>ux8yE-W?eDWWt)&TUuNK%1*xC4wQ)zA_$ zoZuQFV-dR({V|zLCDX|ako(A7@&H+Ycnwnc-Z|u6q|PS`ult_sUgVso zeCM^um9h}JRLRTA;9r5=_zl={vH~N*zWjQOJpQ|1gt7EBH7^pXGgW1xD4#28W zL8_EqDnYMJBvZ&F^jD2ik2$0kEo5z*t@ObhrO#OZ@LJw`(|2&!df*|Y{;N<6R<9Lk z1FJu;`_oDqZ{KfQ$M!yRb^q_RfBn@w&!M$;;vfxV2iZklK+CtG?GD6t!as}FKj-R^ z=ds6*Ug3FnD!DgZw{QDz_BJZty1htV!j;rWn&8-0q`gcIxZ*svpS+5cgX9o-jl4|` zqsLFcy-waD?~@P65heZ+IYquFm&j-2ON_%O7?U&P3-T5DmVAfwAILd!o?O5fUBOsg z!IjI#DF!1Igljk)qm}fpxsv}^!ph$!Nu%i7(#001_UbBz>wksZM?$Mw&tdkJkR{Gi zB)e(4YK-bj>K}+vok$GoVCkLK3-pNQbE4Pys{C3nkRi&yhNWWPyQw^|uE<17LP;Dc zX(AT7+7aXF&i*EDGU?iAU&ifBB0jhQ>hSQNU^S^E_f;lS$Dq}1G>^(Do@Tr%@93yn zNz+Jj%cm{xU~|?xDfTRl{iOMLv+4XHucX-KgGZa=x>Bz&F9lx@$)dGHCd4Op>mpe! zi3#!TBpUDU$I{z(krKQ0l~f*AZkKH>DruZKbxgLZTyxj5&i%((EuF@$u84CshR3-F zn7zG213WweLe;^S&ZvVgr>I6rYI%y$t!bXvJ-;K6Y|Hje47yN%IEEE4)kE( z$Qsb<60}+iS8nw-$SS=`t&^yp60=sLH|X$EZfz^cvc98Uvs79uA*i&P6t!AKsR{?9 zsR^-O%5QQ48av!Osb@m0>1;d=icLsp6L>g&_WT0}s7vFzhFRn=*+LV1WLZ`6%CMG` zB~8@vQ^_Zv&=BWob?}v^q&+Pe>>E<7;POS(%!{-mok&`JP{bZQziEg!-LTVLV=!n) zBi&&23e|LW4{8n%*94x{rbL|9pgw1lm0nMxrsGGO(dFJr==+1{bk?b1USVc0UyZh% zEGs?kl@Q-o@)5SXd@*PK-YL$_bSm9haaZEV?9N{W_O2Y*=;$*#D>ABcUQPC{7gw*O z^G7T%@1_oRzH-N^a6{MrRkWpJRzf@Hm^R(>TYieq>(S2H_b$97mb9LePphLyThgn+ zqis8X_6J{e2qsj(j$9Aw;l=*cVMrx=s1LFPQIC2l9W&?nSup%8s^4rnjxGz=Sj@x= zGa(_~Kfo^{!qVPD^7HjZZF|V4pV;dB)_I~})rSuZTa%r&YG}zLRXyK%ZO~&`aVfMP zO@G2!Um9xO9@!~l?n~31PG_Wrjrs%(TnPHsjrfy}O@z>cJ527>-Iw*KK^Ne2TA$+k zrH*$ctH#mc%}V#FlvqV)m>|l zPN~&edPbL`Md?=yKY!44APFtw#adACww7a(N6U}9q-NDzr|prJ-6)Ha)Yk9ipVTp! zhv^NzVZ?tA-XeU6jvlb;!#ew&^zn&k+o_QT?#N~TDrqD2+!>MT{!QC-)($q3Uar$M zA3cA_o1IULVLOSpBxS;+#%UoHmQSKPDq_tuW!W}b}MJ-xRdIQDjm9gqt$5C7|-a_)C9wdu87Ak zjXi(tfa#M1tj`l&!l~;ULtwOn9quh^Bu9|%>qoU7R z^@M7q6qRd^pi2)oD>DPNlRs)P?UZ_9^_z_&<1oV$m8ZmNYlyp>PG>ZDdV9$-j#qnn z`uM6TgTY8CF|yUowYDX&)y+E~sV55w zUfwjR4;Hw<1Mx|0p$jy*jIzSXTG=8;%Cf~L!6%@HPl76OTN`7a{WBZ;r~)=wkJyuX zG<_t;(xhE27wJ!LI-9P1h6}}a<3_x^qwdqt>T{^OJ4xC>b!vl=Equ7cVZ=N&?kTcC zHt4h|nl#D=EIv6oAt`Bg?5xF^@)RnFLsEeD2e@NCWAy8ii#_KcmpcOi5)>L%_49wdNtVXM`v4W2q* zEt|paxB>IZ>{{|I?8;Uu7$Fw<-uE0>u--wd%N+Cbnx1)h*TyHe z$cyrxm^Hu|r4EiNT{Y#N2U@RmNN=LNs< zs(+Wn5(juE>g{>$@h0o7nmkKXlH3J`;*lOgXI@BBA)7~&uxg#bm?o0U`Uu=)4q$X+P;W!q?h(7GCy8v`XLa-P&yMW;WsHwH zEENl~{|=+aH)_{S2$gL)9>sd|09LL8uHM9uM<)9Fvr6KbMZ*`Yb`rlaX)yR2`Aq)> zduzIl89AtZzdh3iPak0ERXVeFW@)dUQ=4kT2ILM18}L~6>SeA(I%@cX!@KC*O!}>D z&B2NN;}ZMzitE;=uzEn+eHDE*Mi1RO|A5NDiT!)Wb?aNi?y7?^CMM;XC8VB6Y^Bkw zWvV)(Ns*N)fK}$u`9sRGZedHS%H*8A!#P{tt(tpzwrcJw);AN-H+$^M zX24@tiY7&sCbL=81=DChjg2)OiuX!THl7H|1y1psz;0kl>E#m2{kS2}SSXCX21w$XFAisqrW_sdRVCb6X74nIFV4Q2mn**z?>k-lm5)OU4zo0>^`+P-}obG~0A z#lr0C^=q5F=nJX>eiLQ0kv&`T+vtJjBs|xl6C%YL)IA{~u^XF!+Qhyxn~#28^0mbX z4@%*xg6D=0o{<~g{O9-Xno{(PEi8ZNsQ6(IRdnC}Ny>=cA>JLWU3x!0cz%9%^nj{9 zk8ZIQkBhK8;TGU+>{u{sP)mRMMw_l_okJ2k1?J?UMeACB!u*+sD=GrdGRDw7bUR)O z2yL*Me07m->Yx_SJbhvNBRVx2kZ@L63Y6zj)3pmJA`-Jnd*kA%_2QS7d?{njuDgnN z58I~ew`J7e`)tvUfcSyk!_sr|yCmGvwfBU=I7v7A;KH2t;p*F+Gj~@MX3uS!k$eA$ zM8CNF-p(N3fQaH181*Mxf0Vb%mq-Zd>F^{0>QgV)DPS%fBJ-n(;B*WoeS*JyG! zj~+aCNVH?zsMHntQB?^`*3#zM*A`~Exzml8X1;t!W%k_0nY$XMPNpCD`ZcmU;S|*F z9Of!}>##Psx%r`gb~S|hb;6U=3syhB&Y_2ws&I*P?(lw_JojU6+6$%vzFx9>kJ4@D z@rcu`Oi+q9jWAzjM0@y&xylzzZFkp*%jYDiC3)-mXj?%)b5=v?y}PF+^_jAH{MhxA zl6K1GwDQ!X5$T=PQdD@n|6|W+-8}V6eS;HMg z{c1Vpr7uaYSL5}~VGZ^$8r`(S-_6fMeZlCd(|H+uE)(g3*C0bau5eVHJ)kBfVBs_! zG97;hkps&668h55&-G-S7?x-Xiw~fx;Dw{VrH#()dgn_tjjpe{=kgiV>5vQdm;p>LCP(wn|zjR-3<`8YGPGYj6*b;yjCb=^rO&D3S;%DVSDdRuPETix@L z-)}ouc_v9_4Zw|dI1{fV(^;&PtTAlu#uHm?Y^)c1i8usrYBsU8%ir~e9f9eCsT`ng zCtrKz?%tz|EVg{2h51om*Bvh+GTcMBQ*LfS^vVs=y_0KvV)J^pRI2AW$2=LA*4g`oM$Aw4rtm)IryeU(%8SI4w&2l9 zg?Zqir})8pxk`UQn~z74j#h&&7Sn8B@?W%l33yXg+W$HC=4MZ`H(S%DNt3i`(`-%B zbWJx}TA(YXWhrebWd{)f*+D^3HY}S{2WxqZ-#N08OHG$ zVZhPK(%ydO+?$kAaGd}DdA=u4d&%w1J@5OTbKc+YU2gb}tVGlN$JDF&%%q;jQ!Qg* z83#^G2%(IysOS!Zee^~6IZW;UJuJ^PdaY`;)oY9#$;r?3zuM730kzFzjPu&mYMVFC z=&`Ahe2>$U$(cw#HIDU811plx0F-FW0-?$wcW@Em6C4*xZ*l8m84*obM3eG65EYT# zO-Rh%ORR|U$U^hSlMHQ0^urOdl4Us$z0zL3C6rKFF(&EZ$7mJd8!7VF{kB=JJd|b7 zz9!Qv1kY?HtDb?cM&*v`f#&uE+W&Smw?a^O5(TJV9~B6I@C^JTB14ZeRB`&Y-4S!oK}Pwhr=3)B;CdBb5tq&%vDCK-cYHpmPA)A@&l|}z^o;NbovD2MxuNO zWi7-1>C>Q-ame55 z9#}}MTe6VdcxW|GMp2y*jU0*U5IsS#5RY&cM|HQPRhFAn&D|u=aGo0lsgW_AuyAG9 z!ntoO&5s_tQpU_H8n>V{F=fo$Vtj=3;`cWp?*87Y#b?oR-Fxe&Y?|WAZGW;H@qB#5 z?1^qCZzH)>zzQ;tN`xjpo>-v`FdRV5m)OMm0a=x}QZU|fffX^Ib@C|0#jzBVMTwFq zJb@2lQ33LH#rk8j+*3V=UJz9vB5)6ja?kc{*+=l7_{I7{p_rabJ@NXC`#99Qn5`gL z&oVYNBeud9VzwfVQ?YEtA`v9%ZcA%~;{{cwPlnhE>j6fvl^_x{7$GYxDUGm|(9*Zp z`Pwq~92RWtX?ScxYM0J8HUrU>_ zqWL?1R4xoy-bV385)LmFy0RpDpFE9cszR2d!ortChed=a<|Z#nHSb25I9ZFlLp0Th zeI_%F7-j8u!B~Aad!~se$x}&rHB(w$?QhgH9I9XSsM0%YQt_fXx4miKquI}ltJxkX zXbfuAq4t`_#bq$0rKD)} zp-~N3(|p9BKSWWq2KYN=66|?mg*+Z#Bjsy(vhT%0NhP?WQQagXB+z%B@pGTxv?ar$ z82W7UGdaE>lV^-j=MS@27rgT}{Uy{Pw@T+OddU57UW`=oMkgVD7OI@|yU)_Z+&NMi z_8`dG=g6-?EO2%b0DBM>3Re$@V}u$4s4K;l(%Z^QAxW5QN8)#xM7 z?d3YFtE!zZym;u4DYpo@55{?%=q8>SSp6mP9l69Fob$vvVl*Zngu+q^MW-e{k0b@c zA#2md=PAbI?1E|F!`8h z_D;^e81I5JcsPy6s(^oS3ZK2uVNBd~zT;q>BK6r-KXFROAz)U)1MPF^R-{<{t_^4= zi#BW_4&#-RO*brvr8Af+)d9jIJ&`bNW z{(E+_IE#hI49?@iMDl$9MItzGk+?l@ff%=nxb*DC0T&yOknbZt zr2~3UdyGdJv?O-*lw61W=m{vG46-|N+;|r&HVOA%=jYO#Deag5l&6XH#;l8Fu4Y8kIjB3B88V)BBj zPFx*HI5N^<^3=mfg~*123H~CY_|%qrM3h?~sfy1sJ+=PRPmz3oy;RUqdAR>;&TWcZ zy>eX#Bj3^we<6|I-iBr+!mpV5LHvpw;#X9ZUwubZ{-^vZLVfY-#7wsg-Bpb%KoE8w zQ>cWo0wy!S@Y@Kd#ZC>g+0P!#W$)*%52C7gysAiKssUp<`4o;zEmDOdyEkG*V6CmRu@GRh7GszY%qtmywUG)IHg zNT}MgWebtR1gluG!EZPoBv~q`?o!8ya8#OBg3m^2$VvVgii{;7gvH?N?9LyH{}u$^Kt}f?-h!? zG*Sls$N}%#D*^bxsFT122fD1dy4-m@Rwm2vo3O3aj<8Hq=Fn?y#wz>tRlHkVvQKz- z1;`kap5H#I@qzG|Am$EL zKg{Gzt__(R8{9g=Gckd{FpEd>J43MzSyr(8@Pg`HdFFAo<5O05Bo?-Ya~}11R~Ap+ z`*3)w(TC0LGm4F#B*y*<)}_6UUE0>o#G-;pAswSt()g{jNe)EU+-rPf{W8YG(nwRZ zj**68F;X$S z8Mdu_@<=9={384L@}?c_fv!hZ8jDMc;}c_b=`A~Fa=865Pd&+#D8nA9$<&096vv$gP;gA85<&$QD@Lmo>NRm%)dk3n#f(gZ5KuD6 ztlqsu_!mNIhiWcsDhv@Ja=lX9S3p#u^ufYknj&l zRWV$1Zmnlv4PK|MXr{1L+@R{XNW^s}aj{v%Dg%0Xyh&V#)QOFvNC%FpxbF?xzJx0A zEs>y4de{HuUt&;@DHAaSB-FziiIE9U<^411WdsinS&?-4>&8^1O`2F+Xqo88^IAVf zq>;!IWd5n+vSoyQ+=S_@QOP!qXIy~po;^*oLm-Me8Av=!sME_b$n;Te*2sVaA%yMi z)J)`J0-zLhoCNvscvz)TdOci9MHSiXB&U#5sG>NDSZ7gC71W?tObQ3!NIC^L;E8ZT zOqs{-BDsPTn^IN8iSq(LW!;Rcb=?-!P}LlUqq5om5Mm}M-Uvmj6*qd>#5CfBmvLkv z!#z+vJu>DuWN4a-%hOowcS{37yUiBOzA$BB7_dVoUl2r`A7(_WFB&xS9FXDu<(Cbm zhud3rw)>Nd8$Gd^!Su$*>#CR6r1)y*WI`g19C*>3KPmKBEB$kGC`AL0)RiUYI@HN& zhSV{kMB?D%pN;RImy;i8d7^sE(kZ3!2_;*L%a%8K)2n7>S1g=>0*Et9{)_&Vzaih; z47X}B^2&+r731~kc}amOnHH@lyOil3_=fxzSy=|MK;uyhCG~g1UmmwPZO(WVe%e$n zMTGBHVO@N-1t^uyteYww04dpN{Z4m(im)G3sjIFbB6Srl9eFf?!lne+kZf2YDwhn( zhaqSX8!a#*JK!Vou_l(XIc1|4j!izEwd~Z|1#d3SwH8haOl-b%A$@A9XS&;0pJz!f zo0d)NH6p3$!C znheYxuh9pIk6|I&xyF+~MG(h<5PYPQcEi+8E+((I`L7qvvnH0U77U+S%Qau~=rm)J zQI_blSPDGG+-1ifJx|1@hEp6FXOw6s_y<`;Tb+^%2msl?W(ocf~0-^{{!t#j73P42k>1Y)tu|p>z%n~OAbEfz-)bbuEos0 zFhJ^r<1R!f6(Fkzj z1c~iqat$b6JvUJE8gYo)aO(hfGS)N=ahq1^V;}*VE(xE&U+*I1%>#(c;4UQGwFsG( z#h?brRSFGpi}rcu9bG$}UfJ^=JsG}1P|I$7^Ucy3^g25I?{wW6d`}L#XV&n09y=!D z)q{EW+!MP*dqClrK{yYdPn&&obK-v?r*{P$kM#b z_Nzr&4@c2Tc$Gd0OX+rA;pSVPVaZMCE|SPy2#VJY4~7LC&TqMM$=|{ecVR_=m)Lu25619N;g+!$6VY&tQe zFo{1FiGcpMy1BNf%xwFstEcyq9=6|r$pJzBqx zaw3U?HYBRWa)l9XG8SzL5^dtMv&wV6yzuFj9P0Js-Cqt#M(<}ugA>1v*YsbxGB}8= z_G@w-W5p-2Rgt8>CO=@_Z)B``fbf&=qxCNbrN@9wPD;9AeONE%3HThbSfLb3V?-1I zMFdxhUZfc9zw<1hhrH2bA!4jPA2zht`w8}8Jgd^8r0iB}kRpAgRYQ?yi|H>l+hXa< z`Ort7FM$T_HXSsKLZXx{eVaZA>)&4d{GP?{z7bf|2RRC917xs+j&N^h?^i@Grk!|ZJ<-(r`RtO zP6H17im4BNgRjxs+1{VoFTh;6H%0o;^U(1Nbe z8uKkbKhn6Tw&uXZ!S4v@s9d=1^{Gn_KOBUq;}#T;8)Iw8Yig1tct^K|ZH3ZxCj{2G zc(+w2=V{Git-+*(yTWyDW%i2G>z?`Zi?t=I4uA6Pdio6geoD$Zn+>jp%b$np>mO_y z+wvCOcks>c_KvP99$UI)S8(;3#f<@lAmM;m=@`}6G%2aMPH4<~ zwRqN#o+z#3ah0{cZnzv6tF|(?vM{+axiX#XFRanr%Brz^nqC*_m|%D* zwqY-8S!CBuwo*C8LPvGgVyw6)r2$zkhUs!m1TIkC zsWsy-`(WyhTaK!PZp|rZKu*jGXPj=b+ zpt`Be4srONM_3V8k7NNkF*(bRFQ4`1^1|F@Czj#k5sDnRC`~V@^%pM~=NLGM060aO z9x5Sp6-*>iD9-t5Hyorvl(#On2CVF~CL%yZ(v9p^J@{Dk|uP)bI`1sj-bhCqO zkaIlf3_4Zur{EU+j0dA$PI5Oihecj5r9&!N?yBUv8mR~}TkglJz$4ia){E6=NH624 zMdPs!@g?k${#2iCRw~Wuh%cE{DzkH#a^H8hV&&T2-7&G~v9oKYpV>YU=?8@>OS)di zUaixoTU3|>57&~ZXm4RE+FO{4_HeEK`lwz1vt*zhcTT<*El%T!Yme4;Z9%zA>7|_`nXQ6lbaH{;a|dHm?)F{i^B)1X@sd88ae?x z4$iFfVso62R9A7;CXe(-(n|J7N(B=uULtwD{}otMJ2OkA57g(>ZVWY-pItj)+ssgM z^@_Ty#EQMJs^-yY4L!_)~?xD{Ut`z!E5A2BwYYZJc(xI*|5ar z)wq&0E|(^W6rf$!5jM&NL9h0lJa||GH5y0IdLt?Ex?>vuTY>mGp1NTvb=>ZW!@$oj z%ZHk{hGx_@tO z+U4ZCD{y~BDgYc0(^D$}#bJS%%M)=akpR)itzorhNCe+-M0_-DJbo*QW`rq7 zG8H2^V%R-+_Pvq9BPME0uN_2hAWY~@ElB}zkrFm$(H_?h?4`Q zn0a*}i+_Y9NCX8ZK^&ZNLZe475i<3uutX^`$6kwzGaGJbTT!&7J0^-5vT=0Vf5vWl z*|4p0*Rr@99kX6+PV%F=?Z0@$SX7v=3v4Q_T07Bw_`pr#y@9_z+|;#cJlx;1Z&4UQ z1?NSH*j73{fB6Dp?=HH-JboLJaxqf>D?9ZnP$8zs(v`2A|inQZjCCGM(|zc&3JZqAbz^PiO)G{7e~w#;BhmuNN( ztQY4@-#s&9&El-K@|2HOEqrKIe122G!ubkq-ps1vDIu-BxGCswDoKWAwd)$v-StaK zA3aoB@Y0O@C6j}xRS%DPcwdfjRQ+sXTH}QJdV673rqRD>;05cb;^L&lf}*lyXNg-I z>ny=OvyHL7lc{gy97SXa;P1VPaap_34pqixxW0~Y^or$juIZd%8t(?TEeZ>vtCv_m z>Wy}@5?oGXuLXnmwzCdT&IFO_L$s7f0~vw70nrw zGVnIZA!1BRCKu1GNG1xGf4+Ze+4eu~Tz>K8rtaZ?`qKC#~1?fv8A$>^6Wxr#UYOV*H9~J#aC5<9FXWhR?^!ER6MAsuk?@x>%`emelBFMyu{tkoa zi3q^|8kQ4gndG{W!zY1i24VU(3h0{u6wswaB6+#L3y!Ito~bfq)&{HBhngzRJ~X~# zR<^lf$@ty`qInk-hFj}uJZV)qmZHpsW9vLq*4O1Nd1PsLXDnbaJ(0YK>cyismFEAXV)_fS{Ey7cXs_~oK6U@%LLRk? z;@iq*7G%{0blVbh>jSf9YBkTr8r&0>moLO1K5jN%fvJNj91my35Q;M(P7X)$7_oqh zsFjEZA<1heXM(#;DPAvIfA-z@07a=i41`(#EsC$BUxy8Q$mafiME5`$gW-wfM`-*+ z%;^w@AIBIjP+|y|0|5i!6oT+}K@4lt-eH_w5m^HF)C}*3?)sPhw8_=xQ2R2o4AY*Q z<{b{**IHg*RZ5Y2Ne+idubh{^VgYev7rn|-#~}A$3i%b1jSI{ya#IX)AE(-hnQ$gk z`9RQp{)eEO{QOQ8=g5A*VE0$#H`E4T0e(;l9y<-v5Oym-5_~4Ch?6R^6FhN>xNJ|H zCtJZ022Q~<0DwIBcGw~;OOSfbWoK(BPlEkiATKG6qnVRUB}k>**g4$kMgL^|Lq10F z4-j(aYj6dDdFD0>;b_O?x?Ea@LNY8;Ho}iQ7|J6}hIu4|pl;pITEiZ>;0OiiN?3+(dn-G2hpapQO;`wvSo9+FCp{D|upt2i8<=nCj1L zT3wRb)Y9rMcw=dJ?eu(KSO<|6CZ@ zTtIC_XSPJn^r170m}|DOXP^Ros);$XEpp8Tbj>bm13L3eMgsCI=NdY*D{`L(xRhMR#rN4Ax#k)=6T_U@gU_Hj zJ3pu+cN1j{(wQ;R?PQQ{XILQAbxT_;Z&6dDx#GKR06&a#(GF=*p>MLaKJZ*!{=CZcxKLg2VYu$%w%46upVN?@ zV>QhVWGCcJ%5l|0=VBN9zKs4l*Xm8*)%Q^hfeQ?m2#2I(w*kj z9z}ST)*_1O#&d%_FXL5Y2!34;K(c7)6u1Y;BHbHoBR}h0n!GK~HXE}5i$HY0GSXz` z1v!)Es$Ao;YQ}g9ljSj{U~*u-Q=6S%5WizfVYV$dO{2+dDzXwBE@v~JAIi|$4bpXT zqg|~`&`1<9TX-TqHK(DpQ7?>7&BC7H0QyeYhMZ z7?nz{`E6qh?-aKw3O9_u7z!Y*(b5h^n&Dq~5l>jn+Q^Gd2BQJ$d@wucr*i@F=f+FFX zO%D}#;!|`Y{OuSir5W*9lh+2j$g^-CQ~l6}g&gGWI2XC(MO>=IuBYdoO5NH1E2IJc zK*@Gmu^p|d20DdYMh1ZzBzCDqvTnHZElMPuuQq`NAYZRLug%w;hg#Q-&w82uPiAU0 zY$iZMS{MCnQI>mt=h~{4ryEn!COzFmr=)LvPV$N)fTyp_kvx|&jF_*cwmuRtHb&!0mFd70EjXPie;kh;kuZ$5a&FZUlHC*vRDiS4v} zJJZW{o!rT(LEa;_3vj4z_|KyR32Q)pPo%DEMUjC9k~`-OG!y&g4SdlwpYRZ#1#}qC z;>YOIm)K9A1Qfh>oZtXRvY+m`gbOY~2<`CWxx~JK=D8?j`^$oXj|M)P56@yBCP(aJ zJe3SIAb{e3xV}p)R(HeoVH9a;b+PD;>)l#+;WtK83}WW_XFx{x5r90^Zbht$QZTgXKv!#@NRLwmiznc)-R3lhI^b zmV{*-CfOFYK$cutHe(V>XiC#S6JC<0AupxeG>;57FENlfB$wvqIV7bCO;a+wJerTk z%cZ$#plL$6TnNfrdz~X$4DIc`_kG{JUmtAFf7aP&@3q%nYwfl7k#)9uVW=p#+#X#@ zKV(~?%q-!fOF(=7#HF(#>2tV8)QZ+j+#`yU$P~CulvJURklk<@c9QvSYqDI~s?eB~ zN{K=$vMnPk2r$W?75(@YupinI}F@#|2@WOC8r-cWQwah{CqnZmMcXtX-|%j)1) z50-D<%%$(y!|aW=)2pLDp;&qu$kPb&2s=Y9BwDFDn3AG_fK+ubH@7Hrk~X#`$uzTf z&6pu8+9l20C6h@-InL?Gw~NRhpwF4$3Zyz0-zB8ll%B9LRQmMBQ0e4dvc?kI`h~B5 z@W**Avua8*c53qHm3vp^*B9$EGb&n3)(k9jbHAywR?lSi?yv1gm1Gvz&~#eC4DB20 zEJO64GYvB}zo{qoEZ{V3wsexprsf{fYO}NTWRq`6_6$(p1fxxc(;>QBfGdS_Dmp6MEKf7nm-X|)TZL(E+48`3hQ`fxQZv~8=Vy>#-$)7s5_s&U9 zUXhxfzi?I4o!?GNp%}UjG}#WCB>O-Wk-sEXO=vXm;AwnOk-AHvNZTbxwL#P8P=Isd zt64->dRc7KEVf-&IL{Sq+yB}#2ZA|`%bOfaE=$%`_1K!rGnu_Vd8TbmV^)-Wvzrb; zdm3m@Mb)(`0qsZ?2<~Al3fg=+(pM*71jvERJaRI>}wc8Vl~m#^iQI1 z(q+;2=z1=l+3P&!{5aN*8ro4%#^)t8;jfd!b37$yc9CtMcFE>@UIio zTS3*Wi@xRe({tBx>9jHWD;S^uNM}GBWOOED8?~)UnpP^o%4Gb35mYLva+g9vfsqw4 z{fo|R5)6zch81Tzv_ig4OGlriUwQJ$=;9}(D_yRr%H@I3+uUgHI(j~Fj;oVUR|9o>pl%A)-Kx^a)oK;l4~kY!(v^o*$!tmr zMFdR-L$h*ul2oczB`2%Zv?{IG3Z(_}W-8fz;}ZjJmpN zwr5Z)%^zMoSiooo3cuYyGjr%WptOBIUJy6$zu|Ia^^_Eb3o z^DXO_78srDn=I?i1tY2DOXe6Cm8YkbEv_;yDNmR9dbf9%RQBA_xg5?$&mGGeR=3SI zw5_aZSiPhO&P2Lcj3;|O&3Rs$N_Y9iONLS2s?%p>sq{Pq5oOLUl?r@E^o`ief-&1zEl5&OEbj9Ze{7BI^Mn%&+qWsG z&d!;wH~HUQw5EAhT1jJ3ZkgU>U)<*|Y$(a#(tkB0H&q@z#q7hO#iio!xN7q%)vRmL23nxwFpOe+OBISMt2O>&s7 zg^+}z;)i9TJ0~Yt`KIsRChqiv@81@bwFee7jue%zTe#9Ov%E34xTB>wchQhFrL3YN zwbEm7wUfsb$Te_3pJO&=XjFZ=5??;QykOB>o|VeE6&kg%B!gsY`HB`2 zuMA*^W?Xp`LA1p{uH?wplM-+MHXcG~A$l9dzn?<u7lLr!j!B!RY06 z(aX0#R9^94q|ZfN=f9wzj`l3SN=8Z=^FP@6l2&RKWuR;?QM2gz2Q`!-f0AxKl&YW& zvyL!#Qn|1&)KF@jnpd-GHK*H~@d~q*n$7H_IA&YyL2>1|7V>ug)VY&WQ$+jM?(CHK z#{jailT=*tFjGuzV18YvDRcX-2Oq3mH?MTVg2n-J$&M{;dQ?&Z|DRctpWU%6|{(r{1X4oTI(g3zYB zo0pcZDCXzn6t~s#oThz~yF4v}Z9X4vHvRA?UcYf(^pskgGN+qJrv(kSfpjTU0oD4v zN=bfhMm7@`X-zLs>Y3TBM87}=iGIEKZIlj8d( zk@v!dWeBaUa7D~5^LA|HR^D0fnwS0E`qmj`W#w7fi}Ls;Qx5ybj?M0J9nF6ISme&~ zt`Yml>XgEoLYh)3^>dt}w5uh}u(~avtk0_{@*6p`3b>c)W|(LSn4PUDNo+355HPae zupGdg3KYOE*pwms*H7RKWeFR#j(lMQ3M4F`HMHL4E?LwXhye2lGl*a`Mw9 zIrhTE_a}$!ciMkoXYJ%MXj?K(CF_#;WJfZGFF7k_=9ult_T)w<+RQ}NLFB2WOwjp8 zxXxz2O*(%PA5!KSjb$spRkl)hZk~?(Ap@os(1!Tx>p9H5$wo#Q*KTBluSLZFxS`Le zPTa_-m~3Pu1bCuDwlpPe_QI9*rEO`NRhTwg&&stK=^6BA^XpsZ&Nq?W zTS_e;_-JLQ7jAj+Ic$pU+GqKjM_mD_*7> zq3II3@rBh;M44W)K!LwIxD$fcRv2+Rsaed{gPDAqo&>Zs9DR3E)7#IqKzum45+cOw z@SnUsJvYAjOwrBuo`FYnmM+tz>1QNw(d$)dnK|iO)=6}Heo@BU)});Ll9^3iAo-ik zN%^&g==bQK^Rv`^eOdH-%-~qToE&ZI65f=bynK1I6-FWpBe4&9ltkr{_r@Wd9pZJg z4jzu14$4#aY9^Vj6EpY13U8bEM~8DDYCMvO4kMd8{eVdpD4@0w`_Xs1 zUB(5)$=%K>Ku%`f&~5z5Bj)jC#(j?s4dpl3O8f*#e5HTQ`aqI2hzZStB!n7#V?lH9 z-}rRS7j>0xx##fV9dv&5<2||N66OP?+&@fL3_msV_2KC6?^2Knn$7{cHAreeTh-6g z6p215@F>u9P{~kfM?gbrXgq1J^e>A!~swT_68mYw{ARPs}-n)~7T6sNIsAHR)WX`D*j zIYM}%NY1O79oyxeOi^q;*;;*WzoBA%b=QjMPw9J0>dCB7QdcLLdG+s_S1-)hX~)yj z-7fmXz&{!DlV_!CjCuJ+(25SUvRpDdzW)(dbC%4C`{ z!NSZWyjX$T%)qEhWq;N-@yLTuFWph~==hW6(Dj3KPxJuO9!;XRMYqv^fR^8*KVt8P zmNTj9RvoQRVX3s#R7EDGr&HK8(E>-n0z#YTS~7$u(&XwC{AL?VK3mGaZsQpC{x4@c zR(`83B_}zlFg?Ga#+VU3d+$VH$xlIqKXi@S3YcMrRp-=}f+(ABTSea`{OH0KF}+Eb z(&O|5{eKuO6nu<1j_J4T6828^ZB7Nr&%MX}lf;N=MDpxkQ<7##*Gmt}I9b2!fP74T zP{Att75`Q7rm{l0PWggLty-b_p<1o(Q14V9(Ud^CUGwz6BYmT7|FdZ$r04#_($yqi z((5;*tGabJq(jLi$q`5g64IB`DWzFVw~Og_LP~uM-%J0urmnQ7(k`awL#j_-kiO+F zPCvX!`up_XrGJ%vMW3T@)tmJW{bTyy>A%un$!NQk{!^seGR8B0oVhIX%YQk|STp0- zS-DxRto<{yX5KdQSxE0@4`+WcYw@gCa^yMlbMDQ#n%k87eMryo9{zRy1pfhln*T@s zOa2OfC6CL~oh`&+3x5R=SmLrN4r7RY+y_vcD;(#B?0eHx)yW{#Hnp zT;<}*ZJ2)gAD+$%$yoGnN?q}EKcrJt8Der*{peP@m2Rb5=~lXx{(nytMO85QgufW+{_oN~F1jG7>6Na#5tE3HdVWYpGVGw1#E&|E?pLC*p$O~@DYEYO0U1zOOvKnr>n zXhF{cE$CUG1w9M2pywwko-$EYkm`YIr~Fhu6{bSeC>(342;?mSDol+adLhRTRFJBK zI}4})B%X3Y-XJvu_eSx`2WKCY9tRwNl8dkg;TQl8q>LZY3+G`h!$VtyKTnNeT~Z?;Ccw9;GsvPWIym8#$OaCW%^M{p4uRm z@?l*bN)V2u|08hSpCDZjwIN7O?)s4LS~!GWPV1u|czRLheyBsZlR6}C9NQ5jBV4>F zJCVWO>V)xn1Zxb$bx8W{7W+f2DOhY=)SCzS3_#8X8~6KZ;~j1MIlL|@o|y&H;qh2W7fe-z{lpydRsM}X$hmSNOV0P}p* zMr=QV_6QxkD+Zy+cBNQygb&k(FFYuK`z0zWIXbs{65sGPxOsgpF-H5Q5?ZOEJGyeL|X?zBEg4<3_cvmW1>xk(MGg4 zhFp13H-ianhsFK|<9R_GPd?OM0Jt<_+rkJRLfOjEhGZm0;#L)W>{_dAMlK5WU&C)!`oSIno#`1gvjB>)(SkD^2m4&bO+AFn;F+kVko z`os}DhT~%(?q@fSrwFze!Sa1*(Q%9lo8lUb#etj2-G^lpBiaTreh`UCj2(np0W5W6 z)NT-cGBN5l#3OwT)h$Zv7k#D%c$y&nsYvY;$DS{)>o7{-7ke0v>p~byKD2FE)MTvA z&F`-LSIs-InIWdTW$2MH|8k+$Bcg8znlp+LTstF#(1H zQ7WM>@tG0OqY=^uOqDn%T`PH|IHHYW)Q-(xBfw!3>keqtIDJTa!dC7?e$%v;mrD0WAPu>+`+NL=e1u&sWK z!Z&Nzf0Jl3Jw|Sf`GRMUU{8bMI1_jYGddZY*Y}&;7b2tqYL%dO3ZrM>Pf8WMf%9Lk zqiOEbu~>+kg7@@aGY8$+_i2Bs6<Ll1kNXBH7lneOp@4Uk z_mA>k|FCa>UmFVZW1~LaALK{Ep~0|sc-S8tfBz_64E3H#oqDB166~-|r9i zj}4DTyup6oD8B)+e7u(*4h2J_Bi?>w7mN_*qa(h4|5`sZiE{K0dBfiRh%Y?K4|&IZ zJTT)&y~93!gMT10RL%$d>wSDEFu+GPjrcZ%{iI|$KkQvkWbsF!jloc80N8~5{XUd= z1WJU0-T(^MH#X`I`bJ0j{!lpV8yyJ+2Z)4~yc^o_4@1YG^Ss9&90+X~6=WRnkB$Vq zn|N;^5ZVAYz5IZ0)IS&mi6TQp6`)9>N8lLHw=n`e@CNxv*gN1S zr6Bh@C5#GvS`-=!`+Z>|2~jy|Y!u}m4uR_WL&HEvynTU9eAoxPptqs5Jn;7g2Y?Z_ z6bkaA{b8REOxii(3%Wr={92zkG6p>bv-JnY27I8^;2_oxL%Tsj1;>VcVQ*lxksk$v z5BUbl`GHU*Lb?hX6T7n62cFZ2Io<#$JqW%7<{2IGj`##Qy@XL8^dICRnhN)O!CL~p z2r-eM;6Ny}p4>)h`#~*zVBoPJkv}wTr-*kn;^X@^@#Eg`CL$p5foa}--mu_k8^AwC zE1kZ1(=yE$E%EsWh1qo!aL|KlOq-2mR1sm`DLu@(p{#>v`-? z!sXhVj~y}?h;++>exff|#2fLUa7JJt4usHHFankxt+bEz8@!_>;6D7)a0u>3A|nk( zq)ugp)qj$O*kkc#A(o7p?9Fk zVLuuWlt{!|vdq2!ZA31>V+Y3iBSiEKL;n7ugu4E?o1jJFo)5|%3HzZyKa_%jUdhMW z4h6v>4gM0|2j&?_WEG4RzNti59K9HP6V%f$jG%bys8^Af;B^K+v=Z?R6V-?P&?=13 zU?Aj8Y!qbn3X&36iCG{t78x0XaqJr>Apyz^`2r)?b?7g#1zN&5;9Kh*3q&ftqazz* zpAS*di`0GiNz3*BXegnCluF6I`G!iu6671By>uVNP<24fr)au~ZlYManQjKUg>C`5 zm2L%k0lfg|h4ez87txD>UP3Pcx{YoFdMUjWXftgF+Cp1^w$fIhZL|$&J8cKLoo)xZ zgYE#jlXd`2Ue{-7C+!5!>Vor+UYG^gfzfL<;G`DF`aAir#(?4NA4n z`&tHdWmjcTR~D5;f&NDJ4MoezD?hB9meW8p@*<#%l?+8IS*40%m1<=<&=tx?pyw;0 z?@F`M2DDxI6h*eP6!gzfJs`gYC4U|84dxBNpEExP`~~w1z_*#V0e{K-67W~duK<6| z{2K5*<~{7=5x`g2R{)Q)M*&}DUj=-PeGPDm1)Z?R*kgcivTp(&XO9EE!@dJ}mOTsj zDf=nlXY6NypOasYW6!ha0WYu@057r^0WYza055|+1x5gr<7B8$ zHK3N$0_r#&pq|qMW^$Q;*<3bYE|&|K$K?SQa)p3JToGUiR{~hZl>t_86@W(02snqE z16a*f1J-agfOT9Q;5=>~U?bNE*u*sfws0+g3%CV5dHxwl!zK`B)N2dD}hl<*Jzq)zk@M)V9NwUa(dvHhFE z0V-`U>|0Nn0^UfFBKt1UF6Tm?>~8_1l)=wB1&StLBPIhGuNX=}=_%IYaF{9H+1buh zrEaHFZS;Q&CkA~L|ucy91yiAbh z5VeSzi1~=+_!%teBWYIx?a1I-`JW`0=tMh?Rpb#n9}{_fEFPcWL3hGf>(m4NSv*fT zzJTMRNPnG>|M87SFN~C4IUL$)KD}vp7TSFa4x$gzkB>!p-WB8_b$YYl;NhB-{|t^V z#51`TW#}!6*P*OmQ1`Hdw*`g%5xv+V zaBTip9^0-v?iP=GMZbAfILLM4f%g)Q>-aFeMD{&!JS_O2?J-f$;u+yiKa9wpRjhLT6y7b6ENq9aak zZ|{!h>}+3wocoaTkf`BHP&bHWBBE~30=*e>rrNiOIzMYZZoA;o3Hpb-cgJyi`@Nzq z&Jy(KA%73veHd{MmU%3mv$Oqil;J7Nc@FTM_7^vYP=1>>XgERdzS#_X4i7uj&3A=(XKnie*;W1Ars;Fy?F| zIpz^8e+S|Y#Cs6$13mQEA3}T-bM^y{+Ycm^d=~K#;t?^2lz$cIQyuw;hU@4v9hIPg zdpqXFb3W~85c_h;+|$tt^!bi9=*xu;JK%Z5%N{@J08IDk09IzEb}QM@qdCREji{9PbHMUfIO#>X#1?C zu;a2ogU_Gpq{!V)DWV!Ng-F#&;?KREISKg?g)F6=rQq{DomH4q3oV}NoR9QEV6^kB;0j(UKD%=>92_l4hG7* z9dg0$P##7Nx$A)FYUy>PiIyTc5M3>6Am=n09iCRpS_hAHi(-95pMj|8D2G}{9VWzj zC=+l%q_u<{i#=_S1JTv85%43R9ash;t>q5K3M|=&IYS;hln-Kgh_03$j?Eq?&=6NG z_c-pxGWR0x@$^{kb3lZ&Jmh!`c|MN$PkB}?jX0h|`UQd*7WS*NB!J zZ^q^_ph>i}J5C}Wh>(^8j?&*MG8o#=Z8ph-mC*#$Aj@?|R87TjNuu38R2}n4Q$OCH?@GF7_#0kVnY(+#U3DL>&b=MQ1`H8M)kk2WowY6(P zqz#CZ=>LyoDyfx1}oDAanCC6`V>o^LZ0V^`4q=yCgBMK$aSc#Pq+DRheRws#s6HYbKDWY8(5Dn&2&P+09og^wAbwd2HYMrGpMsW7AR5>9k zTGO1ho_DNS&iS6*kVB&4DKb}Dc_&0g$nWSrYb|oR!N;ncy*S6gY-la-40zs$oHb;; zJJ)(n33H#-$w0Z%<`{#E?X$)5iuSbfPNJvKSrXN^DWN>(AB$u-JqEZ=2gxQQ8OQd_EtDQ z0naCMN-OfwTT+~#K`;88U!dL=dY-WkiK`SdSeBr{8pQb>W_iqUgEawrD5NKe3_Vhm zWYQXOUhMuHB>5V6Zl302-R5FM+JHET5qpwEUE;kiA%<^6{u@ad^GJ`{dbdm4qeePK z#8a*`GVi#uu(U_}VoLd{L_qrg$TlcsY zBj_ds(119JoR5qA#a23nRoSyBi390FNRt)#8P^Kr*+=Z+8WL^SfM^hP z`^^r$!ea&?m{I9E;jbR?DZ{x&CI^t^{BG+zqQ!>z8hrJAiKWT()Mp+j>e7s{rk! zuG@+Hdk|OQ{JtMbUUCog)QT8&uj`qQ^ghqy8^@-vVD%aqT^`_w0R64&jjy!o%d872bBL~2utNHHQtN>i$lB2`QkBT}R_Rz$_97?F!eBO+2nil7*gFH(#^4&Pe; zJ!tgm6|Zf-+xwCE&41Qe^IEfJ&FtA{pX^n9b8btaP5k`A*y05_&lb|In^#cSgXgQz zTfB&o^<2pN?e4-f(r~ZB!7N*0khNDh4D^V0m;)RQ99tYqcm?PQz)8RzCzlo^ClOr_@Xbi9N-S(tOB3+H&wXyB<7YB zu7@4AAa?_hPAqu?3%62_Wrf?vb)lAbfxlPV0MiHB;UOTO9>*8*xp90E??sb~+Rl z0G+!wqI1E?)%)I2?3PFQez17y=l6p*GoS7_j(%lzIQM-^LBpPl#uP8dKEs@~!1cfp zKsu}E&A)6n=qtt@&0APh#OtMS_DK%*Tc$_r)v@B_8Z6vOw(Xpsf!LG35rrYT5M|^Yt3yU#eBTa zGCvc!cs4aw#j0fSLv^+)7Blc<=|MbGYQ$55*FEQX&J#OH8vd5Jj}W4t=r2-5nz&l@ z#&2z}5I2ZgagBILJS^@LkBFzl@5DOsH?dm0Cq5F}#mCYu-Zic^t`^6P?Z#W;xUtvR zC!$8P@v)S~-;KXZ%Q$AVN!v6{TgI4iW>?wK>}e*+E@rBkDih59W}56~4mLAn5A%2C z?_`p?T+Nfo>P}TBN2$luWAb|S2lXd8Sv{lH%QDrVHpp`IirOfDsy3;=$e*b<)E@Z@ zwO<{Ozf#SrRsKdDvy@zJb+!`ZN-NRoDc4v@R&QBv^|J=Z=d3~2VEK|2umbXBD{NgL z8?7H$IdY4YXXVN5)@W;te9IbZjg>pCVrzo@t96ZajofElYuzaKThp!S@{mY_ooC-7BNkQfsMUS@&BH8n*S2^^oDQ9kM*hD*$CM2cDym#?q=U^ zTw*ucM~nu~JkJ7ye}O($OeTyKUj8QEpFpvf5E(}(+M-v+2o8~1PU-}IZe*^%FNer{ zC)HtfWFe>g9Ea>;pb(yPPr5KXA+iyZxCwH%+)cLno_vpN^?msP+3G=gP$>C{{Df@v zm^?fI zMuzBWWEz>th!@2LVgrQ{Vk3oY@wRwJL}(rUO^l+I_@2lWhs6<*Ct4|tmZmhtCDM|X7z1ry zYJF;bCJL-$)-h3Nov==bBAO;sjI%A<5|`T@><;1zb}}ulv=i+_QDUEIr;4lWfE^T9 z+hIFQdx4}izZNqQ}o4Xe}30=ta6-D$Wpppb((FZzqkXnL|y_s*!x@JHN z|GN6$MF#KJ@V~C@@6zs9+x$M`Jk>FMlN|q3G9m>DocPO=@ z?u&010(Xm?z}n8Wd^GkW zqz`E;+w;Zv{G~>#ztn%7f2zOSU*VtQuk=^>tNk_pW&T=!oqx5z-oMV@;BWMA_BZ)= z_;(X`A5m3Q=Sv|lGLTPgAOs4it#Y*Yr4T5l)+q$WQ~g@%{%EP=(O!Z}GPhw)&$1_Y%>BH5&Q1DiApZS=J~f?lGVg1zbU4xWWzT5zyGLiV&T7z_>zjtJ(EJk^{_v&)vU zEI67%8kg`_2FC`kp!z3eu13jvSOCp(a00bADL5rK9r^XtekoaECiQnS+jn3~a5l+E z7@WtW2`w_CevosexJ{o-vW}D`gWN(JGEDLU; zu$63MpJO|Ytzqui4#)zS7u-s5d(a!)Md@DR4-Xy)9ts`_9v?j0-x@MP?m(B|0k-x~ zCz7d|r4A*q4nn=OK9iU~79V&`Q}t zGrxs(<=7c%l%!zWqgK|?Of`pwPzcj(Zznp7LL?|cxdDG@OsFVS5-JI-43&ni3r(fm za&CciTES_kA~YwE7^)1>$_-UxjV6X_Ldyb214l!(p}Np&l5K9No?2WNYM{^<+8i1a z=uf4aLOW<2`81NI(C$EHaBFBESw&^2In?5>54DD(Vdbw5d%|79iJ_^SsSkc z)bK;$mEkqvKZllm*Lwkpc zhNcaT9Xc56*9o%%vv4iSJbga+O+N9O_I^1YIXJESjbUYnT z$J6n2JRMKR)A4jX9Z$#q9g)B9$D0*Sf8YP_ct2?v{J!7g$CjK9|33zP9`O(V)%9m0 z1;4bOfcO90h&TVN#V@U&#xJdRDOORe*8EDH z)=*qVu~w)2xvpLQYKrx`pLG-)bQ>r08!2vXmo`z{@iqM2-%#$W>F#gH-$${zUCQ#b zP;8|b6~e73dYsShF8XsK#iTD%mf4-^jM3en;=u11{a=ZhIu6(Jlsl0>w~xqc7ynZ` zBPr%P^XV>d^m;Odti=?^Q=F*VsA<(R@~-2QTB!9laP&4(-0W@g z?x3=}z5Be)-WG4GH|kS9kFSfj(wFE<@}>Iv+lFtTUE=fmGJV6{!Z(tmFW*;ywAeS^ zH_s0UesYD zh4%Co9k%(lS%St;YuEaAekJVj?V*wE@V&1#dRy!k-$9PP!@i>_BE_aUV^Fi)F0xBf zV(l?0@w7kn`r7>|TklT_`;&$J$;STV!v5sO{uG1#$wNESHqn80rdLI>d6@R6L1xrE zAp*)&ZV{qgDo&iQ5>C3I4Ek=+zW_ZObZ5{jfcJtk9M}Q)60jTaHDD)T8p>Zr_W7E6h0)qboO_ry z?qQlZ@u1^TekaOr1kMF#3eXRnM0gP}11)6md+7)-Wi;PKtr=+l*XR*CQA>e$5l+Ln zI_S}@MtSaW8t8jK|CLcbZq-4PZvfG13x5OYkkC{ z;C{^nl*w>Cf?m1<=b@wr+VCLvE^ux`YZD*|B)7O^4=v}}Td8kZM+ z{RDIz>(*s~vzc&?>jtz286Z^$;G@n=Sx+H%Byc&EIST&U+V)UJJF12|^9_PJ+Rt@b-=3;9q;a*174fKb=J;2@I z_XVbb(+vC_I04XafldV);Ismt1ilRZ2;cx9dQ>+6OMx}O{wV*vnon3~-AuR(^e3!& z^AOYOVy4wd@MFM#1e|_cUS)y*8E_A9r_%!JCV_q!_zKEj0)9F0eDL37G!C=1D+4ya zLeuX8>ws@FpLZ2?3ncG@l7BHMkbF zj%$1uSO3pm8tPf;0osRj;b!l zT%3iqa1gl5qP@;?VO)d3IfS}HG`u+qgD*`5Q9;?3{B2M zoAba=MwzRDmuO^uXRQGTSz{55dWGu}wo+gVY_FNGN6KK1dXKM4Y5?dO9biGFv|R#ua9aNUmw*9>*ti) zfEDo(@Ku!gEi8Enba)Qx=D`N0fSv{V7ObxzN~Qw`VRak=JryNyR!?9SnC`;Tns4Zm zZ)5enjWzW)WS|q8>Wf@~QJBmz7h|6>fGf~rl&`{8H(-CPy#tUXU9&dYwrv~Jwrx+_ zwr$&*wtE`Wwr$(CZQp+1?|wMdkm{P;5P>aUZ4Vx?FA4y;hJBlyx<{W3l zbxm>j3TTN~$z`?R%}_kitkL1;IGnZZY7`T3ot(ZnTvbh!>f2?&wbe@wu6$9>%WFIL z$8>e~F7O3mvA6En9`IRN%@S5^gCXt|`I_sr!;G)eK=@}k)?c8WP zvAy*|jIs&GcoKZmkHr&G@)O*MH*$)pe((z_?JJ@qeaQzd$9;S$j|Z88K4QYjR`L;s zI|}VlXswFSmH8UuI<}jo+co#gGq=fbx(hu0J?!Pw;(BT?F`;)-!jqb7Of z3n~+_8~TN&kc{Yw_dXyo)t%K2Ty!a<;~w|?@rs|%+3d@z9rv9hDj%lqi&&4cx_H3$ z+y{h{5;SXA<Utrhf*6?1J-taBjetZB>xdycAlNPN|oD6#8VtJuj+alZTP_0bWVN;b(&INU4 z8X?+eSog~ztcDM~^5f)d$jxUQ4B*e?+lKt>bUEzU&lCtx3FLMOv3P*q*mkG|$3U+D z2;@h|zMz$$pPqMSOr~~7y-|=CMXrmgoqdkr?!`#9*H{Xc!H)0yg^m!<$0vrUm=>XAa zL!s3QTKo~f$|&o!%SAcwonbiwc3kamiCF7nqep^O(SR#Li+@!Uqp~K8@Cj--4oGIl zWzrkYbl*u?>lm3?NQ$wUA$R)2k%glJ}p)dLax55SjcQMrM)@#rG~TK=<1xS5;c0$3@g&c|etw$P z&+t1@jaD&Ue($k}6qIS;<@}GcrKU`#B>;PbYFm`#Syddx~Khx>1oS6dbE5n%md8SoZ%Rax?K)} z#$JHHO=rGcK4kLG;$MIxoWUnFf>IHkotlz8 z4S&`J^8OKJK<)I5wOaN4v=X@_0qR`%40W#K=b*z^c%Ydh1hJDcSZjc}A;bQZXa<+M zp%G!V1YU3rXvN0%F<{3Q>cPS)hlaQt_89;0Eg!g#s1xxaGvH!^UrTCGi=I|2+G6em z&b$U#N3sK#1+NJ$s27__VHC$7EJbSp8_4@OFc0+Sf_&HfcMPrYbUpYe)x0clf(6FM zEg_c$%vU36pi4g+Hg=cap8D>WA{zr3BB1xxd>W&VA&hT%FVPqZXe5~cK1oY(6O=c~ z%QZanxG?4n772+jhCS+V9)5FGzk<3_hL1K6;*aNoz%wzUbYjvjVD=L#;@pj$DC_$Z zx>cb@`f6!i7v1WEswmZD5@+__wy%QWv~$TtU)rV(ItD>ay2uwFV)=6htT`7+pL!z5 zZr2&M%z|LhIjwsm6r(K4QSfH8V;cAm)3}K=h|3oYL>E9a$?OjOc;U*2mZ=5M0od}# zfu`I1%+2yJ)3<;#VP$N9v}58I1M8qFSaO3qyiAzp`cbE+5RNT49`mE8$sHGS7oDQm z05hE@c}JWVj5m*4pJsP=jx zrynTouo2|&wa{}(Cet3hx3^29%kUAVl**BZF96}PL7M~kwM?~}3Zzj-yDSe$+X-^>q2ABjEww0jL4bOc`l&_k<6 zeE$NdwJlpZw~4A0?wLY)E}i3%M)u`qkDC^?q)6O(r8M$H^1{x%>*0`gi@%#63_gUG?8VNOu_X`Q;&$Ol|Q-B@wZ2FCdWHIx%iG1FtvR`OwbsBhd@IB zk$$90T8@Tk>QFSmlVB=8!{LTneKmuuRm-7DvD_hdJoVBfDGB^f<%wHjL(j63~n;n zT8yWQ{2oM$I<13q?$9|UYp}BVX8I4v4!lV z7Zmy%&6(UXnb@nO$HI=Uc_oRquO`D;O1)dk+$WT2S132C){A@E<($eD)#+p_Mr{S^ zeyvsyl}J*9mJ(#kevKId)`$v&&}C|keg$*!*r=2aqd(G#LPkY6gpS65o_NWL2TtmQ zN28#%t2H8N1#{t?+J$qZF}~dHU3=iMmrK^8aZZ=~r%ln)xoBQJ_`2j{98x(oDBPo%YWlRx+{0zOpI^) zZ&&Kq)SiIvqi~_REBJb!qI#dT-va}6)uQ)Sor^ywcR=_UJASiK-bW9=$H)6_zTFI5 zQ*&YY7}I^n$?yz&`1_h#6QHX$rKjp#?KzpYpUygR80+~nR8H`YVx5SJavbrFa$VB% z7HD+miSa|Q9I0%;+MvTN+ksU{jX(!oW>>Z*wwG>TXg5wRXbVYouc^Ol&^8?XueQfF z{OVi2`fe?+HFrI4GV-5+usiHTC|smmizbvb+?c&L27h4NpcZK2TBQ*khhpG zQEm#ADQ5#xwF;~eu(!%Df85kBSz9AS3$QN;hoV14eP>KSqI1Krh@%j9gY5I{39Z>V zL}QXfE90qQ4FhWg(nSkqD3WVtmMLfr6Kf<^2Tcs?oG>+`XlJdhSQ}PbK@PyrJy6BKPo< z$JjTyJmFx4O62!2bMha>1CBqjr^MhTK7Vq!RezTwOd&UeNvoVOb$zSNTOI92SAI4*m z>qTox95!RtBMLStYov}F43`*bN0-}|1a}*_8@LApmy?&14)t7hU**a z8~eX6voEu2yEmpbexPRfC*}H4iP9yJy$BSgcWy3jS^0wT*^}R16PW5{VKI0k* zwhIcRcZ}=wR$n$;qLOXqSISQOkqTcbZ;}obTFT;M9Ax;@&t3^< zxm77=y_SR}?@HGj#Kl_32q&CBAk4GRIKR14C-0o2EHU&;&Zzp?XIQ=OS9$Rx81CO^ zBP-Gidb$9E8ZGp5Ife3+ALtDm9gAHSH!z(5HHO=J8CiI#^(qUH+jiL|Fno+uVi7=wcLlRhzHdm zR@NYPHP=)xVY!p4NE6Xu>Y7b2T}*#zSR6K}h;M5Uy_~@+oxy5RwKV!3PO&2XtzPt( zdGx!i<-Siv{90~2mp)~ezo^d}4@<3<<-R~gyhcU*mSr?|Axo{GX!atOdNIo_0P`(9 z^DPF=!N^r933Lr2Lk)9f{0RPVbdJxojn20byC3${XpI`O)5I)~uP)V2*Uh1Lc@KEdYW32=?GwAVPqU z#QG!%evvx{{5{5Ym@;{%-AFYgG->J_JzfmDKPTKV>Kp>w9SNAaxl|1o1@+kH@SOPWaDXQ(uf3=8 zc(<_T&r{p$oay^f=ydbK}!>yKZyc zXuA>W1flP>-5|B2(DjYo@VJ3?qHl$&?!MgsKMS-&@de=@?%P4JU$Jwsb8+Ob4*)>{ zNoFF+QhrwzI66nh7%kmDKl%w-0$BnL)1zWw-gOF011dG3Qtf%^{h=#Ct9W{9c=is5gh4xnxY{VTYl zceZ9h4XhDNGqR#@(J*Z}M7PMgpH)9&g#|^FQSS{*$U9IJT%{9&+LxYMH{_#BR&ZJR zCoewq5K*-_4b=A`pyyY9CPu3v7;Awpn9&>hn?w~>xlS4qs6HZ%Xt;4Tj$RV<0Tje& zbUF|S1-``(grfHn00PO1!dX9(WZ4S9*?A8OT2IExKqk9*uT1v$YUAyfN0zDi_CC7xH_5+FJ;T{XxA94}vi6%Rv z)Y_oe!Q~KayM&q)Gec8jc3RZ>ZOgVf zn=x%dxwdVZ;qm;3zE7D4rtCQPqXoo83K9;NH^PZ*{mf%MB^4sE$B2OJ>!CpLFX@m+ zA^LtGi6TIYRi6KSPK;E~xnDxT08UnVnm3=#T%iF zHvG~G?WIAQpdGf}cR{%%aLuodqY>P(sRao(Cc!!x(YU1uAC#!|=N82i%OM{TMT+({ zVpxlmi$XkXvTp)fXojeS|DkyG1Xf-E_xdZK_67Zxf?PKFMk`)7%zp;y--s}On6W=zM4U(}PIOpRENn?woK4`E zHE8?j?P9FfBgOFH$JFUh|AkVbG9^-#Vj=Y`sya?(ea*7bMwMvm z3eGhRSe4@Ra@hv8EQ>nM1p%yT@FD_;30C51FD9@Ff&_Im%}@+_Xe%-4M(7Eiv6=Hb z0)x7OlF#T8P}4We3$pa^O)MCar<%aqj(ITy!kxsB^_~|sf^=e*bbit*eQEV`SO7ydZf^P)=?$s5gOgFS+KUNJ{IjH5pq=EIa`#F&dX4RnO4QD$bUrbKF z+|IfnoTKYYnB?dgB?x`SHvqf7rV z>5V?uss=z)1f%#I3w*s80^WGotGPJ}-2HOPRrK+;`kIR$i~8il3FgC}kHL@i9f<`f zN58$mBz>X3r<^DPdI5E6Z|4(}XLHxO)kLK5I~W|36OzEg2;wHxh!Z*u-%Z7VG^2x4 zjRl6pu#FKQTFS~6K7$um7*>r?=12B8OoeC{z<>aQ_NUt}m63*OVcw zRp$&U7CW=M9tny|`lD?(ygLo>YhBEcfW0dY$%?jmKdoKudYipoN?7g*rO?EIM{8vqU4Y;we&e|JeiESW7}5* zM8kAbtKPHNPhgga&_BR!pa}r6p#}iI9c$bm1Q=A-5FEB%lOx+*CW}f|oLqhETL&{; zJFqjM{&+MUP_GHgjc%pq?3lObdf%@POi2=_^Kk0$Ov?-B1`OJ-MnbalEwvy){VwJUk z94no2I~6Pi^zy^gNP`W^qRg+|N5h%ddQ#~Wyv7tB4!VR> zJBJ2dTVB)d`0ZG*LmpFT(|mg_)Xx)1Sw+X+4uwBwX<@{=>B6Y<_grS}UrN|e2@z97 zhO8q{b7s(Pxe1)wRtqssyeG@vWRHSB-yYDv*f54Lac$fve&%e}NerH!5SI9`DCV0M z728j`e*N4{!{*N8)8eY_2+QNU7w1}iX>XvL`u$7dVB!%=Q>MW&saxE`+@wL|v15i0mJlEG=D6KxE z@Uu#9rlzdQuTjc~FBD9IwkCQ}-!Q-^M9k|bh52)8Od1nR6v!QM{lpD-#d;9ryuxOs zj^0C1ke53JhTVFKL<$1Z?L#g$dUmtRr3m}4KL!@{qbU(1ubq3Ei(y4(AQA0E&y>o2Fz!J?;Y2mwe&KPxX`QZ}p1z;(>El^9-n1-uuVo7jC%JNW&KG;R79MfRnR{J| z!ZpfK=CY}GaZcelV>7?GtW7GSWaYT2EEU+-sSEji+F;{D+}K=yI*Q1@i~N@RR~nA75aW{WTXg4Mc(2 zIN3&-8yis22Huz!JUeAN{zl*mOJiYur=u;;FC{M0=ipfH8XmXC8p^YTUcx*a z_4sjWTuEcjv24B#RF!o5IfsX^i91UgpsC_Zg*UIWnFD~HhSG+PCV>X?skP&$-Gq>R z!>s5tF}i7;pT_Ysqy)3vmYZp-YHOfAA`8k3WipyNJG(PdpX^&KuZy#rYfVy~TkEYP zikJ@W8yn%^w6_JYKVpuVQEyp?9Ci=OD%_an$O{ZS8V*pWloOE;q(7@SGqLG1`N%62 zyQplBP7>e_0-fuv5^C$iY@*jJ*D6=;H=I`iDPaj+J)oo}2V>x(5kzp9@a>~C`G(xW zML6o1NW5}!1MG3TPi z=bmk3_MYElC?#6jWgKI*UoBb{8$b7Xk+`39@bMop|Liz&?YK3#rV8zpVogY)(lCjv zr}b7QCA}SS>~v9l{`03cy)abhv5Mn$XghGTE?aWF)}x4#*jmnN**>%lTSeHz##

-Jfhs$JcTa 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%0AT;MpF=Wj9H)^tWI`uI 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 S9=intFSCQzM&(53i2ngr>|!DS literal 0 HcmV?d00001 diff --git a/resource/docs/img/seq_put.png b/resource/docs/img/seq_put.png new file mode 100644 index 0000000000000000000000000000000000000000..f2c82ca2ff4fea5061bef1aebb4ec7c13d447290 GIT binary patch literal 93320 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 literal 0 HcmV?d00001 diff --git a/resource/docs/img/seq_register_resource.png b/resource/docs/img/seq_register_resource.png new file mode 100644 index 0000000000000000000000000000000000000000..ef2c95df7264dfb2ea04fc0826cca49508c3e0ca GIT binary patch literal 59726 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%0A^x`cJ1qb8g?E3e*W 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

NI?U|#CfoiTOt?0zZaSC9}A=cvL- z7+q9ezBGoVE3rREO+({}!!j|%QIB1(+h&~ncyo2E5ntzEaq=woAijl0Tm|ds2r^C; zrk`UaDI%ZPv2PcwSJ+*fP;Xu!+t*bbghyAY1r@~4_i$l!*oH&I@4yA<4*a9&ZBi~G)k zbprT9vcNCZ?WFKSv2kgG-2)e* z8Q~ZAb1QU4F(>C7k>enxT9NNA0l>rnpWCpeJ0z>a&IF+7XTo29Oxuoy3aIywI%4CX zT~HxI$o-$j{-^*3khN4H7vM}e&{gaAq05+DXWw3=!0KTtNdT-bDwu`Z#=92yAOrkN zq-TVlwsUnmb!zSJoStW;$Ok`Lg1%kg;nZi@gL)Ro8z%#qMsp7#NLq zb?qLBR(*|J2s#TwhTV~E0I(2zoDvdDZdSW`;iI)!gG z+gIMFF)eHTG^N4FCM)vrt4Il6&!IGFW0G{+nO z-7=icCnnjqW$lj0!@0lT4AWN?kV2l9b*xP{)kEZtg|>D=(rgwgND#LZ&%wc=3-Z`ug?C0O<^ZX6|I09Pw`rWwo;?p@U zZL+9G0clzq8gH-5Sm=WPu(Y^!h`krlyfLm-OiHefaFmax%mg771`atwpXd!|6ws0OF7+=e|@pS<9 zo)#*9m-^+vhms`1XC^FY2M1YHNys29=mG3X;s|bGVg?9B1~sCZ{1k|VrG=tF^RU2D4BF7)Uq1Q37Q&q=lT5I4HgR^DPz9qewrhqmm?V ze0B_Wt+H?Y!st;p%~(TI`Pid4-w_=bfZo$EPDkbmad8%}#ydf##w5uzke=BeSXx|O zU@O|{WFqbFkJi!(=^Xn9c+v2vZEbB82=&+e0zqVCI(}4CA-K2!6)8#q54n$LnL|!F zrL=8at8HqZYY5_BQp&wgQsWCwCGWyI(FD0ku+vLgopdYfVvE0(uev%qTj%Ks308{% zFGSttA~h^(lrXv_q&y~#?@NlKbX{{)F}j_}c^81V(of|T=m zqO}JI;Q;n;Hq74Iz-Ri4H$|ggt%%J4&zWZRK#ZBQcj^I%>dIlc_dhb*dAkGyi)9HhEGa?pkwC&sw(U2fRbewf#sTWrWVu^I^9Su(eXQ=zdhzyt8?g zDp@S8d_1`sQJd9(j1z(4UK5)pWJw#cW`_{0-DBpF1v0b4fU-(^$?Umv4d2991Exn2 z9iCT15^m20-VGR}*&Bi**NG&U7-F-l*;Cj$IsA2mu_O;|O?9)5@M!kPboQ^i51ZT? zB|0M{oA41--vDj0m^M99jnrsq*6!_yoyFh+a|wIGw?q#Lr@BRzY2?aDjIeX+O8;8%5)A9e7q1tGKKVihR7z zyP**EOetC81@Y5#G4k3V!@y-Hv6AzI8y!NlB3G?Y$$%1F0(zsrkPGsZ{gRR5c!s@# zZS6llMA7^J-3Kj_6G7Z{7DQCoP#G)Ht@&}+cO?t`ssvPzldoS`J`MeQ@!WE4`|MH5 zPg(k^6j9g`ahOGxBl&JA9C{FoM{5ujUJX7ju1>apyips_*@C+CwN0O;&23dmQc}`R z(b8y!U$zY)o(#XVzv@Mnpdca^iGxAAT>JN1NZc`l~NJf*#gS z=B11Lr)#Ydt!we+$`xEK`mUOe(tD4uL}H9yI<2?0N|OF;Ej`|$>0v?D;>!Q1TxKAK zsO-6(oiHMrM+@D=#Y7ndnUaA4yURmg#gO2_eSn5j@C5_2bR@LQb0D5(l8;{aHUxK( zf0b#9*~CjqzYzC{pEAysi$Z#Byg+0d#?Ddvl5u2r9w3u2DBLxf@*0^}ohw0qxMQu) zqP!k>uw}844wuIUU>aJ%tK0HQ;&HQpjJ$Cc4mk1NUcY)#EQr%uAALBy8;0kDL7>4?D5n)zrV$PF0?(jYmX_qXdjs$_dDx63tCwn z^X^KeS#r7)*M>a{uw}auwu(Cnh4QFu?SpPk+DdWN-LKvo24%kG~h9J~lM@$kKs3lw+s-_p@2xWG0! zif4)I$uY>L;GYKcFHW(;c&P!C?+OyrbtN6}9l6u?P&NCB>%upw?N=Tg z{2Thi;7xDZF>;|T2gSKTHn&4_iTa^Bn|M-!U&kMlm$Iqq#ZbVt-s^oc?9NK4X3Eya zK<%sJxSk7aED2Mh@!}ue-|Ne=Y7Em+uRTYk>pUNW-n>yFd%UO3$0&pSp0ty9)m+Z* zW21Uj#P0?bTy?Tceu6J)z#iLob$54fd5d>R>u#F010Ab5c<`7O^-)lp@c&+C5c()G zOp%uxiwrr!_$~mRXk}Zh7cam(a_5F{FxWA6KFGN_RjS=R>nh8wz}mJQyHa`&I#2KJ zh*M6H_z#`8^48S&XDI9J?`Wf_t&ItX^_jWP$#Gfk##l7{a#=pj6ty%OYEW`guqqW? zy_`s6xrLYS$lxsfk#h*wqoYIIavQYQD{hx<`q(fX?yOKRpB>pxk=WtAij7 zF@+?%s?9p0GdQkqzBSz@dsps`pHpE$R&j#8jM?DmM?t9sOC$QMD4fq5Gj&cyl1{eA zYLf)mK2JvBT<5Eo)Dtz#J78TgK^7kTs@do?V(JVPPE^L$^DL*BO4>FdCd59gUKY@= zAyM+GsEkO(<(7nE_iiM9bZm$aI%54uUk(c20{Dc#K86YL8~?MBsN>)|LM@+}z-vAcn|feO1^6ylt9*Oz67!P;r*spURvhZ=BW?2FEY3qNZeh zoml^mxg{q@k}Nm`MfF%7)?EgtE~Z9cWL&GNWL#aVm{9YU^9ne{1!cMA_IK(t7--`f zwTo0=0P{QQ@ruf$>x=JMnwk*BLP<*5wN!4FQ)wGuUup3H-J{myQ3gsFR0bC&YFcGc zoy*iN)d|vUjyzLX!gal9h(Jc6=>g;t45bzn2zlZQ+bHg5u>p` z{#*2YoH>j)HT*Z9lY#pwcmg0y&1}){hZd@uo4>}fqdE08HNUHAxc%0*z;J)FQ~715 zZ5y-n6G~{=U}n43pPIqU%eOk9vjM917HA5AV0DyEdo5PoBLWCDE-tPd5L0nYoyEn) zd=l0Xu{b6-`SH_yV|II1$BoK>$|Oea%upgOoF*0DUp9=TRuUBGyc);Uq(UO-Bu#@(t0)Vn$GQSl5>I$gqfsNs<8 z55rCcz}-IUtb$;aw6s)@Tvx`)(b2pc9*IW_#D=6rh6N_&0PbcNjWHVEK=TeV|ZH?iTB8faw zO_ezy0yd9N>Ne$}s)4WL(>Zqq$9t0^|CsoDs``Jt>-#%@;}!pjZ<)pW|Kn`MlI`s) z2FiyE7is%+kjNVs?ipLUSmU+O+??zlEEl_e=>n4ApP%9NL2K%($GzumwUbSsHR>e9 z{fmBl2n#)_&wU-}VL#B^Thl~)!&F%t?bMm{sYCj~=P6}=_E%FYJ^t#UN14|aT_3Xl zrsMA6wkvfy-@35;-g}K>Kji_H{AG^E6#j0@36c_mzuR6K^Bweu(2gbLuirFMW=ovW zc-+>w>mj?bL2{mKIn&?4x+xdRDqUgYIOqD1=l68c9W;7IeeTkQn(O~O2Ak1~#=Pel z@;Yg6dd%JZ=K}~AxANK=AOBLg?`~xzKQ=iWZ(`=3U+v-$t{$;^xMtCIetJD%zlmO{ zZN?zYfIeYO^Wsx^rS#Q$L|fC*?_^sVo_Agw^&%p>hw6nBQNJm!d}+5Ww?ljD8U<7e z8WF50e6|(j*C_VAr|G+5>iIbR*M&bHUHE%H`tx}DNlma}UGjn2IO43w`D}eAaKGs| zo4WQ`^?|cgz1KHA`|;F>W^JEuFR#)uB%uTfjIWVz4L|;=V3pBBHq-3Ov}kcuDBT$^ zTr?A8p#6NR?sf0^f{*{+K&$U@%=ygB`O(WjV(zw6r}53enUmw0yQjM^&$rEa^{$E( zW*6idA^ueBNJ!&vEFfq*qoK|}|NSzc_Vs9mTid$_QyEr9&-~?k+_`an{n(t^PGG#0 zU%fF*b&tQa$>WRuld}jt@9Kag5q@vEt9{Eudk5>!?)<4O6!L_}EHvQI9UR`ex2~Tb zC5Pg2v>oo3o>Z8I55b9ESzf}qAoD*1;$ByVNeG;{e;=6z_8;Xe2A-&Zmi|G~k9PUX zXZz>J=OnUc@8A!K@)V|cP^ou)T15MRHSku_hf7D+enUH}^a0!HGiT#J6N~W!{r89W zx(K!dAB^dFc|7~qprW^qiPFUA`N{rFWyyw{bZYc*AE!quf4}$l>od)1dX%m9Nmc(k zC9C*j{!dpIk-$yEcQfbH1A(XNHcan$z6Fw=9K8%+k$YTurztm`^umpQ46S3Hd$xhh z;0!cuFa$QFcXUsx7EAgd^5~f;{I=(CN%Ne);`8qx>!=P@oS)upJDuL7^E0Jk+VC3T z2{^)jp-6lx6MLqsl}rAVS8C2Fz^!c5AzCChW(k5awc9aD)0ECes?Jk)G|C9^p{P;3Ayo=AwI0;C($6<^oF{dhQlk zrb|iHOT`;7RR7@PelkIAHj`}(j_L@@T=+WM>t82_?js)I4yZ@n1gOS9QKk195B9iX zOrtg!fq5Sy%R8XO*E$9vm)%L>IoNNEZ zzT4XIPo9CD9ghuT4%T6HWA!FA7I2cOqEpYj7bUiTypvF?ULND^W)-}hUt+IV7k09{ zqCKvp6JN(7ZX^~{Yr6CM@Z<3h)>>v!)mwx3y+m?V+WN$=NswqpBCFJFo+9C76TB~9 z>aO}!2}ZNBvqTrImk)x|x-hK_&on&hpF43TF-42`)(E_rIj%4nmh>1I z&viRl*^X@M8?2FoE{gFmY7T9*l7hsfb^S~F$CoM-Iqsa-!Xm4fw1<+?AG{Y1@jw=W zh3fuN100djT=2? zT(%&+NGML7JusZ|jx5g#Adr)kQguIbaB>)p%PLC?xF@9@JJ{B>2qRuFSe%UGB*ER9!6UFy+G}JB zu99wTDdMfIhrt`JoQ5%g%`Jd5;XTalAayZm_SS4<{X(E*P>7v}Z}CmS z?|;r0)Ec7^dv*c@1c2tY7}%jwhP$C9??h??BXxk_py{?)^+;*H(x< zI)XuYHF_Gvbz%5jLiZ+@#lsZ#;Plb~N*d*I^?Fl{4G3Q>Y4@r*Kl0_y zM8aG;$=BDmF@mnTcpyOd((Gyerx*GDf-aiQ_`j2M%o^AIA@csgn8!TUJzDS#=27D0JgcG&HFh8X?|3CvxWn{Z;!sC2V9t*pXK1$OEhWG|W4U90j6>u-RdQv`@7B!|j@ zCfoZ;p(JoIu{bGQMz=j*Af+^8%h#|%e+-=LxHQ@9+Y-Wqf86yy@=)aE;~N@sf2yC_ zU$6hT^826_&EsTF4z}3=H=idLe!VT>;4C}4@plCa_9EbD_&Og2Oxv)sYE+cLJu@KB zTHMBN$nWgh-J9%;gw(>PV+c|w#aNrt0*t-A{SoHtY&9H-KlUH@e(O8hs8?H~ZF~H} z(8x)bcOq_)i9aB1D9}G}=)r@ggABP?tX39cmSQ`y%p)<e|k3EADoV(D$Eb zS84l}{aid0yS@nkww0tP01P1JxJSe^lDJ*-T$x7QkZ zRUOR{)lv{h`1dq5kX82OGVZrZOj=j=chM-*%;?00vQ%p0_wg*s??p2@2yQs3r17S~ z6RTq-08I3n2pUSdz=|!sCwaCedAz-U9(iu#|7dvdJ=u_FTTG_Jr(vRq)F!(cQvy@| z#?n$pzZy+r`%>}+)}V-3b7WHPA&;%8_)`BVd71MNgdz$U+AyDSXu`mAnK@zdyw0cUtZB4n~W+9}&=pHmx0KG|is+gvN@!tqp-nu8`rx3CZHor3D=pfA`$ zgFd2)zO#g#|2BeAa^d>dQ_}>Gr0}aZr-IJihN~pN zM|tXZ-eXm-k&v03i)Zww?+WTvO!l7LkKj&LONVhfgFQDz#qfSnCVWHDdKq5IQR2k@ zcc4Ck*;(+dc{=#%4a@t$GM>rTw(8ooFfwm%>NR(s|NoHomSIt@ZTq)NK}mxU0STqM zK~P|gNOyNCAt50p=^7Li6p-#lKvKF#KvcRL8IbM<$$5`i_y1Yh>2_$EXlBq0 zfdCzL9U)vcKa*Wp^>mPsT)H^KdigcI_H;7L>q+UDOU1OtbU^IvcEK4yI+MbZl3s=P zVv1z{k*~uY@~pTU;ue;^m1s2jLi#(z-!A#7-YaKdw?j$80=>((YtqG0c5Z}E)z)f~ zBJ7axlw!cQX>oVk)|I-HB+L6fEB0%k*#sp5ghDUlfpqf?5+Z1Y$bsC^RZ+QGd=m>L z!4;QoQk6U#)WZ6qSX3yio+SbN@ijr`{1jM@ueN)-I>u3q zMPlz1;il=^q7!9uce3@8eQ7YRtm*S=Tsu|0dG>Xw)X#d@cni_q|QO zP9}f{%Zm^V<>jllS;ymmC;%g+*`U)q{wvveC*oFzAD1?K`YZBQ>veZ?S>NfvP5kSp zt?UwP{#X#swfKe|HgG}93F>w1V0^r{mwp(A<~e!O*e$^ptHeR>@9$f50cV;>fE9HX zd~|x2O@th(V+095i;m{4!iZ_uEtGLZo=vjqWX_h7M8PQjWCA;IPo4%TAnbuK64cRr z5cKG*Nk&0lPki*YxR+MJN6!-TCst2#b@}V_!xQa}N&YJx0r4?6H~UW3M}vm($w~0! zEHF{~`k^xz_&efTyniP2LRJLV{ria{>UE(J`rA;@&3-@X0=m;kC&!(Jnu@CW#KG?6 zDz(w^#^E_F-R9cyc1)^|-Tv2279V%N;d#=5?%TI31p1at&lWKU{_iBKlVig$d#dl< zzR`_-GfA%TIX@4RT$u0uPM7-o_pGnv`FVY!HN_OF^ubX#6?&Gqh7Ek|cHTCq{M=+v zxa6a{LpwZfJM#JC$3PDP-=B~b+GiJi(=RqQmIH^$aR%m;GR4|Pzm@NiJb)plx)TuL z7BsCp-Qjl%pMSMKIt1&DJ>1s)$gePYbZ8(0g|nJxP39=uw|O++70GUg!*7!_c=7RV z&9_n1vHqHoDfc~83Nmk!ji{1*Qw?36YB&L1=~o!0^X*9xW|o~!H2p|h_oG`o+Me2= z+g#e&{z&Iyf`)f#mrI^>B)J9hsW$|Ov^UI(T}YbXNGs==NY;pCgv@Nja{;V zm+1U`_GZI+d``D_xa=0ujU{v2`_apXBbMS5T1)EHXgh(_k`IW1vyXTER+x6bw9+jP z(Vg!F?V2>y<&ra-=eqU3`gQ~Ze#HjZL@=;t2R9V(#6?HLG3JT96O?EcR2*rpG=>HS zUpe2QH&X!xWdw|18sy3_hWlgSE*506va(tLGqAtSk05k@R}5UC2tYSSw&&IGP4y32 zfP{fOW6kwsAZlQ29QZoBO$1mp2|Qip)l`xr&Cc^ki`lH~Y+@QQEt1t%3fkGJV*GWJ-K*-+aVF)?d>fWti?E1gp;{%~?|CFQa zPuLIHyUk%JuD^69K|NU!g539gRetP(%N>uKyi& zHOflop&#q3-!~>6s-GR1o~4=}o-o{;ixW?LQ2~vNI(`oahw=6VgU>2FWZflmi;KHa zIKE{9Zi}F6XcSnzk4`ySpUU?tuB}+HXq7%^j|P(qD2e~pTPJQ|$_}Sy)Ne00VqOv- zh)(Tqm#$WX`Pvt+?=#!aw$?ER{OEfU@PqQvb$Pt&`t-=_?eu>>xh{&wNQPjwX8emW z{Bl4szEw-Z`On2k?`{l=V(8~oMr~c~N9#WY4i0zg!)Tv=+)J+dRF_}ZsQpvGim0pr z3jCYY)QKm8JK{z>adC0EzW$Ry4!T2J3ts!k@-pt>+E}KzusIl8!0BuOo!#t$Xi~Z3 zzCJGf_UY7z=}R3n0?OfN)+UyKvzTK(blqlfqg~|4&gR16Vh8SP?b1iCu7ciM{0R5~xf`ZoU$k+2B6Ax*luq&-JhFWL82>(pERWsMd`$bf(ZgxOLv6Tb`?KLu z%3l^fn94{$Oa{i$^!8bw)5n$T47Gf zt;&hS^B$LhLm$>d;oi{BeX69|w>fKTYtbCK{F@)THUIeI4>+az{BcB#r}FcwCY)@c zrW-qB297Qjj)i8vbyyiNB^lWu)YzfQRgO59FYi>nnlt#>H$ABQ!1BoxPLul4o}Mr) zdHM#$#5iKhuErA=6I1Cl^Uz(EsEymWHp*pzP>z<{UhE7l>Hw8nv&Fn=3 zWn8gDtJ2>)aB#^WPB#t$A28%$|MS9+7n6Hdn*)8%vKt7gbDAqAfwt)Mdip;-f(xl% zDo@t+p=e_o^?C&L!u#r@*Glg)GVXS4Crk-GMhZ3xla+U>ZB_4ae35!C#YVzU%BrEM znJ0FnVH4$bM>L+&XyDp6{1lSbaM4*A=V2XzTC|VPR-(W4M%8(tagOSbd?g0oVTpo5 z)>pzt&sS4bDzYbL?Q1KHMp^exHgRl{LrvH-s+=#;X{LY*aK*h&%`1;`ns9Yb+Crpg+@>{_iWmgid zz2Y|r_eq#Tmp)x8sljIn+} zGDnfyF%d4Dnw>V|_9mWQDAY2#0n_|V`Ja`}=OT|YD!Df2Spwp*d@Iv@pvp&DDv5kT z{;-fL!y_}tyjz6tR<*S;o6FUSx~o4KQ=g+E`3E@j3-mL0ggH4m%LQ-VS|gO_!qt9< z8(4DM^A1dZ$Pw(b&Iohybjp|xeW6$TudI3(*{yz{Sr;C0$8=D7BxsY5$MS@-(Su*vYy*6-)c~acDXQOQ~Fb zPdblv{NsLqJwB6rv~WDNvr?PF-c{^qGw_7(?}qVsW_s6nNp-beA2`F-XFg-q)6mGU z@f9GVpxzBnQ>3Kg7G6*nj1fX8$|e&C7N=F-9=FeA6&oV5bx;gRsZ8(+WDgZv&s{-6 z`)>Gwe;KO!?LC^FUOmM@%fXS^mq!weE94J zXdP)jXB}v1+gF+4&{nRZx#TK z-=VfGe77Mj{l0;T$p!-9^%}<^DT?h%3qFF`hC#~KT?%2V?Hx-TbxEkvJlcWK>*)1+ z@qc|A9G{~o1-0s(XD<`~vM~cey0)R=>Vi$EOl%7Io?IaD`}dt^v=j~ceP^`mhkaj@ zCoZXM82TK|Aqi#o&xd-@-quGIiUy}0`I1Ai`YF#pG}MXmt*mtL?0z`tSKKxhQyC)_ zwRrp{f5XGYxiQ~CPgApH902E9@bT(;@3K0~)k6R(ut*h4((-8W=sTp0mekKu7^TAS zG-!kn3PTh8SqF;(S*DXlzkU$*r$}iZkTjKvw5R&aTONqI!8tDCDJ+s)_xu@IS0^bR z%Pd_x{i}n*R=nlQ^q;*>=a1x#+qo%|SZVd{DJbHSDx z>%kIwZ#ZypVBF~uE@CA^2rR*!8^0DvX&S1kryQti(Ab1ZXxfYn)Y@evRssf;2icSr<2x5F z(ETHV|H1-e|N1AxI)!X)UKY>Et#K?<4HKMYLZ&ZG2)o+TjOXnS7ZtW#X{4oozujaokj%1p;X?gCR`M58ArY!f)35HlzpI^4g#Fb$ z!zAB(5_6q>x%KtsGK_z;KlYr6xy0HKM{%(sL1}KN$7h6H32rjV+b>A*rn9ly!ayYf@hX$q* zj?8GEUE*vw*ESTR&c}U~Nf`62@5sH-Xr{gKMEhfEN_%gBgPa>9jdJf9JE7s&ERwc> zAJIp<3L)kaz5pHplT;hBTorrV3aBSnw;=Eeox;P+$$cb&kd^{l^IxfrQ(#GTi>LE-a88WSskBlPCee;s}^oj&SDdj z?tnPv`IKBDohvWj8>lD%N}r&X?cG#NJqU_u#9WsKa(X}(2y-p0Tvs~eW}#7y3$#{e zW@fH`kBGEJ<+kTjcDuJH<^9*0do$m`0?-qCT}a|b^F1<kp@t+q_|@$(m8H&UChOV|C*8h2jXedtlfPLFACHoGA~?VviZwM?nB5xG%? zE%~nALU(fFlkU$9vR7Fc8C$<5g@vK&pIciQ8Rsd-8_CHtFrUfUI zwduu_-$7X!s)u{%Ga*+}P}$cy=@G3&#IaqHR}gMJrs`@x)maeH?=x6EfuIL_j1Mn3 zo0^*B<>h6s(Ttb5J4~*PL9z{cvSzo|6eBiAfzsRF=}5o&{b~@yIQ!k(q5D_A^9RRp z#bV}I^3h&)Ep+E4HQt9b46@(46DquiKCyiB)X?zstUkbt;xerK5jp2zC?7p^Vp!Ah zDSb)T@c4@`4!MBVUcP={OhbNcT6Rafn#UlURJ1_UcL7GSbxRVhHux2FAFydsg0Gmk zlr$nNb$$p}JkeahWVHIy|1_^&s!lU)h!78GU3MiRx6^WtT925X^)Jx7d7JAjgdG|D zST8U*GH*$%8vFF&dMKh_j)$-hFM$;G0Y~oAfq+&h%_c>;(NcG&#d}-Q+w9b>{VWBa zK3S;Jo4*PSWM*P=Sf3F2F*E%*x#h-C?f%p?$w|!i_n`CBMTVbsEc=`OE??gW%zjTz z7Sz~k>Jw}jX9dQ#r{pU%b{P8lAJ+jSUJk_|qbsK`{6my_$2 zIE>acY3u3|Qq)L9s^^skZ|B~lYf`&WZX{EbZnK(4ND_<;ZphClT-1ox#v%Xd*D9=) z8m89M%Y;xAa;w68PI$5UDNP}8MO#Odtu89Pov}0@8AAy*_5V6pOkk}ZwucHhUqq3S zvwgyU)&pl$hP!uVLT``386FE5Ffri=7%5Vy@KnS4af3mIw+X~2cv5nT6rm#4ON*}^ zc{(L|(T;hhK{Ygi&u&rqF+JGbjOQNnLW&Ob_LjiJ09KO2W;5(S;>OzC276uBSFLi{uI!q~%Y1uO^#p_wAIU7j{ zjn9uG9xLjtvHxTmHF80ie`Y;<(C2Aka9UnOSm&NJ;@nxuhi{2rpBBu-RDJ~X6Ud4r zpvwjAJRZFgdJz%b+|ulmJ9to-!uf%iO3(&|!k`M|1anh##a{JZam^Aycu<@+K-hv|kYDeBZ8 zPQ7&P+%c5`S3voOra;NlJ3nSd$EzIoqS(BV0jk}pbn8w@x5f5qSLf#D7=dHp74zyz z5ORLLsF5SpoyeZ@F0jQ9bW=XR5HBe6ElYoezCD)IcU zkNw38p^=;n=O9XgGL>>Pt*FZrn9DNW1Nq)K*XxThWq&mnkm7HkQU1-ZzzxD{Z)s`C zCjI67T(Vk*fZ}k={fBY5S!hX=mN#b z5xVgzqp!oDf4bubG2PU3MrzPA+I}BLu3_fld2#L< zNd~-){PDw_F@F*q5tFH<2zt|Gn9m*`9c}Ng!@3IJyd(ad7Fph};OYxrw9I(WX6~+> z20RP~8|{SssnB6sK_VZ!16Tm#;Hcu$qeWzni?Kw6|j5cFp zLW1(;*O~QQK0ZD+wx^bf!U(_*;K>8+%dcO*G8AJoXhH+lC+t$(U-`*KFOmRL9?_e-$M6Hx4WEb?0%(emXV{4BRJw2PhC; zfTlE}L9^+4jFh6x#%as#r5udAe^ZkA4b$5_#ey+f`c5=Y2OZ;PU{-fzv4R9DNQ7*T zg1SRsE_O)04PdU7Au;ePhG;I5zkoID(~>bosaCLAjFArRmD_o zkuGIO5tF4uSVoufCt*VagXqGzTKbAb7)|aY!G^}wr6^>wU>bK5Mov|ZrVVCLKOeaj zx*(<)v!H=GM0l`?PL)iXi)3Eg9w}(*@qNCrtDm}hEfQAQ{)2wu;3xfas{Y5MjuKVy zgoy9m&y@}d7k0op&l(uC-(E8=M$t}u($+|oV5#*`^;x9pkoDJ``RUl;mMawmo8lrZ zn5JmC{`!i);8zS4F@4Z%Z+G(E$!amGn`Nu}{wDb3;K`R#U)OVkWtDu=@8%^P;^|G| z4?WFW3*<~PvhjYIO0X(PPB9^oxG>$Z9u??J5DKA)N~QQ6p|7tWi0z81k&!Lj%-qc+ z_8xhwPI@FyT0@WNgT+Ollb4b46%TWK#C4pfx_o3tRnL+$(n@wte|%sFM4FqMAK-vI zj~ExW!rvAV6aKHpdXn#ZP!W9l_Klr@K&8=-An;CS?kB=$6O~=}!M95AG)VLo zx^JjKFTxV^P&!z|0Ky6AIjx7{?t2vds*W>VmAfQkE}H)>LplVUt)4R<`R(LrN(${+ zGk;fFIHPRijj7@T;Ei~I0iN#6d)y1Spv&vTfgn`}>`oVt55K9hb6VF)#ueMEaW!Z% zA8K}j4Q{l<$I6{f1(RN-uA_4Dq?D9rI`dGr7iFf z$6Sr>UlvR*066F#8f6FFA@kwQ@U;a___0OIK*u`)18f z4&I{9-I{s)DNlAf>PcyLe}x>esDLu~eGNK&ef-1u)c)%7VHMiX@CW2^5c@>bKUb8b zpwWM#Gv87Xr2UNO#=GH?65g`+8rs^~+SR;M6-P16&LHuPTDf) zKln(B?(lpdtLyMcq%;Z`xoXwA#Pa&l`yO5fh89jKDw|zO_R1L;TXy1Hx_HqOarRJ0 z3h}nD7NRWni7JFAlRoSJ^4oRDtyUM#vgg%IYe$ zH5`cy$#7BU$99ErW547rz&qK1ufsaW?p07wB0hY1K0T3h{48TtDDHtaDr2x5s?oM@ zQRfqA0$h`@dl$mjBUwykYV7sHTRzw6@|-U-9Xg`VF^y*jl9-)X%5n<| z$Bg)&LEcGKC+(rJx`u|+hS6{+jclDqnEO5M%a{8@U^`T8)F|_C><_y}l!Zq7V|?#i z@p`QqaiH4RZq?1zI$Tg_5Y1%xXq5GMQP&2Bkoju@KDtt!DdH1KybxZ(@o}_{1iWX2 zNWn!zqchyG<&XT!aTPO-pL`9dKUrgi@MT0`s$^e211=_AI2;@t+T*=Pdpg4P9IxO+ zs7y`W+F7$cD#&EcASJLEb5)};&LVIxN8by$p^`g#U=_nW3JPaxBqYg##akeeI@#O= zWED>;shu?kQbZYzzN5LXW86Dd9&zWsfTjjL7ZYyJ{{)`@7Oecaxf&gvN5KODpwx|u znSC9x+}b)?xpLY%It%9k9J)olFUOsfM8L1uC=~WnfhMrBFVuq}?M&vSH=xqpK}MCu z(-Rw$7PA!9Gz8wQ7KJKUmWj zXo4i09c(jP=Z0Y2K&l>$op@M34}^q-R0tC(6GvC0vCB)5vWeYCVF7by_!*Y1DGy$o zYM3Z!Pft(xiDtsK>3AhUKVqwLc@qT|yXkBSJA!~4w4 zG8{Ur$^99p74P{SF%QZZnC9&9IHX<^<1Pn4%ZBY<4~%=|6%>M#h3sCpIJ>WCb+tFb z+T%~XeRhb(3~X?7bGQ9qz4x4X^XuE@xj9Im8ePqi2@7?<*FRk7t?@DA7ZeB|9)G_q zdYe!4W3TnuK^4kv=^iAm#IUTV+M_Jo;z{ne7PKe!3qRH7W@F>C`%{eZsKE|Yx>nTl zP)r-}i5Ya^j_~^bgK9@N;6ELV$3a^aSd6)3BbBhk9y*zS>{Yq-p zC47dTxQs^SaE=HQ0k=KmvA<=Ro$XqoW4BY|`d(JoOGHWdADhvas%8^s&unbuP(Gpp zT*{I*pNflnx;s0oeQKH}jeKoAwKZF=4R>yEz@hKHsnV}Wf=do(Rd#%ysyw9HZc#);1}nfq1<^{Xs!$QtnUnw}2`9+mVEK1C2wrfm z>fK5&7vSe7!)5b#$b7UQLnVQ867rJAJ$eI*qV(r=V4L5te)^5tk&%f>`uM~V)+26% zy`I`zvb)(I-l!@?Hqkv24tpT z=bRqByM;*I-~LXwIsmw#U@H51wn21De+!X!ARGhN^F}j&P4@GteE%>!4mNiD4>kg? z(WwO0=)Ak?FO4Wmq-s1~;b@eNxL1WVd-xEUJ`DwmCoJsjo%A@VM8fthcUA+p2J}cW zqj8SHrohC?JP_FV=@5CG*OWMCRX+R|FJAm@L6WI`9h)?jZf0gi5BDvEK$8S+f)E)t zu_?pM*qFwYpONvaniJSL`tZT4E6KJ*<}QDq-;$LB>R^$} zHmQ$GjMUW7(o#1u(J)GiP3$l!5U#rawP|Fag9hwb24Ph-|5F6~%cj;pB)&pc0ep>n zc6bTP+?(oHv*jKMkiiKFh4=d*H2WNAE2>XIzBRsk(vVx$Rxk}Gx|1#ih2apfM0ZJY#1vm- zb*M_R{%45eICH>*deVpT?dsBCJo)za_VJJx^jcStr!KO0VQIUbCCR|RaKukC(wCR` z`t6%H*ZUcoU|DQ@_m$CAxT|@K+Onw$_n5q%qo<&}oKNy(O#q%RD3Gzw7cmXhx>Ht> zQC%ebVLC&%F~;3Q8+f>5dBkjiyf6^7&+cQzpM}usZKyH0IuHSb83Iy)Me!UDm&K zmz7m+l+~3{b0T!jF=`n0cZ zt`fdg1g`h!X@ODR`?1l{ALv^y^X=qk?^a;vJ$lM{{N9c zJ_{U_r-Y=Wsc|@eACDTHxRf~nvCNo(A~ zp9Jp@Cr%8Vd)3X6B9p?%T0Sove`pM1efjMRIf-w9s-x$c=<`C(dl^|-uXy|+APR;S z{8Dj&<**H&;_>Nv1qlTl2_(EGkEa&3-OW7^nDFPH$DXpfCnUqF8rc{LF@gw*zjhaU zphXlS+9?=}hEsBQ`Xt|T35T3HVR6i>%gy#en{X*wT3U|O-HW0h508$r;z6Nq3&;Dl z`|??knLOiWTHk#;sV*KweW4jbZcsMI2-0R)5290OiEjX+cC9XKgUf`&&$8R`{xSlhYr z`|FTq78ZAzWNf1t*>*(;c@akn53PRNs4$`0`loR$A9cfX{2ZP3T;pa=}F z@AEYN&X{sPpANVNtFZgQCN#;if&y)0_Ms)Yzj26mobq{8m>Q*}uVZzvx4DD7IR4F2 zSut5i#eU-EoRj_WFT&#j!1I>|==u5i%k7V@c-R~Y{pQ-wOqnTLP9^@y>#DeLbLu$e zz7;?@q%@W{Zrtc(&uWRkx&r5#EnFy2=E4rhaq=FIfvN~%dfRaFCT=9z9(5*bRw=~b zfQ@Nqz3fU8w1iqDA4#i2K`2h{y|9ru!Bj$6F|$}ELDyg@xL@T%-JWwXxi+3t%omhS ze~FtUs&KfvU|&cpO;cq15fYY8%d&FDYG8Sq@?unRS8$7sYD&HKZ4VxVgVKfDr2ZZk z*LxoNR07u(t5R^t0*9bB9O#5KKw{I>vCfUTO_p|tT5n58?Syn3b0j!|Wa|FDxD$UL zzC5J!!j#j{t60042;ss-{{erpMd*2R34D(B_VyqFu*5ng(o9YcZ!D#BZSJSz;je>qG-rPr;c$#Obo9fEyK0AGV+i=uL(X0Q}{}|rDL+^^Bga`-`$4N-7 zX;jx_IK0%=Tjx}xTp7k2^*EQ)8uoo%3QlhB%2O*=cb4jf9$q>t$N4F^T%Kqd0c$c` za)Eys9QZgk+Ea&6nbyRg)gN`9YQJ(HND)JaNZW)pe>b|GyEoqN=7N%KsI^m0G z5*)xGt}4wI#bQC@I=~|dS|_RUV1}to?`!;S`EEaR2+A|T)EbZ%6gM0gfELZfbLKVr z3_9KN@>jeLq3A2EbR0RgB{}NBoT~Pn6%{rJ`}=LrcQ7q4ziw-r$Hldxt^V_PrUh~J zdtjx*av7W&W$??NB1w8n$06z?l^1oISj_*ru{~x$PbK*&GumNpK#$1WOP$+B^u2U) zBJT^98(DsO5)gK?G7)}2=}Wy}P{?Rq9hE-+R8f+el_IJ~Ow=vE;sxR?1k5j{cx;Yd z5ue$oJqni?KmI^d<(N;{zfksotV#FJ5v>71x&BNE1di70o}JEV1`z`Delr zHhtr8f&p(8zYB0f0it9j4=mmt&(c!I=TlN;Gg`!*8*%4-DLF22p}G_z`maK`iaiX- zg6O%8s(BY3;)8q6N0F+d0XERG00<~o$%z+UL<&JJbgU-DqIr#6vr|n^)#kGHBkAz= zaC-l&f`$fnhpurq?Nz-suJI0JXcV;!C*WvDQ_#-G!^6|-e`IDh4VWHa)}i}rle*s<`6&9i~HY#NVGE%AeoxQ1?3K4|@DlmJXVduCO43 z$?0Q!NL|9loE92XScIJ~kbb-*3Kq!P3i%6?nO@1mR9HIcd9ijFe2~jDDZxl~0cNG% zUaFx?{>Q)U`Du^5r8>QI30mh1V4|SWsb<{UYd7@x#q6~JcLVY!@Dq%tB+Yp%WXqb1 z{r3s#+GOQPe9rRW3DWAlPQk;xQt)%@0kT4iX!5_237Y>sbxS6=)C0$r*x{IgFPhxo z<~$ccPy9e$ZP)yF;B3EDkj_ zH84xgC;-}xNys*OM>3yr3UJc6Nk7)_=+y`(sAjZz+LvFDG?F&_k=a7_>&Dv8`$lsi zJdHMErSs6(k69XpKkrDQY=Ri9(GpD+AH^}yPlsB-Yis%s8vaGAPEQN3D*KvM3e@P? z!9<;jzxYBc#d5UxW+R6Os>8)a=iY5QiQi`6M0bpHdUj@5VY}ZaOIKr%XZ*B|EZO$5 zc9YY7>1CRQV3mptv!YVXuC$a$|N2Vvz?EwzX4o@a#MDqq8eD@@r8+E~|oaAt%qG>01a5h@&tG$2@*vKEodL_yx)@5dS)CO#ZX) zMeGN`nfrV8<*ZA8h4R3ATy=^i5+{C}MqKxfKTAc`k$ho(UcK1PP|XmhJ4hTMW_imh zZbESW$zx~E#AgBpE|AU9K*WR;=6{0p@`y44!_pEKIgAan&1{yEXs;xd&R9yCe&F7X zL9zq>tZyO(r41dI0f}l@z1~AG{x1w;OZYGm@wf_tnIKW~GgC77)jSJb7#-jgLU=z* zp$GowBmMhOHYo@4{G3l~2t<1cF!K2QJfJDqz*CrXgjehC9h>7-Qy$Z?(sq~adO8^R z3^L$^5Qift>I$@ElW;;P5!EvKbvWhi2%h7C-Me6l>;CA`Bh;zO%+an3=|uSGaN%Ra zic(fB_0P4^AxzH~6Kc>j@crpfeuu`=b*ukQXK7}@c-IxGC0vKmfQt$A zG@OHcwU{5cBu~E6oViL$HMVm~9YRX$FK0wyJME3ZZZ)Oeu5;5L;eH;b;XUCvKMVN% zH4fy!*lwy!`=FbUTK8XdS^dD-Wl2w;=CjMsGCW>t6K#2*eMdT9fb>>~{LS%Du|ogA zJgvK}oZKYp+-?$eN=V19Dse{#b&#Nc@m%l$KgpYh3SK%j~%J!g6HUS<&fm!26yxB+k~5SrTlY4x<6e}UF_#R zwBHCXTsn%5A=KY zdz{KH;;=Jy7?$giTsO1wg?9AFP8-W8^&b}`J^!^XRio4NU!I&j{*rQXc7n#7gHBpV zAa(ZQMVRlv07q+bGb4&@Jvz9*A6aJIK}ax%iAznOnsdTA+;E8b6FTDn(xZa zzvB#Wtm)bQM?hwjJ8vADk$Uab&`1&zcE&${i+jOmNrU!y7*M zzrCSjW`R*n|BO?)P2biwq}KUu6CO#@PBe=Dn9)1zlZ9U7?%`pokljs1GYCM3Qq^bXH3e%G45-CJf-hZo zdF}spqYs4JA+ho{CJjKD;`*I-7WVMbBX{?M|Ia)B zHByTuXigRq9a+VXkM>7Q>v*s^X_&rOvN)TQH7$hwn;V20(c*~!t|m{)q?=BX2@2$k zulh~sJT4L5oA#3Kd(f*7|^60EGtA%0J)c$VjrZ48~jLyG)^ALqTqr=>QR>*jrx8!MW=P~r|n9r(f zp2Mdo^gZs~1ow}Tob6#l$F|5EncadDW#p;M_K#H@mtUAkop*bkZbMXfvLj$SvLSsIZz@m6J|tAP)c}ieNpQ*2^2I# z_r03d5?HgW4hYaKOTME$7C`;FBHaX_t04H-$2`ZT4fMXj;)qYN>1pdk^1Yonm1IO$ zuMSUiJJxT@KwL!U-ZJ8SOd<|csj%M zptT1A$|EU9bYZwn6Z*Kp8zae3myxjt_RdjJ8H0nR^$*&ft9U|&Y|`M@&<_mql3wj( z$KVWf^nU70MMXu}UTVCn-0zF;VImgVQjFB^dD!bz`zYY*^Zy`Q9&XysxS766s>a?Q`7SS=8m#n+U~f#N#VNB=}7(GrT>dJfPlU7GS8_5 zmo#q=>mPpsfXf(4NB6T$<6|?&8Z40{&SA5BNnr5%INI-o%Z};oNf+}CtwAlE3VnPx zL^ON8;a(ue9uXX-?76Yj)-Eq}J+uFqg4FaTcfa{)T{uRQj1>Ft6h_hcE1^t*8)zHf zB&2}rVeBxT75K{NXG0yMxbZVr-KeOjCr{>RMI#!WXKV5_pOcW5m6b)FH^tD3%SlS` zhWlZLiv5`8dMh0aUqtKcn&~*Vp2xUz)uiX7PyN;5U`Q-|$p}kfEtDD@6p;n{30bmw z;0cl8a`~DC)@G_8X?xVv)%uEc$h1VhW0>wE~Ek0Vf{TXRqSmH@`j2qw9fyo2Krd6*)j&R7# zEiiGj;ZiN2RhwkK5ukkiQp0B85+h#*Yrt<}nD-%_c{S_Q%lP5Dl*vh#QT$mW8zsk}v zIosPz#OxhD8~qc7g0lMIRfvV@%W1z^yPN#->w)ezKKUZUt**N^HSdySTUiEmx)r^2 z4{9^gGA1y3U2TArai>{4U{|4gpi?O`gsWYkzK?%(pJ+(+MKEP8qfLCu->epZeu@8D znqc7btGRitQ|Sd6`Azmu_$CCz+s)0*fkc%3FhGHiM|;od&s%|pwN6O0$B!S|*epTM z3?QzJ%}uPeDx%lLnZ~iZx92%JDY3!YJ@yOtx^*R8wU?Qmm)-(e;05}dhT4_}uvZlj zw1Wt^yuZ}>QSEApA1*63ClP)C~-3J-4x5wjdLG4(%gQYoFG|1cps1 zvaz!pR6Cg$Gef)C#l_{7a8#X>7eq^+LgM+}GYineg4nRgij~m`jw#SSD6ogcP_4L=te z;NKLX+uMM;N_;YJpsg=cYN8z9c5G+q{48PolL(r~<=$10tf63xx$1Lq6NQo3XM7k@ z-i9+F%rBzx%MUK_@lXzwN?4CwnjavNzJ`xq^J147QG@*zrS_#SH+FT z!8q7vA1y7nU@37EAPb>XLhx5G6cA5W!|fRR6A@1G=IvWZMP|f@Y4Ke#F@tJlxbLj0 z#{g3Saus23WR&DITv>nb22LIl5;by$8UD_r^{!=SRU+y8fTaLIA{&A20g{lCzJ8vO zop#=A1;=$0H*+bnxp{q)j_8=ETjxCg^eC`nA&3Cx;$oV&)rq+o%VXTGq&RS{q^O+D z&#r-V1f2NKfYne{QZllyCw@R-U9Sg(jo1vgDLnkTi5k#Vmq(V1RXy<6cK*h&D!gwx zzBDA*q11uwo!j@+euM|M0s1tjfajipY1wFVe&qmNo z`lkKz18nHK()k=|>pU8HKPozWjT<{ywL4GOZ;+z<*L zaJ-hjUhgz>(NxCoB_R^P={vY4;SfE1NmmIX*er7gDac#Jwes zu69kEDYI9*txoF{MugI2qD}pdEYAlrGc)()cL-6-i@^gNxgz0`JJJ$`47ZHn&NZum zaYkxsDSzWTMI<=)km7*pyD5MV+^n82VL(WRlP8j&mp9Y#Bgbv@`D4LV@8j;}hnwRL z>Qw?BJzE0$G01UQO-Z`jw>h6cc*hpp_+85O95+wR4}M^o^_d>a__2TU&#k4myzhVR zgTO|5JS^s>m{YYbZv}#r35#6)wfP~p{*iK=O=hysI5f<#tAr;;pPTiGT)a}!J@xAl z)NmP9Y+%K@_WAt$9BKCFpDz`WK7oV3!Qn2N{?@HqtZVor2=iSqfsqIzOawjUCqjOg zA|rWK<@w@y4amP$P{k}(7%3>2`!&vB;CT0+{FdK18<6X6^UJgiEC<-Q7lO2cH>%7? z`nL)*Zvg17R(=tu3FrnYtbw(Oy4u#>H+yP^H~~%z0t+%-D#D^!7*h}nVAC=}n>xiHQPDe;<&U3^4(26~!fQecoQ_Qgx&~DQQ+jdc zbuMg1_HG7TChi}pf)4NLLwz^II18+cITU+vV6w644Q^vm_Eg;jzzM+gDwA-NIc1Wg zEPNh0e+_=GCTP~~T!}IY7q5*M`aR}t-K8{Lj>>vUEzN!JX+PtXf9Sh+u(}bP%|!xC zGYd5Tx?CdWdn~wHTXl_EMq}c5@2zPG zy-R0Ym-4kUt1xX*nE67!S9#b*e|Cs@;M!#zon(M!U>=?K^~_2;rpI|}LE8^5v9kym zN;JkjQsc#kIgBmqJ@6%JjPnWvx*`w>GS~XFxkplzJI_Nt)O-kRSgn5Je46$4Npyjl zzVCRt>5{o`L7-WVT;S(=dg86u^959Yb2fADhY8Up zyn@!O%+jjA&M4o~Z-#)ri~8e;x^<4+Bm~gw;jaMcI5M`QG82*~6b6=poJ}V&$;eso^Te z@RszjY5${GP?x%_U!k)sROhAKz^*ZXUY6H#~s!V9n@5aD|7ue8$bL_}8n4Q@&` z!2_|=I*5y9r~qWpBqL+?xpIxxp7r;Tt|>e-nk4n~`;U*klWzffK8MQ`D9Iz&H3bGU zQV8=Dxx2rWc3pnTX|E3_ z{l0)Jq%d`=u~8pPHhxV4@2HgrY3kM1OD+-u8^pu$a{ZGjZ@9G%>jNzP zXsFkDp{K#{_O0rJ1BZ#xph}y*=B;=ZPUxtS-erO1tAm}eGf||+KGUdrOO>YeQatbT zXKx{0D?jV2$H>>gJk2hgveHs5{wEFj!+}6u@~)ZzBlKxgmTFud~4PloLpQ(!LZ77D>=b%wtgD=3tc$Cb(LE{v zUBhshtfawad^iyJANfhgMq(x;bd?jPYeQB$2dy^ay9gBuE|3hemshpu~O{OhCg-bPbgT;`RlKeBa-O}ZqaylBhzY%otw$n!g*M%i2r6UjOF zjtE4NSLOXS`MsyCPKD0Tu7aa zDz|`UzAo9Iq-ny;;$m!MWaiz!v#qe4WFQjem@^@O(8uFLO}ER`6=Ms9T{w>nCY#mf z_bpb7rQUR(&j5)FAQVhEz)(U6XeM|Vf8idD;rwB1Vp0NAqCh0n6wuXC5NNXYGLMXo zoYQ$DWwjXzjTBv=0QE=dajVxhp(*!uU6ogaibJ z7X+mZMtRQ_FF8!5QkFh@lP=lf?d6ggO=q*1Fu?}J)kyo?{5%^$|Bs)YDzKft$)E>V z2_bNQ9$*mzzM8)F9{RPyNe*XJg>V#gVf{3i8(7&+6hG4?o6BJY?;eY#9+-B`QA9vOxwz79~lt}4ENJ`9X63|j?{l@?IG#1K@Ax0E-}3wY5f zMw~r=4LC)wd^2P`r&r%`sTHuP%SB>v-8F!0bnY=EfpkPfF>w?#Mj{7N&I8uGyjn(= zfx6`mmP8@JpdPqNl~uJ9?LgLPTII_8`-Y1l9Db@`?ao%zC#C~MNmA#nj?o7kgBwy! z1{{MM6WFbb<76s5zZs{a1HM_tKR5XV&*h2Ek^fQc8d|P8b*3H-b)_= zHN$FyTkptI#2iW8Sl??S83@;ZX{lUM0l^fWrvu29{Q0+Urly+fnkf1LyYh`hEjUI3 zwMZgc-_Z#AEM0D-afJ&GDb50K0yWr*t@LJwvQ-0P!29AQdy zXfZ6^VJP6JO6_>N5#_V(9L>L6q>8@hdlu|OaGWQ6p;MBEBNR{UA}^iYq==q+(G}E* zb&^O*6wzOxBq?$udaN-U;71eE6J(m2mNxoZ#By6HkR}8{L_~py+x1Jhy5mM1e&7xo zbOh;2uyxvndtGUY-Ncu*kTZQ!A-ckQU;0Z>BNY?%Pa&v07>4|EtJmvCkK&3w2(`e` z2~kn!od-me+yR+BxEVkZtC))#W&QN&6I5R~5IA*IBWaW)uX$)zcDCOTI%5Bi zy3NQ~pqzI|H+;qC0;ZpUGz-%SC)EOG!jDUjYChR}lQgel9?XC}7p!91!Qg!J9Xit} zA`Q+6oI5wJP&|7uTQ+VBbhQj%%miv4(y&-o=UgXq>uP5fo9X*S!uY-`S*ir`Op97C zdhlUVQ9%JcXzccd!!gnyFfkxb2Sytg&XHG5Rkem|;5R!+!5^r+-vR>zaY8MpX8VtZ z)h)HKXWde!-Zpb>)(dg|R%EXG{XC>DV}g0Z+}%Nd_`y;%3q8vk8-qa2rE6bf%T0IT zEtHn2`S35cdkddp>l8`a{eZqgy?OmPynO!7O_FVaGS|n0Go6 zy~5x+v@futtk8mE>XhA3*@<%>S<1=0XlZZ5{p2>TC?au_>a0%aPuOPhY)zLFWW2>p zx#&Q`_kx7*YN+ye(jYnI;$T~Dfx5HJuvCIbJ7q9_Zvbjkx^B}@TZmCrx_4s?b8+4{ z?{r?|=IFA{q2Or9IwLu_1Mz$i5fBLX3;gix3O}p|(=X=D3lintu)TOX+V0*oQiCLj`h18yWmmb^yFUv@y7!3Ma# zy0?O%vD8G-ig`iaMaMoZ8mrXG8@jsWOCntAL$c!H2IR3i__A-tuxhs(?_c^Kwg0hI z!uq#|khfNjVKqv@jt8hbS0GH9l2Sge^f9eBfKG6SR`4Tzj_Ym}(=OI6#5(DH8IX10 zu%|%Z!Lfbb9vYeM6ba>4N2jn49|*O5O7WOCx~1r-q*>LL=Q%!Uk|frZ^E@b-nLF%X zq#%P~mS*u7TbYO{-23h01i?%PcfzoA>m-eI%dXoD9lIMq9s)*ASGF%lpr77INGv8S zUE~dKNqK-}ID03-<@WCGDyl4!-Ob7P;P~#6^b_;JpalKM(O$w+MfF<#T%Y~J+VrWy zn1bNfin+fLqCd;9mOsFTB}FUFhWYfBsRdgJsux-e_WVTPtTOwZ?!xPe7a+{N!cBOM zfw)^;x0k_i?KmA+V&e!mQm2Q2_(Wy5lD~f}tUvby-YI3E)~JD=^m2%SS}()P>+sg! z&p*UFdns%y{zCxjCu@H$sCaSD1ItDGnZm01h?s6}=OyXn0HkWkmx*BT@1g(vj!^1y z0!FkMLzw>>lQ9OnG?kcvIctFsP+PEghV@3Wg85qR(#Z}6)cA(n(h2DwG)yg?g`Fe1 zcEw$uQ|X&gSFNv55cEPQw#|A^P2*23S7`GH~|IoI@_i5lQ6dv>`_5Y}#t;m^;$*1&ru3D5Z|X@q=EtmEUgA}v}r z5CbX0)KgjeSyLrH!-$ z-+se(x(v8gON5}OD$7Yl}j5M zV6@cbbJKdg|Nbc#l9Sg&5binSXek>Rn#=J7htD1H^DIMxKa+yL!AC6$IF15ulm1iJ z4V`COmdav%%t|eMaAB5d9)drLHN1k+RtPzT@0rZ)wfN2c^CkM)%q`K+c$*DU-VE;)`ZLVFCB1jA)-ykmZLzF? z*CYyO)#+~@D!w2dUMZGPBCBLi!|a2fhvC+a#_l(J2m{{`3a|{~akWdHFDOqA?%u<; z-c$PTtPm(0-e>>2P;lX21P5F-F@W~pGvHqYjg#Z8M4!|Mlk4znlI1 zc0ozP|NZ9sD<}TP=y{CtFV2V?oTKUP9}JbTz=saUf17uY)%_7HxHl@jg7d@Cs}_I6 zmVePYaE>ZFLjV8QhD*ugB(z<(JpFNyQHoq~@LBa}Dz)=g5(hZ~@5EZmle)Xh=8b{O z|Kp9`)Nuoj&M#m0^OgB=iIHM^=vDAXOMSc(4=%C=Cg>Rv{C&5knhw>(HQ_HdI1{$& z@9eQ@;lX}{Q~dq?h>P$F%I(zOqv0z!ll2M!bp*~uju<8Vd-Rk*v$G6SaKyoV3V8$b z-?z<@Y}ifZ6{u!@e|~`6-?zD*rF!&{1K7pDk9cr#=g!~5!bicq@ytgG_zU;S>e9bw zrr%f~XVO{t3-`mvhyKlA+5G>+5Ape>chzKPczESgMutO)@b4?F*!0iKlNvNRGo6(9 zWzEB5OZ+3=6C$FdHx0k9@WHWv-d{M|v*$df`!8|b};r}#f_=A=a(_uan2_1DX{JME>+avYNcK1d`I0tgkE3l}bMa9qEnqSE=a=&{}{QkBrf z$ZHkCe%kkZD_^Z`c^0t2=~iuFZN{A!w-mtLNj-VD;1#R6<;ITBXyelU(&$!TZsf|= z!Sog6{`?CCQK`*_*YkLEdN=aFpO2L~SedxGxZxi>b8 zWv>NJCp9h|R$%5no)Rm#CDq{Rd6G7HM0jXJW2BYTSn^KC$mDa%{v`+VlD+n=O`FF2 z)Ayc}8U0ck-iIzgZm-f9@8%R|)C}Rl*;oJc_^BQpOT4Wp_xaQI^l5j;9etC4EOb-ePX3|P8aC~U+jW{k|G7swwjBFT17S77wQ@^)yK`^%|OZ^qGy?<=+1E3-vz`rH01q1(kd zl6QZ?`;Ijb{k@9f_EdR(2Dc-~!6k=R+%iYMHoUuf4}XU_vn^G9cxB(XC8_QK?oC$z z+;LOS+%3uZR@!i`VQBOCkvyg9_P$bKv#k!-^7dUvHL1JA$N$R*aV}eZzutZLYax{k zeaf$(dNh)fq|oj0{$bT&kh|n(sk@xGcU>U-=hx$Gkdx|9-Pgv<2L2?d#%v0DHf{&{ zlpF+jN>RY!V=@0R957|$CHsn%j`tKt4x9C@9BbATsJHj^>Tl^>xZ$_4-9PQh4R34W z`Hu_U{GCyzk~UCrWHWYO(CT)Oq(swMj?j~lbe8>4T3J+*B+ z+E_PXd>0$^rF8SnQ1WO2nSYLJpIilF8r~sNsbqL$U5L7xcDLY^$I6j?Rfo=n-Hx*5 zc*E=@zn^OC_>sgn4Y}r(-NU{mvWOj{@ zICy#cDAh%|;b>buZj*OGzJ^e(9SUyd_V5`JrU)DY2|0KUexea=X?j z4BOI@q?R{DR!eg!xMY@m;F@g)X7=YCUn7X1Z4mm5S94~XNv43%1m>B*{Mfw7LYtK` z=k1>(FQ)XNCxoq|r}XrkH=|*EO6<~$sk4mlUj5E8$^@Or{*DaNnhIcuH|(~$*T0Wk zG-qH)t}$Z(%KlADrJF&%aX^ueDtQU=0o&h%xq19XISGRw{+wM(fGtcXbmLF(# zx@-xrpKy3TTu{wsC$y#@&LZ!VK5`%RGTnx;mJ^6|8@&!AQDlU*le@YaEriTUx(dp& z>I(eo^b8Dh@m#%G% zlF|iDo%PJuA!v{&(MgWT47xELxNvw=%+rkD?M5Wy^iP*7)w=eY&*Ros$Ccvi&g9xCLzrvnHgP^( zM=?=;u7c6l!EfRjqw}1>tz2S0qi?T*=N*0jGrff^mmzyD)UDH{&tG68EG#`R_M>ZG ze`E0v0!9X6hhV-d+2g#)-?tB$@C;M5l$+fe5BqywkK>=U^3A*3c$N&gR=DrtbYD^H zMYr*{p1gG0(^U;&I!<6G#_1%@suUc;s5vz&NyR16l3gm;o~q-j)8mej^A9ez(I21@ zA2Nv#-kUo)eJaUCz&|(^^R2a9&}o2*?*gX5%pt}rMC@FAaEN8CT=135b98rplnOfC z;T8q46U*rWXYSltJBHLjl4PX4+LuN18}PQ^5J%rTH^rQZ{OOYj`HW1{Fv(xpS!g#F z{}+c0T0ez%JfDJ4CnuLXeEZg|TToL49`jdR$#ZGwE*SX*Yue7S5#od^fOuXH2EI0A ztrSEiL`1e<02c-ut#t6m;=)m!AWD+LhrS&%ACq$kmj^2}O9ccJgp^9Nvh09l4X_$_ zGkDMdz2Xut8|~+0F(|a)`kw~_qh$(EU(|Rd_m1|O&F-rP7#zS@Zd~3S6RsO|#B4XE zJ={P1K4%jU$Ev6e=JQZRl$AVx^K&l96AAGr<6}pn02KkV`V*A6hF?&t-?=NOAoS)r z&>nxRtaRf6qX(KR3OYUE6!F~B(Blg{6cG56^z-;IIb{QO+^;Tt&g*-9qwlt-Czxi%$67ukjQ}o` zD6YH6rw0>PLSiq1>X8}CrG9A?e)3$;opZ`I4yX^{9Z13;{)mtO4=*+@ZVg{xW)M$_ zkCm0R8!zuv=F_tB@=wf4^P0f#0bofd`11{6^Xg}^?$7bik4a?j0n_H8Um&+S&vPL1 zAkx4p>aYgTmJ9dxM4Ewb1b3;1i&x98XO}}jpb)CSTm!JuQS%!C-dV?~e(AcC6EEdr zZ)RJ*VF9>(p(Q;G-M=4okNCSA#ufQCj*h?Celsy5*Sh2*`=+YyQqI0)^L;{UJ-ss| z3A##D=kH&(xrl$#;rvNHqU$P3w}&TFVgxh=ZC~We&eVUuw-<1K|Ffk<0qeB6=W@+g zODg}gz(Ctb2Aa-8+v57^qeTBD&PzZi#K)$mrvqg}nXwAhsmiqH3F>{_2js7N%pAJ! znx3{p0b%j|`}d_=7jdSPuV0HhG~V{DYC+ggLW>nQP_fpMS4!)9c%GYda|YJgoB37( z_s?Hy>Yv}bb>sX!;g_R$O60%)?BK=st#mzo8nWj%VF;Y7s|Ki`6P(;TC1GJ2oqPNH z0Q!zeML~V+hs_K5RU4Fof`Z5=JCuiqhxB)E&4J!tOb$^33We8!?e8~IFl+*m^|;+t zmK~9nfY269=&=NVcLZYF&V`qPu`=s*TR;!OhUn(n_LIDP_bkXua-e1DqlQh|E3Xpk z2je$}CLi$KJ?b^FtWeEkJ+4L+wB5xzGEP%(kC}I9zm&GfEcvxZxJ?(=Mx*@tAD~kV;eQ#Oqm!Ng$%VX zsD$G>ScQ|5rhq=G0}B^h3=3Tk#Lm14m=~qN(zD6PB%UF_$Cr?jDj@c-Aw@x6VuNz` zb9Qs9;zo%%1_a1+;vlM++>Qm69Rrf}gakS@Iwq!0uK9VSNm_4jZ#Z}+**Q5Oh^Hh- z1NcH-4Cj{9gAbzU@oJTJs=+aGk+ACoAa&O|Ry?9S5CHPpa2!`ex+LDXJYkUIKt))_ z1`y3P@3xoZ+wRWJTJRX^*iUpkTsO&$8Z3L7ae7&qBrfDMpQ4D!n2VI8tV>bRPFGQR zef{E;=0Qw(bo6wqTHp57J?+2lHaSYi`fH4i?9hPY7t&A?m^+ENL5tkHXlTenW zb67WtiXbE;CMMQK!#dvfk&Bi=4O$#o^MS!$8FwexO;Q6a$WN5``8+>=hXG`Mmcv?C z(KaZ61;wbjd3YuqqB97^ZtVe9m5qgkRFz%-Q2yTD>%7&sk14AYvs#-G;KSj-C+|5O zE@1-&qW#hqVjM}5&Kb}j+jGx?6%$pl`39Dp*THS0b`@Wr-r%EJ1vf?-_2*ylKw&Sz2x$4z`IT2%j{R)i2 znQ(<6nfgKW_80}g-&H233A$G`HKtrznwk@*21hSk>*VT`n?7_Kn)xO5yrj}Lh>fUV z>V0L_gN}`Tmu<~^Q64F{HbK`W;nGZ~(iB}(+kr-^Q6fA%m-HU}d=CQ0C=p@dZYOTx zBlvYozO$&kkIP5;Fz9v_dtWnS|@H{ol=X3qi3Fclf(Xz3y2mWw~E>P4@gN~DB zc`#k^q+;-Xh3f_tp4KrjNx)}MQQpz9or6v-d_-&a5YCqlAMnU)nO?fhDw-!H>297p zcraX3b{_r7?XUX~%ocdG8nWT<<>j@=1AP-zY-?f1iC_mE-AfKa>DA*l52{>SR zE&iZpg91W44IwcRk-&zo_!~;xqWnRPKDiwJBwE`vtLM8NAYL zZ1;Ej_>da-zF-$HkX_vlL<_dAz8y(%!<14D7}labTB> zu?g?vELmCEaEA=XGdnV`>;+;~j+=linTvv(oBKM(ZgON~#8upXee$t-LP| zY(2f99XcDf1}9uNZZ-qHNoubM=C*4krKA`I-G-~#DR4%WPW`+HdatCUr11FY$2|~W zUZujiMZ{<1oIQqHN|Kt9=ZJPM-DCuWlK$g0ywRL&nM~{YyU=_g~I-miNYE=Z!X@SYKUKd?+b7%2~KObl4iW@Rs ziMF@5S9{gfbtQ_tE5?M5k?|HE2?CLupD&u!EMv;W#K3?>_CCyqCY}V(88hk4C8*E` zVzu55T`8tkR&L@8b8}}1Pn|kd<_>Lbv#~%kv9@t@D^Zsg5xI}fXbJ*nk7_tDO?_Z= zG|~)~+s_7c3=H|aD68@K1I`L>7)c??&9@(;N+rV`O5=BUtQP>0w`MQ&rM7|Q54pjm zz^7EjR4_6Qd^12*4i6+C=cN7>y^uEs4a5aDLYS5)-9EoOKTl0|biVVVnRw7Ta2l!; z?bIka!E&@NZx#A|g&`d#Ni#L|*`JObdvD+(-$NkjGHAyKU1}S8)mUC{ZERR$<{rKU zrXvjZQr%C=@;${RC6VFb;?xj3es;<}RpeIpWa@@k{rcU5o#B<&af?-!m#1&&SneIx zI2AOsR|mt$uL2Laz$nMg1ki8X6pz6x!bLvuM<2u#XIf4J`!C#~sHlj7T}ZQt~ze~_%f z*B-9Bp`HfqdtkvO64j3;SJ-C!O2hmK_wUlfRtI=bHgc1ZQQw;S{Pt}NAomATp7{3+ z-@&`{ax}FG1r$bVU|u>Bc!}J8yA~zSWru<`$p@b+z=UyJ@-}-+VC?Vi(4ts~JBQU+ zC`4`E!STB_?s<86^GNPOP}JZbS$~0uc~~t~mXwTaq7^!75|ffTpny|=b=i2fnjFvc zeD3bZ7Hi+ihP&ipJlB_)=Yc`KuT`w+*~GWxULM7{`EY-usz6n2Y?&ckXH6zf>H#G*Guymo-gUVR#tnsx&lV3D;VAbj_Q zBGj;2wCp+-EW^0#!IZ5Zm>=$p8tS>)0t?b9&78jj&D5NwXCbJIj*dL8DN#|)2uLAA zpQtPo?b5HfJ54+uCA|U17h;bc(2`=`=j7(9TRbWdId-JNAgzFvIb9W{_#mgK=(H5r z<|}fVm)j8*%gSWsWlEM2odh4W=Vye>DoKoAm=k$W6BMg}LdXsUu1nSPpP{Rs4l_Ob z(WB({_I6lK1)vpb#bd*S+FIEL70}3CGxv@r9ybnuCfw^fPcWyK)GWzu3Q1OL0e;7kY$qr z&R0+RH1<6?%Kf@su)Xipm5J#!*%Zpkah20Z={A-N0d!qeaN-XyT0c&pUmXJ7#*5wD zXzWMuL;KKzZel0%8zd;$(yqZ^fp&8jaduz_yNG|iR9IZR44f;7&W?`*feds2?xl{p4R5_uxEL8%|mb< z3Gba8hlRg8MW)3(b}CK|&e41#J12(`5;85a@6=dHv>@>iEvmH0=82d>?DG>9X;ZBP zPf2xLo#j#g4&tDJltyD)Yik14mEaEdRtrpryPBBhI9D}^qqw6}wvZQnms3}dmc^`S zN^j>?Y3lK|@;Ak40qgpEOXXAD&jN$e4rc~;g0%MSkYY0HzJoL6sG6)0ujU?xth-8uhUr`sGbx;!&_vvhQKNo9yiODnlcZ*TnaK+#z8AZ=If7i{&7ZijOVn4=Vh z0=kGhUS7P#%I};EUN&Je=_2x}q=zYLQ|{eNPpGI(5y(HeV0!+RVcw-#G5|r5~>%qs@05w2TgH zoD;%68UFf}$7*tU*|n-4)A6l?1{KYMEung7&%DzoBo?&EWJ3EvENB*Uoz$5va@K_w ztCS_`$s$}X|1*?@kDx==ogvEcSC4WPO6UoK&1*r1ut(YV%yCqhMn$dec@s(0dOluC zrwc6~_ZL}rnHb}qt{o^TYZ4Z*{Eb>dE^bRN_A^?nrJX6l@mN&PwOWWm z&$X97>vn^yLVdiLmb% z*T}Tdez*_T8RnC*Vc$SCy4?RLPLI6x#F=j+6#~_NjAxg*DpC>xxK2IRlM5vQjF3$Rr(PL&5KGS|fy9aFSn>DWHZJ%wbX{bmxHx=oJqBU_?ic(PcbfQJdpKVE3a zK{vJ$>_1!6V`4YUv(fWYHH3vB=hhI~-J?t|*Nw^_-JdT*vcqt*t|y-Vv)zWS)q^{m zJ=K%nJ}Iv>mU+-#ZY2Cy{s zoDzQeKznk-Wh<>lMQXR?d5KH75>Er(pD`00FS%YhQ6`){nwD0S`hOo&EHgygx8lYs zl=6Qc)9f(<$E+-$(%MYo#MK?Fg8v+Q@EaI+Ob^( z;a`hSA8yDtvV_$#&+1+nn?qIe@2datxyg?)Jfh|tUp!yh1I{r|On6nNF zUIBX>8eFe?l%rN5aNXMKDJKtU;=ojVJgop$ORvIKhc0OjpMI10)!^l*n_SuteBbTm z7jqmfWJRhp9PEY4w~zxLD!0jHZ8OQYPDk}11qnz|Y1)X;$O_cA5ty(e+1ovX94+Tm zKPwYI5jcY+6U@r2?eU5lueB};WxWtUUZi|Wfr_wblYH+Ovd z=~8W4W6Ts%C@|-Jj;0>g#Cy7R&{rP_hGFj(ZHKGUoE0MghWl;)65TWTLt{Emf~ihc zT^CZtEGc+t^1|XX{2_qr+ZmeL3R3MSXJQ7GtLE>rd3{r^5;_&b9-DRqdwiaWkXIF3 z?kDA{%c{_wqQZFgc9hEsES*KjPCLX@$3iiAf21bH%oq@^vNDo?+>e;RI;PvTa)q8U zNbyo*gn|LdM{`)Z=Y1IFI&U=b5_Xf;DVApKYuwn*=tEjgV(P4 z`TJQ$MAYz~*XB!i16S05XaYeCBJGFxbfHh5K3zXYe(?4VrX!`t0AcHEVrQ8fO_?-( zY}Hr`%_ruj9lBKd(mHB4;w5oo-A|AMeTgO?y0+({z0>e3g&RR*t>56c8D?b{$JGb- z9Ke?zGhBgJhFi?;{(=m0TeZ&Ac{6WC1@w{CmX7dbTO=6_pA>Up=w*T zCT32Ch?KIAC4UlCPflth{Y;hTbO*98Cd8f{%3B&OFMGUP8&z^C77|lcZK8ISub%Z0 z7i679_9hw+|T-I?3u#IN0A`Y2QI(Aq~tW!+OW=+^;cD-LHSkr(pZ zrJ0~y`W5`Zh3W$jWnUpgM2;@(3xA2Zx$|Dw?VxOJZ+SYcIyrEN_dxevxRu>N1>Dw6 zRm*a__W++K60FY!1&o*(7*L%#gCT}~G$77QAXvwHOnbq9%Nay3wdB9npo{x~*>ggQ zv@LnR4TNkqF;v3R6ob0N-8B)+K<2gr8)6|;92~8w|N;w-aaAjQEjdAjRG-SO{*|cV8r%jac z#Xg?;^imUgUs*q->;mIr=#dRUduaVCg!teP@C6M;PZu}0ZIvCU8H9(2LofG-f%r86nEuV{U2b-D&f9T6%WpOjsdL;p0CLf&bXqF^!F*l90+4Ydqc!bEbG zy_ncoJU;SZNpJ;DHu3N@y=5yD1s4h=C122Ba4H|LBN9Vh$IryXGz`wJ&Q|2u><5C& zm>yy`XD_Jdei{69b!+{sr?9c9QU6dMr!VK93rT9$=*Nf%kqi07g^SDc3=B+wQ_$1V z&CV|t7U$kitE#Hx^GlE?QhNj&&(Gv`DD$sfyqd~(9t&kSIyzA-U`g`NVneAr6RL`e zv?I@nKGB!-0zZ=%rff?4vJ{{H@X_G1oEvW49^mZ^g^?W*EEqak`fSb{!lN7!EPTLEEL1DJ*(u|I z3;Kd~dV2bY7vO=1haU_np_wzq+a!U?rPUa&3|kiR{N z-~576u7q!)Ud8zGIMXHQ{C zRQWDwQchw~*XnV8V&N5%{!#KVVa#tYb> z_>BsizPkF7C91M8GfP~)LI5G6v}OF)!2}kF69r95@1FtH&$xby**3eSkFD)kZoxzU z%E9^hkDzK1@zV`R$}*jO_pSx< zDn5rj%CwiWB4w#uh1N(cV3+&`zHblo9|3GPFQ!TlPB89H+-VQP^brH} zJ7JH7nCR$A*_fD_zs%T(Y9&ja)>${8h2OUZaN3N(W$BCvhxH7?t_?qb|4og@B&F9q z!ZU?nZ4>!Uh^s4gv#&?v(MU>2BoYAveE%*%4LPeWKt+(5*a~2%6pmCuphN1ZA=~_3}_vchWOqia91(FLk|k14ZB$*zm~*9!R@#pVJV*VQBi} z0Mk;VJ6%p%aeb=sS<8?Z2X>P-8Vco5cC0!bbI%s0zAYcvilk=f=F}AsFHgZnalN_Jy@-yMELnN0W;IkQ=gSOfA~y? z`zyWfa5sf+9DIS`ak{gAMgjWN#wKU62~#O3zMjEraGP2GxmwCiH;Pp?ki z)EMi2n{c3Y`yr&Z#7I4L#8~J9byR1YmI^!j{j~4wga`B(UM@Uw5a|%B;#N_`r*?27 zYp4wsbF`B~x?7@~($0kCrvW)cx6ngGiCASJBT>*!^HG2KK-r%)~pv{%q?5W1%qus)>A1xaK&QV~i2asd{*Q(+cP+|pWQAbV) zUDCoGCf-yCrG0j(=d!7&ee2U)Cr=gV%Yvpg1xQO>Tl<}$DnB_L3yWluM)c6ehL?VW9vufM?ZUKM<`B27ngC z3P1|0Qcp-ra}$5atXvif#dMBwK+pvR)_-GW&>S9a4iyOyTj)QkcwUm2+2*#z@DdTs z&(9n9wIhrRP1q?UB_*$sgR!*(B92#=78kd(0r0-_ zZTD_3^{^Jl+mF^qwBBxjo`oUn+oOqa&US)`v(%F?Uj+>6d8=N(euM*(0b1cD^5*OK zuo}8EmeM**XJBk3`T1*d!}C9rxsEw0l1E9skMfFMzAUe2lDa=?WN46^YkhxZ=P}fM z51-Wf0CqBYQJo?SY6+R9Kt%pkWGD}QBs3@xZ|&XHUk4V>N#aXyJ%~t(BOG47e918m zmG3fL(c5jv_w`d*SzH3K;ZGoBi*U#YWju!Sv*|4?+Utd^CY88RKEmn7jq~xU8?W&c zXB>YRhzOcnbtpW#IO$;zT za-&DRqMV${T%BEAl1UW__kLIccY|rAIO8`ic*Ru-%nJ3Qa7ERl8e8INg_~Wxbi`0T z=B2pcyZ$!V9eRRrj04~i;o$x{4CVf*3Hjb&39RBW=~Hy5&>4Ay?pJVYVUqWqJMePq zTjVdyC=`1_V`_Q}H4g-?OUKxbLnx$;hEY&bR3wqqY_I+os-`!_N=0Sx8$>%3WC6Gj z8%?q0n?VEE_{;?smzJmrPZ1E5>TXOHfM{~e;od!fWrKngU2g>IdY!TMOAmBsubYAjmUSpOlTc+;M$KC{T5g$9!=jWz+OoRe#F+mRD*9^3Ms>1?-% z?S?)pC#7OK%^cL0p$Bd@ZoSIXR#tvE8`H=jb$b-YAz6iGISeU(`z~UgJ}Br22mu1I zh05}`Pf3E#oG$=+`Sz-%KKT(PSL*PQ!4i?V0s%F>i|j2HKNcgiCk+a;fxh*xU%l!x zp`lw&?ph@wBI4uc2Z-}>;~=#$IUv0NmO%h%Y-Ggnk*kK66H3XF_xz3>08!*NZXB2z z8omn(O-d6x-vSVu6TUT?P7tVf+B4}PAtBhBW+zY`9ygEX6%?FmWTG*t^*Tp$IoQbM zx<&?Q_Pnm%^6`383Q4MfKo*)<*R4 zFVYZ-Yu$1I-VY8|Q+jlZ30xRwTmsEq^n~6D0_WJ4FFZ1`?c*3%2`~6{#pgZC6NHb; z=JJ3TOn)47p;YMKK-=s?c3cGa?b(jMcmh%IY}5t7uBsCu0Y_z!g=FRA0N*4UCnDBD zS69wHGkOM(0RGTI1G?Vykqh4nPC3?eT%WyI@B?}z2o_%pz22~!NdbEn`lf`6;{S{O zHJzOuR$g8iPjhH!W{B={qjQgY9xJZ-({Pxs?HmaDaK``lU11vd4D;wPCpu#?GJ=m* z3C zS9%HhjI0Sbg?g=LwZ3Ept5w@iW6%W*0D?;v?XliqgO@-U)?;Jd=b^5DDT03iyxyMp z1}qnvzFK{KGgO@Gb9H$akTw&1e1T_Kojvias}=VYhV&muo zsy#5x`U`6dJZ@~mr0k#s%PQql@ z%EL2=XU*u+#_-=PmH_&Wxw~#UIvRRs0>?KPLv9FaYoGj-PSV1q zE)uP+qhnQZ^UIHSPi#87RG$7u*UqX-NJs#d^&~tTphXSfzZeXDX^ zpeA_5HeBy3mg@47_w7%gP0Si3fZpRUgAz&lFsr-v+)DX{g&?c3hFOPzrl1KVedB!R z`>OHs>g$=*`q`j&&JAa0XG=?#UxFk*t?ts)B^xt#FKmfyZ<+5bJ(L-Ii%00QyKWCY zKyb|=GrqGpu(q>i>ku{NOBKT=1MnQsJaO?V3f3#F4}9I3T4;!^M`61bLIsJOE6`-$ zVC7M7f^0I~*81cOw3dJt7pra-1m0y;-l zE$%v4)M7e)jGd{S4P{#j)D-1$$n3_sPGVt0V}bqvGfkxEx8dg^WKwj9g8SGI<0J$; zYSPK$qaXP1GDt6E8%Th^#Mn(oYS z;GgAvYnek9sg|V6I2^7$$Iy(tw)3j^%;e1>G$3Wo_VF1qVnW`S4uN;UtJ+_Q%_tVn z`5vzS68|V59y2DI;$e)#>Z+-_JlSKg?>!Q?s`(8F9TQA+o_26VwW1v;tf71TtZuIC z4Ra!%6-+>CB`IZ+#{E|*9VPFRN!ax*H_Y2(Y0rvFNaP_B*E7s{OP<{5BIbqXb#t`? zw4Mnn7|_-h%FZFP>v@~)wcCPw?8$6ih)k&xmVzYy%|WZ$&qd3p{|vFJmPp9R3hatR z1`XdI7oQ10QnQnU0sceELY=7>r&sy(x_G{jftKi|&HhlAqdv=Zv%q`L_q+Ev#Kc%s zt5XDSrt=z{bD!mPDB{B>Wp)V8Ks=98{Z0)i8xCyaBeIz>?z{$|nQWM8!DR*H3g&u$ z{?*8y;rG`px-NKYB6zgoPK0KsRPgn4aw{XA6UG%*l$GfLY$t>Q@C_=B23WIM%;k4> zqNpA%RfG!_y41noll8k3p|#|aDH%QcZqD)#{`^TR8jTV&P5P+>udAx+B+?%~$O$NP zsVmLQY$=jiWs8lhP?|L&vvCrjy>sVI?U$D3W~G|af&xw2h9w{QDfY_Euit}2Xlfc8 zts2^aX6#zj($H|h*AkO@a^a$Xjjlqa1d4+3K(Go`dV5j@Y*QnfQpE!(uGAR;|B!xF!yij~W|$iL_=*s!;NkVFE*rX*amR44 zc-w8Uz+439 z^}8*+0+XR(BKN)d!$t2a+3V;;=Jgcio+7TRtMg?iu~s-Ey6Xb*QK-V?Nt;=A(#(+x zTCIDJTz0+pOV&6dpFV|)vcB;9Vu^gPc6KH~X|c)EBX=-AUTYBe(0YYf*^!~O$eKsL ze3>$;wLivxQxw%{Swvi9f5}~X)q@`~zFO9=Y|$vbo|dygr z?L^6XEuaNYP^GSd#Jf+*L$}#S0&Hzh|5;eA7d(^%h6J;hDC8s^0@-C{=l#)YWB{fq z_)g0RzkV6o^AaeBrOji5LYNU{@+6`4q5ge+Rv6CqM{#pkTcR)1d^^#qR;KFYY=7*R z%@bWKJAZU(J%BG5ZO{JeB$x{9gRIa>VNoX0RN_R{N>#)R9%Gd#&9#EKRiv%rYfUGA zvL$LP^<`RYP|=smJ1h*eRA#8k?H=+I@YmK5ftlazp_HVn(jPd~gRj}6sP47msjknV z1O0s~jS2IczX7xhC;!Y!Ar8K?rmcxPDBj96Nb<|Ve+R1;e^~TI zNY$ewqCb}}0Ksf%R~SpQeS??u_7q%OY%Oq@-;c%q1#` zo+TQ0u5rfy^{rUvuju^stp*jp6g>Nl#-0500|Al*Yu^%#Eo%yp<$l2qg#*`Ab^tT; zN5_0`ffAJ8^$E0Mi|m2!a~pQgU+fFCdmY8(L*=WR1IJ#qmr`46*!U_29?b5lJ@|sZ z&~pb<2B}Z#ilp^1GA|w4;L(=vYF44OaO2HTt$_%Ijkm3cP1UWp1e$G#ar1Eu`O^xG zCCs*PIW19yYQIiMbN&Yt*sVt zp>U8P?%MFIR&Fq=c>=Pu7e4{G8mnU9Ymu#3giVu^O)f9R36X=>+&FkG0t-K8a0o`} z7I{BAO+$&I8+)dMWoqb1Ji4TbFq)LdD3O&S%=o0$@`LFmoNdcc!ckA3JteqsQn2$r+23ZY#$btyK-Smv>A3?)7k`et2COJ^Jo6SE^0 zGzC8>kigZ*Vi8s^=j=f0dE2g|T+!;4#HxB^oCdGw6sY1-NUT9rfh03TxeBg#k19+1 zSDzKvjuRw4>wWQLm5>PzcN3WS{dOiM$FmtLxxTpKk5v+S{t9hq z7mB&b{LaVp?4Bfw&kWB!@#I32QKfM%op1qOM~JS6q5&=6R*yY0H}m&1u7qFwaj$WG z(T5!#K(-Roc?AP1_z})A>;|3JzI?@G=$_rXqlqKpoja31^95e6Co8jX+Q0XR=g+wT z{1_>cKCM#^A?*%0RsbLs0Wpkw0`@eue1x{=v7MSc-Lni5)K4QLpP>5v;2wGnT#%IP zA06$UdAS;MSFlPD^)EC85wTCi39nJ0bQ1JW}vH zvb@)U;g}>du|Uk6vYZt~iwU~VB6o`LF%Cv!J?Pb{MG9;xA+ookb&4aIg_LcwM1rq5 zb50iZ#`v=`HD<1h0NJPckO%qeQ#$R%DP*4?-o{5t_D1tPmxptYzb26fB9MJxW(lyH zPA%17pzQ?vpZ61L1B}d1KmEAA+o5Ni<77+V3W^JWcs4yn!J!ar^F%V$pMQ4fDn$k><^15@Z->$INH*?4;Xgc7i~jjnDFu)7k*E9;P$jT@$zx^fOu+|;2IpCIE=cw3z5jlK0f1IbWeyy!_ zp)NV-hwGk8=4ze)QD=?<^j(6kZ+)~-8baf^nJ0aN!ImBvW2S(Gv4fDqTeE$;G(DXS z%$sPjiV&%kI1_o~rR3Cpd@BuC0*qF6NHS}MEYQ7o-K;!Av0lT71Y_%eyq7wPM)2WRqfA;9UW+Dm@$-+ylCNF(cxbcpUwRr3MGJ1mgjG}I=?L` ze=dA0KYvxHR#wi?pz~O1UER2UfUpbyZs7Z4}P=a-jX?N$(ho7Ma+&kP5xC}cO`#B#yzuay)E9ingE zI$j-tbz=JdmW3tfV?4!o+wy{x&Q z$6ER~a87|hPWOs9uEUTV+7u?N4U#CPsw`44+IYm@T6~7Q!$HSg5J8oWbCUaS&8b9b zPH?jvr|eJ)*}keHb{*6T+ug^vuIq&4O6M6biYoTkvW7JA?5+m0#gE%BOYpwC0>j#F zI`eijRC)ymKdi{uJpb5`HLI8mAmXi<=sd}e*4q-G(_^KfASXZ2oF$)^mcA~PqJQcw z9w>hy?7S-A@b(e&3FGeWUU&fsM>n~77$*}evDnwfp!>W3Cv1z=SO{rC(u0@WxP}(j zRjzvI6B{`I25Bp~pb)&b+fXbfFV8BIV(gH?t{Ax9Zj886e$%l*R*lgFNG!Z0J5pmc z*$#O4&`t-5824*pDBZ6k&BHq0W`Mhj#l*#_Wl|n+XIQU8Q>+l7y1U{5BF`p8MDe=* zb3L3!6A)0nBsF`{0;UM0X6z5;xhsOTWs-vEs*J=PR|PJ4vBfK3t_X57nI+~2bo2sx zHh<@k2=V&iH~gJmDe<+bKFW@ZEPQ4wxI$^A*>|6Xi7%5SadMT=Ob^l3}!#PQ-;k9)u!_6vhnRr?-%ICC1 zM8o4g{FdQEt<$FP=N1+ga1?!DsoQZwTqbnua^)yRV+xJ>eY`9#*+4+`Nuts(Pdl;a z|KT1Ag^Rw%7M)092@|GOQPu-V##9+hk}!>)yH%gjkTC{@I;2FdO0y}6hlq3!z4?`m zhLhIuC&;V0TaD6rw&V}wAsY9bm`eZ?at3ZQx#R!R4gnd{B(a6CO9X5mF==Hl1F+*Mk&rZfSNw% zYz5(73?iT92EqiufY(9sz~ulG5D!?Pg?(=zj>Mp$?aY7%B?B!9^v)_*fSVzR2TSmK zXkhZU;_XJsytXPm2s|Vu^e1U^heFo$0RbyIAJ1r!{0*YhG12GF$0eHLxEpk}wTIq0K?l6A315H8zhe{7$MdOZm9k}9jKKSdbO9X|?v!vjg0 z8qzLP#oxV4M9*o>T$va~bWhpUwFDFQ9Ok|zRlay(q(+?c4iEkQSTu;k1R(;&T`H73 zMnp7uJq9JabnnJDnBp3P3U2%ff+XQ(z`v>te$`@IT5PzjtDTcD?4Y=UM9squfHqa6 zza~hk_HVw|x_oLBCgu70T?jqW=G~T_Bd!WGSSpoC*(W6>UCyR}m@qd$Pvi=g+v*jn z|I&@c1AvQXY7*$Nk1fEHke_t$g%c%%R-Y$R8OsMS`cs>l1j>#T6$1l93>rH6=9@E` zn-2;Qe9NU_q_6LaP&<@TYOx^ZaF9Yq2A5rY)X?zNIWskthvs1L!r-S*SF7n1LSJ{E zzcAuFz`a>3k<-?u{&)u3%&Lgogz1AlmK!yP>s^IDI2RCi;$tAXu`b&nLug1~mXwoJ ze&8;;HOTL_aeFFE{r+M1RA8&Tkm=8YqJ}cc2eLOP*(7wtMtm%(3l0>{%cX zyQ_+a-j0ye%jFD*fl>=Ef<)E^F?;HJvbYMq>pemo#faXw61`A*A#|BzxDRBXV2&`_1uO=Mvlyz zFxZtN3Y~0C=j`e#X^E1Fh>Q$yfRV%$Bs0k62b*rZl(HotFCW+Kg*DOeZ=gQg4vqwP zW9pM3a%6295N{V!Iwst^_e$Xb+06rxYdxFwwj(!Vzq99o{ml{ z0>&9B16}NHF$kef$)rr@--kYPzp+1zRr&^>6S#?!Y0yNLp=ZC~t7F*yfLpbjST0}{ zxFdPQaaJJM$R>qYR>F_|IF$zAS0NtkGvKO4_vmP%)-_Y$J;NhXi8H%jJ=}hNYlzI& z^k7l_pPL!@1Owl{FLY|{3JQyq^9#RKa!JyoJ$Gk<{iD;fl9Df_7H`PsGS0Upccd_< zhZ>ujuHK%ouPhb0iif6u%*u+FI!v|!n*bFAkveGjA zg?NC&&70zDb6@V943|#p{VIx=AZF@(D!{jydqhPfQsj5i^qB)afNBBHXO)eB< z=KhOq!O2f>m7_3A;roTwiMmayfH0{7eobPoAxwu%|MOB(bn%xE<=T<@(kU>r!2*!So91(9@7FxQ1`zVi`SsauT0DLEG8B|b{~%lo+!diWXuIT2PtQ&Ri}Dm> z^z>(a_bV1BM%%kP65`_CqMSvSIYqKAQf{5!0_{}&0{4Cf$*!;v+UM;7wpAu_^{2|k z_AkMImWE+{CS;@5jVgz6?Hp|0~doKM>DEXG-5> zuXuBQO$@@oFH^3oL^a40rzS#tTSMU^5Xrxyc(~d?*LlO zM+hS_)8Nw+DxjIf#>T>Fs_WCde3>Sc`EEWHa)=+-=9s)G2FLwT=ZHqKDik9Uis z%v}yRk(Cme4@`0|xqQUa>Ls#%obQ3iIe>5tK|Z`$2MXs^C|cp|^SG1Izan^@$U!Kt3I3YON|$;T*prXhGpL zauuM@)7Id913>pm)N$5w!G8cR+S3nfE)qM5$%;?14o*C~oH#+n4O%t}AnsN-p$d~{ycD~L%XPglM<&321_8RxwTv0VOoce8J|Yo0EZl{T z=mR{?J?J_>R&^SP4pTta{YEd5Dnxbt`gM+$0T%Gh__UM3ZI40e9wT?>>Qj2~dxM}j4Z!Dn-W0Q+Qg-!KhqG8% zY(~3$NGTltZo9e#uSWB&ROKE^pSb`1egVk2-kh>&Zw;iezAo^Sbf(+3XF^4i1fGn= z|1uk!+0!?aBD~4L5jNg@#eJl#=9x1MCTMRJM$_U%_pLUh3qM44Ms9Ph2|Pp&cs&iT z>6Q7!`PUq4+*Y#f%clG(_n~4C2 zPO^b`v(I@8;}gE2Z&yqaDO*O(vrlKFW=iQPd{YC_0GmY^{L=nIhw+Ltpu=B7@iZUD z9)N5y234=H0#S7_$KyMw1h1F%sKbAsKl{vx3;j7?#JGX-Fc$i_>0|$Y0yX`)t|<)U zlW(c>IUi8Q-E=ECLM}gpaDwXs=PnO^{(Q|7M2wJ~cVcwhcFKhlazboa!}H`;9S@D( zdXVtQJ&Yiyv@&))xH?foP@XQpbA|7M*EEyh*L`{~6cBdjLV#*NLUVYlam3i@8RL!*H|%>L}T z^yM$x?S2m!Ty7K<3wyBjT$`{_)hMVX_IEW`kvr z#y#j_$5RTEVI>Pub@}W^&972PoRW1rGkAF*kQg->rHg^@QIW+|6dYYBS;`fZtfM(C z{?r{te8&m&z@&uDT*f^<6d-R~!o(9&9=fu!vc#zCNx+AfryCkoQ72aLuA4468ghs; zPizrIrhu-4G;#&C8O?`Mq$1+n{Wc_r&dvDUGs2v9*iE;e-I5j&aQ<)Ozjl3i9Ci^P zt&8=c_bs~unA+Of$g#rx`GDt6nNq_kZ@6)PZC{?S|tRx?|Ob7&J^1A zvzgs9o1h80y$tuo2T#)Uy;`1Bf|Wu#+(g@oi``pw&8LbOg^7jE2uYM)G{0KMo70Ke zmaAq6Ttm%ehybpaC3*8)p!1Z+(UM*UY!yhN4!a68sya`Z4*XGJ337f+_0jBZPq~`( z$8ulc=Pjry(&MpiUGvOjOG{XrF9yqu%<1w?BAq>FRpx49-Ihb{S^b;Aq4mdW=4B?D zn%Uh5io@JazKTa?Xjrslp6q`A1zvyz{H;lXD39xY&6O_CMPEYg3_nL8OV~`*58U+F z&J(W>#udT{^0T7wH&OxxK?b>E%Qufbp`Q__+P>K7`SWUSNOw`5r{)>mKNa$2X`6Gl zLT7BRu*vzE8U2Cgj{Wb>6}&$kqKZq6xTYP-{HT;&*O`GaAG?PuOe?igu?cbwgng~Y z%i8;^w^E(2Y`sg)F>1;E2YvcG+W=(lO7dnQ&!uF`eZfD=`(<(zO2ji!7s6aQ3410# zl}MikU!V!|*$;~u1zDyNj=g5}$t?uBQ~vw(0G=owkP%AYNeSPt$fw8oa1+XR@SeFM z)i8WkPATz2%Z2V;E0gyXtGm}cn+ab$1GSz8ZXgmtbj4r(8HgaSm0MzOVXe#j$%%}s z`!ke&`yWx;gzQT%awzpQ_uUDjVFDIwixH>BoCuk*e%JQj4#&SUYPoUn!J_`}2fG}g zu(x0|??F~oyKr_#^kw(nZJD95tqU+x!=5Qp6oLHf1 zevvAVe91DZ?Q2^a`w&0+wg7`(n;Z~Dtg-U)`-`!q!}i_3nxo8}%_!XwNPFAFR_W*Z z*#~tSiHw26adAz5U(a#(d71m)0gziSJ0te(#t9hlCCLq}sBGV0W zZldxBCf+AfyM&XW{fS#$PG@o5dt?udgV-apOK$DYYk&P%XCwNpv*n!A9f2YK%65-( z+&&dPNcRgC<7hxRrh{2gamB_gfmap{wn@5y%Cw?M+MJ6j%YzzJ)S?!#r4!`#o|MYY zjTB`YJ-!oP?81aCuTohOqk%F2ep!&KTHuy9jTCS`b*P_rS{*~b2i*n#|~Df0?P z!@GBNI99=}a)GIxzQJV<;oZGarTxS;vwiM4&Fvl}Y7J3`rB-fnmeQ(af7hu~?I33e44`!A_S5En=3&n8Y~3J)?b&)y zStrFq^=9kM-%D2MsJikyf*>wL1cRNdJ?0*_>pYG?g)F?@GsD$nB4gO#4oW~mT}zZv z(Er`F_z0$_I2+IDRf844wy)p#yo9;5!Tof4%tCZyzJbC?UuvPS?eD{WkxGRFZ|KLo z6#~B4u9Pe6yDt(z?KoQVEdZ9k&EiPi%5rV9-xB3$Eo1YN|87A2cDiRHE@XdUxcj-c zaaEL{KuJ?=c%V#}$Gh|wLYGwRsFNQC&K=@F zhK6>=`@#MviKni885n@`x`3Dt0v+LDwC~I*#yn$aMS$huWk$d?*Fbro6Ei0vLvxwM20x&3s&67`_3<9$%ItGS9GMFdp1DyBkJWb@mOcMaor3qQ&lg+-*ybXlN z1KnYG0C3!$or^>sLO&Ryrve?Qa=-@9fRX6L38!n<#A8qECuVpN?d4==H`%{FVj~Np zMF7VnQ2>Ck9$y)S8W=WxXc9nisJO;BLW5t3NR{>+mA9#P?#+*gIC4Fw9iuaJ6c07f z`&=1<`q@q6K|o9J8`HN0cC@>R(Z}m7}UXl zm&aWdbH=+-QR(UFO*~iibRn$k>+46Q+!sOj>zSC)zetAH-G`nLxn5)=VmGz1v5`xB z0B^Qa0Zs~IZ~?H?%LSd>c@7btMlV2L!ELENylax}3|#Cn80G^bbVcsR$0Ozj+U*aj zAY=OdbHtSx=J*Ybj4Y)ko^JuiryoN#U1MW*j2^?aWfc{aGF}$Uj%ZMpLEGUjQnN!s z4I;wDx1%M%{*t=e6R2Kdjk%aDHwb2U)Itx(jHHaP|Vj(1dP8S&d$yT5#wuOuw4YK69jsIj5}~k5`m)h zGN6!VK0fC}p+EWBqC}oxk47B460cBka3o+>i@S8#O^l6UJUtNtcJ>xo;o;0~-{b~2 zLh04@NNTw9Yk0usi^wwXECT$~EG8`c;rR+k6q-Tsax-FDzLN|qITM^CY^ z$^!JhfMWFu_k!{oU{7~mLo-JFDSJSo?}MB(k>u6PH8vr17z+vZ@WT&4>i>*+AK(Jj z_yOPv-k2h28)vxG_o+n00eLg$7nOJ5d>FvR#l?hRa7~SkbQm20DobGY-lzVUDH+vK zGGoFdgx){5aEAzlsBqO{P`s&ZEG$;QLqB6(@5Mqh|m>E3mD*v#zg z?8N;e7wp&Jy2{Y-^yvxd!)Jh@`7YhEE)a}PC%|7bSLJUG+01$q_T|f`O;&x6>gpJW zii$FHx-(wBg`w-`pvx&NhEmk-b+|0s(Vo+>Zr^(2z-bJDFG1qtAP6P28vG30g&Tqh zFgSUUu8JHw_g-{L8sn7rXFFPe>5iEp;3$~A_Iw)4u*_D=+%YD0%yR% zkq+{K08p~MM9kdT(r5MdN5gkyT*WuV6r{@Jw$49&;E0_@y}23)h`BU93_fHB{U6LZ zcw<}->S$L)p=0D=ZO!VzyXAFqEt;tR8EvKO7ZFzkFV7$ay+lH`W(@Crv2*7>8zV3# z*k$IOE0a467-AhSGUKo~Q9x7+`3o2rYYbjqYTtASirl=sZN|=9;Mb%6F)=46F1sN( zOUp+01NhezC_7!c1p2f2ioY|@6-btgOVQ#P9_bBLvyKYPn)4R6vrAFFr-*kqz(W3w{KEnrga&=8{+E-4bW%s zCk@UfCaD_!ldU9Vcz}MBR$z&m^FJ2{2Pjk$^uUd(qGSnY5m_3vIEx2WgaG2CCqcv^ zQYk0)HkYqE0lWnrK?XDec&Hk`SIaNLO|oP-UY5rlj(ftO0d(;8uGY9`77uXc zt=^&{ej}@k7Z1HmD<+F`vK2>^qF-dW8C}(#PvZ6_$o zzUcs@dfYCQp<2)1zy3JqkMhE|T1vB#AwtBE0EX|MtJylwk^PweQ!xxtFDXy^)@5R1 z{CB!LrMYc$*_b;_pl}Rs&`70T7_rCP55p+ksKn*uo^ip5ENVpNSB3cAs)1uKFAcRYIfxu|&vR;SC zfR&<#2S1$0UqJw(ia7l`V%ytF-$1862JPbF!hi-7Hfj=3fVeC3XNi(NR0JJ>Eh*G)6237j_^<5P; za_|d91b}K^B@lo}iUrX%Gj~_bLer+MM`cRj7kPMiI1mD&R?dR-%tg)63kV4eC>dk) zf8~C|Lqn=~wO9rRFp$sy09nI%sjct;I0n!M)!`ngXQLa}6?Fcu&Wnq@CT@6mi2EdX z0@H)^r%^66AEt1vw?@ORb%825Dagz$y_cLQIzK50Zd?W!-kp<^qy7Rsll%GffJ9+0 z^nl#4s%iO6ENOU6^}^HJ`A-w>B(|e0a#_hEhH!idb!?b{B+0nyhyRr)65@0gnh6;g{C>Q%U^(jBnUde7wMgF-13F%#AIY| zK8)LNA+AUsAa}lEMqlvpGSt<>{pcWWb zu*beZb;QNNW!J6SbUtD^&Z_(G2KMqkY+x02W)g8)x9@U?OujyMH~I(#csj}zc6D^T z{xF^5e^a}cRvBRAr~Fs*?*P|h^!xJiJ`9FGQ2MF1s~!e*YqQwt)8jC(Ts<40>FC7h zBRWq0M1aZ@>#;jdCS9=K{;>{e@C31*2=v_A@Nf&RA~e9};H^IAGaYI*(S{d8LRwtL zY3bCdF+W=e~ zYE3@o?YOtQ)hq_PIT;Tk1uQL<(oKY@>!rbuyvDis)zwuvRlo26?Xl8m-7<8)5_j}> z93TO!c<7-yV!0U+1a#a>EUw@mS>G+gL-A)GUvqH4x|9ja$ypkLd#d#mAivSYV$#wK z@G?cxRc(fVs#`XLd&oPK=KYROvOhu9F9!-0m%fs=bMgV7<(O3;DJZbXr0Da$6IM$t1-Ek8{*uKAiq_*GyM`No zyo*?klCAUo`_>QB9PM~vfce}6n{Q4LdGHo@OZ?%?*GijVVc8?|^#Q|udW@XH$jIu} z#2Xcr{5Nrb>omIN>*8K*QqM{P5C;k$Mq(s+GTE)M0xzu1=OM%GwfE`$W)5S%Ab`)5H9q^(}qtNl8vk z0Qd}9X%q&C9Xce16&3niSNjs6*7*Lb0g9ZD-QDjHEnb_61Dy5l)-Es@dHdoKTVEo0 zk1br8oB=^C;86$Y=v1d1&_3TE4FxxYL)q+gNoX{)8Kxm%4KSD}AZumCzxh0^sgBrT z@Y(`TMZA3e&}t*62)J)*@}2>b=bLkE=_qT=VPy1fYZrh&@CC14dAd*ZbJz@dP4{um4o0(J=ZJm)THy3csr zF84lgNv7C4OY(FqPN3l-qOeAr6o{b9I+Vl}d3cU56Rj@rok7C_5myEwIM8re$!7j= z{%=YP#Rzly>DTu*fIcJk`~JOqcf=(m(>o>v$NTDEow(ZuIs7mpF9X5^yv=1S)!jBQ zHUTEeu?eUoGTVExD>of^m5)q-mJC$BhY;UOxM1r1Aa)Z`j;Q(#v^4vAwo|7Xz`0UB z?%M>p(=?cK@@R++=xJ*M&0qw8K=2%R^B>nv9u3f+A_W&>>j?1WuV(OL`$-B$xu9W& z+UO$87idN2iySTg_3P$CQ2C|A!Clb|uB7JEK)%8G|2nc?3#ulOPk@77w6ORJx1Tbx zf{vcvb(CR1aKTNIWDwwKXlhzaO~WW|K>>kZ29RlyvqkV&+MX6w+fe}!b4ke<_ z+qskc=KLiE2ybXe#To)P1kXG$`{~cwOaPuX&=F5V60`{IgHs1aoT) z(gbL@U+W~%9Z#ltBjF@Y{9f7q&`}NXl>7{x2)f%8?WdUR6D6;Uy|SnCS4;XmYvoh& z^Gi@dp|(wwryq{stKWU-3?Vn`O1Pvb`@{Ht!UY9|Y8~(l!Lmh_npaJNNHxM>v>|qo zZLmj>o7jeRuxEg}D_r;fX#z65627>PALS-cM7=?QicnhnreO7l%Ur!BHJBbDUo2IY zW+gnl4(R8wkQ(hX{pa}xEvR83o-2T!R>moE_0s9Jpy;vUn3U7FQp-0P@a#z^_TEB+;>e+Pd}`j6ExrXPz&F zhuPDf(ZC@CxZq3k^&w5%nNEw6PR%NHe!5lDBBr=Li`slKCh}*-MSBz1Xr38sIDL(w z2V~MatxUwY*nm)NBkr0ymWn|j&h;}==jOvx<*>Jsp>Au^_UqA|OoCkl+*)VL`CmvnZ0xQmA;rJxYJ{Raga;)**(cwRa7a!EW!O;#Op_@=D?}~ z8oYC|yJXl?{KeC!8K2F*5=3QPeToO83J?*V7{Da+9%(7aJ?h%yuZdYtzCux|V#Hn1 zQ=Is{K~;kuuuf~|Yinw>s7o>@ADv4ZumTmj@%wNeY;*LuF;i97u8pzt+5bFoahW3K zyw@&zwH$2(A2Q942Xwadx5s5kTq>JCC|Agp^}q!XTBPqBW|dN5ZNVlQgtDSgm*^>W zkFtFEdkF&kIrrlSogO_5%$*PJclq>KdG-#7>hNE0{y=q~r9;D3?XCWU|3V*@b`2`e zi60q)-ogc>aj0jBdQ~=N$Xp9S?+0wZNHzHj)}=b&a+xv`InE=7fw)YN?D zFW?&?DMoGEa6ae70ouf%n`40G^`_e(Mmb`n97jl83pf?z6KG z)*qe!&xFF$0!(-2>(pgg3sYp}`pGe{zGvvMAAuQJ@RM z{!zsfBXv|$L&^W_`ZLt(vB&;32JMf_q<>!aKAfc<^7gmZTmUA^z^b!~?2O%e6-rDs ziEBw*6Wz$Y+97`vtTd%UX(D=5@0K-Y^k=z3MdIFu^;`#ckjV5JEJbN@bL^SKP-Jc& zd?iO5&i?1;JK-e%F3~&d$SA-=hh&fZ`w=c~BhzOO9bygt&o2)p(*5^}$N%@2hcrn4 zd+ba9{Ut=C|J=@Z{(9jf1!D(?dqw^4y?*#V?_iwxKfgS5r@-F6aEv2tSDgO0#REuw zdb&A6Hy!Td^_2(@j2l-TCn(0KZFcbGIU_y6WE1aWrz`hac}$u99Qz9uJ)LsD$vGQk^3RZTbF;|z{1uQRW*2jEs=EZ z7MaW0e)N#W2(AUmK3D) z=mS^TpOI`e1^-BS|Hr1vjEQpMkW%GM(tl5^SWlm)Ty_xbo^~G|tzBSr@&%XW4#@p< zFy6Iuli!TE3P^2;VM`S%?s=oR*JZai8JIlpr$E=q_Z5?9>ex>j4WIneZLCptnvCTK z6-JaMCYOxFPvB&#!;QzdNtDJE4~h}nsH$=HsVnv~>Ly>ohu62UpShbfGI&tWdaSTb zq%QlKP1lS#TYBs7S!p_NP@KCc_@Fr|P_ZM|Z0@IxtzySdbh2N7=h^%3!gcWyUVmMR zi%-T(9UjE@tE#EZ%}tL8X5Qp`psMhzBvCJO=VmfVNl}zpQRu4Pn%6j4*)2*DWBo`I zwA8Dl9zl(p!qsIxh9&pD*VfTLBW5$v$i8E;e20wQ-4ZiOY9i?UDd;k_+>O?rmo^@^ zIoF#}o)`c+Yjdt%TJHTt1)tsJ%-y|4clfAmY|`AegUctR%a#AL9%0E5>213Qp=Keb z8ft*mbM1Mrhv)^T=L-;MjOm7mx|m~JDz!Qns!?j#K-;A<1D@gm1D!}V5|hF@4opnI zxwxtiVm??cjG$)C83!d(jqK(+)LW?x-1cS$4vS{FQHPamGn@EZckgE0Xyjs zskL5)-7J(}p>(@)_}{z4D=YLwV`F2aa(6fOzUJ{9a!^5=nwkCC*dP%to<V+?YOJS(~OWpPRco54H;BhuSXt{{1>l z*2}ABrHIJZt-yz|5J8Hx%&n|kgEiHh$r*s?Is}v0U`|PJM^0jB3D|hNd^tKuY(TiE9=d6X2XOGsf& zmNdg-1D*j%SSu=shME!8|NHO~t%k-0R>%C3WPB#6i_;u7v6Gi`3H+CJhfl1_w_r0! z-BWa6UCAVY2!64G=o<;hl}I9AKQeUA25n$aV4wzgHw(*G^qrJ?d2$|az<)Kkm zV~v_jQj^gKx;xZTe>4V%hZnD~XZh+J3BNOc^WGIq+Zgld6Vfn1L27s=>?6a!%kh=V zwvDyy zLF@%6inc~Z4k;wHvMznxHb_T~yJ}UV)87N3eUi}fI^)5(26}WC+t0gWP#DDhcH=V) z2ws_Z18KYv@l4W#Dm)Bgf>C>>v;eBHD}`E{->5~|auR~UL`K}P%^44EoLo5{EvnA7 zQ&<$jn-Bd|WY~x_Uh(otWSG>n7=!^R0>zg%EUx=VtGTDNA1x&b(k*y}@PyMyb`A{; zp9%2bN4iWx=PscvRVdiyW!(nFbTt-1cIb!B6k;SDo`%+O!2z~a=L&N$fiSaLAzJwlhk5x1;Fu)7DXK!=U{q_OH9+c$07>Il2Wo0u* z-K-oVKnfQGs7T~Xdq}_FUa_zix+&yeNAt$MdsYO-r#-=0C#lT#I-2wB8+?xbNa|?19gdBR}N*R z0tGcX6gReZG#mOhbMH9gDcn|X-_Fj?n*M(l*kxnm*+1|6+qh3#)0o=XRYV!e!Qf6_ zO3xWaGqS_!-Lw5K&g39Xm)+M%&@=qT4|t@A(y8=!0uhz<_2vnI-k`N??arA&agKL> z`0zR96uaokZKnWpPGYDxmD*oH85oc(z)1Ra2l|t7csN-_WSBdPP{F7pW-?n$0o$C! zVC&*Z2UN{Q23Q%L{NL(4^BN5_-oq-oP6y)(G7^0sKicb0VGM~NF;ushX3IWhs_iT5V?e>Mp^9fc{~WA94f&0k zD5CiE9`X}kN?;#>`FpmU9AEqUAImWKz}@<;LNHxM_n5&JSPoDhx<8cXOH+P{iN`?=WuM~LS<$A;I!R~qb z|E4B~l8-!{ufsKF>1A13Sw@84SyK6Ry9OoF2mp-o_2&J(o!|`aQmV`EV4hYM>HhAl z(walEq~C=1W!#X~I9wVLM48lIvCU8)uvVC#=oHBPNwkk)JRRGqU)`|sqFa$gDYW@O zc%g=o+S)$ec4YUNVE{(nXLoZd;nIC32f=B^fX)i#8Ps+~)$zxMc6Q4sjo}FK;vTSx zGo)K(dI1`pLGe>`x)K3xJf2xAiIvc4{^yCU5Ry*__+Hq5!F$etU9$rt-(P}g^dOw9 zT5F6-P2itDmoVZidl>w*Km-wT(8D@Ot02EMVRs6GkQBXMhFEw7d2$+>ie|Lo_B&$` z27o@O5rIex@iL?Sk=>_!CV(NVgWRCs-*7KmqZW|4TSjmjlF?(}!S3cwqX{?Kf3MwMDO^cf?jb&5K-Sh(D zp1;fp3BEHA_yW~Tx(FrUhlYkq5hEWz&T1{T6Q{~CrgYoEif56wkBMIOnQp#17%yUq z7$T~1QZ7QbwG^2uH;Fo%eOjtzz-9_ehhpeg*Sps({o@W3aUO?+;vb5vKjFBj-SuvF?x@Y)kcXv}IVUeR+hFnzW;A zzUC)$D9%oee>xvI9*A(}-*9g=AG~O!pTj52ZYbN4UA(;yC$8o0Ar66#S$`1Ds+@EZRWBqpUG6g;#eH zId+dSSThwBdo6qd8|C%*iZNyld&GDVzb98|QR|i&Q+a_&NI>wid|F9av3TlViM?L` za`!xplmFr74*gY+G$pwUa>l{0?JK9qxRn{s>us=p>rx04 zAtoPONxQWCr`xI3IP<7V7S*C*_j^X{;&5}~!g8}C4>GWi49iXW@#9BR>b~s`Ofvr_ zOmNv2vlOR8eui)?f;MG*L<3%m2Go6ekz{}&dh!6`X+qr>noI_un+uPSh{!Y8r}q z79s(V69{HX#a>3Hc+Ah55~-~PsBwm+dwO`(W{uvQYJ<6H7mNWTP4((4(6r{?x|2P7 zLb@5%5&j|D^JOs zwrPmDni}SF<_>(;27_D7!+m}ElxKy7YZ?WG6clU>HJlc=p-IkF!jI_Et@+Q#x!<_a z7c~PexTE+h2J1tfA`h;1!Ir%(mfMZnUG2ifqLj#E)L&ckccif}Gp{>E9DkFd!Jy` zZkuxmknDokxRCNOy$aX#*+}jc9AKS__f2iops81wikM_>SE?@#FZJH`j`$uC6dY zf6qIOTZYJN$hSxH(qZ1S(*By#{vvMAb-F!CzCVR5Ksy2r(!dOHNB=@T63a8)b=(@T z7hR`|=TLfCTB^gr+o5*c0oLaH$OtS44N(EofP~15kU``i@hJPw~bXe`5NU`C)Qhs(jwt6d{o8YOyZJ)|&e4yBEMmf{0JM^T5SniN%{ z$KZKau# zO@5+E%PCHQ5eP)R8Ol#Xdj5_zKN{@+pTKs_fJRZArX)G;ps5+X60i@Ww~5c+k>{rC zOMp9=vzcdNXBpT14pe~3AfJ5{a_(tv=>G3I+{_oIogWekoP>6uZ;0%(NV{cF2|-BG zM5D}q0R>9oN;$`v?Q zW{kc*KEGZAaR&HpLX0pcIjhb-xG$FP%w5?T$m~$fI-#NT)%scUYUJ)Y5amhD($-$Xut6 zWS$6vTscydWA~r3y3t7mHY-lg#U4?Qug}$}$}MYR{Bm|fan?|ucVXaMQX#w66n&=> zJt|C_irJGEhPd*IJdiniru$E{bDt?VBol+)e^V!o4D*JF2AE$uh%oCGws~iMEBs_x z{wVukE5%=3B&xpUdz>p+qjA{4M1X<}+)5~@sA*7nHtg5v`Z9k2DwQT;qlJLeP)_w1 z8)zgJ;T_+_yWj!r0Bil>VgusfB7`(21oPcMaSHDehW+NAt|sh0KV5KpNhOLx*tR(X z4M-Rr*QGq0E9$cws8ihXF!3FB_39TRkQaG8esQZo>}+hnHU4(&;VR9=y~(5vwgTo(^tKAb~dE9^?fZ0`OlCPfS)a$oEwnQfKN*mF|DO_ zb!JrGr>EUU8dK5Lf?z6<0M9qw=`!AgY8}#5S0q18AFFutH1X0YWW6I|X%d&)ivBC7 z^({=$)efYnp>mf+Xo7e-*PS7r$!WTWO;LmO6XhFOEm>g0wZs(Ax$t7~n;Q8aK~9g6 z#v0Ic>uNN4u*Yowkn^Kf;p<{t`q7h{hhDEmd5WMgs~>ZUS3so)^%&gBya?uqCWStN z>wCr)b;45J81ICYXNwP{;>!HXaMUvK$w*2?bC?@IVpeV)05^j&zh^b_yj`_P0a=Yg z!5M51^BI76aj+}UfEDvL;79n9)sHr5rbdI#E{S^jnkQw8`1@n5U&VxOm@9{+3UhyMYWy2>|C9-|RD0GjS=+c;-GaT}_R z)^ouuc8B!Fde*$Kk&E@?zMlcwJGU1PG^8++^l9noAT=dGGPXp0wmnf5$4qGmR#XTr46>2Xyr&9|!X9{^A3 zc2C*(u!(rhl^ud03fscZIQ081SNB-E21Sce5itgVnQk?aOdQ!zC3VkMO_~eh-+xYY z9@w^m^rQqWlJ%$V7)#t`!=hXC-tuU;+j?Rami`}5EnfAp;lwjTqqzcep5lA(AXUnI zMrb(6fbgPiWMo9pr4m3YBkU44ZoN<2TMID`Rd&t_9kv}VMxdy?+7yFp$tFW5m_3_+ z-PPI#u!`Ihd5CEDb}p*aqa}P1OUu559)k``mvaVyE+Jl+1Y#dflcK(ad#WmusVf6X z20YCsZXC`ZZP!GP97x9gzAqGU%*+11(ka-Xo=|4G=oe&r`4v5e+v2WXD^ z`u>I<8mxNH)Lo+_DV?Cy&_bNg_^WW(&il!wMCf3$UAneJ*ml#x`AVX=bZ)`*EgM7S7 zGyM>Il&nJK&69uKQ;z@>lsXBJS%HySZeLHg_mRb)6lpL3oFzH&qfCyvf}A>hw38-t zdK&aFk&u}0g(VEo)%c}42r|;-(Dlb0E+_@U-df)N!`$4xCC@M`4izQOq3RAP zOJFDb6b;+b7TKNR*w08wd2@DshXC}xFE5`xudm+>+nWvB+=P~4U2W~%HxAphV_P5n z)@S$kmiHB5l0z)%h9Vw@yH=Y4Phmr|5T7P$w>PpJn(jJ}gKpS$Gc(4_r#hLdeqn$7 z+FZUY7LdYqsdhXf6Hf)&CjTv8Cn8epnHUQ z+T_>FQZ;VRE8K zZaTqFXc0FWY(GVkYLV`901or1EK(Bp(34K5K4Ho!Su~(0;k>*Gu%Oh5&G0y~zccBy z(8Zn(ww%`9Xl&Cl*~3U>N)i+lq|op&20da}1bEUm_gPX{nU{@>_E(~moS#(MAGU2Y zu}EFBzJuG}!HL>5s!r9+KXLgA(|Gfy2Yby}D$vut=$}Wd&T{J3n9=ubmy#${c-fP> z5I*sJO;LyxS-&CRYSnWwcbeGBov6?tENaz@U2bH5n6yUow>48jz}!}l^N(5$3D&{C zVMwORd6~IOU`=0bGz7L87A>l9Dpa~9q0kKd6>H~AEtB8@v1xC{ZV!_SHgQFvt`8f^?4=- zPqBT%3!q9MycV@*KU+?$3lXB+%WEigA`IucF^ zhS7GjLqBwN(QdyHG9_^iwG)7L(j5Btjt7X9$xss)w%wmcdh;jrDr?d~E3m-_CI*+f zgW;M_>eFn0&;;9^4Ze-_9XRj7E5P)unMGC;smw+5TDMaQ`w9D-3A>t(+qz+DK>$#w zDlVDM`xzQ0U2pH~q_OQ2J=fjU)t~pN&vPRa;4%YV`H0bGU)nxuq|TIIeM%cI=t2C{(>Gl zIOyp3#wNp*^!8;z`_xdF0H2h*|6K;xfm1O$!$f|gjy7y(sSf!NL693JD`!9kA zfWG#sJOtP)idHT|;r#ouuW#+%G-cSPiZDTOS03?dAgZu*D79&?A3<9<@(^oU>HIt7P43NBv_S;fGTpZlh0Iw6_EV82x#@{mYQh zX6%u|dq`~ltH#p6g;S@l??5(1WeW^9n!aVQYF>(QC4oF_;H2d?VR&qBz&!aoGGbz- znO$PIa13^Q7{Ao}@>BBWThY*)K<=OVBWC$zOcb{(p|B69`?YuclfuG1-Sr)*ILubC zV!s{2X-Q`Me@^~bbAXY5M@HzM-@k8k@50@j>v9-f1@B^_pk0n&HwQXU1JHnKG%bVqd5S<0XizuKVTQxPJu%K?`>|2(bgaP z^ywvk0agke62TTAJD&OfKOR6SdM*HTh&E445o{Z7@hGfqRD{{g{Qg3shXYkiwFC6m zdh>SS)9ZJaTGi<>1uqT=yRU#I3zH6;)AjX(>$$>1^e-9)zxli2u6TIeccGOWWbg~hV1+&jt6eMgT>Jtu!fXa zk^56hdy%=ETR`D;CquX&FIoRu{YM1}d%JxWX(|z+)6fvJ>??V!u*^l^1>E3wB**T! zCwVhuw87@PeV&3BC5d~+Zg_Zn2V6KUZ+Dt67`TV=dka8L4Ey~ek0cq1v~8N|2s%Hm zP5y7dLugNF-@iwE`{pIj{28U8=^zB4MSZOa-J6$%9f3RDy* zD1sn4qkt45Npe!6B_JSCa*#4nph!+CNGOs7i6S{jAs{G{6qP875)?s#NdDGAz1R2p zb&vOrZ+t!aM|;P(N>Nbf?6ddUYtJ>;oR?R=JK?WdfWaGK@D7#%NcyR_Q8YBfF(4j2 zQaC_GInM(ga-}>$wd0+=|pxi0Ab*OKplS`?)&2g;`h*lpac0&pskFT{s(k zsBfuM9=B9oh98Zvv6pv*>cX3+V$puzb+fxW`u(Ef~b}#R(c;oZ#I87!P@zj(u zYNk;t_2VQ~LPnl4CsFl9bgj_T4))*_m!}erv+G1A_TPEzZT)vlJo_$V_#+qB?p4~> zuGqr6gQwFA%Hp-c7%bly-;GY=NSHFYW_;)N>#iZeU2s2zYwtBMid#For_18whmu+Q ztV3u}*MgqSPN>z5T=8L`4L*8Q_7oei2j*Qa;xSH#pPDeJ0q@G1R9gP1i#Gqo7gkMn zLg&g2CRVYk zXxu6+iC$+BUU{LihsS3*f33WEEZsJjj}N?8O%f8HX{e*-X8kT|f1sqN4X$Q<{AlS`xr$MxE@i`)NkI%O0V)|AF- zh0)B-jt|3{*Wo?E^Q`akBcVpzrP#B9^NHh=UtTiBl!bOis0stYrK_(yEkGg1ONL)? zbqB?+Q>Dp=r?N`TnQH6jvdhXqL3r$Q%j}>0v1?mm2`VwQpR%$hbNOVq_fDTb_;qS( ze4J{>)*E#U5%pCj^;!`cC(7 z(2i|-Qsk10kSfRD0sPvQxZk`ux<6tVMbC7yPB!=@!ZMTbWBU;P{d?fx6M8DxWZvhl zY|&ufW9Q=FV1MC4_)t)7diplw4~xts-Zk^>!XtClCEi|TkIK5wd(+_>xR7QB#ICpRT~$ofW~h5eaplb)ckcE-EToDQ&x)RZ>&)prWF0ERPQ;GJ-EUTKDd_;-hbAs_}5p z(tL2JmuVMeXkfvoE6TfB~fn87ZB+47Lx3Jz36?H0{c&E5ys?WW~Ncj zAvsGUJv~F+sCT(_ZJozDI$G^r96o3-!(Nb=JHNs7X^eAC3k$;p!_{h&*KquC#mnPn z_D=S|5nxDu-qAi~=kl76)pT|KXoI+vL>EWoK=?@qG*=0hqR#ry4U=b0kYBK%Fh6cr z_QDD*9C{-<_K?{*Q&W>4Vs&lme&ZX;%SmUet~adSgE+#zUrA%Px2GyL>CmC=m6dyY zD`|ooOYcMy7CAj1J<4oqir$jc#sA&^EqaB5;!ob>He{DDh&3H9R;-Q?te@P6y%JI) zN~jHRadCk@umJO<^%WNg-ERM9NeXgw6XzgxqJdmvz?QmIC{YZR`3LJ+V&A2&9JUu&=1HCApvHBLpjb+CaQdG;?~ z#WAAMAICo1)2r_4`xpgLNkCH*3}I7-$5)n)Q%`um@A|qjmG>Znh@-h78GTk5w4Gk{ z_DvS%9DdrKe?%yPy+`8+l;_3A?7K?KN;~W4#Wt!=XAIv|sh*aqz5jA~O?;y|t$aNz zj7Uf|zx#cmjl9#8g5pnJDNIdG4^K}+U;}_kU*%lDXD3q?lWc@mncg{>fZC z`-{c6L-g+e|2uF0lLq@cQn*t79gY46v2_1CF0TL-FyrG(qUn##Jl;n4^M7?0B634Q z1_sRjN+7m`f1a<-fAq>&_v%hopLak1*J3=?rDK{H6LbA{L0tIpQoZXK!)EY(M>()W zx%sdEH%jxhCmF*j=Jo5hd+vYx>k4On&>ve*ad^G1@b@KZpX;99Sln1;lT{}FzLS~9 zA2jCvip2ZgVY$}`X1d?(6}S9#7du%kueEHL8wdY&6Eh6~KN}^kaJmlv)nM>HXkNT~ z7Dc%HVQQsS4jZ@dfQiTd0#VdOC3ab2E|NpGd~tEXGCqRKz|~`{d#)f~qC* zb#b4$tVBw&@(m8TBto}zG?s^^DX(#dW_EqBpU=Vfc;e8t-vb`WcnMhY34!&iAB8SU zTz|o2evdD@^X19ToB2K2IvOYPp*x|chHNy>@jO=Bt)7R^fFfzZ)bIyb;xf-g5}x%F zaX{D(cXY$VX}UM|1JzqD7?mo6fXb1Ql>9*5uSHj>PN=D_@ZRiHCeq_WuNLui(w@;H z-4c#LIA?RN(I3%Od%91YF;wlSzGHo}bMV;w!Q6&^DVv*-=ZQ2J0hK&o07U84x!(>Z zmXyy4v;MJdwI&lZ-isbmvAq_{YKPuhk=N1ph#^}l)Z@Q; zfG!LD-HsU&Pl%oFq3G_(+lh%9d1)eCW$n~Joi4rFX`;z;OGMO=nl%j9 z7pSJ1`0!#qsYL$~eSB=}zH)U_lKu7TP?(%fLxoM4y)QfkN&J^@(7q-E8=>43{1me?-8NUQ%3qpD{&$`LPe5w8?F4>h#@hRu4Lx z@Y|^E4(9*G@^0v>|J(y(;{3XN(qKliXnji~_&~zN89)nW;U{rnWiWH`oIe zZFkU{t#SpTDhyC~Ao=bz9O?m)&7^_Cr9j}_S%;BOdu^x#-Pp_NF#-@uU`>+|@4Y)I zK+ctrFl2TfsL*|iqQ5kJ7Vl=a<&Xm57#Ei^zst6pFlbmjX+J3Afcjs2UUJH}g&rbHg2b34$CD2rCge0CGag zyUtUmTgK}_wz$`r3>a?;5SUKS0Y!TcTi3zUAfq6dA+ZXiN;6f3XV4Qhf6C9VN-!gA z8NkiU0jw(MpvDoyJfn*vz}5vmHH!GS=Kg(K;5t{i0_Y7;20D9>ltYdF3d>AiU^qF2$b}M zFEOx>q$%GDC4+91H!e5+{sURWHvlN~FQ4BP3nPQ1kSl4`#7;0H|2!DeoJ3R^UJ;WU z`B%r&BYc8#M0{r6fqsewDdQW~<0~YH9l{bpyY}lD8fNl_9vglDO<_Q+23GaAl{GWo z33e(pKu%!?W%TyYvPhm%z5a?gH8oYUkQ0@Vz?ac*^UFo5{Kw17eznEf;BLNeL|=Il zS*8ecD%m^pV*tlU5eXPn)7vIHLr!oGQiFxKrSC_y;t#Mro1?ynHIOMPb_#3yr^k>i z+x^zk#3bPxHcA?(0p}PW6JgI0JAe29;uXU<`|=x5n~^U8ck{+%WHt+Nj)90x1P#|* zB+W#IKh*cK$O8id>#|*+a;$h6MY+)jR_WD!iDrn@>nT2QsBkQ`vG1KdRS4aCFHeFT zM)e*D5qJ8s9SK*{YV65GI5uSA5{dy_zvLMw#OyMXV+DE__C$d1KU79$;4oNlY^%$0 zMJQy7(Tma*h|E(K85$>M_E~Z;@U zYJk+IaR_~zA5;G-sA>lAY$Jr}H_>R|tT>Ivxh2NM*%)H##ey<$iilSayf2EFah;tq zA6ll1>46l@j3XE`T?HqLfIHY3=4-uxBAZe#5gTsSG*m|pK%sp&7e^4|RU=;OoPY1T zJ2_Q->t&2xlB{QLjuXVxODzS0_oOeT<+wtr;L?4p?@^{`(>$+9K*X1dPSn-UK}}G~ z;(mS<@X+~VJ@)u8o^s1O{}J%rN*($iG`lVHJkJBe37Dsj?~tw`F2w#KP3PO=Pr$v> zV{B&mhhQ=d)?8Uaz$TA+rS=}0W)k;7y9pm+i(oi@+r;F&JoDfgbI8wBHE+h(CuhyoMr7x0m$v`2pKqLS|I_Ks24&1$a*Niu( zC^J);tqcUl`SC_Z@$#V;bncA;gV~fCxDeTN=?AbldCVrS6lwL*9TzAq@Z+!Dm}gh)Y0Rp<+KH~v7Gy+*2==+rZl?_w#0fKL zP^se|0k)b!U^1tHou3s`7=)I9)3&zv&To1Cdb@uMqxGR{utKDEDBn;LORFh&QJs8 z;wiDz`82h???j`zhDLrMv`ImmLSqoHI`~JB2Nfx~6HVgTDf#V>>Wgakd^N1|#qGch zf%OYoC<8_K>k$|kHAiRX-rz3Z;`JutR+x$(kuF$%k{7u^7j)h{Uxx!x!ySA{K9PYZ zl1DS*H9gc0gH}NzDY9|PbP*N@y%+EhDd5{b()C^PTY` zya@x7jR#m*@*PXJUqto?O{dZ&z#V`tP8`Gam{vQG;obvI$9VPxZt{e+clB+Li;W#` z#A-71Di?8vydxMg9rotS;Q+(;9(?{_M@pv++- zpo^hgzt%a)&9ceMmz9-$fN+H)#A}ULQ|&r)dB03fzURyr^!~{PZXJ^g4jH@Lm&;WQ z`iAnSqC0wKyMw#jN~;dNg^nFqI`?}HK-pTt337!j#2?0ugkAg8g29Rp-8AQvlS`uE znkWbE_&+@|(;Hidpe63Z{&P@$g6hbEh=hbh^k~_`hcPso)4A&R(?ECxCce&%tx&qM zVuZF6gfeXfgvS$4(1|zfcCn=y?UW zT^ql|Ug(%JFfbTzJa7Qk$H%S zFMmFX%sHT(*5A3eC~a32IxGnhlnYa+BRGF>D4O^1VUe&5kc=e1HdGTl;9JLqOe?>) zQ((w5Ks`4%rzs|gc^7SYrrrNwWo2d7>u;znx3SEbg9oNBB8J@%rB04OpIL=)R3)z= zbl~T2Ou#I?>$Q#eA_>d98x+HRKoYOV`Q7^3N~KQpEtF;q_<7t#L3hpbV7N?D3*J-A z3kr7F(kg*&VDbGZI`JtD7x4iiUKSeESfc1+#4l|p**kutNNqrdY{CCx`yfhZ0%f6sv!Mvz2m!KD8~gEYa-=|{EAUgz z?j$6%6~0?|Ykur770^+bj+}l>4dQ2Nm9PU`qZG5JgcwoZ z8i2M11_ket?G!}5k|NYb2kAM2=F?MCkKecrnst}QUL2A?nLI%~p<-b%1VqpZ*Y{6u zLX!T$3cJW5jBQs*7>X2y%kuRP z`gqn1R7aP}!iAP|w)EAyBDq=Hvu8{DmJS6|j=-Uecp?Doz-sO*9ql+VMCP5nWEzZw z2v^JT`FW3_p5nDTH`$LNl!L2Du&d7{hYwHRrtwX=A?-7hx~B`Y?A}I2UiKiqfy^;7 z8`N-Sw#=Tl8C{a!TMRlcf*C2`Id+J;miTE0(0*(Bsyz8qED};yV@}9dBX5f+h}0QZ z@1a+48@*AbGtSVpTn5>wBJVus=%Dt9bRZw2{A*#4@lL2Lx{+3;pFk&~&tK3~BqP>- z`H;v7J&*Tylae%TTcFRNuhw6xKFg%>JD)U0kpryb%Y1@j2!MXBqJHGPuKyeaN1%WMztp$hg#X@;RhMc00fkGU$Ak zF0W9ByItn{s8}Jt?LVrg>ooW=`619M_&zGVLoh-VD0rt>sGPX58Ja=&AB5mo)%KQt z1FIulVyR5eNdW`9M3t^O)ji!`Z6IgEW*nlO@}eY7nX3o(-Vy41OR8nk6s5Lr88;Z0 z!2!#*wqFkww+ylnCV!0(2h7qzF;qv^bi&IH^5c(gGf9PaUL%NfQW z9H@X`3!xtbfv|{93~+*p#!iLJQYdJLO{Yd0hY44UgKD~%=mNEmEv2;|NjRO0I8x%Q zx_D}9hSgOy;^T#=LEETdIw%9*U&&x%RcGfN8d%B-k16JInTFDk-K~A$N|(CmXzf}s zrG6~LvKCDAwnVVCqt4exe;+h2^=XhEix#_Y`cINPDn*r)v6}HbKhsRz%qO7W5UgTM%m&wIf69C zt(bqYXMh=8fy$?v@>GPHL+L);V=k; z_GRHc1ID&#UwUI8ye7Q!Pj&^Z6LsR`qKFYV+7kKB@M~W4TRC1~eiJ>3i<^n(E3IV& zSMtE}5c~QdS5tp|JAFOGM+0l%!UnIFUe>QK)90%3#Lgd#6R&`Vpv-_hH$MdeBiFA_ z8#l7fBZ9KOquzUAg__oalvZSU;Naem;-^KXB2El{1R^(gHjN=I%cy1NJ6ty5;QLBp z!XKcSS`tAeZR}=rO&WA3**o_4^l%SXwr^Fck@k(mo1p7 zn#O1BRZ6VX$4s3X#Wfu~t*h!Uc^~Hj?R7EUT#$++HJ7>JK?JcUP-p0qowKu-0cOq9 zH?h$^$R0?hEBwp7sr7{S1ljq7`W#Z5^+$?5FhmMHy) zfCtupIe+i29TQ*f@R$R@1&S=Plhl-3Jw*AbCPLqM=B85n3TILe8mf+UVKW|D2|{w^ zZjPY_I*#g7p1Xls9dAFV+uGWK-kp5w{5C^GRki@PEI^N%i(DSojTK%^?8tcOcFNama_poTLG9VoLmxHiShC6ch^xDm^Ewx>{)Dq1 zWd1I`G~DJ~>!l8E^f)(;kA2P3l&3L~Evz|iNc^_PPoA!pixqugu9Lt2G4qAI-R;d+ zYhr8jg|)~&j?a?ca9DoXwX!IBR%RKuzX;bcMjBfwxLO|@W5WvT$KsDszts8*W!&?} zdGOyAMEUP1wOEGFuQbvrTw49{4YsIcWkkttZ53oze0W#qd$bkSe|*?SObPgYmpg+^ z^+%Tqn=gN8CXO%2Xa^nt{J{k4e4NR_J{)PIS&t;&nh;5t(NVRVi);&5R^8!5vcqZf zy|g_GGC+X5=XJ&qaV$i6I#2u&nkL>10TC~fa4RdyUg0FVs;p_71*wd+S(?t?MLQ;k z#wx{Hb9{s)q!{!;`i^-Bgzl`tImu<%o;%almsk=!r{fQpOR1J0$7r7Bm*Cy31;NRG z?5h6+-6wrIZ}Ma^Kk`M6rqkEJ6C6Yj!QttNY)QI&CY0eghpsOOBU(o%q3ml;s0vl? z(c2Ffh4C{bjp-1h)w0l!b0V{DNbaN~&Z5k}XuybA<)Q4IyrZt_6WvHXD7j$nB}hY9 zjd+=>r~z|e_Q1*bUw z8PuzE-Q^xWGQrWk6Z`C$yKF1pT%;tIC&np*54WJk4J`^sFFfHzz2cw02OE075mKP& zAWqIj4(+MU*XceTn$oFk+oFUumprtvjn3DqE2;B)QA3n)n(INF^kkxs|5*lwKah+J zt$IT(841P?1_0i9l0$6YZuT_9v(n)&Z-2+vRc=92_xY@vO`p)UuU`jra`>_u;8nrW zM@`#0V9kb16}AChFI`Au$P}V3&2}HP!cSqWmMg*7^NzsC*Zhp{jNiS$wS^Z2n@~R2 zaxZuiydn;P4c*s6C0kG4E<-TtE+$j0C0JL2$~=w zIX?iFgPv|xM00QxYQMgn{?n&V(V!^tiUA{cHzr025kyWG{wCET%#FazkT3vy%mNPC zGtuf=c8ozd5_o+<%Al}s7YfmKY0kJ7xR?%|EdCrB$z)cpLg-V1%FLmMjEudLbCt98SG< z`#W_)=N+qRhHmFbub|SMVuOZ#S|#QCSPsrx)(->sZ3>Xx58+SCa38QeqPaOa7^Ly< zqF8x5b=b40KsX~ObXM$r>$NQ`<`jbK)5pifRWhLJasD;XP)Ofh-zGOqRi3tT|gZeMbO5(lnsr;u_8GjUt1>BruC{h>X58BZ``*au!8&fAi(b z7eGoslYwwagU^~Od57-q0LXPe^dAbEJ-T2BU<>GYTVSZ6-}i2GbQ%pXdWbb#4aN!7 zm)Br@0e}Z$6gMnJ00ksIIBr2gv`_4fjCw&|&=bT5g7!RVWxy)_cx#(7HB@WLTnFMX zfZO1nb1|b@#~`+qxeRNuYN~z${&q7*h9?3CFVA;B&p5+3dY-y&<7N?M&O2zLn?!e` zd_e>o-ydttOEqy95U|gP)C=hDnCxleJgf*B7Q=p@1*VvVdV9YkGRTwHS@%>)CmaoqXFtAvu& zF$PbthX}V=@Zf<5Bu02`&@!2y%qyJSl=m$t2&XHWdPEHnOAV-IeMVdxq$DL}=}}AH z0lT&z>>+}x0ps%1vf$m13A=nRFeTmmxA3*pOm4#43&PQD)vYQ+lM~)qxA}Rei=;ssd1Te|b_Y{<03a z%UG(JwosUdr==9}_D)_$Fm+WQ00Q(ePV&ESe0a23$f}s#t?srvS7!v2JvE8&TtDRH zo#4#~hZZpjwAMXoUDZJ}v(6VPH0a*EDMf^rXYkRB+!)X2ZEd1xi2AqbVm$V2s<&zq zK@i=GXOykt9Y|;5bU{%A^gg7}2)awBVI85A?Ftw{78(#1^J3fx!*1||mO_JYL@>ZJ znv^3@*wG|HgwbI{wP1R(G{w+>;ohU+lA~?fmIzb^cl`Tl)vP}<3^=#9yX&fjF7=wa z90mj*4?t@iXds(^6OX4^Bh<$s^AygqL;$wVP(#PB85Io*^(UGSowLam)7 z+eC~;EfqoGi61%mFW_e{CDVYFsudSf?4TKehnF7+N>eX`xn|GdFsLE06)+@%oGSD- zk`EpAI!(P4z=OS7A2|ThsBhJu3hgptp6#!p0`mnxE0=2altRaH8|aTrMm}Y!p{dNC zc=hAJ>X2qMYCEQW>?TNzP_Gi{$TOy~t~=;hpL>6qBm-`D2c@s4_d`o<*6RqieD(W* zdw}_U!{5Agc??>8I$U&{)SxRH4TS*K?J;KcTVfxBIt3_dNSoXJFv%AK2=)`M6~B!c zHp$b}fVpS$&aXb^9{Tg#l|U#jFP9=TKs4gIUmO++ruF=IQ`1EG=aYV2ie3FT-9bpB zgubk-Y_bu`BzP|989&V2y}$G)JP)YJd+5$`2l+|_*th#W zdAS^XFfQx}XORjwR_)2;09CXSdMyYdH1;p@s9>+iM-;L{aD;;#6YTZCkB4##?YDpN zOiD|C)TO4SUAvr!wS`3?AA~h^{t4%Q>m(^@5&h|5c@a!G$ zYPl`oJ<^;!F#`ar07AXp9g)O-pjEnAECCfGAh&~uuEj?(=v!w}y~GD*FsIG-##qB2pk(Mka$X`Xfs5rSbqd^2Pm?EG*3L` zlz0UK=wu;bt8Xs|@my7y>aFOUoSeru2F2aJ{TW`V9|LBF#R$Mm7ZwB9C>Sf=j;3>zbRKw01Vrhd;6+WIh1D+|^Xog1y6Vj{nwnwQN_5Hgp8irq zMe51(=|v4b#9nVFeCTaAijv71%8W$H>3R()6- zxTKjszTJxV8-5KH*L-B2a^4i-?69RVG&F?uE{TF9h0G~k8M!E}3NrFUL`RLet?&U@ zgBZ8INRYT?>*t1INPI+GH!6dqazDQrm=qW4xM4g-msoc? z(Pr(xy~njxC@^ccKARfL1N&yA!Co--$(^V%|AVC(BDKLAkQaicjiK;VuTR7WxbQ6I z9W+VRfW{l(VSiq~k2sa|?FKZV<5F@(+bf7g@~5i|Wu3 z=X&cph_JxsG{>Oko5e!~>Ux2u2SX3a%tD=K5{Fr1MrWIx+DX$Y;o<&%j9HEHt-|Z6f#%hY(2*K>EddDqKN& zux9&*nDc($jsxz^$1~u4&FC4FClS?*L-v{=%9P5C#{7+TSe77v8jHcAcG3{s-qY z;bgMQ=O1Y)4)5+NP(Lgw`Ei9(ir?OO22g&8@Nk-L1puFljeTiP@Q!JQuIJ2E-Ow^t zI#8)I^nh{s1Qwi>Ihng>;#4jRCTMcvKhYW)7A$J{O@~2~ppm zs8{X3AFo19O-~JOXQ@b)nHL+#hr`TZFiB^i+1nm;ilF$yM30kg*LFR}1hBmU;tvgh zKo!j@=NGFIE>Aqx#tViL$2=!rg1JU7G*Q9PhE-;nah7-49fwsWBd3N4oB|c@fTJlX zl0E7wijxJ6+~(Y_nAFzd{7zobdY1;34LJWK?DRu^p?fwi`QlPqQW9v2Ajey9Q_#xR zNmfzbwf{DP$nOr6Wav9>x0^YzY*B_;RPb7vg!!GMq$vZ{YFb5A|Lcg>#->I)_(mYb z3Du`cVxVGiqFS+Ue>dx?@sgzsDfCSSGO?k~F3%3i8wSYcUH>gS$SGaZF3g?`MR(|W ziqWy_&!Hmr?u&|vNvAG%>i2^Fun|Mwbb)i@)_aix-Sg+z5ol}!%{Bg-3;q&yx<4S^ zgCJ&fR=_P}EQ)*lw%EVL)U(G4n*){@Y_X45GtsC!@8`N{+hhj5;=foTFU=z(3aD zfezR5jXO<#^d$9p#fQqZWJ0T6XmK*S^oxP>Cw8-Mg3P(|9-A)^bE(3RZ|LiRbcXcJ zB1`AE$J13uR5H~VMV?XTBVz0`E|(*FIy+PKNL8I>_tP=r$E}$CXxbS_>3oVG`#sfE zADZZ9`=CoZDdJMQv7(a4xt=P7WsWRe)%>RdML6&MhDo;FUneGX_vTv4sDYNc;m3^A zN+LCe3WtqA?V@{K8Vce0dL;F}LeiZbd6qK!sVEHsC#SXn%D@(*G6nN+?jS=ei)Z%01B4V)GqD@Iz^L6 zrKuA?5oM*d@0h4)v{})>T0->jCtkV6=Ng1WE3i-;&?sm$f))#xn7Cf;Zy0t#>4#J9h+qJ38ZD=Ak|K}wHM%>xc>O@ad{O~J)C`)WsBHIy3G=JS8y2^IqoHB-et*oqGtywqcGGAI% zd_`j9VVp9#g!d_n|XizF!Ih=<)4o@MPSYOg5S5o%bCz5-8kYZeQ@WRw8wZm zG!|PR@A%>l?^qvGcrCvgKMLPP-jp4twD~Ou_!jHI)ra*PIh#L88~h=aErPW+9vOg@ z6r^u~_ZIU1|F=s-Zl-Osua!l|Ig& zy|}60e_`$a1K#pRZo*?3X8z}?DKL~d0}PALUTyKy8vts6?u!4Q*8X4lVKv^t;WJdO zgE=NAC&6;{dsU&H6BGo!y<0%}dq)pdAQZ(i1 zz_mF}(AFR8AuA^=+}YDJ2L&IG0MOrw8yOjaGZkM!Nl{T`#4P|I7NF#FNX8Ajm@-1w z-`{^!^AcnuK$8Tv>CoG^G71WoP4R8?U-jxXfP2?@84i3Wytj_cE_Ub5ssbTNn(0_RO#S$pnVFRb!RtZ;Np_^@0kde7N4cfWJ{@sR~ z3k^&@+N&Wls-#bYlqg?8MM+8Y@K^>YN-V$e1+5tJlhez!ka{;2sNZh2o?W^3WO;gg z{7p=J+pni~0qONmi<*U?1C>_5Hokq{xwf_j9!1nCC(hhm{m`Qe(pA)nP*;|k@CJ`C zgVGJCf!1Eg*<9Qd6seyi#Kli=4uA}N$HT91$Vf;`ocmn%=#kvz^<%zm>uUAakx09u z;5%#W=22hxa}8YSE32wH;D1FXru9)pJnFoH0Rp=o{8G246~nW zDYZ;MP_Vgs8Xje>^97X^5bLP;IX{m(@t>;Ct84N`tJUXih7t;jm$`7oP)Gm?gwxAw zFj`G?Lv;a(!g4XKkV^h2tY2?C|FBpnA9OAFjtB`c6C`*p*^8WWauUGjgS6;C(dlJ5 z8JYb8vw%bgaulOuxE2`%b04f<_mEwK2M;%rG1Il|nlc7-%?+M`jU?wj6(S4T;Q^H>5gpWe#QNXn1GJ0AKo_1Z* zYw+~IwM6+g^k@tDHS%zCr`e>Je+J?wF%upKNE1{{?;&k5A+_$DBuR&2=@hER)@mIJ)Kd& zH!5!u`$JXG+*9x&{I##{fjYwp{v!ecai*AQ;2IYb;J4B@L+3@o_-;DSv_`}T?C8T7 zSQ(?Y-Oim$D{)kaQ~wns4#eCuxK01KncNT604@VNJ3DAdd8#?k*9Qx=&)yma&5;C) zvfC6%{B9Xh@k2!~-V}TP(Ibgo?b(N)hcC@(cCip(UA7&d0w}}F?+}<}Y78@QH$VLO z(5KFrnt}kx^0-)IjsYS^0=z^bTK$rTjGco67<1Tre1!r6tkSNAkxPywVBHT54MAm4 zuNP(fa&XYR;>;psgg{Z$aFm_|%$oRG9zu+M-^SqyZwO&s0ahX3XVx1(O`)g9-BgjS z5GH>qOcoE>L(i0@)_D@!zlw{(V>Vl`#zB#T#~ek`Vp1@qxhkqdf5hp(96P zD|D`blqi&;nhMf#atiZJPBkJ3o`dG{Mn2-717IIlgjDyBpxuR+j=+ zPox&9q46`;_Zbb&SLfw9I5_0Zzgj%DW?^9=SQ8J{)KGrV%QC)4xUZK3&H!mH46#1i zAjF;42zu>a7u;N3b$(vxCHve>J)HRJ<)N%$B*;5Cg_$cWDK&!Q?oBkGMtx&Z{l>cg z{RF6MgwZ-XIPlAU0Su-K51wk&0Zj5+1b^-j7fc^@PlL@U%4oQ8-X9>JnRH=r4~8y8 zBfqG&?&(o3vT^$L#(Y89Bk_b5c@y#TAiE4;fysVovToKHt5}O&KO4g9X_Ie?dI4YZkqwwrGBkUc)1R!iZ<=_!%6c;V_Kic?n+{& z<>y};8W@<*xs6QA$IKsT)an6bhml+%kNaC&XOz5f_u^b5z?u0$D+FvZzIfjM+&K=? zd1yF)ko7Zn%678EEhn{~2jxGreF1d4b}=5Rud7>cfrd`#F2Ns{P14G)VcER%a{)lH zD|3AV%O%|k$}F||4dijtUvser)jeHYT>M7z0C-0C4GcUuyU-Cs*Z_rm;#({adtISM-hfW|F##|ZQ;7D8lm@q?NHB~H_}IsvarOop9hl>RN-3W zuM743m^BP#!&}OoOE)U6y?Ulu4=IGlDxe!o3Qw&?m8Du}!G@EjdTMgAjZsWQM0b9& z4u&GFDKD7-kBfPC9{j#@oI7{yIA;aP3q&p%_#Ee_P(=a`_JQTYCR2ZY)Y5J#plMZC zS3{08#{fiCi?5S#1;zVh;@6Ug?3rVfj zxsKr6vRB}sGX5ipHFG_CK#*f(@bO4MZbQUzX!t~We9{0-09pa~eAk-Xw>&}$R%HQBrhb}wbNyyTP= zp+0T-x6bzVXUxow$Z|j5ZP~tCgAl>aR)$!}n869qYCW^nTJ&gp-_TGUH1q*bcP{Z> zu<;mV_wWZF`tyZtCnpzYcR?37TOmh#D;sBb8+V~|zCz-H z!XTS2r2q5Bx!BtjOs zQbVEsxDuH^uH+x?%>#z@Jlv3t0N%+>Kv+c3+Q!Sn#l_KG(B9d@#!(RNS;+mokhi^q zy^ytwke9uUw+`OcM#$C8BI22xZzyzZr1;5 zY($a!Kpr77+W*Gbh)N5JiA%CeNr@q2A|fU#C@m??E+s7?C@CZJ?~M&I2LEDgL`DAN zl~{S$yEtz?Q56>h7nINmc2jBOr`d&0pD|(oeJ#>bf-+*#?9QH!j^=+1w&?HK`ETCZ zUpMpn-ed%&rT_2lZSx-f)xG^*6MtOFzjbdgsDjcW|MAv-uctqL-+wiuMZ_fqB}By8 zCE+=V3X8IfNQenah{4w~QZT1Q{;lUGirmA$y0_oU7`c|e<}@rU%n$bn$eCwIZPNbJ7YJI>TyqbH_Uh=zHMZJm5Q;Hnw?4yQH{?pbShK zarjbHMw(qxLR3%+zW#TXyeKjZ|7v*tFN4poNi7aBNCG|@e0v3j;faY$z{2}CFGb`( zTVcrB`MuUp**M#J*s+UlzL#C-q`f1IKm6^8_pmtuA=cW49pcunc<*yB%=lS!k2K@p z7{7r83vbn{=+&1c)Z(wUNgVgoKSD*rV?=+|X}d!7#L}`%G($`A(JiM-IV}g>*~VB~ z>$&dfGS6M1XQcMS71STc-htb%7Yr{&oGog;QMheqApnfHe4 ztSN2}IO)rq8S4AedDTZDfFk~|Wn#vu>gQ)$bA+%~_gp{q9H(kNmT3AW>r=NM?FYNv zH}(!#9>R5e-piMEYX10(*Af2W=fAVvrhGCN$YaA;x=##q4gBO4O8j&__Uc(b++t7P z5}bLswco(lXCQy!oTi?QjQ(x4d_Fgq<5+WrsNBIyRmoN}+p1olGld#G4|;zb{c<4H zD&i!Q35QH@{wB1@FO*0c?jGYC=Dj18S;e6y|2lr^ zu0_6sqh@PxxrTY zKH>vsZ;kI)kvr)XBpf47#nGIma3AY>{l@Z^+oCrXUrayF?h7#}^fI=-uX=s7>$_aP z^Rv<};>D>A`-B8(l#bi<4N|{()k(_w1Lm?-7^WDT^TAtp$=;CWu=Bps)u(cG*5%Yy zCL`-J39ApjHt9-nC^6G%UbHpQT{B2v%RaWGcii|HU+Yt)q*#fe8kHMfL9`Q>mc~Au zDoW*d9b@~toig;T3WjU<_S_dqZtG>wEe`7W^3DoB&s%#ZsMBA`!Q$$W^k(kyC%FO! zGwRQLLwVy)$*Z;@Gz{2^RMH^ky#|B0=x0sglg-@=^fxHR9QDjB?)4N8=18uxK1EGa zTXs-{eIbZTvYirr>O;*=rPb%&y!LpK_u6eUm0h(Ap)1E~#xGg7y!FpJT9tdW%e6%8 z-g!{n*o$v+te+FkkCb^xc6Cmua-Ru3=u^RP@B5hIn5>3+Uh*`1++9&)=UAaOiY?dG zGB=18(q>KDVmMAc|TZRmDv-CO_SrIF2= z75%GYj^^R#_sKkQeBADDcDUs3<5#XRToT_$4NVv1tj7u*-p!w1op)q}saNrUR{|%e#I~I`RxUd-yP~OJEeM!#Z2qy zxkC!}dxBk*c^nmzi%wWYe~7=uf0J)67JAiwsm@`2o2<#$w*B9g8&eggwz*J?!G%v7#q z94L_u!9CyM(LzHv_Vir7TlSMQtCYbFg;=ev+mO`vpK|rz!QT`mf^128sLj+5{zB3u z_zOuX;IE&VtLV?SnEy_pfB*2YV<>iZ$dlb&Jl(8p+}VHT1n|<&O%_Q>kvC}CSli=q zE@si_@D&3z zKaD0oqcptZza^TO3aKe6;qdM@*6f?do6XRzuZeeeVBd^|djAk(z6?_P7`z&6xv02j z-jgJ#^S~&#?A&0(VDD?=V&@zFpKeqF*48gb9~hIzPr1h zcdd6l>-RqI^Q`q->;B`uzh8Ur>vMgs>l}{rIFD0wJ=LTzn$tCQ-keK{V~SaY?*|T% z7j?BnY@kzVhe5fheQofW&P?6Xzkhn(w`EwyjqrW+^UVu*IL0I^pUO2^E}1ju^kM&t z8*M+Z&Y7c2B{5y|8poIMt2ST$C}e;S@L=6y#77gPsf!QhInSN*Dqu6Hq<019%t!y0$pD$^>@llQjdkjD;X6>Py>D?YC$H&+ZT`F1PkNsZHr?4|SPyxCT}FpA+3 zQ})%QO6kS(hW9#dw?2Af#lT?QOWGV|$--lg?z8>+{~F##+?2}twtl=R)9#YrW|fKP zf%?~)<`3szKC(k;PPr^QC`)D;U3zTQ3eUS8H`xq#6X z@3omXEV*{YY@VpMLzMT{z74lidBs*PS@?N@6~~}5=ka>+wdP8;8&@uU!q6!3Ele^d z%YH{?NXPz-s}D23a`+(bqUO+dB2M_z<^7xQ@?ILeYyaO1`R^V1|MrYDzco+riLiPx z@5h=#zrPM-qtj5&7O4gqL%K~m+k%S=+vNW`yu^*{%iy2&?+cF#HLm^bWA`OzBm|@y zToewI7qLq_l>K!l%H?DX-8g3UkYYKxgc_Ip<0HPV(?VmJl-dVZ`>IWIr{`J?sD}T2 z--cD^rXRZTurj_aFG`t@mo(q&zQo^`ugfoR62*h^XmF}4=`;8v{{t5J4=9SdpRn#U)waqTlhJtq(@AW9=45aW^c-N9yMCR;T`1>Mh z2~qQYu;vJo8SPykr%dq|NjEP#@#NJ4X+wNAory(()91@@9K|9`^Z^%CBBcNPZO6Gj zV>!!5`?pxX-SNk=7B!Zo( zv$pq;dzl=0WC>p5silYalPl%O*C&rW7+OW$cZCw?{paufzx%oi!O+fB3f{@X#}@_R zCCda%<_dI?Zhrsj@MQ-4x(CgQbF053S5jyXvXwX27zWNcIub**(8X4npcjf3Aa0V# zqCXZ?M@G-t!V{{RnxbdQqrq0-vNk&T$FnJ6F4k@gQSUybs;ZjnI_*L8bpPWSf}SQM zq%{bDNg*gWx{As+|Bu7Kae!Qz_s2TraGL&n>#J})KCHfb3A;pL9DQ)GlbhtU0DJoX z!`Es0j19{qGXGCr|DCn9+a8BXHP3>Byo)W{KOWou%HXS$0 zxna8Fd-gf0$%GV@esSzyXZx`*}|VG6w4WKF}Hx|=N_gT0xb=|fTD z7~`J2vNw%g!`XQXgV;Cps_#At#>?{2NV$!(uUd{mPIC>c5YTyPV{-WL2P5x&7kXc| z$6O>t)X;iG%!F>TeERb4miH4F*|)8c?9q6d=ju8<}=W zbFgR9%{!XSm+1fXiD5KdqD?*=^A1u$(nTK#e9)^@U<`CK(W=a!uo8)XiajW*^MUSfFm8v-#1Pu?F_bj~MCVAfY2Sd7 zf>5o}WF^{ElT%V|pbIcoL(uG~t80$&n3YJ^TIm0MwPi=^^D_JH5Du=SV8X)Fwx_sG zPk;~K1%ZR(oJ%6?Dz#Lkrfn4z6wo`K9$MLoEo*D02<*~$^8;j7^D}2;Z?6@)(4(1} zlbpO$QnEhUj}DGfCIm|z8p7_}c?PERdHwThvGay{>%_UZxIovhjW>7npq+Y1T(V4A zNV%*ty?2tHQHx21UhI2Gy%%0C#!hedqJi%PO4RY9oq6paf{p5g(f^J?pF2{!(;+hr zmK21m1cC{R(`2b!mu6922C5{)ZhO9_^4Fd<`|UR{zs@f0$IJHc$*I9o?+xNMP*7Bf>=8PY-{SPM#kOxxzysATk2_>$*6GWmNVZzBe)s0u zvkYpgsu0h-t)J~kj89Kw5n=q#%L;t9BkR1HaH(yq$t9(wocKxHmfO?Ya2F~6!3%73DCOoy!7;5&b@?Nv>t-ti2eOU~3odn&N1Dy1+ zyyYUb_mizd_nZxP>V1i(e&wXtU&l!S1C1cQT2a6NNdkR{Iqc1y#!TK(Xz^DJfW{i> z0N%mYS8M|XY2=YZd9Q^X{{Dr$w)S>6bggUX*&T;~YI#-vn>sGSezZ+cEPPhKFno6t zdI7_opH0z@$Ge~fef80$+K+|iFJ7VM7H>2?F^sDnu;zNE-DziO!(FPgJ~=izI@*ms z!?bVc2>ScWNBhJs^o)HAJ$F4*kFan>;y#)_1)+g~YgVl~`G&PRj*N?##jEdq)qQ#opV|^|8B_%6Rwjp8IAp~_eYll8VPwMg%tCZ)M9D(GS-pV=dEq2d2Z%c zN)K4BwW7*S6eh0qlhWA2Hfl^<+&y9QO15)Z)}LfppOR}~^k99>@jSD3RqylLWnRSn zhBUs@a96;cI~y;jJb%8sw)pAQtP%=0`b3~cDrTI&(!s$e08&W)d)Nl-^c>dt(<}$v zdqURyw25yxs2Gbde9WsaCN{zMEH=n^FTxFhZ9NUSxe|^Dbw(|>2**ObhA&s9;Spv5 z3k#7)v5DwP@FKthlkz8NrGC*t(ag7v4*kwZEhF`UWaz8 z6}z7*P8om25@8<@vI7DPZ3nPNQ^Bwv?!bPpQ`m9v^rw?9u zBSI4w|7co_szPX1z7Fd;*Qx$IsITvTXQBJ;!|DZA_GD#Dfb;O^sE7^9I!H{L zK9wOb)Ysq!ht*`M?H9S-IOyKJTFBGhzJ1$DB&u`M>;X<>kZFc}l^FVX$TY&`0`8ia zeXoSujI;TC`2eE%10-sdeZ%F0CE|&YY=$_%v)=3$FL6nPHd51_Dp6q#w^vh9YuD$a}&T3r{aO$JC^gNwgm zzAxd3%dVd<+1m~~rE%O0-RQ|mu*!rl)VjOV%r&7Co zWwwlJDqnqiG-E54F-G#hzqmlRJVPhZYtLgd0nIk!JcuMR!VBfZZlu@!Ru_6cia&m<-Zrq`f=r2E1|uWh7kbGXJ6Fu9&m(4MAtJL zXS0Ck-@~BcHBi9E*6+Ppevf{#ae*ACi)~wgMvR3(-7r|d`s-!qp55{2)Y5tBq9pWz zI6%z&j6-MHoImR@HlY>ra2RE9PSrCza=; zwz=Bw;}IVf^8MS;YW6kb1>_GPvWtI?i||}fxK|I~oO)T>uv$i+twL$9S8Y~%xKrG& z<>5H#)Woj!ur>nKlbFeV*{&%WmmEW;q??n5_g7MxaRz;}XE3!{n`x_D_s0is-?19R zama8bS)7>ORPJYtW~#DXzVDCk3H;+kLCj)qV(bWIYP>z7C=jYRBg+ZJZLOy{Px*YtaEfeuY#Z=S zhq|l!FjYvYmztO7qf%w-735@P z2TXYn?na~@9le=K8~9ozB7mHeFycQCY;1}{0OY{6ea3=K!+qKm1+#~eH}dfCNV*-( z#>x3ktpDwD5ls>F%C#-QE%!{7HK}T(^bAJz_6jxb;mo{)=;7BM=nAFLpQJEcNqR^o`_*dt|nokpO6i5 zNKHmPm7 zm<1@jYrl71`C_QC0CB}uQs?IV^saa@=QPQImnOa#c?+MbpTeMxkX@!;wLJ7NVti0! zWV9!n5Q*q_Or9#_Pt2b$&!QeWjYLe%X?oO+J_^0X>9!yPLRhR_>d~Q)2in4?KHLqp z%#gRlEsgPfyOs(q4zv`G3=|1Mr9++Pr2MdNJ(8)ht5JDI#3lfCT>I0<-rhO{4;SDM zG4_T_!vzHe$@*dE?o$@}3s){IM!@Je+-3JYwJPmQMHi0g6sECn@+ti~)|=VqiUodO z?2Nk+pR$35Xteb-l}fE#zc(aKHOS=7O8%m*Pyte|k)dHi)=n1SMA?rLG3$W_$W?xUxa(8pYikf< z#9niD%4@!OJ7mj}{ePv85k*T~pt7{9VU?d8!}R>)dD_RL-e4GAhaLu7eR}9Vq0l%z z+922`UjEK+6<1L4>Yz=aIwX+YkpHoiC8ycd}Vq0E!(y& zNBl)Tb+f>OcFE|c-Fx&gQ{K*Q7&>G15IRHuk1kIWPTDB$IV56q%M6%zy)%|Jd?obr zl&N+Q10nRn)^Bpf4DWusm+#*l7Fy@C*6LUGvf8li7ebt2 zQ|bHEV8fk%zpc$f+f&fVf=o*ST_2|Rtgjol;LOw^$!$t2pk4`Rzg5bl!7XTF&|FF&Fugug4qrpwD)n4eoS(|46EJ{n$e(=2N$^$Ddo<)TX?x=ca$yvCM`E~Mx4v~s%l5} zqqMX=e0=SgYlP0+l*0Fj%N%eSWxYA{)YaGYRt9_hwb09Pl&SLcC=c3l*$1Of5JRM= zrz44w(~CUlvLO+VjJ7Z)`_GJjZ{2?BX4wM|M$?hhBleF%cpeq*7*qJZ$KtRLO~=%jG= z>~|z4Qb@dF6LYk~lrgxx2Jyz;ZQH)11+2+3?9-n=pnnA2&M?B5?bY(|*7l?FW64F^ zaX3aH6onZV8+t2+mw#C8w`$e~ESDx*u3qiPicnTjNeR-aPDq*5NICuQ*>EEU(SCQ{ zteF{4sukvgapN0DqY;xr7PC9%Dg+brmnTCh*Y4c$;}y7bh*;vK-zl} z4_2{`3Mhue%$zsrxo+1JgIw30f@-vYJ1f_%+uN+^JJ)&U`3~d!JCM!Wa_mXIK0L>n zY>Kk7GKKQ2kBezjH$a9*mLo_x%dTkaKRa+2BiSE{MUX_xW=}Cm-1u360 z?2+RQ+ztcMVv*uFe8$`bbLempTlbximXbkx>f^vnA22lFhB-#FM){7kxzc?W@b!^3DbD z0JOnI$GMZPT@zzUH7@Xl6r+|14^vTK*Nd&bV%UFmm0i3L48_}DL>Iio%;Td;O0-LP z_H4)Y?UofW$CI;gwE%esu?2UBUCk&)y8PZqAE%j89~K)!8ojXS0G1Uj{dEk*pk*zTJZ&KZ%a zIJ|CMX6tz+*f6<8rWqY}YsTfR4U&!J)ztjOCN;RM0a1Q6db$>a#atN}t*xyg?b(2& za@spwk*ut!n9|2(_Ik!c+E7$LloYGt*j6B*GDE~G-O$-eklYvea$~@oc6yIS8cz4E zo@88ewB`ZlOv4!?-Hy)&pdpwd`^497k-Im=BGT9(Ipzq7YO)uwO3db=-t%~Y2uUO{ z)fN*bf-Iboue!ix)l3WzK7KsizL?KrcIk%lX};$WrN@^9KbM^GrPM+nR5dR-;n3z~ zfXzrulEi{I^e2DeGK9>(q8ek9X zFsJ)p{POJN!1Ew?IF)Ec`7bK>Fs7vuvR(66q#|>5(1>=;PKM^8dA4-3!BjJAQ}|HB zp&2>8)b_Ur^?fkNZRyh1;`A(@AdPPXYTMvT&*aDZJZe4v;>(Xt*IMTWOJ;Lk1o`_# z>BKw1WKI|VpKHf`=`=|rVgSG{D^6c{^^yhwSGL`!?@XM298MAFZljwU`1$)s=ESRz zubW-rPNJQ#+vE=s6R6ci2OM44O3lVVwSt=i&g%U0OL)}hUPR{7^(0b|p%jN~bi7o> z%hNM;J7u%a7?a!Bp>)3K(L1u?Q@!?3rl`hvo$}-?9Zb%hf^omX-H);roKH*J!M<%~ zX6Jjej&b#O@kNk{Leo3r2hQ2bZ}#iz-m~Z&lq05=aEb+rx!b@N;m#J9mL?AP?OIpc075jHwB7b>a#wk|n!`-2sW_kVwOfodn6kKIFV*8TH=WZV zlNR3-JwUeHu{2u)C6yh=4zFou;fwUAoVe4v(MOcaBV(=m>M&F&WaZ?F0@0QWG;`s? zg=g%k3tl@_3w}RHzWx@mwTcYGE5Jk=K>U(bs1gEzAt^?Z)<&gfm>BYN9-V^7fC`gCg}K)jI#!^0WMx5Vp`r`DA4{I)E0 zQ*v4ai^bEJ7~g=S6R}smBo=dtjDD|SwGw-1u`(-Yn(090xW}sk?oyHNr<(1Hx`Hk0 z_=UbW-i*;Y(mpqKdS36*Qa6+hDWt2JAHLhPKNo-5d~L;FPmQl%WVLf8b-90Mk@K0_ zVHezuJlP)J<^el3f+yrLy@0uk44&W z-=8i!5oNoRe})SSeKeW=3i#&#^e+4!G{=9%2>)2q0u26wSizy|jN@p^k8t=F9IBt$ z`T8W20y)s_ob#}()*#Ts-J~n$MLaGZMg!OpvFR&T<|h?Kc8kA0M}?{l`;b*sTm9 z=>w_pE5|Gm&kAPtByZQtkQjP#!xec|=4jV;df@;vPyX(<`bNE0QJdX+Po>j!cprXr z`o~7*scC3HT_gfP&}B{r`>t}pXAo!(g19rA>BPRnU~(Cijf8GoLd zxiI`v;{_@`e3UEz@(8IaB;wec5CbPi9NFZZjLb;ZEM?gr$EUww4?^r+r4pYN;+Z7J zPP9C!1bTujzE~_rq7rJL>-)!)Sl#P?osd{Q66PHzXeKqo;*JDB5t-l1SNoWz=IO9w zNZry{4q)WOT)=61v80rhl@%}OGi-sYeT`WE35g4ynF#1`ge2VT?I0D#KIMj zqJIv{_%b#vt@3LQV6I-^wEzWFk`aagw*4?+CCbJ1MslU6jMo+>V;5Zk@694?)2bot ze{G$*3K<%cmH_P#T=npy#sOXRs0k%Vgey!TR6%{YH30>Xg5v(Xqe9%k6NH35<>(*u zm`@kK&jA5_3WY+1EE12Qr2)$bk_hAEBDnOx_IQbk@BAjR`D}-(?c)q=ZJ+nV1`^oA zz7vpr2;8n0vnS!{Qy+$%P9qj}eiY{cid0SRT-F_DJS~x2jr8>vDAvlmhz=sX_<3uI zxC3tPX%D}8+#N1UId<6K>n%V;0FCH56bN)JR3>3FacBkS!MRX2LnXF`$(K( zwxOwnpbz0Yk1p8* z5D?h}m6;C-IdmK*rhG)VY%zPO1QY)iRbQBp_+#6v;ZcA29DW)d{lzE^&@BP9&Mhv<&%bk~esr@Iu1-Qmk(l+t zn=?@QUA%m~EoQpevGOV3H)HUkku2M?!(BZ05v6HfGWpB=ls-|Pi%{Vm;2`FaBCkrL z2keIBR#@9BPu~|en)}T!{DtI$@6ZKat1|%Hwtgb=YiRDmL7NAoH;uTHrkq)+^6&WG z6zwtr9@>9u63ID6JHEekN-=;4#XD7raI{eW`0+OJ5naRKnv?vCn5mzhFOX{{B8*3- z21edABzYr#9{!D#EX;aFaSZt;^&`}&@94$t5+aiboO(9$zR4Fv)rdEA%mL9s z%0jJxezxO7lv@S%uoa>-1?HrtvzTv?noOlyn$d1 ziu;(aCT?B1l8W?|=eRcONk4mkBute`%J)u7BR@!0)))iu^|p?^0cDI+sdD;^`1dH) zj(xA`!(t3?yKaC0MBK?niUiJ1V{RVV?0}0T@9@6HL<`6SMWHSTw9)6#y9EV>g#+VK z&PDn8q6Ku8MjC}9Ej${bl<%F2fX_Y1?N95)Y1UUGg%>|@70E3ueM}o9mr#xKUbpN0 z%))&yMW8M6okF&h21uD(7=f6cY3$a)lbiakBcF~68G1FJ>00Jq~%5jFd8cP_&&AcnpkWSsm+*|VC zBfn6gNyt)@;+h`{SJ${?hJgtJQSpoo4`6{`rSlsLgCWf1$T_Z|&Kq zSDzPt@Do$sx-=UcV6l#Uzn~JfcK}CYcDDDq(I>55JYGT6ht7mQ--QLP_;Y~|;V!qH zCs4^IOT`V5$73AIN~~VI+q>EkEMmKlPQM_k?%24v=Q+8107szowW4fmtb5s4E0MfS zfBs!fs(BEL=;zy0En5H2e*}f;=kwZuNWZDOCq{{lTcco(!*&Bf0eIF2`htHVOL3(f zR17a*>-|=KKwE}<{g%*g&j@;5u{7S}Z*K)`#-!lQL*V>%-yi+;T0tn=!~DlHgEevr zfz$8%3NG50!+$+W>@E^y#KCo_&(PA-%SOn8(mt#|H^zmy_K&mht4DIC!gE!lwsNQ| z0jD!+aWzI<)DnQ%rD5dw;^TCU`_^&DeD|FLf^6&nO3a88t{$+zR{dbPx#A>(Ao%wa zB#Ut;MK)lFMRc35uP-@Q=GGedIhZ4qkATtSafZmIO((H{!KqWF;oC+FLr|s9*YmwI zIn=ppS`*QuO%+TgWP`qU^Jt5YMJ#&G2=2$;y$+bxfN~5J!oj$K?^3fTE*eXXYrDwbQ=IUPG55LJQ)S$!Bl+fQ&I7IQiilhOmM{keDFcL)8EZT6OEP5Y!rM^nx?YH0;e z*TZ8K6e4RLyTX-3Y|+&CAi*iT-A+vaDQT1s!f4ydj|LD(hk7}XifzmC*QIr{2Aj;vp?sxvnnYxEwuNb|lwZYUVD5k=1DS{Kra> z617rfZ(jVNk1&E?BVlNqyB`LxY9d}U$q?h{U`4yGoutx|`*P3X0!Lm5`mxddt?Tyw zf@zg`o?AspMSgCez>El!vW-cPpFH`hfp_n|mI^w8e03vI1|NHV1kJGU&`B&ZQL?qQ z4XaVq4s=S)9?@Qx3}90wWOpa%O##Bh|FX}sAV2>|=msXRC*RJVbagj!pl0aZyKA$m za9Y3;fJ?ZClvGA~V868VHJVX3_fEU*{Q_)z<1!SvlGsni6w6O>&hy+RN-{MuDbRgp z2?`PA$@(29E{P@9A0$_@DvQ z&Pl@qJV3{XP-M~d@`H3>`y+6x5c{r4MhsWmPt+Epdm+2lFzxkoKQF!TpoTNZ@ZE|OAtsfg3yEKd!nH~pStBbE3 z9S-;n?{gelqDd!ccgZt?ZsUqS4iQ6mjy^ZG=nl(qKTmD4yq&s2aI_wPir)v`)J8-E zOsCUWsDPXyi*?maPJqAS@t1ieJRo@mJm2W^3T#!Uh0=z>%Lot>K%oG3%adcDc5^?_ zvn%%gl&LaBL3d(#;Ptd;4A9(3RJXy60hA*o!WycG-*15?C4K-_YIqY|SI0A}-b+q0YGdWrBUcP!(X z4OQ&ERpibLCnigd#XACtj0)!f5~NYV0B@K7l;e z6FX>}xdHL;z4q7`4*d&#&gHmL7`r}jX}8I1Cig=-jQI+#*VvSg4#y~YCh?M=8D>Mc zOt)?cyLV5Z|4T;PHRG0?yrT_!j>9A!_Mi=9AYe`r@5@Rlk>ex1t^4U!l{=WkM0&P{ z%~=h`Ff-2bxPObmZ9ulaRwVv_!nl7iK`s8xoc}Dcfc_pzJxH|EtZ*#-RcOK{?LtcQ z52ph>l=lyR`VUL}tFH84@_wI78oAXD{~4+0QQS@BrZm z^?rpXvyO0<{N8=P`*%kuR6s;0wqd`b6T%U4@j4KWFoB3fEPVq4g!5Dk>zxIv_>h-%X}LSpkxK?kwmvylk!Q?Keg0chUdNqA>+E1jZOUIn+0|n@L3?RM1k0< zs`aoFBR1xZ)IB?S_1Z%R*JLMDCX9_+Q9>Y7061hnKU1O!tF-uFMBmdi&oysWYq)FwbC7#Ukc3@>TZPt~tvT(^^a z!hlL6@ZB8%LroJ0}aaiz#AT3USKC8#N8c8)6v)O9pvL-Xa%43DaMbnA^)Tp z60_c@;C}z}Z8h;Cd&MPyjpRC!0+1<+z(R!dh2xDbrh$4G+iVG=0a2Z zXgnUx=ZBFLU-eDmt%gXtINI0@ppxj4C)?Z};pQ4y4foZc`PO=8IY>Z@2o*w`Dv<_f z=Bz$shkW)f6P;0WyXik}Naar;J?1+x4T~(OMTaY05Z8z5b{ri%i{qxts5C2)|6KW6 zX|8@?WP8qjC6Djn=Ql_7hC~I$qIJ+);MR4l-n>3*4KADRc*WRx@-z?3YEZ2;>qyP8@QL7WU0>G#4^ac!rz-RwM zj%EmQj!oY(!K{_f^uwI8teW1;2EKm71l=I(Msgy$m`07W7qp1!P{`LaiO`*}SWUdd zE$tCO9)T>HVeeKZegc8I`!!01lPX(jcYT|0;MGK>lRh58wjD<%D{kWe@-UG*tF*b9 z`1WdT0~h)NsGMgA(p8tU5xjsCIpH%{qwxt;*2DG7^+1Y4j>U;-oeD3zMi(Y)fHE1U z*j`AQwi{O$gzo#>~+M@ zB2BQhk*@Ph>RZ2KK~hRraUEdR%4xi^4Cc)~>&9fix0^tXuI(q8QBWKa!fq>qUaWdU zavU?_wD*Y9{xZa@g)Dqskl_VmiKwcxHE8a`rJcjkQg6J6o01-SY_VBD#X+;P>7gwv z|8#RWg|C+0gN+4u9(k(zvP1Oli%J{*bZH>k19Og_X9`^OXLhMJ7#a36SN+X`5L+Q~ z6BW^z592|(Q#?qf--0rj7-Ij9MdMoLwvtW1`9*AIx~jxLKKIu1;GbRnXQKSCF9qdN z&7=fKW5|V5SDwphKMoo7cAMg^Ew*0q+hSi)eYJK~5Yv%xFKe$5ydGktvGz2_`g04VDlqdmSBpKQ3;iQhb#ml!fEG@U>qT4Tj9PxcSXkKEI)Uxmy>8t~anlX<@e#84vV*I? zU=U~YX{$qvr^xlpZF%W{A=Tc7gH8>kK=t#3k6mfChF@|t5*5m1i@k#hHmHQQ?$OoAEyRO zHzVXp*j*DMY|h^I>H6kv+YqRqKfWOQds@vKC*eH~L#U7F3Cn8poLy#Q^ybQM7p+lx zp>#7Un!t#`K~uQ$@!=!z&o;p^^>k9W`a$;*e+}?SX_;Kqo@=(5!>{2|joyACb&ACD zAPzZcA)o%cOS%W%;;|@YP#exFE0;iumKnp$yx4(PoNc(y%*TENOqZv}_*kTYbb}al z<=Ji{xB+<&Wy=O#}ba z>>PTLJN><2#;DL{3N};6o0wGQIJnwy*>7ixV4v}oA|Fc3=-SHvs2+4LkP=1Zy?Idh z(($$f?&b6&#(eIdi+>8+U-ej#mH#QxC(u>;WcT*HPlj&{(ug9QcTIA*1)SvD)j!UhMjVpn1P$W$XVlbPrp_$>~P0pkJqA;&1L`T_4dC z)HuH|2L=8t_B^puh#^QM()y(0e;GQjU@5nmQrD4PlYAK@-%PviJ%%(7Ku0T?xO52a z`bhF(i%&^Lc?dJZ%SS}^{(ehg`@}n;5+C6Ji@EVM;2F7U-i-{)_I^d`4?JmAFa4hNANzKp9c#{+b1xGX-B!DEY9 zeYDth`r~~+duyYhKTP_U%?Rn--QC|-u5hv#G9ppi4737;Iq2fH%MbnY%q3mk=@P8s z>7>Awg!WwcpJRU<%B0Ig_4}WP+Hkh0{l`&U#0BgAmuIVBCR#n<|8#V9Eeue_dPcnvSU1>-nlB0TK~;6R5XY7W!|&A0XJR%(ginsPrla3~f%Qa<~9ABtX`?Z_wb& z1$35y%W@_K4xsu3?s}yc_%?v7{M|7Xqeu^2hLN`k2D$p`mNjX`Kt@UM5VObFaz{pq z)v$CkYFNCyyvm__igS)8UoIa-`3Z-?sN>@Ub>%sScOYBCqzRBo5R~Vi7vHq$K=|Xz zg$pJ|`=l_q&yADiSs%!h4<9{BnKmAU8vxN-VQ3!$Ih3Hn_c@iLau737H)k%&ccfl&9bq+JgqgXo7wfnaUS^NJPFP*?Bb z4Ae#R-F0z&a^TvPEG#^NcS)o;m8)pCiEIuE3Mxvz)`ZTZg4ozc#S6Q5e7=O+ zp@$N&Ez#f?K`)(D*d4$((mxVFVP|DEH5mMEFu6fkVa;{Mbq^&MuOYqUks0c$P@F#A z0Fq!)AXg8sXWNxG+&`h3y!WTC>c#B?WQCcMr>G4BHM*4LRgz}E~H zZ}UG^J^o3SKeRbMV{Tw-j~cILUP-1qJfT%IYkUsyfiCIX@4PADmnSxTYJys z-t$=m$`~oRMkmSe9e~FQ1$ox3n>O#7zGud_@+L}Rn2(A9H4*e+_EoEdP~Hc#iz2&0 z#8UTF4vC7LOq)QDnqo*mC}3lopjx6mNgH^sM`=VLOiDejgm<<$mm5bTVKAvj4mZUB zGYi5-iJ&Ka9e}YrOLy&ailIPef`|Ru2c6H-CMO)a$x;Ibff0=s7GFw3K<}ki#?PPO zJW4|qpJ(lA%z9eAnsVnz!&=`XC%tKQu5t`Z9yL<#g@(pTP6o7YR543UMkke+m{_Be z6->!f$yet--aml8OIUW#o7+i>i0sM1AHu{nHW-Wq6g$rh`c-JOJIiq=E#N39OTH!X z&{15TyeDu$qoA`vEeJugBot0TlAwOpn4Hwar)vz%9L_&pBi&H+C5k{5eJfT|X@rH7 zI4@?~v2m0rLj$6RMXOviuwb(Ioa=dvR4>W~f7pjHE+==8O&)VC+Fx zG2DysG*6K302)LPDbmD3B)T)~`?hb~Eo+UoFAV#74moKGs#Z8-J~I%QmKxVadof+y>p1XImf zf5@IgD;077ZT$rlH{BTqK?(s;+MZAlQ-_6@zgqCxN7MHMYARP>Ja=U>WRSFeW7(ST zGccuc_^{fhsEiD4n?A%}hDJv5r5$SIk#Q;ZKt>E3NRZs0CfAIKaWxMIKo3t>4&Nx>!a>6c_qRdS!l1@V%NnmWE4G}jp6ECMLXrUwk^iTrNrl~qq z5*c{%bfW7pzg-{l1H_#6U_Ta|Hv%gaM1NnK(!K5M!+Vr6rc1>8{M7`!ABJyD4(^%x zc!;Suc$b`PE1Ete(M=1N{G|TT_qt4t6?Whl6dARl8R=r+RRd(GUH3)^KR6PQ&YxIX z<_lmz-%>kjbS3rE{ybU3?jZ&)p(_is%zPAf@v~uJ8|2nHQFc zx)&epBLQxf-|+=y&QxA0DXE=1aRkA}Ad888orpZB@5v)0x{v>I%QB#;x+wZOsDvnD$H}XSJfYqtd^wE4s(bf)$w4`p&G2-q&rm|1? zvjyn9=i-`n+{_A+S5it%RP7ukMqXLVn3+AjRz@^Y)cI2c*rG41lXnr0cPouBgrK^N z*q;Pn3r6ft`_&9HDeHstrqDe736W{H;g;reZj+(x1}aE$>&25Onoo&uu-meRwXugtl};ge$uL^fB5iiav<8L z;Q0zCE)DMO_NF1M@VI$1d2u5|9<&}Q?@^DV2%MC!mxxL6a=9mZl5t%efS@l`(G=%4 zQ;nDiN8AM;&H8U&G!*U!1a#>FHEHlQ_{jVk$LRjV|AnRv!@Ee8*+> z(Z+ejw7NnsAY&t*ZCl9v6=p1?G^CD0Vu_bgOFUQIQ|dNz-Yqnb!|AX(`q;)iXdho! zbq`%U9iqvn9DSZI?lZO6wPb-?wsNyH@Yh$T;4K4hZd``U55-E@d+>z$w`{SF3){aL zm=)i6!Qip*=z*D%nFOVy{c!4J#-h)XW7=^f#(4>E&hnijA@sM%?P^4@+;*8ft!+-W zep=o%Xb{OIBBC+dyhBQbZ{`>t7UL&X4GxR3P~$(7{V{pbJJ|;LSk9w%Qca%=+FsPi zfjwW7O^Q&>+tGN}S1nZ7{E4I+x#q(gqwTo$4S>O*)()Z%h9O)qea^e+yZyBOqdvd|YX>xbdDo;{^l zxC|uPBCkQosVip1Yu1w~TuB0ove~?w589$;Mf7VFp)1$8fK=TN`;~T1ps&xk4PBIN zgQlGb7^~fa>`|LT$+JLb&+wL{tYzZ$Zr3P`N(e3-61vs4s!J)&{n>P~A8sdBx#Il7 zJ>9y7-L~#;-n@Y=mI5l!b!ysYjHp_gOuE-rRIkEYe4epIJ{37rS0h-5q=3Zq=B1N7 z<=F8NN;8s{H^YEsGL2;_7Uw_Cv`FsN2>`^(nhDuWlMpHRcI@2>pL2mWB6 z>!^4tFE@7!ycNMCEEVe(*sJX9oHb1w8yK*W|3o;x+R4umGirv*G|$BA-+?7((AVHf+acTIH3 z#DiRr@w!9o?Qi`j|N6sCvdswGz!q3M^_WTXUq5j0HZ7Vn6`YXnMUT1}<$j~jcBASv z8+HF|d74cY{+Iud*-nAerQ=sb{1fL3rHVcFmK^%WBNR)AmC12BF8=*goqDL;Ije8? zpA=wfYO1xh6|Z7(1Bf{Z2;#z8pUma6z<|91S3E1H_yr4D+4s20aRi|Ok=iDEr7*En zG^(Fyz@=z?L( zoWSPIKUPtdWPV>{7nMeGyurB67oq~sa&T`zgm`snE?=(QE9yGoGv$biFf1Hn>oPHr z3o$bfFR%LX;{|$1?FO>Kc9|-p@U+0_Ws$B0Q>~DYcHy?ScLO}C0Hv%Kjo`aqxqbnuLq=LUUkKI0W2#X@pKkm*Md{#B;w*0I zg~Pa`W`&@`Jez#&?%lice!Q!wCpRL3^G~x>2!WV^Hn@qU^zs1qSVJornRh+aDQ)_b zh=N<1n|sU=?Fab!HV@`~MFiQs$yn>ujjt|51Gm6pf@?sSY7HXF^+axC{DiWaj}&_Q z_m{f?L84Z&wEJaL(zMbl&()@@#z3e*(r4|Wr5-d0J+OeO5#Ubb1%Qjb`wF8=hM`_W zlvIit$>AO{PxBJBLQ%4bd*&GhA;W3L1ZXT2~l>g)#0U)v>1SHGqAPU9{`b$oH z{B@e`vnWvOcm;mKQbGdBQx`Yx+7I;hG2!L#I7X3Fi2a#bCd|tMd)RRvdDFRJtC@D$O`^3RQ z)joENy9nd!`|v)m9iI#wPz#F6o^aGtP`GKV*L}-|s2~LrIUUvh(?c0ax_v(qTES%` z3|Oyyy62cr`t#>%dlJA}OfmJAHq=rf?_vMzzBy!dN2-_X(J?e^Msq30#~$z+m;n?-mN@b#N)yK>Fjs0R3n>!8>X6r+Xo`$Y& zR=x$^GFojFzn=w}^fs01^U*whi-5pw507UC&ue>-?z*x~~8{3^Skd^Ry%`>rOVnYVkb@fw^D8cY~7XcdZ_+C;8{?USC-VXA>xKFC;`; zPw)GnfeV+Uq$|2XfY%3Pt#>~8eS+H>xDsam?VCdoQ$ir)rDYyR(M8)M+C(J7My#8! z^+z9@`1#y0*Sf%aOG?xY;!^ys0fQXp>kT-7ZR;{o5S$DZ zmyaP)c^FNNjWw&}Q;^aXW#@?}v&%InOdn+d_&%`T=CHZvVfJoqW>}^!!*`N&0Y7Q@ z;n17EUpFEQne9pb-A>I!WKUkY)vP=w#qn%XliA2Z^-(94^%0eRdUx^A>FuUBCEt^u z1nX{>e0hO)2epD)^E9oc;aPX1OWm2N&rjL??oxyf8`?Er zi1|Jy(j#`!;Kh2n?bbXp?@>lS&9L;aGvYJLGgs7C#lM#dD-@zqSHC5z^I1lH^>TZg zaCOu!wqGU6=D+l-BfompO#JJs*|6%goPVuaHs*VJeBZxT?Q=%lviskw{@?c1+sOTx zRhpfZwR6|5Hf|KuuUx&lPeNj9dK$!j7A-k0yJ~R8gI>e6z-=Po05^daNuUo?>iYWO zwlcg)V%FRh7iuf*H)JL1c)E!Nm~W!apFbbj7n<^v%?=}Oxpk`ui5FZcdO_LQ*`a+E zpnZ%hbw2~pv*tQO=(V6h@Z8J|G~Vj3t=XMe|gvvDRs@ z`;lWQJkzPx>nM*KgJFs~M~+-_L(c(?vinkEV&d*nq_bG#YHd}niv1)2{@NMnvi;uM z>pIXXKQ4g+{E|kvka5aCR~_Fy(|Pa^y-)64LJ$pBZ5bmY?NV+o9mHxS)6*6fwihm- zBemnl@$!eL^>}!Agl61Sj#{>21H4C@cTEA-wK^I9J}MsUo~ zFnb-2>jhXQ{Sj{l)*+Pa?(D4o`0;*i#+ilnaFwRFC$MFU7W^R`m}f#haT^+Hyn@S#ZCrk6r6s$#`qb1p&NHE7 z8$Qv;UO!qWwRXoDqk!pq^x-NIr_ntV`*!Z!X<=c3d7o}gZx)h;_VgmuDN}2;*3?`( zZ%&Pi2|Z_hKQW!JQjI2+ z+MenN&-EtHIoaNIx3#6VtYGPi#C zbv5396Y*9t$W_!fT7vq?0u$W_=%3|c;`K7q($m+z-Mrb&&FzB`x=MH(ix(E|f%<@w z`&{c+X_qLjNB}rphE#7y>@->WJ`UOsU%xuSgT^-1-zKRhG@6L6nZvoN| zRN|uBrtM;w&SxU1o4#@TO>&^u#~CE$nA5t=f+^%p)w5+26fLwa?< z=H=$0QyOdd!j9N8b&tE36e7Oo(FO|el9LTVz+%?inF(_t7I{Kn#_Ss)w;6z*{@WjF z0J?BWk)HxQppeq^ji%g5Xct2A;7;P*#6-csI}s5L^|?aRiwHOBa!&lz(W=*z83B>f z<<5+XVl{~$$m+M1qlmot5OmR!7`LNEUX%URB{IjZQ@3~1Ass`OiknA7lq$`b7%U{Y zWlN`{ynt8cN)#iNl3o#|lp39LqNF*BkjXktHwZPp3!DCz4TwB`*zldStSp!Kp@Roo zx!=BhD|GZ;Zqa6H?(|3v>ILBLdfY;^R(6>gE@ExqOs*?P^CAH>S6A1&2Cf%B5QRJG zTVw1sbEOv4_T9>jfuZ% zYC~v@qR2aUm2Y80k^xW+LE8*OEi#{yWluHORq27xlV4D<%HU=ddJR#KJ-1<+b>r`^ zN7#(TPjemOD^SH|kgywzF>JeeU#4w6kI=Pi*Fd#fkbUOt*=YbM%dvA4FJ2aT z4)^!J&i%%hRR81gH535eRDkV%wauuhIDGf*udKhnjgaRz<>PK+f-&l!r%Ky(F?*Kx zxQ529#F{&A^AS?_zZS7gmG~d*y?Hp*efuultU<{VmbqAlkfBUTlv$*rB4d^Yq@>U? zB@I}{P?FMsN+HRZu~=xLkRg!_l{qs>?DN}j*ZutVvG@DF$Gi7mzvnpa<9O~{S>N^j z4A*s?*Lj|o1;&q~-eQEao1UJiW3ga3QWwOV12KgO(0M6^AM`UmwUZWConux!{yQ9q zq)Rz8&VQm_Lsxu2HnVqB6nlW$|@`Sqs)&Wyx6;E zVKzIifZKQOWUIWx5bHEKv`l++4*!=YP71lKNB9T4ETi;W{Ffb-87}G!W+5ytgO88Svg}DzQe+?K%@AYS+t4|KCf_7@J?>s~`qw))JOHkljAR{H0H<~J6UuJ( z|9o+#hl3+b_Z`*H&@eWxX~D&70aL!(nX$)&JU?R)VNGj+sIc&=n}|;-2T4gk(%ion zBU$0L-qnj2g+)rs%i9T)z|o?uZ7>FjZx1An4uFlW%M9@!Y4GpBFOuT0iVhh?Y;3Hw zWiCbFa%5zCPfySw=&yJWM*H~kIN~Y&btzX2@32KKFNn?n`SH6`Bn_5qWI`zM^bo;$ zIDFU=DqKqcLY%zduwD`5UsWA&IsBK96R)R75ftr|sL% z%PpX1qD=uX0aLy)`QGN6R4sQVCqA73C2)b{12q8aK|tx~%Ass-ZtiFXA8?ALsGktQ z(OAJ|!F90Eb}CbLwUE%<@ef1?`1$j!Bh7*0QP$!A-psBA6zzz&jg1_fob4@W!`oAG z^{Bqz6`gq9>&(be5OiEc;RH7e=EJjx(8 z)2$$y)JpoG2x|$plbDUH>Z(<<+drD@`}dZ%l%~t7Dk+iY`uh4pGbS5jwqu7c*YX8| zVR!j1UuHaA!@Oa`29#+S>5P(@z(iFEU8`$mQBhH5<|x9(s7h3hEm=72{n0WO6=Rw0 zJ9l=pwH-s;Zfdd+5D-w=+L10x-z6%yLTx6`yIdx-GLW68Jd|CHoHf$8y_`yl+%12F zv5*)ch%|U9O01pr0Yzy~-c=y1dAl5RRid_y{^A^ipRQebr zC%Ls)*W!Xek@sl#E_avK=I2P~22!hb<*Y06zAQo*g&?_;fn&_0{VzBMPtJSAXJS&1 z>EreaB5Ao#JxnK#6wjMd(NLW0BWuq&SQJUV#SpKP>$;yk61ZLTIQq_;Ts7)cVP2@6 zL>NOjIejUphjwD(>sK3*039+1D?L7!L?&Dp2L9y5&hv$-#9hS94r7XSJt_et+OEAA(igAH%@R z@t04Z%Ea_R^8nGKM@br6L!AJ~Qs}o1ouSZk3H-C18`4qulfMWPspeUhuCofYUQGXy z{iLMODlXB6k`$qPrqddY2r?;coXX~aG%up!B6z1DE0)&OtgGs<4X!_PxxKwz_9(P~ zXQRknC~34Klo2ihL~Ran2DeI`!2^|2vTmF|PxwX>7N1B^UK2z!q(Fxb^`IxP`Q-Dw z9+XBOfX9vaJMMkBB}5(2V?9{{?qfhlirRhP>`vyl{~ zBApirgt6`=!wpD-*8jM|4fm;v$Rgx781Z|LR1r3eS0C^0M;>|-9*PM;=!YQTI_~WJ zHrMqKpguXPEo}(FsF{Ppwe_xEy$ad@R!86~`#D5zMa66^_}9ByiSa*jmlJ}+vUDPG z;c!OHHR$^Cb|gfx2~Kt3p%nd}A}S4BA3}{T0?+WhJ0vF7J8S(2&41nyD?fi|=tUpCG2o&z2L_-k zvW=MFAnrJdR9P_JhPvm^7mpJJqSC1~qOx&BQ95@&tVhfANFDEH5GSo zOP)`)S@QmSN3f#BqFaNOPO(cwc6PQdlG`#s%uO&=19ZD&(W2Gj;>A;_ZQ0T@uQGro zdV!}E`h7R3%LwSFX3vHHs?OIngvZd(_p&$6KT?zp;a{T}M8>QCwKx40s0g7&MP8H$ z_5$$;B?SeJxdhTK0y9-(XsnlWnj5x3i%%q>)%8nIZNSs~PTT7?(QC9eG?XtLA!J9; zd_71@>uP9;V*Za$fDRpS^V)k8FmztHWC@}8jf`ZYvU>+z;x^c-uU{hb{L#&us}vQ- z!4xRby6_;!O*4#w`0xd+;GT)p%*lS>08QH#YTG0;uPGfGV zQP00OlV;%0tn~Nq`UM}h{NBdD)8n7VrZ!YhQf)<6VPPTQCQA*s=u+dVMPayC`7S&+Dk}PLa;l^8S8y|TF160_n~ghu!v>t(IwCKBdGzD+i<$Ke z@7{TOcwk!^-KlxTi9Zo^7u8SSSdXhXCWbPBDg>^hbbS1Ha}&c+kp5yREY4!0qXX8`0|O(Z-H^Y*t%iB=Vuy0; z2kBx`Qn=FgsjI7hlN!Sv@(7o6<+Y6xA)B*sjcd5Ny7qZ$i2M3WD076#=F5XJQC70( z%L|5&DMeTq>)9&%_RX6We0(AP*;TIL44Ofpzu0|vXosFIWt%4(tmxb(ku~afhsYlW zOxZaHvnmmH4N6-$^asYrFG+Ja9Y5+Sk{09q?dOeNI~qZ*bvSs?U*#^;u(T~tQv0&7Ov$b&yI&GK^jV;Es z0ePS4DL0Fi{Z9xJ(yLyk*BEW)0}MqEJC+F3>2s$h_76T~Y*1oGaOPF@G7Z)#Z)>$Q zH5Dt8iXc}=3LJ+q#Eweh&`cN24V!|t(t__}vZBfne9MlWrFy*F+<|)4Qg#L?A)SvO z$1&i_{_=C{BK3qY=Iq(Wn~okmicW(ZKi8?g4H4{jR|-38Xq-t(N>b8f8}_8pZU_WF ztdpbLK#-KUL^dCuUeNZR7tppop6vd#9*orfmLh8l0+7Lhdz~gG*Y)@!JO&^mle;)_ z5aP!Y>pa-wn}w3kd|P-6_r0C z+^`Km@FKcID%U@JP%^u%0U zB<=a{HQJS~mt51e-MTH>iXx%BnRlUYr`E9mN~EYW5IsA)M6x!&0BBy#&3vOUQkc~F5ZY=SUd8qz!`5t0|OUlXV$#t+=U%)33Ft=6c}0)H7Cqeo&r9@1wtOK zFPdgAA?PZQ*dc}%!d0-Kb)pYZw=K8&7{qxBUK2+pnS2Uh(|ju~t_@uF+j_wg)KxJm zn@Rx>%4Gcjtn6qW9&z@gelz(p%0oI%y408MPf;|^MN6o(W%tx2ruT=E&9j$qk1FPKc!>`n&Ej3B;wu(;ggHK9`i7jMdDKAAQm3~)u5A+OaC2Yr4Q4&y9 z-aie-=b;K25>~vzI0{M&2-ctZCM5RgrhC#^<2*{PWJ14$8?601_jCfT?6uAM!4y@y zqZ0!*XYY@w@dcPuWcjO69=2^-*(6PK3>vHs*Ak>3I&{cc0&qVqNVE~D?Xjl99~W)P znOyT*N7TSJhn=cpMk8{Nh6@6Z7F=#^Z$C4LsuNdTt`H|9h~I%@JRGB z>>Ah`K&KCmjn!SDID314N897Ua^_1HF6@n%$|wUJjchxTrn;0zX76Kw^0$I?iHt!# zccL>sOz=?Nvkz_fdZBvIU_zul3FDa1R_MqZTv$3rBPQSn@(2dd8@k8Sc!B&rfBrBt zQ>&+YsVF=1k|k{IvIlTqXn&sNxSqc4x@yQc9VJe6^uWN;;P4`*3lU@|1DQpNzM=ux ziNT6Omuiz)r+3LwHr@$`7m#b#^lPP96Q{*cNh90 zFyc5E@~)DMPGy|3%>Tzp$B43XGeso zrWdMwYj@IC9@BHZg9%qb}L9*FCX-H^pXRCK=}A>og@VeSLG=n zIEKtMNu>5Dq!lf>nqV-j%HQfCl4kZ#5MM&T?RP<+x~Asy-Yy~10A(^cY!=iH5(}0u zfQJ!M7t^AX2;AR+uHNd{!~^QQKqN9S5E4Ikb-90h&My0`q@*4BG~dXEh?rQ2D^r4# zk`AFVsZxR6IPIk_=inxcYGUF)Nn63ELVG=8`3}tLju#9K*6h=R5WlTjwW`_?m3qk= zKx)pcwIM;c$H|D=B{Fd)Fx2H$KE!oBor+S06clXC`qWUUf5o%lCatEr+TgQJ9FVPeqX$*5UcS6gM&Q+?5x)}g^TO3Wa!Zgn zapb*;W>|7W(2)BN$SBp9C%^1@p z(|~-@Uy``*S*NwlM36b@atUuK+LOxb*YDrAZ!g*A!-o$mr-jHDPq!lRBjP26azpsF zI5})5(mBq0EtS0s&NAiVG3OtaR7K!@>9HANMo9dD-P>mmgFY>LO2^j7DB}I{XSCz~;!%yJ$(x|jL`MZ* zC*a-V$D4w~Bb1bsOqEIe-l5qcv<%zQf!(azxa_xrXEJ!(h}YRyc<)x?;7~-?F5!l_ zC&acqP@qFLDLRArR^kl}4Ma!K4kkDOOAB079yDQ_Gp=<2p-=m~6?4EyZ+pADxgBWF zF|#Y)=zcc0L7UVIIXX7=;Q7ewk2S9`r~(gN<}Hh13zLoCFGy$2Eoa7Pp>sDbPM6Ga z8c{gX6mSk{YEX?127I-CH-jDkRY=A>6j(chPC^cwX_6_U%Ar8iVv^HBL7*P{_9xC=j{q4A+;>wZc z_SV45;VlG&CL<{lUch{c`So&s zdIm1G=pXqAD6NW!-evIVZc56U?b+}SX#t^P$W?omuFkQ=fW*jWj_K;_YlH;s21wf3 z0SwdNVz>Is)zW8)d|+^Rm~GhBI1i?L_AO>0Af}|G*ewuozO?@WgSN1hFUn;ickcxT z3IH)v*AMQ2j=O}eN?+20lwuP^jYMb5F+Z$Yd)XgnRE=-r2=9Ry3#cWAo!fz;n zX}urLXCvTVxw4VRbX>AW-siuy%L2$1rx6nq1I81p%+pyE&F$N_BkG~pO~`%Cqh9~y z$!vPi`As~@m)y8ncV z87MP=G&-ykZz}4wp`ENL`M#pn_pE=2QrLBi7kXY(6V3^DUB>nn-1LMsPzRH`E`bUM zUoO=dPN03jv-SjJ36+P zO9uv(DTB8Fn8q?xqM|cUcc!POLva~$K%-)dzYcX4S0vOgp|A2?x*|pfeP+`mfW_=A zyQ;0T<%Tje6F}D^BO*G4&%pD1H=v7z13-eRV?zz(`^*b$>XRlO+?kgitC*OQA|IMl+yh+P|yX03JI+~&R32iO6-^@N_M~{G{TK=Z==^5;k0xZw@izY~XSdg9p(O~$& z5Bz`d*C~LM1O?~J1O}nC2wSO{@#Sa@;FtX9dE;|ChK7gFoIVX!6fqQ$o7>FV`g(Nq zM3FTd0z~?Lx6tuG#E`qL4a&ISSCGkM0fAQ(kqX;i9d_c!n4bdrxjrWrt3K8GKYl7S zIyyQOgzNxIF~k4=%U8Z@DW{+iWnpY(6&h4gx!cUlK@LvO_v7M2Suf{R@UzZ5X>kp z)sj4nHWokwau-5hro;_^nTJ7TWM~;E(*|yk=SFj7SHF2f`R;)4ia8-I4{YY1EJvwo zzr%D0wF;QKrm=ta#a+t)ine+8QqN$R=v0LSnA-cHWr?WwQb^bt7K0vSThIfet#bno zxqEmBZb>`ZVF%(cIZW0xz~A3LCt$gjy3qDfKZ={P^Wf;{MUK;RbS|`Y8{GwSP}kBrN8F|LkRhBnaUxB}WDC`$9qI9S?^|0#k_PO|I^SVeLA_uQtSO4-@{MDq zRJbu7U6VGt`52@NC0i>`%?#^*-SX~f{U}$(pHO! zolo5c^x{Z%VIjYwzb{65=tT~EL#A%UypCRrrqS?$MZ{x!28@}9OionnJ?M7qSaHIQ8#f>hvSBvb^W2Ow2)+VPx7B=fv%_rWZy){3WafM;NC{*G^fn3anpH+%MJJx~TZU%`zE0OktmvX%Lz^lRaaFSP)BjVFZY;{u6qw}#XZCv8QrLru9t69vY_j{+4l-j z*~Xy@Pk=Gv*8TW7bdx#9iWMu*$m%ssqNrxrlvUG(5W3CCdv@=J!7>LgZ}6ZI$^YCr zx_3S@!^5S92h`Mxu3qI`P3VdT^2jNxqJj_Eq-hfd+|FylJ3U044?f0@F|iZ#Agj$r z`=*_38xkClV7XKKqO8`$xjm-bcC(3L=o;hI5P7RDu+flE;V6xYvhwnvI(FOTxnid7 zIf0bAnQy`>BgkBGwjjxyHX|v*lRh_hi@#pL#q#P0FNuvCef9zaK+}X}aNSh#xg~CH zZrB5z4%XJzUA=4`C95hLi~?k}^`^?zrmL))2M*c~-mhCp+}Y|HY_Lyw9L!}dK>NV5 z(epj^XirKuG2~|KrEPadG~ythfp9`Q%FkQ(`K;s7UP^r^g;-v)8-cVK9ix;*V2PUJ30;9!C6FNO2*z z(zo3>o5mfz$3kvP8`ru67n01=@6hWMem>c)>wX{*$H$wbn2mxJHq!Ubq+{^L<};WH zHwChzxrY}02sak?oGx{z;OXPQ6v@jLE|dvOax4V2DEl}yUR3FlDslmniqoo!Z{nU&0LV%rp6oU<$yvLj4&gz74kD^_! z4at$(ysdA#WPXwLMP#d%qS<@a&yQfWq8-I94CI%^2QV`@D?==tY_3*+!oABz)H0xT zITeg@7|rH#+`nHQ$SgpGEiJRRByj!tgZn6O48vN%a>NTz)Q)2K-GU7e1?Z23B(n6c z!2Ar<6Y!hFW^yd{?%m6&qA29L`Ooj6tat6+iSwjM3M0$50SU%zG;2%C*jx2Mi6wuf zB^Ef6P|Lv7kKbp?xvC6W+N)|lCpT@{o;sDg8xt3jW!fH zgr*kp3TG?IN`(rpxYNj}t*7T3hNX@7)Ni}$K?R5c`!4-s#~$7?2}$(+^J~Mu zf~SvgixHg0UGqu_S_QyFPRup*F5kH0AlC19Qk3$#p@GcD_Z^D^10$=9LD+Jred|ph z7#Mi|e2ac6U)9z>FDNd{&cT7`l>j(D3ajq`h5mQhskcl5J8%E_{yUNok}(3J0>{>8 zW;)IvNMXUzR?vbu|Mk1B0D&S#TN4vI@kgG10ND#uUxvXjdhzmQ#>hR^OwwP;-0Jn~ z(em~=*+v&-EVCIYAtbKt?Z)sG>DndaAb|t?11!VN^fkN_M5lknD7yZlnUgz;v5~&R z5f_C%oZTf0+%)@8>%{6Jaj%p|T!4_SqB82zrFx_amW-otV9>6suji@o8$?!Q8dDWF zpd1#C*hGft2m-$IsTyd+Z`rc=zC;oGZ2de`XSV^_MBgX>%qDIRm}MjTB{mye>f+9p zhY8H!<)X@zS5PqX=nH5B;Y2wc@_a&ks0gI%@c@9SU^nBHISsQD9uqLQy$S_I~9-b}RL zsiXzPB_(OQPcFdSjJT+Mu!|t6;f5kFb<6D6!#!x`jFwlA#v zpd8trf13z;eh9R(ps9Z8>kBbo!3kpT_TuWdN}!JM^6>%Y=;(O`a21P2S-Eo41qhVS z5OeB)_Ae`V1R!Iu$Q9cQICNKhm?|mt@omgwujDl9UT8q=)&y(PDUmvF0I~*IFJx9e zJ~L47xs!zKkhql|H8fmyUuyb=G@cwZzPY;8HDhI|vTavYE2|~c_qi*_5<|N{SkWK_DV*#G z*TKLYm>adQdeR5C1YMzl9I9IQ3EoLplwHNO3E#xV`Kvao+g9VotM5Og&Y;{jgfinv zMFl=d&#B>Xk|OWwRokeKaFe4aMQ?@F57#M}X0W)BvLL2}%dJ*W$a+f&4Gq2va%J@st?p`0agc+zDbi;F~jU}sMag!HozlX$gw;57dUbLxsE z_N7ZdND+#lAtlpp$H;@gK@bzd%ih%0!3x(WGb`%=$rvz(v1m0IdnRE5YEqW@Rz%Et zSyi>8cUv9LGT-G)>jNk-S=pSbz?GAmi~TNlg>fEv3I_-HmdeS`2}*_5lBgCIP3T4ugO3^~!14GFGb_~IrAzjjTS(JeajO-9 zE|L(0gs=SSbue8pd>+{VEB>M5(;x>L>UC70hw-j&>+O}~+wAL}@SL4!H6N~Ai++AR zk5%H8t<>4?0(yHLk%q_~H!xu4erIakt2-8TIaBDpu=fR?}TRkUmg zC_=ulX1osm?Ko`|w(XA1b5buc00pCEVSL*lyzGM?gGmFNt7nwkp-7>KRXl#|*!fu6 z;Ds{q_8Ldg&F$~+A6oZJltLkz`ONxy!LwgJ0zSE;__m%`SG6!=`By#4(VncVEHZ}L z`?E*7ZC-*3^Tg4k=dXXolB52q?LOdy9{hMz_hpem@$UrszaI4_b}?>~W^k3{)(nlJ z(M15%Jsn%ul*`dkSHp&G5O*6jKQc11YZqSCX5w`{jm$|)lT}na0kjz~_mDd>D(RF? z)A*U@l3fW-d>13gd-5PJGBGi6KL5a;WSbu!-;R8|w0K7`5b?-mhGpt9S5~}lb2&UD zq&(tBL1Wb6Os;F}y3oMM{Uo+bydEv+XP^-w3|N;Xk)b4!ig5=C19xLHGvj7)TpET) z*7d$%#bvh;|FAk+QJLm4H@tld!;t#UB}yH7!Iz9*+JmLH@{Ef1_?FZRBg}Hj+hFys z^k_PhAwcCk(1Coh-Jym-+J|``Y>`KUOu3S)Ax4v7IU*(^Qr0=Q5md#)+lvZ4tgA}a zRlfX?#?VYT#hD9!Czc$0*=jQG;JQ?a2pR@i`Fwq0U5Kt3!U#Vn)?AA3^8rxW`OYF7 zEbPwi}?8Id-Jr7_|WbA~qw))JaMD?8w&R<9fY#@tnDA>~qTQRr>~#ZPTwc4!=o`PnU7*s$JDB2lg@nC5Q4sFd^0o znuIs>F3{^L&IDcC%5oJ}!fVR%acJu|eCGN2z6hx!dtgnup59AKhNj}qUAr>Dk%sV- zP&eVuMk5U(4pm$b?4nW%Td9&Ah%t<(7>l0yHVHTQnP0g8o`%U&ExJ$f+xLxM*3s!d zc=(`sdco)r6QPAdr_nl@Bv?vT`3+H}3Z7+jB+MgjVf-6A4zfl3{hLH&cPv5i(%08V zOr-*K`=%vkxWl7cl7%IVBXqQ2b^V4#S3nRfYj@i^uCng0hrnKD-PsBDw9iDVKYU06 zHH5HlGBCs%P;plzXWvH;g4O}IKwmv9wL%PT%VotslazBvB#$BeYui~OgJD+EMN?}r zq^Ogj+SdtT4uoE?m{5ql06v-?zLy+#5el?z+g>d*6X<^aD+dLPqq{6bJk}-$`3NrA z(c$69>#qK~U|IgiQStMqZx8|zYpuKnOOc1fhrmT=5Z30c?2;QcysJ*qezW7xA5NSP z7!(q7xWJttY{t>n*K!0y9@e;j=WOSWL^Cj5vYInzx$7Q8WN6PY8SyP<4QTSTARWWV zz8UY{2H9A{gI$?I4op8Y&0SCB=&X;0*Mb-awnNIqvN?iV)n^HvVJ$&dKGn`vbFGm( zve>7evLwF(d`Ub~Gl<3woK3*o-FD>2eXl8Od`SMUe80C{&(^jbR4;g5Lh*q7=Ut9p z!r?z3gZekGX5NVvY?rq{zz;&FRb7Wb`S947f`iF%P}5b=ojuXy>|Zsp?qH>EUvrAN zqNu2-eKp7e0pV+!I8M96A~*YK)5&jrG=IdTx-yy$PEJy1;(X;a4Nv-EHULH zu=W>tNNmBB^H;Be+oYxj&;ROGY)Ax#$H%25B=X*B-Sqcg#>dUUF$TX6Zs9>p0(X9Q zI9py$PS+M`OX!unV;=+GQwXR9<}YeCd@}j)t2gjKRkPJ;+3?=)h0rHR2?!O=;!e7W4goyy zb3n|1W@)+g`tQ~=qt-*sFOC7SE=ho#F4N;2!7cv1>l625>)7chNY637AQM5h36?tC zQj?1KgZBkm)Bdl~AZjH)M$=;CAq4;x4QA7~`2Apjyd)AF*R4*%YH9+JnAp)AddRR5 z@IwWV;;ngbHHpVKjJI!P?iLnW<)W7p4Y6EoY{=}djg5>i1Rr5)mNcsP*(xo z+1vDJ*cz=CydiXW5WtaNN>?05ULH)azoC=0iX#xoh#f^k>*lX|gkxxURq08=kH%L7 znpNMhti+{&!Y?rFMFDsn04guJvAXbLapC@f1WsH)Xp9sj+vT+%>7v)phq0EEz}q$VSwk1_nHt1BVamN4 zIsluOAkyvgkf0qdPe6|U&$}n|E!#^`p9B~cv|boO;Q|B4A&L|xrn(8WKUx`^ymrF| zPh=z>C41VMo0>YVpMXv#d4jS~ftScrQa9ns_3~0#Y_Ww}RRS#nb%99QVw9r6&|kH} zUKMz#bhR_e9QeQ~dyFK`vHoBe!@$<#f(u_4m*@Z~r3g);t}dD$XoDS~p5Ll>OYVbv z2~LcJT8z3=1Cy#v@mXxNYb`o@w~6;l3uWu*yNEkWGT#u}3eF)Ky>f-P+kL?8 z9>_ncvX!wduO-f&6f{iI-ykrsHnf)Z!Iz1l^_5E$oJbkuiqx)LllvBru-{p0tKZ6; zuOnVI>UQ)S-t%(+eb@p5NCp1DB=}e>Lpxu}u_VbmRxnaSHoQi)VcZL1;=+R)G3fiG> z=4126`lh{PQGo7_-@79VsSqL;6v?c0vr}JD@2SuSV_-Qf2^!&GGcWC{C9D(?w`EJ< zYZDk42yMe{gUhFbzT^)t6KO5Y_cpmEcS_G7rpl3&mz#TyQ1CZ6l9s%E`xaZ1_7>xM z#zsailiWkaBS8fftVJK5xp51XTxpl&dBQ|E#iU>? zS4VliV;yUWZrl9UCAb6Y<7>Jg{ImK#U0d&ET{8SJY-U(zK5EMe!}G9GH|f3GUlm`D z!ts`#wsmdzwQKK@GJ+d;BP(l+kcVpF)>@5G-Kt1iWc%`l5@v&$$y`IJ1T&W0b#!5Y z9tj13uJj!$>As*FcThMEq;?BaE-wGHck5MDEUxkx6M`R-Hv0=TEB~N?&v0QzLlGx> zDm@oe)vTW8IJbu6S4%GYZ=I^SzpZGZIS7Ob1!X<~R=oi)ciVS7v_eVMteob^oaE$Q zBm=kGceF2T2j0=DWu?lWN;oAB9T&nNNh-6|OBC}<_9GJ=$d3wp^nQ=>T?yj)3!ngO zDoYZu5(gU`Q$!y?BK1{8TQ7Ke^GKk{8yqEX~A@_mA&D`izTtiit88gNCn1A(mtGBY?EFn;#sj_!~4rwM`A{8>#|{A z0B<@>bo7{>a@SAg4)1ocBeCt_h>Vugprp;~^FY@pzGN0kmhT|OfaleVF6F0BQHUS? zrKhIMkm_WtJ1TQtzz=JJ3;Bqxt&riF;3$sk!3tZbz~ru{&yF-bobYOK>p`EYlTB9u zRy~+Vt%Y>sgH-!_ir^xAQZV+|&6=)zsrId>(7(QZk_p&Te{0 z{*!;?L2ZWfYzU$g+6gS&a=N{8QkV)hvW0aIeoQ<8(N~-VDg;8V_i%+GQo?L8Vk$M% z5zEJ80qH#*!i8h=D`87QoRpIr0Y8%qd{wblc+VYu`*1(r{CS^iv57%gO}}3#+!Y}7 z(76#)7o^WT-76uHgm%++=mo$_cmQDSE~>KM53mKKS#U@&AtN0@p>3`U=Ct0sa^;Fk zgoB_1u_(VDbUs1~C?!)r@m>ypZDwAjqY%!_o;|zby`Y>Ld-ScuZToYX(tT~skSTg))W|N#sc^I{js+$ zT)M=>#N;#ZgsJVF;$CQi(7Ff<3R?Gll08leBd=by5cA!yVLg9Br44P^dgi_x`hj%RUTWqtvNRZtQL2o%9fN{8QFGlR&0T5t=X zW%UyV4L^4=Dk`wKSo_b4)Pe`CkCJ}d#?cFznevS}kV!!yjtdGf;g8q6j3v$)cx9?C9?}jgW*Qnq_e4$_4k9tvGPY;ErHHc8+m9|az&6x7$ z_&)zpV&YS*L&D-e-(NhTrVE(~2(=HfueS3F$zpy*nChe$g_2O4QX#o`2RIFM<4X6CmS@z|2@|oKz%Z5ald=($(1+9Ugx3af%Rq$A{bP zxFA9i^073Vj z$wrFu#g0^$UOLZc+F@Y!vo3BBbWv_bgB0GOR;*>bpm4|^@tUCTFw zSkqePA3XROFV>~APmqr9*yj=w8`~TqtWUHxl1uQoS2p@R%Fp+Lb2l`!n7Z@jwX4wD z$Q`719SWFSa*$^dSKO8hm>By{KY&^x_fVp~g3~MyA74sMS7Xoa z*V%Sou+o6np>P01!mkLJVNO$S*GnT7puU;)iXYA*D-fK@Vh?B**G$Y*Fjpb-)(id7nZ0i=_iH~pg|_mFsbo4WT~eaR<` z=t_p1&B>5HKN$do{q0iAv7<-rzDsMonT=Bou_8e{-j$S?Xonr_Gf^TiIo1~>m-+Ca zdini5=_10yxB8Y8SrKNvA$%J+6i=Y>fd=&Bk>nMRnV9dQdi(7h(TL$tVB4!=)zFaB z@EL;_4S+f1&L}1NXc9n4>c0hBfr2U0+LD`_8}mudbN6DwC5SE1_x<2kpTUyARl{d` z_&Pi@NS;*8(fx@eJ^pc1@`a;i{JY3C-wp%>5fxu|?U5#>9mSY9^cm`Uc;Rigwsr#S z(k=Jr8?K4Fd9xL4{J#3s>td}f-}_Jej5R$0()Wa_Rd6Y>|31(dwfMduud@|-VAw|B z54c2r@wKC>8yW)Ya|v6~sErQlcWN*i!3Ug|wcOUbcV{`&-ow~qTg;*&gr3_bQT`Dd zg(GT@sp$mahl_D3u+(-(g8`1D@qjVMtX<;{{q>BPg58DsgqW*@4!sr+xi0DT=YvCcxcKabXtpL3?ra@yvRwy!Uh96@tLwm$Y(} zXujYS?lCuqJ!wTvP5NA)rQMBxK6RI{kWk69XZA1%Xk&K7`9s2^Kz)el*zAOA2bo0? zn9&e+sli&6>;q7%;AR8o8nd(R5s{IlZ#W`y5)$@75pU`an{oSnutz+%YDf>k!tD3J3!G8XbnT4EWM=g|y_IkSAvD8KH3OrBf>Ctx(S^M6Xgni?1yEZYQ&F`b07iu3gwP3p}wQe07XZTyZ)XlGW znt6A-;_@?u-VXBWhtb0M`uG8?1-I}2jkTTj$(V`EetBYqlu!4WhFY02pT z9KKEgTH{qanNN<2P=bqv#PNE|6E>TiCK@*&YXelO;2C7?J<87Ei3tUDDKa}yx%@tm z8-j4f!R6;GO7G=5Gw?|ohDkvRSn%!Ct&udGYBC$hgV*~oE4Le4n#`ehH8S!z#*Sdd z)EHhAmGIEKKY`U#^wa>#9-WJ8T;aY<`077fUB0Hv1@x;Hy!Y?pEz)DmEs#H>nqJJp z0x0kBr7HkmaDP!>Vn=kO6FpzRXjHPE3dSY)^Ls3Gmh%2&=+qDf@Gu*fcGg=S!nKG4 z_jR*W(pCzg5qD6agM>)%Vr#W3aE#wq^33lO&uy`{HmR(O_@@qcZik&VDIQB zI>qQwgZvakDujTXC?-ZacQ|KgY``9bm6a`Xv8n1i%!I2>C5tm5t4M?#g>nh8t6`N4P`fXP=joH&BaLu(O%gJ9ao76XIc9O4!qk#}13ntf!UiT7|dXD0=zMF8XLG#(*UTUfjE*~Pq z$Io0d&vmgcI{BTkXLUd$-_NJvWn(+Dw44xXLWqF85d8!0xrr@!=`T`E5fx#$5&EuN z{motIvFE4m#K>EwwFQ$8PB&BAAp`w z57_R-`$6^ZaCC}5gg{itfh$`!tZxCPU>Ks<;J59U079kYT9Jf2K(qjOQK~2XQ7@PT z)JSU_L$HN=|n^B7Bp6{W!i^R4J_yhbHG0P z^3y7G9&Ta)&%Yu&MhB~|;N6cHc9M$7WH}4?5A)1JTG!FPZ4zQC5{o=r))dbxf zS^bEgP~f1)JFAv{%{S~a^fe!Gkq?6(BIbQ+S(Os(s&OB+?q73HS=>-S^t(%^!%oc6 zLF7Q`q}>h9mU+4r1 zH3h&ND%$K0>cMTz=`~}D6m2n!Ye2`u;|I>DKpmX!`iiWaH zuDSYf=&79eY(X%4h^TC)dQ=@w1my zy>aZ&wl{Z?bu8qXdh(v-Jmbq3_v@gjV_^yTtJ2Dq9}oqrOJicV(SAbn9DXg(Gd%k& zDJjXom`xtJbl6Vf0;T0Hit7P}j3!U#Z6XvL>0T0xmF~Fy?R=+8?$~6pu^>1=fBjsX zPETC(Q=5>x`p=b4XchkJzxUew4*dV~pa1Xv{$D@e7sJ4Q$K5yNelIC$O@^E1J&>PM ze({Rc(MkqS0wD;@!2m9FDT|7HY;EJUOd@shw7-MGuEe*LLa(pKz%~MtFj^EN6CONx z9han+@K=r^{>G7*|6N~OJD-UOz$YY%&tS*!_RB-j?$dw$F0`VEIcGa}p7ll61)ocR zw-CANr;3D|{S{T0zf#)lV*JH<)~p z5SI1ZQ>wY1F^?|M?LJc)L-i|4u=9!imb{)C7!IG!==<=+_b{P_I9@zyN9e$1eSq4~m~%5Vh>; zUKX}yf=&M0L2cvl5V!>;vVDj=_s@Srg8Q;ubjj}|^9Nr(Y#Yb#{Y9|u)(Tvg{Jqk( zbWm|sRrmbU#zeLG)XVGP`QML8&}+U<>|6Ew@eGm24-Y<5hh@$`^si6t|A!u6+Q;+6 z94jr?93S3GxouMYW*H96-F`-y{pM8;&76*h<|ozWW|$>qO&a%@Nt~ZI=j_6VewJh2 zOIJQ6WzAaUDAIfA)cNz97B{|NWQ$FTOCQZJRegLC&x2+I`{j<+qsR0m%#Sf11hS79od0PLh=H`d6x5JH8T&zC+7;-5XjJXbVJR7{n z&ik)b-@FzDCbFIhf6T5zio9-Y)R*b+ZQ^|109GrgO{QBBfM5j>;O+fk^WXc5m(q9z zjp`v5>olqs+D^9C0GVzzIc3O+zD*Rv?f>j-;t47QZ%8`}uKd@# ziohFuDA1VWY>SV_0I~IOp{3O?``3$_4Qk`1pUn&SjMD1o|Hu1I0HA@kAZ+iDyeqzU zeKMo-uP?9C#A|5!?^pT|WdaOXj~-XDVg36^G11-I0meEUx(-5PS)LmnR_xEhMxd>_ zLi+(K;9rl(#?sL4MZ6;4=vDYyF|^10pNVtKD}%foO&eISRDXtMZ~x9N;^p<6`$Bx$ zR+YVB!#{RP#PjFRr7)BpD-WL2WFv_5*i@ject3sdBIxHUlp8#?v66Ehd$^J==6JVY zD$jh|;az$S``Q8GjP^HgxWB7poLB`B{s-k>iF<+R8LEyu2AA8sTm=WwQ$aJd-9&nd z1$(B7ft9ny%C)WJ0{R4g+SOEqYxHF5{K134EVI&7s|f)?XKEassn@xXxOFzKMInTj zHQ^7onGm{QzxLl>ziYLWl;PH`6%`e(EKM2q#>neGS6tytHG4wr!arYNFUJ})AZc~b zqN4EG7ACqvrhZ#UX8YE!wo6@=Z0is zG0k;NrJ2l2#QcY!dlGL$lcIgbz({=U8ReGNBu5kFOoI z&OhWk;|_AJ6dd|#*GC5M3M5(Stb4(s+d)xXwt46Hr`&_@eLhL6emkei$dj75R+$MB z5aU~dKPT1{2WBN#1#^X$?J&;?soden*P?^>mz>YR!{W1MJqy5ry7A*z&ZY=qQ=R$o zhzrgKV|2_?Y#lt`rnNX)3jh5V{`)NvyZ8Ug*0^xi$9VF}i#m%jTIXQ$_TBkOb17oK zHdpnI1-mJQ$I34rJiNZ=(oO4biM!;5LD+@PJuIbp%CjCgExmT=#*EZ-CsmYGw88@$ zdIE<$>d5?4``R_B!>xm_+iL?EgZEXJ3w)C|ob^oVy{Oo%omWIjJ!ii1e({*SXw7^2 zTwS}X(z7C7q}&;-8 zd;xT4lFm~)7ES~9)cCYnqCgC6^5hej1yQ_*| z7O+-voWK6y9gneaC6B{Gd^`I0Yqf?lcGOuO9}WvSsp8+v85M5IWQDLhvi2nY(4^Jw z%%nW4Wix)&fziW=60-s}${Q3-luB1(Zdj%@(3c(hZ@`;7;fqN+@}PNvxytR@n^yiF zoqKfNPTc;EMT@tW@5WRvdhs?$I-k)3;}2eQ|I{))rZ}G5pNrXqPDRaL(;!;!Jc(?M zP^^F|M!Kkv(0{*`J5HGBF&myqGIa$`difQ4A0KMAsWqostJO|{<-YqFXd`3K;^F>EZVFvYLRJIRV@P#$hTVE&Rf0}z_t3WC!;|4H+=1glphuf zQ!!eCS?b#p`1Wzpca^|rZ%>bBgN?tvfW1zRP}=SyWI~^YF?Ma|rf)Cy95R;B@JvAV zt;6Sfq3oJ-85eOvYHn$kW-La_rbdgg=V0uuIY2pcv+nH{HA*2iAQhCK#xPC{l3xG$ zYP*!h&YcNdZk?|;a~YIo%)WR7zqr|vcg;tfzB~+8zp6V0CC?$!cp=7>=3pM}T1v)v zq9+*1FU9zDL2bSng+9gSDZQF`EBJ`I* zyTq>4dX~-QEd1UX!K0c~zEv@=;GB9uYM09`!T`xGsOxb}$Mf!f&vxZ6JGsVpbpw*S zwW{$^WAWq-V-2QLs%H!A)`pw1zn>)#sikaqW7(tCAPgLilI3hR*9R zWCWI%SeQUCtsAc!uYaK5NTUnL919&jE zUj!Z?xv8_!FVajVm6~N-7Tt)AOSxl_@YQa*G0Wx~Ng`o&oQ3Z4V zKds%8k@7OPbE0ZA^m!+&w-d4s;vp`QL3VI2S*j>Dy1r{iPtq=9yZRmXZ1qZA7Tw-z zQC$S!dhZ^k<$y>$?MPiqhPbbWs9X3>WVv7hcb91`fdx@+|65fy^Ill2nk^In>n zyk%);(*5Elo_pZOHdcXbkgHHAWwatpUNfkMVs`b>EK$DXE>~<6tgSj4c=3aRXeqec^vp z_a)#^w(Z~Aqe!$V%aF*@j9JZCD%tma4_U^}$c!a=q9_p+kzGl4qEL1%v`AFeib{zr zQ4!g{^Vah8&ce8=&h!*PuJn(MyrYdx=X`JLzaDJgqyrf*M3L~Xh6laI*x zsPzDh+dG5f=J?yK0;(>Zp4Q6tEU0%`6AV-o@zpFN=49pZNAh+8C?wt{v5a*~&Xh~( z=Wat|i+B4y;#KlAyBSY)u20DDWxkceUb`D`aDl=3YCja)PSg^PxtQ6*8>430@~0iGUkme3;cS%seKfnLw5-W=#&4Vmunh zM*2dsWT~z(Ipu6R8^DFz)*cjU5e&;K7spMb)damEW#m2Prla|#?xJZ;QoduRiCtW| z%S`6gc5VsDnOhGw_qmS+0kaQfa{^b?!x3|R#ez*3Iftz@r|1{R5X~z3Ph-c{#O%?Rsli3DHoT5gl zhm&RyWZr#~Y$S3-4x2v{N{W;5079I5efXW|217}XifN8wm-a?R`s!H;4i~ypmzUf@ zIPlUhUl!kADxp@R<|C-3tu0x_w&5jYZEgb1zP@}$LQLNS41M$!UucX8 zq{HNhcuF$3WTfQjcS-cUvjwmJ5LSByNZXmWQ>!97cTRUH2 zc@&cjiKi`mlIIGF`-kas;C3a|?#M=u9*ADsswCLv?zQg8o(*2()%e<(XZPt@Vk>h4 zr$4Fkv?9W8z9ppf!8elA8eh&$+RK*}aF3J^qAk9Z8tXJ8Jl0jaxnq27fPvNIA{qif znbwjO+5ahP9wK73OrER4 z+m}Q??cXTW28tG=3))ism%#%6Qnt+?!z{9+>rLVue{W-1-ws#c()FXT7KZP@=yz&N zCK`%FGd^ZFWE?FQ)onQ0V&0K~xyo_eCfxr%pd#)lz0qmS??TuYU{+<{Ukn;B@cQD~ zmKQ&MZTxt(vzH9M-4Y+#qF~cpb?abnyn~d5Q75>LG(4Z|H^EUg1ifomhrk`-3M4bG zmCc1Hf%TlBT_YwihXrX0HWPIg_rJW3V>=MTm@<}jFYnJ#!I(e3)jwu0*&yrItlTA7 z#mp&0wngk&AD*e-!EWBK7A|#p(7@|*yH}XN7_w7CYn8bV)`F?b^xl_=Xq{Fo2Z9|~ zREO&UjrjQ4+c_22IUO6mPy`t_aTX8>eT-_zt%|S%O@h4`k#fDeFulMy6$pKRaM=5HcHRg!em|9K^Gy&(Q+R${nbS$gV*w0VQW!nZGCz@ z?=U}LGc+%&RA#DW4fGxY>`=oWU@KM@l@l@B1HLW8lUY5V?(xxvPba7h9jfxUtl}Eg z1RLQErCcL(^Qbzz5J!bHQ=Ddg^k7OWWG3k!a_6xXeLY-t;I`#um6^m>Gk0ahAm3)% zrz;i1pA9O&AzNzuOfF|mSY(R&u2JEQ&4*s*jez+&>1yxZr`Fuw?kvU6Matuzp7%jZ zfCT5RX~S!Wk1Pccg;ZHX(WS-<2E~ShGlg$;97itju3Wq2Vv}Y9;b5@ZfDY%#9az2^erZ%nO(s!gUT&M?) zWkT6&%;=mQU2B|RxKvllti-uBY@?W#>=%QH2)Xo9`E{}_o#+aXaW)?88VU3RwCFmi z_o!y9q3!^L%JiAzl>)%!F7(PslS3t^2dlW8E9O7P)+jhxZyX`E^?$ME3ng|#@?V!t z&T%!4VyCBK-{ch>J4!kxoFnqsZ`fbjRR9V7nuP=W6a54NlC$1^5KR6XH-PKUKr|s> zR#K85*6np5Q;5Bd>jg*#Qij?(CvrGLOCDj$dZKJkQ|`_S*ihT0{QX}e$F z^tn=S5js-4UYT4W4c67c9$!+SyRMfnP#8E#9J?^yFgie z#-BMP-Ux^ru}c)UGXmqUNW-C+J9_8F2d8xjHJjslMqcS;JXD6ENaF7ehwQve zHa9E%HQgLL%oBtR6F$+gc$!iX0^!?|n<-Pp=#g~aliPH9e51QD=HWstXD)>VpJ zagiw`$_I3{)F)iZ1pv*?jrBdL|{)syx` zF-aK=Md!%YiuJnte!k2Y{Z4Hgp2;dYDfWB8lqh8J_b2Sv{xDc+LCHS7N(% z89pz2eQXV30Nllm?T-MKX`@$z3Gr1%1aB4dJ}Kl&0?BQl zzcoH8>e6kkzEz|4EdT~F$o&Yni+Pg&*gYFP5gii4rBUn;?s&3ia=whbvXXC*y@6N} zj12H;fCtICpC6nZk(PAv16O}l?eG^v6Xz$Fj-ypK?2lPEs?rk*^^fO#rU%_OSfY=( zfj-}zkT}V|?;U4^m*pA{5NoU90PHQ&OMjDeEX*d{=H*DhynnjB!$FoX1o`ZJO>e0w4HBXHUCPa-1|e$8df(wHvy_5 z4{5jyGCAeTrkCb+rssx&ho6&BqrcXe>4W-c1FUwQAHctpC2d1;UKZ!gOr>>Aht^!EwE+6Px{lAeNAw=f|WL7em1*xRh@1! zZmVH|rK}+W(zY*%AJnAkPRy|ydTo8eKKguBGF56d$QFL-e#w6zP7H?%8&j8G+3MUI zYvCO))FN`xNi!fur}agqS4%%*4iq9YE;;!vV6{5#HoN^Iu?hg!FN&Ss4vVA)?avIo z9;8=wsHCJq>{R0z1O(9HO!2H2F{=kAmGLP(Juy@0j(ZlcO*NCfi8*I7^a9)KGESTH zb*^G!B3|5N%G^Bb8hOYm24}+UvH}#Mwc&>v--9xSn4AO->E4fs?JfD{?X#!J@EhtT zSPfgjj1vSb4+NT#Ox^;NYX3yhKKSwG(F3rGAZ9C)*(QlX@2pw+|3kmJ@Q!0hP=0V} z1;YEFsi`0<>!goYjvFj31mX@$7aS##WG24G&}pUz3QK$e81iWU^XqQr;Bh$O_YB+! z2Aea_RLsFRS>15As2qf$2)z8Hz^cX`vh#_kMv4OZt*gYvIAGSi#MuzSRF6Dg!o>7i z`5EMw0bnySqK`rZ^;9s-LR*gr?q~pG`hJYlxq79_atu?b8)B^ScXJca>PPhVUFWUsSTX;1SlSg1K zz+?ftG$ymZBGMNenC(;Q&kOApHBaDYxf?0)4!m(?40H0Q3}QL^5r^aQXpLkk;;)$L}yA%d?hPtZG2TQS!gj!$lzy2E=QJ3JpXsy4JXHRl78lfZ`xS!Jrh zdx31kjI>!Fq`C+3R}V`e!Hyv=5BQFN`TeCscW_v(5`Zl&Edg&kdMV@(R2IAjc1+)L zbZv#w`W*)ZS28i}Wh%YEI0ri9dr$<}3g`@y%nJfwmoxhHeC~r%4b!E*;*y3XWatL( z5x^%+DMJo}<_0-F0ZmIIqh4`Gc<&RwS1|4dTurQQB3`;nMsxW{>f!DezI+UG5_tk6DpTUyxPsth8 zU$Rl(dY*d|#&SqwH?@9)L+P;#(-F>3ui7fJGPGe)c7j#G?>wZQha+7jfZgyWXy{(; z&UFS$EdbTqE@(j@53?KYZunIbd7XprGP=t>KE_@kIO$zxy`rn7nqQ6I-@ZNN5!LZE z=+?GBdZfLC40+q|_-6ct@bGX*nUolN;C&ERmSzJ^C%DmA|AbLd8e9dlz*u~Ep{15ck~ei(%I3#g-|mo z?;*!zmYM*`ga9_s$PVMel0h~)h2!kowF$5dx?vGpu(yjYf-dNpaqGv+wu7_()Rh(vx8Ap921x3kv1dR6ms^$$b4=T& z`U)6z)Xasj9;gq|^^^M=YZz1k!Ec*gNgx~qSRp~%3~peqcJ~Ka9|o6~x$0V_d}SLX+SBdfT0Z(jBB)TA4#eHyRPcKn ztfUBtgfW#)K&-=tPz-om3#u1`1K?^l%zWo%B-^v9gZsM6?$VO(H#JRU4g+XbAwD(! z#p6`@u5&FY4wo`cA&tkK-XkybS*va8ShO>vO^fW0=LeFmIT!(Lg(N7TeascjSQ8Im z$tk{4{K;C_Meam@%)w|C8F1cuPovS1fL&e9N@2BkkN9B_NI}<`8ZN}PbnM;kOdg8o zW&fN3B_u@{>o$^a{X~EBJqxA8`+Kx4w)=V?U0ON6RH2<`uBS5`>DWj4l5L?7Kdq!m za;&^gmZQM@M&tZtbD%gK#!Zv0WDb{9K(sPfUvcqSw6cyRJLF%FUd8oM#F3S zRR;_wLS{OhcW@{V+%MNY7z!Tbb)elIZ2*dE1n`L5;kc{AJsZ>G~%j9eel?`a~fz*_#E7j*CBTK>a$2?}|o|Tf2 zsVl&(q|>c?=eiIJY1Vbpqh@Dn;n-$1KMEcgzG|>ly7YzccsiUZ_KA+EQ$qn0*W|u6 z*GSOlJYDa+8XFg`_E4%RP<+I0Suy6U_y$@K%<8KInc%~@@RtgbW%D!I(BN`%7;yiP zMqt7?+k5-fiVzPt{SA)7Ss7mtR*^FOF-5pH=Qy%0UK{1B3~ew{Kr)Pa zziRe5E7}}9zcDmZ{X?{fzVq2FF;~C|k~e3-_adv!N(iGdJ*Zz1*-@s9Pr*dySCnDl3)68Qy0J^NR0b#7mBCUO-?82m{pAZ1Y%F5L*klYgd z`x6YuJ_AlVjCUL+zXy$kd}~2r!N2KYygV@0k8T3tm>k6WjX6#P=cLp$z{%7}O^~GV zI(-0bJFPx^E3uyIeP;+}=gyDXZ^|+d1Ov?Ri>tOFbUr20!BJCxjr7IW|#UxRgl#kcn@4< zH1yO|RZRf`7aaww-|1C#l}H{6;UUwNN5MC^l|jln57ELQLQ6aae2Npew#nH zo_gdQE|l~{T>i8!pD&g|42koP+Q-HiyW02AEp*7+6dp8>d4JRwAYx8FUYl0QTvl4z zQ6{5X-`eYCDfR^Hq&r_InD2&AJlUc0i3|Yx!E&AP1D@>WZnuuYR7hc1@4t;3Ku#&` z0bH=>iRQ(6NOC+#0LM$BE2UmGz8*V2Ys(ABGU_G>2EtC_pSB9>)mhu-6>P*m_2NW~ z860pGO@1dn%;Y7xPM&Md2`WMZ3&A+CuqB+^L9l@u(!y3Hz~!u5*R~@MNPhW<=pY>s z3gTiC5I3gpWkp%@wCxek=col*Qx3y{v8skJn?4}_4_8FqDg^%q@GH+xp5x2L)E)tT z6{5S_81CIhnR?`)E@qUsaO3N}y)vbJorg~QL;%?g>@bB0%6%~#fO?1fq$4F}`e5HO zFeu)g1gHy$Pz)(veN)ZdjwvNdqi}hFb{mZAm({v(_Vi9pbNo< z4n*=1oO_Tb)c^MUDvQ9mk1SMoJ37OYYVC&nN3(He!Q)X9DC8fAt^2c#@VyK?-YF74 zONrl0Wn@qogF_xv6h_XL;Y4$1!RVtf$}|HS3q}EDj+cOHdMJ#EsTm4KM&k)26cL9- zWAOx(yO*o01Gqp%W^Xd;e`B1(|p zn}ot*31}h#uCZh^nLu#|t%6r}vOru?&kCJ-di1PRij zfhHgW^4k;tZRaE?Xgn5rgU6vIDP$B5O9F2?xF!(MSd!#F>K*=H^p1f2r7ebfs;Hfg z42B0?3WH(5vb3jpI#736yLs-Cz@qJ_-V7Sem5z3DXHZ?ywlp^k-5%rPt{_qO0k1ZWGi?f*qve$a}4 z*cKvgfh6F`6f|sG6a|YWk&%{3z=Hd~9F_kueZr9?(Kt!+;%)O^(kGk*8BHNjP&i2( z8g>Z|OGHyha7l*Yhwbo>ru<)!CxYbS<@e8M0+vESV~LCV_TSPwpt%&7DJ&VGxj5(? zVS(UbDNv5Z{@o%p-;{42rJpt?IS9D&9obx{~4Cszj0aEy{GY<2~zEzORK?8@(l zm~T?Lu{rGpX~U7G0`h&{wk5>vdY4q#I^?4=5<`krZGGggvKc9i}4Uap?-AA0zCU?5xhbDaf3*h40e`>BI9^M!C*x zTz{~5{$qU9Wi0b?na?6`gY}=A*dF6(G-WTm%OgadvlbBAC$dA5-QlgwG2>0COHESt zYiKuGuDQ6LSs)HwelS>0BYL&&`tA(M%$GNpNYA*1v}2klwFB;qO`N-X&a+G=`ucKwu*-x#!Z23aG=uBePX+6Uz zlZ!6|*q1TcN)y-JmHog~u`%SNjgIK;Kz;+kwPk1e6IB$m1?5m!p8Gk~nkH@bS7f*C z?r1TMYZ)xr6}k61wLSK>wW!jnC$TC=^kt+E&FxwGIeEQKgW8rSsexyE`h|T7?j@h9 ztT*o0aA!`k?L!?lbQpg3B(AVnTp;}3OO?ao9GE)Qlj~o1&Ni-oQ@B3%@cm8EUfmj} ztL7YC#BXZQq>ZO}@7`wIE{_j~%HQPkyz7+xaUT z`V2qDg|502qt)>Tv&0*&p*bB~KaB?N;ElSeExE%?J#BrZRTF2XWVu7U=DF~%_f{U6 z>78lMo&NOV!Pv~y)Na!PVq>Az>kZ*vi8kTAQ%gSMRJB5uo>~!FStijdO?PvxIJvtz zj!RN~x6_vN!s~-l^0eXHN#VzdWaY%pBQyQ)Zq0NK@-^r<3is?4@mR|fMd1EiDojL& z<5lhFTIIidy}HywChqB`GBh`vo^ip!>#_D94va64$^XQ)#&-Xmgow;mHHT+`Asulc z;^8M`hE%&+S0s_9FF!EBH)=C$7-w{88~QX31~AMj?9TVIB~Q(HB(a4Q_bi(mOV6O{ z8LTO$`@Lr4CTUtsRvPqgeSCbm=ehIVghMMt(4Pxj@w_V(-gNI(ytwkZX#$tk8bKHP zr<%ftos#R8=!>53W*X?0da;^igRS6A5Zv0OMsK7#-Lg$u@|1Agew(cp zrkRP!h1c)z=(y(eB2>q0FoE}3^@E1IV_t8Jrq$Cl8;8&Oeopd=D_=shQ`pBPdMnG( zzuR7F&Q@mDBfy7_?}~d~RmN+jF-&X9tYQ7AqAI|yT(_T>@7N#Nyan4{t@78Y4@(N#Zr+{1h zKq||b_Ny2#Lj$k=Ooun+N3vsxUGTj8=YRc_(r|v<>w(xg|{EWaWEfu$ao&be&6&}%oP@19c<3yxa*=f zd=m{l`s-a8{Y9f?N@-u4jq8e5tTMc5cb~0dHKs(hS)t$C{n?UcZsF{+YOiP8-fIsK z6yKhbdRWMoes`*&yYYFFhF5i)Z=0_`Y5@6xUe~H{iuLNO>!Z%>BQh5zo#d`O@_bj# zbVAcV?x9?FxsBbqz(Kikc;SZ4t znp8U{>wPp|lsR%EkwOG^frug#uxK)wVu93<_oR9J+Y0+2>w(?BtzqEl;BPo4;(y7R;y}=l#9>in;PxdEj){bp1g@71%mwxza!kZ;^S(%+BmOgX z@NYVY1>Tgfm}4UTx7;9J5-kbrA6AlpCLXRxjScils#3Z?wwpxH!|IOPfaP$OTyyx5yl9Yhk9_!*ORn@PqSVl z8cxdL=PT|kw~H6L-LWil|N1%;x=Oe8*gZRjr*)v}z8xCF(?_sMYkj`z`d$mBjkph7 zx_@d_RxfYHsm{$C?Q&ZMF4!CLhNX>2OuDorgsqcSY`~2vv9`{(2{a0)<*ycITV}ob z-QLj0?6RFBovzC{_;%DiX70-)n)9W$R%CqHpR#73h??}B6DoTiKGZ3$ByC-}DIfLR zQLSvNXrRtb{j9e_q=&9jO>49-W=8CobJ4tfsj*+MmhVnaaVw5h(X`Ib?0CmOe`>^b zGpt&6(XN^Ld(-T(5hsc&lTKXNy?gz>m3x(lsjM7_@{Vp!McaG4RUZo&2>INw{^i$x zyHy=0Z}&L8d-#c+pNx}V6BUM*`C7(ottxb+>@zlZp!D8Z1LpMn)H905hpvg31@UW{ z+H6}D@m8AN%r5IRs%Dd!$!)`W?*Pik{gk6^(do%8S~*q}*NsXmc}T@{U*3A>@Qk9? zuRXyOt+?yK>t&5jAC%I$`N>koVP+qi9LwAq>v`+A=4#Td$-+t(mhk<(>qebV>WX)N zDOd2=)xI&}#_dYt`p!7{2Q<#e5;SJqf9T^rfduC9c^rS7>du<8%>0hGzocud7U4Ld z$+)t~v~|C^XTO8|$*0Wu?K}2uDHrZ9P!GOI@JVCH%HQmBpP_CSoU%ek-j8)t_tZ%)~~e%z_O_epV6_O7E>xNeqnaeK>Q zOH!68iFM^X-o{eU8fbohbm!I7OuM^&4gWqzu7cRKBNXC3 zH%m3E=$#$unSv7W>-@tqw(yCGl-w<`9E+K4*i^DAZ=^C%zh>uXxy(z4CC5*3*o?2{ zYt)i%`5;|7+L|`8BEd-_>PrXWR^q8l8r!E&}%gWxsYrKf85UZASX&3m&7K zt!C3oXP!-1s7YR1yJLs0FY(}~TJJOQZk9Hdlcz%8t(4@*{J8EIT|UU<<%T1)@>^J` zuyq$mF%jbhpQic3{A}kJAKjq#_@;g`XIVHP^jH>X=`RQJ0u}zIp!(l`ATM-x;e`Hq zATQACzaGdx6Llm6sOev)<4_tW=33Boakn))v!*sG?Ehpr|s;eT-6Zqg`2 zB>BkNWu+gEdajleOgU)d!M$ZpR_x*FnxnO=#I&DJc&Go-mUb`j4c*ns`liYjXOq0D zdn^t&<=?F02svqqI`SleQ;%~;ko~pI8*r+JH)=I_$}P9`j=KF+I-=?vZRwVfuhq%X zLT2h}BJJ!2-BZmp{k&@xs~hbxm{w_W6(dS597we0^;Fu4QV=Zmn`|A3NDqdf#;DL#$0oxP%o`-kFa%O`{V6=GKBuM+#(=TB;xr;M-{CID>8HkF`(y@cH=BJ%>1Msam(K6S}auqODb6rGAcfJ>R-E!Or@r z+qD-_se<>m7e?)7m5S=iG%k8rgYU3Y^t>S6s~F{W{XmMw+|uxq2`pXuDVycr`mnVu zP0l!QR8+gEDpUNZwXfqJLcvOY2Nm$#&D=~Q+b*SMxD7;Z*w>!!p2C}DvNFf|R*s>E zqGk5|^Yt(Mof2Qg=&}wj%@Dt7_a&xhmgK!Du7Ji_B=Xd*O!UMbm(%fQFZ(@RZpFQ9 zk}9IabMw=kTvxVZHQj;ULh@@`eB|FP5!-(ycteFGPb}+L=_fYElGtM%E+^{e9R4`t zvnN`QME)?BTul(PPTT5#cx-8Wy++lAXB*}sPo)d1E88hY8EP7sUQ6iASVqt7xGSmi zMY1s0;+=pHeeyAL`I?-PT^paiV4tpBdR+s5^lzxfpIV{+#Wdk330TUYdgSV-RRk%NCgdR8>%ZE zwMbU_WmGT=gDWG0JX48?B7KuJkPAuF!ssnbC`QMVW~)y{OjH;h1tqX7xxwT2egBq+ z$)Wl(5Dlq`whdyZKz)0lsv8zeT0f*YRW||(Of27JJ5@J43jb5mQ*{Hy>$fYA>0roQ zX`cEX*0$8|Pg0=TTYI@O^py9Zz6rcg3;w>F`2O5SD2$eu8w|1p+y_lX?Zk>8V+sTH z{Tlb}8u#NG|Lq$8LL!qF%^M&g7L`d#V1H=~ zXgHi)sh)r!0Q<3%9~GgA7(E(|fr6KUIu4`iZcjtOqFeYMpb|2Q@(N@{oRXXbg`lX2 vC(DtQ(ServiceType::InProc, ModeType::Client, "0.0.0.0", + 0, OC::QualityOfService::HighQos); + OCPlatform::Configure(*m_platformConfig); + m_resourceDiscoveryCallback = bind(&IoTClient::discoveredResource, this, placeholders::_1); +} + +void IoTClient::findResource() +{ + string coap_multicast_discovery = string(OC_WELL_KNOWN_QUERY "?if=" EDISON_RESOURCE_INTERFACE); + OCPlatform::findResource("", coap_multicast_discovery.c_str(), m_resourceDiscoveryCallback, + OC::QualityOfService::LowQos); +} + +void IoTClient::discoveredResource(shared_ptr Resource) +{ + try + { + if (Resource) + { + string resourceUri = Resource->uri(); + string hostAddress = Resource->host(); + + cout << "\nFound Resource" << endl << "Resource Types:" << endl; + for (auto& resourceTypes : Resource->getResourceTypes()) + { + cout << "\t" << resourceTypes << endl; + } + + cout << "Resource Interfaces: " << endl; + for (auto& resourceInterfaces : Resource->getResourceInterfaces()) + { + cout << "\t" << resourceInterfaces << endl; + } + cout << "Resource uri: " << resourceUri << endl; + cout << "host: " << hostAddress << endl; + + if (resourceUri == TEMPERATURE_RESOURCE_ENDPOINT) + { + m_temperatureSensor = make_shared(Resource); + } + else if (resourceUri == LIGHT_RESOURCE_ENDPOINT) + { + m_ambientLightSensor = make_shared(Resource); + } + else if (resourceUri == LED_RESOURCE_ENDPOINT) + { + m_platformLED = make_shared(Resource); + } + } + IoTClient::DisplayMenu(); + } + catch (OCException& ex) + { + cerr << "Caught exception in discoveredResource: " << ex.reason() << endl; + } +} + +shared_ptr IoTClient::getTemperatureSensor() +{ + return m_temperatureSensor; +} + +shared_ptr IoTClient::getAmbientLightSensor() +{ + return m_ambientLightSensor; +} + +shared_ptr IoTClient::getPlatformLED() +{ + return m_platformLED; +} + +TemperatureSensor::TemperatureSensor(shared_ptr Resource) +{ + m_isObserved = false; + m_resourceHandle = Resource; + m_GETCallback = bind(&TemperatureSensor::onGet, this, placeholders::_1, placeholders::_2, + placeholders::_3); + m_OBSERVECallback = bind(&TemperatureSensor::onObserve, this, placeholders::_1, + placeholders::_2, placeholders::_3, placeholders::_4); +} + +TemperatureSensor::~TemperatureSensor() +{ + +} + +void TemperatureSensor::startObserve() +{ + if (!m_isObserved) + { + cout << "Starting observing temperature sensor" << endl; + m_resourceHandle->observe(ObserveType::Observe, QueryParamsMap(), m_OBSERVECallback); + } + m_isObserved = true; +} + +void TemperatureSensor::stopObserve() +{ + if (m_isObserved) + { + m_resourceHandle->cancelObserve(); + cout << "Stopped observing temperature sensor" << endl; + } + m_isObserved = false; +} + +void TemperatureSensor::onObserve(const HeaderOptions headerOptions, const OCRepresentation& rep, + int eCode, int sequenceNumber) +{ + if (eCode == OC_STACK_OK) + { + double value; + rep.getValue(TEMPERATURE_RESOURCE_KEY, value); + cout << "Observing TemperatureSensor: Current temperature reading is " << value << endl; + cout << "Sequence number: " << sequenceNumber << endl; + } + else + { + cerr << "TemperatureSensor: Observer response error" << endl; + } +} + +void TemperatureSensor::get() +{ + QueryParamsMap params; + m_resourceHandle->get(params, m_GETCallback); +} + +void TemperatureSensor::onGet(const HeaderOptions& headerOptions, + const OCRepresentation& representation, int errCode) +{ + if (errCode == OC_STACK_OK) + { + double value; + representation.getValue(TEMPERATURE_RESOURCE_KEY, value); + cout << endl << endl << "Current temperature reading: " << value << endl; + } + else { + cerr << endl << endl << "Error in GET response from temperature sensor resource" << endl; + } + IoTClient::DisplayMenu(); +} + +AmbientLight::AmbientLight(shared_ptr Resource) +{ + m_isObserved = false; + m_resourceHandle = Resource; + m_GETCallback = bind(&AmbientLight::onGet, this, placeholders::_1, placeholders::_2, + placeholders::_3); + m_OBSERVECallback = bind(&AmbientLight::onObserve, this, placeholders::_1, placeholders::_2, + placeholders::_3, placeholders::_4); +} + +AmbientLight::~AmbientLight() +{ + +} + +void AmbientLight::startObserve() +{ + if (!m_isObserved) + { + cout << "Started observing ambient light sensor" << endl; + m_resourceHandle->observe(ObserveType::Observe, QueryParamsMap(), m_OBSERVECallback); + } + m_isObserved = true; +} + +void AmbientLight::stopObserve() +{ + if (m_isObserved) + { + m_resourceHandle->cancelObserve(); + cout << "Stopped observing ambient light sensor" << endl; + } + m_isObserved = false; +} + +void AmbientLight::onObserve(const HeaderOptions headerOptions, const OCRepresentation& rep, + int eCode, int sequenceNumber) +{ + if (eCode == OC_STACK_OK) + { + int value; + rep.getValue(LIGHT_RESOURCE_KEY, value); + cout << "Observing AmbientLightSensor: Current ambient light reading is " << value << endl; + cout << "Sequence number: " << sequenceNumber << endl; + } + else + { + cerr << "TemperatureSensor: Observer response error" << endl; + } +} + +void AmbientLight::get() +{ + QueryParamsMap params; + m_resourceHandle->get(params, m_GETCallback); +} + +void AmbientLight::onGet(const HeaderOptions& headerOptions, const OCRepresentation& representation, + int errCode) +{ + if (errCode == OC_STACK_OK) + { + int value; + representation.getValue(LIGHT_RESOURCE_KEY, value); + cout << endl << endl << "Current ambient light sensor reading: " << value << endl; + } + else { + cerr << endl << endl << "Error in GET response from ambient light sensor resource" << endl; + } + IoTClient::DisplayMenu(); +} + +LED::LED(shared_ptr Resource) +{ + m_resourceHandle = Resource; + m_GETCallback = bind(&LED::onGet, this, placeholders::_1, placeholders::_2, placeholders::_3); + m_PUTCallback = bind(&LED::onPut, this, placeholders::_1, placeholders::_2, placeholders::_3); +} + +LED::~LED() +{ + +} + +void LED::get() +{ + QueryParamsMap params; + m_resourceHandle->get(params, m_GETCallback); +} + +void LED::put(int Switch) +{ + QueryParamsMap params; + OCRepresentation rep; + rep.setValue(LED_RESOURCE_KEY, Switch); + m_resourceHandle->put(rep, params, m_PUTCallback); +} + +void LED::onGet(const HeaderOptions& headerOptions, const OCRepresentation& representation, + int errCode) +{ + if (errCode == OC_STACK_OK) + { + int value; + representation.getValue(LED_RESOURCE_KEY, value); + cout << endl << endl << "LED switch state is: " << value << endl; + } + else { + cerr << endl << endl << "Error in GET response from LED resource" << endl; + } + IoTClient::DisplayMenu(); +} + +void LED::onPut(const HeaderOptions& headerOptions, const OCRepresentation& representation, + int errCode) +{ + if (errCode == OC_STACK_OK) + { + int value; + representation.getValue(LED_RESOURCE_KEY, value); + cout << endl << endl << "Set LED switch to: " << value << endl; + } + else { + cerr << endl << endl << "Error in PUT response from LED resource" << endl; + } + IoTClient::DisplayMenu(); +} + +void IoTClient::DisplayMenu() +{ + cout << "\nEnter:\n0) Display this menu\n1) Get temperature Reading\n2) Start Temperature Observer\n3) Stop Temperature Observer\n4) Get ambient light reading\n5) Start Ambient Light Observer\n6) Stop Ambient Light Observer\n7) Turn LED ON\n8) Turn LED OFF\n9) Quit\n"; +} + +int main() +{ + IoTClient client; + cout << "Performing Discovery..." << endl; + client.findResource(); + int choice; + do + { + cin >> choice; + switch (choice) + { + case 0: + IoTClient::DisplayMenu(); + break; + case 1: + if (client.getTemperatureSensor()) + client.getTemperatureSensor()->get(); + else + cout << "Temperature sensor resource not yet discovered" << endl; + break; + case 2: + if (client.getTemperatureSensor()) + client.getTemperatureSensor()->startObserve(); + else + cout << "Temperature sensor resource not yet discovered" << endl; + break; + case 3: + if (client.getTemperatureSensor()) + client.getTemperatureSensor()->stopObserve(); + else + cout << "Temperature sensor resource not yet discovered" << endl; + break; + case 4: + if (client.getAmbientLightSensor()) + client.getAmbientLightSensor()->get(); + else + cout << "Ambient light sensor resource not yet discovered" << endl; + break; + case 5: + if (client.getAmbientLightSensor()) + client.getAmbientLightSensor()->startObserve(); + else + cout << "Ambient light sensor resource not yet discovered" << endl; + break; + case 6: + if (client.getAmbientLightSensor()) + client.getAmbientLightSensor()->stopObserve(); + else + cout << "Ambient light sensor resource not yet discovered" << endl; + break; + case 7: + if (client.getPlatformLED()) + client.getPlatformLED()->put(1); + else + cout << "LED resource not yet discovered" << endl; + break; + case 8: + if (client.getPlatformLED()) + client.getPlatformLED()->put(0); + else + cout << "LED resource not yet discovered" << endl; + break; + case 9: + default: + return 0; + } + } + while (choice != 9); + return 0; +} diff --git a/examples/OICSensorBoard/client.h b/examples/OICSensorBoard/client.h new file mode 100644 index 000000000..36b85ff46 --- /dev/null +++ b/examples/OICSensorBoard/client.h @@ -0,0 +1,105 @@ +//****************************************************************** +// +// Copyright 2014 Intel Corporation. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef CLIENT_H_ +#define CLIENT_H_ + +#include +#include +#include +#include "ocstack.h" +#include "OCApi.h" +#include "OCPlatform.h" +#include "OCResource.h" + +using namespace std; +using namespace OC; + +class LED +{ + shared_ptr m_resourceHandle; + OCRepresentation m_ledRepresentation; + GetCallback m_GETCallback; + PutCallback m_PUTCallback; + void onGet(const HeaderOptions&, const OCRepresentation&, int); + void onPut(const HeaderOptions&, const OCRepresentation&, int); +public: + void get(); + void put(int); + LED(shared_ptr Resource); + virtual ~LED(); +}; + +class TemperatureSensor +{ + shared_ptr m_resourceHandle; + OCRepresentation m_temperatureRepresentation; + GetCallback m_GETCallback; + ObserveCallback m_OBSERVECallback; + bool m_isObserved; + void onObserve(const HeaderOptions headerOptions, const OCRepresentation& rep, int eCode, + int sequenceNumber); + void onGet(const HeaderOptions&, const OCRepresentation&, int); +public: + void get(); + void startObserve(); + void stopObserve(); + TemperatureSensor(shared_ptr Resource); + virtual ~TemperatureSensor(); +}; + +class AmbientLight +{ + shared_ptr m_resourceHandle; + OCRepresentation m_ledRepresentation; + GetCallback m_GETCallback; + ObserveCallback m_OBSERVECallback; + bool m_isObserved; + void onObserve(const HeaderOptions headerOptions, const OCRepresentation& rep, int eCode, + int sequenceNumber); + void onGet(const HeaderOptions&, const OCRepresentation&, int); +public: + void get(); + void startObserve(); + void stopObserve(); + AmbientLight(shared_ptr Resource); + virtual ~AmbientLight(); +}; + +class IoTClient +{ + shared_ptr m_temperatureSensor; + shared_ptr m_ambientLightSensor; + shared_ptr m_platformLED; + shared_ptr m_platformConfig; + FindCallback m_resourceDiscoveryCallback; + void initializePlatform(); + void discoveredResource(shared_ptr); +public: + shared_ptr getTemperatureSensor(); + shared_ptr getAmbientLightSensor(); + shared_ptr getPlatformLED(); + void findResource(); + IoTClient(); + virtual ~IoTClient(); + static void DisplayMenu(); +}; + +#endif /* CLIENT_H_ */ diff --git a/examples/OICSensorBoard/namedefs.h b/examples/OICSensorBoard/namedefs.h new file mode 100644 index 000000000..cf7aaf8ec --- /dev/null +++ b/examples/OICSensorBoard/namedefs.h @@ -0,0 +1,35 @@ +//****************************************************************** +// +// Copyright 2014 Intel Corporation. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef NAMEDEFS_H_ +#define NAMEDEFS_H_ + +#define EDISON_RESOURCE_INTERFACE "core.edison.resources" +#define TEMPERATURE_RESOURCE_TYPE "Room.Temperature" +#define LIGHT_RESOURCE_TYPE "Ambient.Light" +#define LED_RESOURCE_TYPE "Platform.Led" +#define TEMPERATURE_RESOURCE_ENDPOINT "/temperature" +#define LIGHT_RESOURCE_ENDPOINT "/ambientlight" +#define LED_RESOURCE_ENDPOINT "/led" +#define TEMPERATURE_RESOURCE_KEY "temperature" +#define LIGHT_RESOURCE_KEY "ambientlight" +#define LED_RESOURCE_KEY "switch" + +#endif /* NAMEDEFS_H_ */ diff --git a/examples/OICSensorBoard/observer.cpp b/examples/OICSensorBoard/observer.cpp new file mode 100644 index 000000000..4e54ebe19 --- /dev/null +++ b/examples/OICSensorBoard/observer.cpp @@ -0,0 +1,71 @@ +//****************************************************************** +// +// Copyright 2014 Intel Corporation. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "observer.h" + +IoTObserver::IoTObserver(IoTObserverCb Cb) : + m_callback(Cb), m_destroy(false), m_started(false) +{ + m_observerThread[0] = thread(&IoTObserver::observerThread, this); +} + +IoTObserver::~IoTObserver() +{ + terminate(); +} + +void IoTObserver::start() +{ + if (!m_started) + { + { + lock_guard lock(m_mutex); + m_started = true; + } + m_cond.notify_one(); + } +} + +void IoTObserver::stop() +{ + m_started = false; +} + +void IoTObserver::terminate() +{ + m_destroy = true; + stop(); + m_cond.notify_one(); + m_observerThread[0].join(); +} + +void IoTObserver::observerThread() +{ + while (!m_destroy) + { + unique_lock lock(m_mutex); + if (!m_started) + m_cond.wait(lock); + while (m_started) + { + m_callback(); + } + } +} diff --git a/examples/OICSensorBoard/observer.h b/examples/OICSensorBoard/observer.h new file mode 100644 index 000000000..8329a7139 --- /dev/null +++ b/examples/OICSensorBoard/observer.h @@ -0,0 +1,55 @@ +//****************************************************************** +// +// Copyright 2014 Intel Corporation. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef OBSERVER_H_ +#define OBSERVER_H_ + +#include +#include +#include +#include +#include + +using namespace std; + +//Polling callback function prototype. +typedef function IoTObserverCb; + +//Hosts a polling thread which continually calls the specific function +//supplied to its constructor. Client code simply uses Start/Stop calls +//to kick off/suspend polling. +class IoTObserver +{ + mutex m_mutex; + condition_variable m_cond; + IoTObserverCb m_callback; + thread m_observerThread[1]; + bool m_destroy; + bool m_started; + void observerThread(); + void terminate(); +public: + IoTObserver(IoTObserverCb Cb); + virtual ~IoTObserver(); + void start(); + void stop(); +}; + +#endif /* OBSERVER_H_ */ diff --git a/examples/OICSensorBoard/sensors.h b/examples/OICSensorBoard/sensors.h new file mode 100644 index 000000000..44ad4414f --- /dev/null +++ b/examples/OICSensorBoard/sensors.h @@ -0,0 +1,90 @@ +//****************************************************************** +// +// Copyright 2014 Intel Corporation. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include +#include "mraa.h" + +#define ONBOARD_LED_PIN 13 +#define TEMPERATURE_AIO_PIN 0 +#define LIGHT_SENSOR_AIO_PIN 2 + +namespace Sensors +{ +mraa_gpio_context led_gpio = NULL; +mraa_aio_context tmp_aio = NULL; +mraa_aio_context light_aio = NULL; + +inline void SetupPins() +{ + led_gpio = mraa_gpio_init(ONBOARD_LED_PIN); // Initialize pin 13 + if (led_gpio != NULL) + mraa_gpio_dir(led_gpio, MRAA_GPIO_OUT); // Set direction to OUTPUT + tmp_aio = mraa_aio_init(TEMPERATURE_AIO_PIN); // initialize pin 0 + light_aio = mraa_aio_init(LIGHT_SENSOR_AIO_PIN); // initialize pin 2 +} + +inline void ClosePins() +{ + mraa_gpio_close(led_gpio); + mraa_aio_close(tmp_aio); + mraa_aio_close(light_aio); +} + +inline void SetOnboardLed(int on) +{ + if (led_gpio == NULL) + { + led_gpio = mraa_gpio_init(ONBOARD_LED_PIN); // Initialize pin 13 + if (led_gpio != NULL) + mraa_gpio_dir(led_gpio, MRAA_GPIO_OUT); // Set direction to OUTPUT + } + if (led_gpio != NULL) + mraa_gpio_write(led_gpio, on); // Writes into GPIO +} + +inline float GetTemperatureInC() +{ + float ret = 0; + if (tmp_aio == NULL) + { + tmp_aio = mraa_aio_init(TEMPERATURE_AIO_PIN); // initialize pin 0 + } + if (tmp_aio != NULL) + { + uint16_t adc_value = mraa_aio_read(tmp_aio); // read the raw value + //convert reading to temperature + float beta = 4090.0; //the beta of the thermistor, magic number + ret = beta / (log((4095.0 * 10 / adc_value - 10) / 10) + beta / 298.0) - 273.0; + } + return ret; +} + +// This function returns light level between 0 and 4095 +inline int GetLightLevel() +{ + uint16_t adc_value = 0; + if (light_aio == NULL) + light_aio = mraa_aio_init(LIGHT_SENSOR_AIO_PIN); // initialize pin 2 + if (light_aio != NULL) + adc_value = mraa_aio_read(light_aio); // read the raw value + return adc_value; +} +} diff --git a/examples/OICSensorBoard/server.cpp b/examples/OICSensorBoard/server.cpp new file mode 100644 index 000000000..598e37045 --- /dev/null +++ b/examples/OICSensorBoard/server.cpp @@ -0,0 +1,359 @@ +//****************************************************************** +// +// Copyright 2014 Intel Corporation. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#include +#include +#include +#include "server.h" +#include "sensors.h" +#include "namedefs.h" +using namespace Sensors; + +void IoTServer::initializePlatform() +{ + cout << "Running IoTServer constructor" << endl; + m_platformConfig = make_shared(ServiceType::InProc, ModeType::Server, "0.0.0.0", + 0, OC::QualityOfService::HighQos); + OCPlatform::Configure(*m_platformConfig); +} + +IoTServer::IoTServer() +{ + initializePlatform(); + setupResources(); + m_temperatureRepresentation.setValue(TEMPERATURE_RESOURCE_KEY, (float) 0.0f); + m_ambientLightRepresentation.setValue(LIGHT_RESOURCE_KEY, 0); + m_ledRepresentation.setValue(LED_RESOURCE_KEY, 0); + SetupPins(); +} + +IoTServer::~IoTServer() +{ + cout << "Running IoTServer destructor" << endl; + ClosePins(); +} + +void IoTServer::setupResources() +{ + EntityHandler cb1 = bind(&IoTServer::temperatureEntityHandler, this, placeholders::_1); + createResource(TEMPERATURE_RESOURCE_ENDPOINT, TEMPERATURE_RESOURCE_TYPE, cb1, + m_temperatureResource); + IoTObserverCb tempObsCb = bind(&IoTServer::temperatureObserverLoop, this); + m_temperatureObserverLoop = make_shared(tempObsCb); + + EntityHandler cb2 = bind(&IoTServer::lightEntityHandler, this, placeholders::_1); + createResource(LIGHT_RESOURCE_ENDPOINT, LIGHT_RESOURCE_TYPE, cb2, m_ambientLightResource); + IoTObserverCb lightObsCb = bind(&IoTServer::lightObserverLoop, this); + m_ambientLightObserverLoop = make_shared(lightObsCb); + + EntityHandler cb3 = bind(&IoTServer::LEDEntityHandler, this, placeholders::_1); + createResource(LED_RESOURCE_ENDPOINT, LED_RESOURCE_TYPE, cb3, m_ledResource); +} + +void IoTServer::createResource(string Uri, string Type, EntityHandler Cb, OCResourceHandle& Handle) +{ + string resourceUri = Uri; + string resourceType = Type; + string resourceInterface = EDISON_RESOURCE_INTERFACE; + uint8_t resourceFlag = OC_DISCOVERABLE | OC_OBSERVABLE; + + OCStackResult result = OCPlatform::registerResource(Handle, resourceUri, resourceType, + resourceInterface, Cb, resourceFlag); + + if (result != OC_STACK_OK) + cerr << "Could not create " << Type << " resource" << endl; + else + cout << "Successfully created " << Type << " resource" << endl; +} + +void IoTServer::putLEDRepresentation() +{ + int state = 0; + m_ledRepresentation.getValue(LED_RESOURCE_KEY, state); + SetOnboardLed(state); + if (state == 0) + cout << "Turned off LED" << endl; + else if (state == 1) + cout << "Turned on LED" << endl; + else + cerr << "Invalid request value" << endl; +} + +OCRepresentation IoTServer::getLEDRepresentation() +{ + return m_ledRepresentation; +} + +void IoTServer::temperatureObserverLoop() +{ + usleep(1500000); + cout << "Temperature Observer Callback" << endl; + shared_ptr resourceResponse(new OCResourceResponse()); + resourceResponse->setErrorCode(200); + resourceResponse->setResourceRepresentation(getTemperatureRepresentation(), + EDISON_RESOURCE_INTERFACE); + OCStackResult result = OCPlatform::notifyListOfObservers(m_temperatureResource, + m_temperatureObservers, + resourceResponse); + if (result == OC_STACK_NO_OBSERVERS) + { + cout << "No more observers..Stopping observer loop..." << endl; + m_temperatureObserverLoop->stop(); + } +} + +void IoTServer::lightObserverLoop() +{ + usleep(1500000); + cout << "Light Observer Callback" << endl; + shared_ptr resourceResponse(new OCResourceResponse()); + resourceResponse->setErrorCode(200); + resourceResponse->setResourceRepresentation(getLightRepresentation(), + EDISON_RESOURCE_INTERFACE); + OCStackResult result = OCPlatform::notifyListOfObservers(m_ambientLightResource, + m_ambientLightObservers, + resourceResponse); + if (result == OC_STACK_NO_OBSERVERS) + { + cout << "No more observers..Stopping observer loop..." << endl; + m_ambientLightObserverLoop->stop(); + } +} + +OCRepresentation IoTServer::getTemperatureRepresentation() +{ + m_temperatureRepresentation.setValue(TEMPERATURE_RESOURCE_KEY, GetTemperatureInC()); + return m_temperatureRepresentation; +} + +OCRepresentation IoTServer::getLightRepresentation() +{ + m_ambientLightRepresentation.setValue(LIGHT_RESOURCE_KEY, GetLightLevel()); + return m_ambientLightRepresentation; +} + +OCEntityHandlerResult IoTServer::lightEntityHandler(shared_ptr Request) +{ + OCEntityHandlerResult result = OC_EH_ERROR; + if (Request) + { + string requestType = Request->getRequestType(); + int requestFlag = Request->getRequestHandlerFlag(); + if (requestFlag & RequestHandlerFlag::RequestFlag) + { + auto Response = std::make_shared(); + Response->setRequestHandle(Request->getRequestHandle()); + Response->setResourceHandle(Request->getResourceHandle()); + if (requestType == "GET") + { + cout << "GET request for ambient light reading" << endl; + if (Response) + { + Response->setErrorCode(200); + Response->setResponseResult(OC_EH_OK); + Response->setResourceRepresentation(getLightRepresentation()); + if (OCPlatform::sendResponse(Response) == OC_STACK_OK) + { + result = OC_EH_OK; + } + } + } + else + { + Response->setResponseResult(OC_EH_ERROR); + OCPlatform::sendResponse(Response); + cerr << "Unsupported request type" << endl; + return result; + } + } + if (requestFlag & RequestHandlerFlag::ObserverFlag) + { + ObservationInfo observationInfo = Request->getObservationInfo(); + if (ObserveAction::ObserveRegister == observationInfo.action) + { + cout << "Starting observer for ambient light sensor" << endl; + m_ambientLightObservers.push_back(observationInfo.obsId); + m_ambientLightObserverLoop->start(); + } + else if (ObserveAction::ObserveUnregister == observationInfo.action) + { + m_ambientLightObservers.erase( + remove(m_ambientLightObservers.begin(), m_ambientLightObservers.end(), + observationInfo.obsId), + m_ambientLightObservers.end()); + } + } + } + return result; +} + +OCEntityHandlerResult IoTServer::temperatureEntityHandler(shared_ptr Request) +{ + OCEntityHandlerResult result = OC_EH_ERROR; + if (Request) + { + string requestType = Request->getRequestType(); + int requestFlag = Request->getRequestHandlerFlag(); + if (requestFlag & RequestHandlerFlag::RequestFlag) + { + auto Response = std::make_shared(); + Response->setRequestHandle(Request->getRequestHandle()); + Response->setResourceHandle(Request->getResourceHandle()); + if (requestType == "GET") + { + cout << "GET request for temperature sensor reading" << endl; + if (Response) + { + Response->setErrorCode(200); + Response->setResponseResult(OC_EH_OK); + Response->setResourceRepresentation(getTemperatureRepresentation()); + if (OCPlatform::sendResponse(Response) == OC_STACK_OK) + { + result = OC_EH_OK; + } + } + } + else + { + Response->setResponseResult(OC_EH_ERROR); + OCPlatform::sendResponse(Response); + cerr << "Unsupported request type" << endl; + return result; + } + } + if (requestFlag & RequestHandlerFlag::ObserverFlag) + { + ObservationInfo observationInfo = Request->getObservationInfo(); + if (ObserveAction::ObserveRegister == observationInfo.action) + { + cout << "Starting observer for temperature sensor" << endl; + m_temperatureObservers.push_back(observationInfo.obsId); + m_temperatureObserverLoop->start(); + } + else if (ObserveAction::ObserveUnregister == observationInfo.action) + { + m_temperatureObservers.erase( + remove(m_temperatureObservers.begin(), m_temperatureObservers.end(), + observationInfo.obsId), + m_temperatureObservers.end()); + } + } + } + return result; +} + +OCEntityHandlerResult IoTServer::LEDEntityHandler(shared_ptr Request) +{ + OCEntityHandlerResult result = OC_EH_ERROR; + if (Request) + { + string requestType = Request->getRequestType(); + int requestFlag = Request->getRequestHandlerFlag(); + if (requestFlag & RequestHandlerFlag::RequestFlag) + { + auto Response = std::make_shared(); + Response->setRequestHandle(Request->getRequestHandle()); + Response->setResourceHandle(Request->getResourceHandle()); + if (requestType == "PUT") + { + cout << "PUT request for platform LED" << endl; + OCRepresentation requestRep = Request->getResourceRepresentation(); + if (requestRep.hasAttribute(LED_RESOURCE_KEY)) + { + try + { + requestRep.getValue(LED_RESOURCE_KEY); + } + catch (...) + { + Response->setResponseResult(OC_EH_ERROR); + OCPlatform::sendResponse(Response); + cerr << "Client sent invalid resource value type" << endl; + return result; + } + } + else + { + Response->setResponseResult(OC_EH_ERROR); + OCPlatform::sendResponse(Response); + cerr << "Client sent invalid resource key" << endl; + return result; + } + m_ledRepresentation = requestRep; + putLEDRepresentation(); + if (Response) + { + Response->setErrorCode(200); + Response->setResourceRepresentation(getLEDRepresentation()); + Response->setResponseResult(OC_EH_OK); + if (OCPlatform::sendResponse(Response) == OC_STACK_OK) + { + result = OC_EH_OK; + } + } + } + else if (requestType == "GET") + { + cout << "GET request for platform LED" << endl; + if (Response) + { + Response->setErrorCode(200); + Response->setResourceRepresentation(getLEDRepresentation()); + Response->setResponseResult(OC_EH_OK); + if (OCPlatform::sendResponse(Response) == OC_STACK_OK) + { + result = OC_EH_OK; + } + } + } + else + { + Response->setResponseResult(OC_EH_ERROR); + OCPlatform::sendResponse(Response); + cerr << "Unsupported request type" << endl; + } + } + } + return result; +} + +int quit = 0; + +void handle_signal(int signal) +{ + quit = 1; +} + +int main() +{ + struct sigaction sa; + sigfillset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = handle_signal; + sigaction(SIGINT, &sa, NULL); + cout << "Press Ctrl-C to quit...." << endl; + IoTServer server; + do + { + usleep(2000000); + } + while (quit != 1); + return 0; +} + diff --git a/examples/OICSensorBoard/server.h b/examples/OICSensorBoard/server.h new file mode 100644 index 000000000..b77325d27 --- /dev/null +++ b/examples/OICSensorBoard/server.h @@ -0,0 +1,71 @@ +//****************************************************************** +// +// Copyright 2014 Intel Corporation. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef SERVER_H_ +#define SERVER_H_ + +#include +#include +#include +#include "ocstack.h" +#include "observer.h" +#include "OCPlatform.h" +#include "OCApi.h" + +using namespace std; +using namespace OC; + +class IoTServer +{ + shared_ptr m_platformConfig; + OCRepresentation m_temperatureRepresentation; + OCResourceHandle m_temperatureResource; + OCRepresentation m_ambientLightRepresentation; + OCResourceHandle m_ambientLightResource; + OCRepresentation m_ledRepresentation; + OCResourceHandle m_ledResource; + ObservationIds m_ambientLightObservers; + ObservationIds m_temperatureObservers; + shared_ptr m_ambientLightObserverLoop; + shared_ptr m_temperatureObserverLoop; + + void initializePlatform(); + void setupResources(); + void createResource(string, string, EntityHandler, OCResourceHandle&); + + OCRepresentation getTemperatureRepresentation(); + OCRepresentation getLightRepresentation(); + OCRepresentation getLEDRepresentation(); + void putLEDRepresentation(); + + //Polling threads to periodically query sensor values and notify + //subscribers. + void temperatureObserverLoop(); + void lightObserverLoop(); + + OCEntityHandlerResult temperatureEntityHandler(shared_ptr); + OCEntityHandlerResult lightEntityHandler(shared_ptr); + OCEntityHandlerResult LEDEntityHandler(shared_ptr); +public: + IoTServer(); + virtual ~IoTServer(); +}; + +#endif /* SERVER_H_ */ diff --git a/extlibs/buildDependencies.sh b/extlibs/buildDependencies.sh new file mode 100755 index 000000000..4ebe31853 --- /dev/null +++ b/extlibs/buildDependencies.sh @@ -0,0 +1,114 @@ +#!/bin/bash + +set -e + +# Change to extlibs directory +cd "$(dirname "$0")" + +EXTDIR=$(pwd) + +# Check for cereal existence +if [ ! -d "cereal" ]; then + git clone https://github.com/USCiLab/cereal.git cereal + pushd cereal + git reset --hard 7121e91e6ab8c3e6a6516d9d9c3e6804e6f65245 + git apply ../../resource/patches/cereal_gcc46.patch + popd +fi + +# Pick the preferred version of boost to use +BOOST_MAJOR=1 +BOOST_MINOR=57 +BOOST_REVISION=0 + +BOOST_VERSION="${BOOST_MAJOR}.${BOOST_MINOR}.${BOOST_REVISION}" + +# Determine the architecture +HOST_ARCH=$(arch) + +if [ "${HOST_ARCH}" != "x86_64" ]; +then + HOST_ARCH="x86" +fi + +HOST_ARCH="linux-${HOST_ARCH}" + +function cloneBoost { + echo "Removing old boost repo..." + rm -rf boost + echo "Cloning boost from GIT HUB..." + git clone --recursive https://github.com/boostorg/boost.git boost +} + +function buildBoost { + if [ ! -d "boost" ]; then + cloneBoost + fi + + # Determine the + TOOLCHAIN=${ANDROID_NDK}/toolchains/${TOOLSET}-${VERSION}/prebuilt/${HOST_ARCH}/bin + + OLDPATH=$PATH + PATH=$TOOLCHAIN:$PATH + + rm -f boost.log + + pushd boost + echo "Checking out boost v${BOOST_VERSION}..." + git checkout --force -B boost-${BOOST_VERSION} tags/boost-${BOOST_VERSION} &>> ../boost.log + git submodule foreach --recursive git checkout --force -B boost-${BOOST_VERSION} tags/boost-${BOOST_VERSION} &>> ../boost.log + echo "Reset and clean all modular repositories..." + git reset --hard HEAD >> ../boost.log + git clean -d --force >> ../boost.log + git clean -d --force -x >> ../boost.log + git submodule foreach --recursive git reset --hard HEAD >> ../boost.log + git submodule foreach --recursive git clean --force -d >> ../boost.log + git submodule foreach --recursive git clean --force -d -x >> ../boost.log + echo "Copying user configs to boost..." + cp ${EXTDIR}/../resource/patches/boost/${TOOLSET}/user-config.jam tools/build/src/user-config.jam + echo "Boostrapping boost..." + ./bootstrap.sh + echo "Building..." + ./b2 -q \ + target-os=linux \ + link=static \ + threading=multi \ + --layout=system \ + --build-type=minimal \ + -s PLATFORM=${PLATFORM} \ + -s VERSION=${VERSION} \ + --prefix="${EXTDIR}/../out/boost" \ + --includedir="${INCPATH}" \ + --libdir="${LIBPATH}" \ + --build-dir="$(pwd)/build" \ + --with-thread \ + --with-program_options \ + headers install + popd + + if [ ! -d "${INCPATH}" ]; + then + echo "Copying headers to android include directory..." + mkdir -p ${INCPATH} + cp --recursive --dereference boost/boost ${INCPATH} + fi + + PATH=$OLDPATH +} + +function checkBoost { + PLATFORM=$1 + TOOLSET=$2 + VERSION=$3 + + INCPATH="${EXTDIR}/../out/android/include" + LIBPATH="${EXTDIR}/../out/android/lib/${TOOLSET}" + + if [ ! -d "${LIBPATH}" ]; + then + buildBoost + fi +} + +checkBoost android-19 arm-linux-androideabi 4.9 +checkBoost android-19 x86 4.9 diff --git a/extlibs/cjson/cJSON.c b/extlibs/cjson/cJSON.c new file mode 100644 index 000000000..31c43dd2e --- /dev/null +++ b/extlibs/cjson/cJSON.c @@ -0,0 +1,596 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +/* cJSON */ +/* JSON parser in C. */ + +#include +#include +#include +#include +#include +#include +#include +#include "cJSON.h" + +static const char *ep; + +const char *cJSON_GetErrorPtr(void) {return ep;} + +static int cJSON_strcasecmp(const char *s1,const char *s2) +{ + if (!s1) return (s1==s2)?0:1;if (!s2) return 1; + for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; + return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); +} + +static void *(*cJSON_malloc)(size_t sz) = malloc; +static void (*cJSON_free)(void *ptr) = free; + +static char* cJSON_strdup(const char* str) +{ + size_t len; + char* copy; + + len = strlen(str) + 1; + if (!(copy = (char*)cJSON_malloc(len))) return 0; + memcpy(copy,str,len); + return copy; +} + +void cJSON_InitHooks(cJSON_Hooks* hooks) +{ + if (!hooks) { /* Reset hooks */ + cJSON_malloc = malloc; + cJSON_free = free; + return; + } + + cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; + cJSON_free = (hooks->free_fn)?hooks->free_fn:free; +} + +/* Internal constructor. */ +static cJSON *cJSON_New_Item(void) +{ + cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); + if (node) memset(node,0,sizeof(cJSON)); + return node; +} + +/* Delete a cJSON structure. */ +void cJSON_Delete(cJSON *c) +{ + cJSON *next; + while (c) + { + next=c->next; + if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); + if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); + if (c->string) cJSON_free(c->string); + cJSON_free(c); + c=next; + } +} + +/* Parse the input text to generate a number, and populate the result into item. */ +static const char *parse_number(cJSON *item,const char *num) +{ + double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; + + if (*num=='-') sign=-1,num++; /* Has sign? */ + if (*num=='0') num++; /* is zero */ + if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ + if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */ + if (*num=='e' || *num=='E') /* Exponent? */ + { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */ + while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */ + } + + n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ + + item->valuedouble=n; + item->valueint=(int)n; + item->type=cJSON_Number; + return num; +} + +/* Render the number nicely from the given item into a string. */ +static char *print_number(cJSON *item) +{ + char *str; + double d=item->valuedouble; + if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) + { + str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ + if (str) sprintf(str,"%d",item->valueint); + } + else + { + str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */ + if (str) + { + if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d); + else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); + else sprintf(str,"%f",d); + } + } + return str; +} + +static unsigned parse_hex4(const char *str) +{ + unsigned h=0; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + h=h<<4;str++; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + h=h<<4;str++; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + h=h<<4;str++; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + return h; +} + +/* Parse the input text into an unescaped cstring, and populate item. */ +static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; +static const char *parse_string(cJSON *item,const char *str) +{ + const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; + if (*str!='\"') {ep=str;return 0;} /* not a string! */ + + while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ + + out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ + if (!out) return 0; + + ptr=str+1;ptr2=out; + while (*ptr!='\"' && *ptr) + { + if (*ptr!='\\') *ptr2++=*ptr++; + else + { + ptr++; + switch (*ptr) + { + case 'b': *ptr2++='\b'; break; + case 'f': *ptr2++='\f'; break; + case 'n': *ptr2++='\n'; break; + case 'r': *ptr2++='\r'; break; + case 't': *ptr2++='\t'; break; + case 'u': /* transcode utf16 to utf8. */ + uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */ + + if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */ + + if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */ + { + if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */ + uc2=parse_hex4(ptr+3);ptr+=6; + if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */ + uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF)); + } + + len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; + + switch (len) { + case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 1: *--ptr2 =(uc | firstByteMark[len]); + } + ptr2+=len; + break; + default: *ptr2++=*ptr; break; + } + ptr++; + } + } + *ptr2=0; + if (*ptr=='\"') ptr++; + item->valuestring=out; + item->type=cJSON_String; + return ptr; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static char *print_string_ptr(const char *str) +{ + const char *ptr;char *ptr2,*out;int len=0;unsigned char token; + + if (!str) return cJSON_strdup(""); + ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;} + + out=(char*)cJSON_malloc(len+3); + if (!out) return 0; + + ptr2=out;ptr=str; + *ptr2++='\"'; + while (*ptr) + { + if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++; + else + { + *ptr2++='\\'; + switch (token=*ptr++) + { + case '\\': *ptr2++='\\'; break; + case '\"': *ptr2++='\"'; break; + case '\b': *ptr2++='b'; break; + case '\f': *ptr2++='f'; break; + case '\n': *ptr2++='n'; break; + case '\r': *ptr2++='r'; break; + case '\t': *ptr2++='t'; break; + default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */ + } + } + } + *ptr2++='\"';*ptr2++=0; + return out; +} +/* Invote print_string_ptr (which is useful) on an item. */ +static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);} + +/* Predeclare these prototypes. */ +static const char *parse_value(cJSON *item,const char *value); +static char *print_value(cJSON *item,int depth,int fmt); +static const char *parse_array(cJSON *item,const char *value); +static char *print_array(cJSON *item,int depth,int fmt); +static const char *parse_object(cJSON *item,const char *value); +static char *print_object(cJSON *item,int depth,int fmt); + +/* Utility to jump whitespace and cr/lf */ +static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;} + +/* Parse an object - create a new root, and populate. */ +cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated) +{ + const char *end=0; + cJSON *c=cJSON_New_Item(); + ep=0; + if (!c) return 0; /* memory fail */ + + end=parse_value(c,skip(value)); + if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */ + + /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ + if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}} + if (return_parse_end) *return_parse_end=end; + return c; +} +/* Default options for cJSON_Parse */ +cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);} + +/* Render a cJSON item/entity/structure to text. */ +char *cJSON_Print(cJSON *item) {return print_value(item,0,1);} +char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);} + +/* Parser core - when encountering text, process appropriately. */ +static const char *parse_value(cJSON *item,const char *value) +{ + if (!value) return 0; /* Fail on null. */ + if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; } + if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } + if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; } + if (*value=='\"') { return parse_string(item,value); } + if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); } + if (*value=='[') { return parse_array(item,value); } + if (*value=='{') { return parse_object(item,value); } + + ep=value;return 0; /* failure. */ +} + +/* Render a value to text. */ +static char *print_value(cJSON *item,int depth,int fmt) +{ + char *out=0; + if (!item) return 0; + switch ((item->type)&255) + { + case cJSON_NULL: out=cJSON_strdup("null"); break; + case cJSON_False: out=cJSON_strdup("false");break; + case cJSON_True: out=cJSON_strdup("true"); break; + case cJSON_Number: out=print_number(item);break; + case cJSON_String: out=print_string(item);break; + case cJSON_Array: out=print_array(item,depth,fmt);break; + case cJSON_Object: out=print_object(item,depth,fmt);break; + } + return out; +} + +/* Build an array from input text. */ +static const char *parse_array(cJSON *item,const char *value) +{ + cJSON *child; + if (*value!='[') {ep=value;return 0;} /* not an array! */ + + item->type=cJSON_Array; + value=skip(value+1); + if (*value==']') return value+1; /* empty array. */ + + item->child=child=cJSON_New_Item(); + if (!item->child) return 0; /* memory fail */ + value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */ + if (!value) return 0; + + while (*value==',') + { + cJSON *new_item; + if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ + child->next=new_item;new_item->prev=child;child=new_item; + value=skip(parse_value(child,skip(value+1))); + if (!value) return 0; /* memory fail */ + } + + if (*value==']') return value+1; /* end of array */ + ep=value;return 0; /* malformed. */ +} + +/* Render an array to text */ +static char *print_array(cJSON *item,int depth,int fmt) +{ + char **entries; + char *out=0,*ptr,*ret;int len=5; + cJSON *child=item->child; + int numentries=0,i=0,fail=0; + + /* How many entries in the array? */ + while (child) numentries++,child=child->next; + /* Explicitly handle numentries==0 */ + if (!numentries) + { + out=(char*)cJSON_malloc(3); + if (out) strcpy(out,"[]"); + return out; + } + /* Allocate an array to hold the values for each */ + entries=(char**)cJSON_malloc(numentries*sizeof(char*)); + if (!entries) return 0; + memset(entries,0,numentries*sizeof(char*)); + /* Retrieve all the results: */ + child=item->child; + while (child && !fail) + { + ret=print_value(child,depth+1,fmt); + entries[i++]=ret; + if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1; + child=child->next; + } + + /* If we didn't fail, try to malloc the output string */ + if (!fail) out=(char*)cJSON_malloc(len); + /* If that fails, we fail. */ + if (!out) fail=1; + + /* Handle failure. */ + if (fail) + { + for (i=0;itype=cJSON_Object; + value=skip(value+1); + if (*value=='}') return value+1; /* empty array. */ + + item->child=child=cJSON_New_Item(); + if (!item->child) return 0; + value=skip(parse_string(child,skip(value))); + if (!value) return 0; + child->string=child->valuestring;child->valuestring=0; + if (*value!=':') {ep=value;return 0;} /* fail! */ + value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ + if (!value) return 0; + + while (*value==',') + { + cJSON *new_item; + if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ + child->next=new_item;new_item->prev=child;child=new_item; + value=skip(parse_string(child,skip(value+1))); + if (!value) return 0; + child->string=child->valuestring;child->valuestring=0; + if (*value!=':') {ep=value;return 0;} /* fail! */ + value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ + if (!value) return 0; + } + + if (*value=='}') return value+1; /* end of array */ + ep=value;return 0; /* malformed. */ +} + +/* Render an object to text. */ +static char *print_object(cJSON *item,int depth,int fmt) +{ + char **entries=0,**names=0; + char *out=0,*ptr,*ret,*str;int len=7,i=0,j; + cJSON *child=item->child; + int numentries=0,fail=0; + /* Count the number of entries. */ + while (child) numentries++,child=child->next; + /* Explicitly handle empty object case */ + if (!numentries) + { + out=(char*)cJSON_malloc(fmt?depth+4:3); + if (!out) return 0; + ptr=out;*ptr++='{'; + if (fmt) {*ptr++='\n';for (i=0;ichild;depth++;if (fmt) len+=depth; + while (child) + { + names[i]=str=print_string_ptr(child->string); + entries[i++]=ret=print_value(child,depth,fmt); + if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1; + child=child->next; + } + + /* Try to allocate the output string */ + if (!fail) out=(char*)cJSON_malloc(len); + if (!out) fail=1; + + /* Handle failure */ + if (fail) + { + for (i=0;ichild;int i=0;while(c)i++,c=c->next;return i;} +cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;} +cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;} + +/* Utility for array list handling. */ +static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} +/* Utility for handling references. */ +static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;} + +/* Add item to array/object. */ +void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} +void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} +void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));} +void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} + +cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; + if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;} +void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} +cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;} +void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));} + +/* Replace array/object items with new ones. */ +void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return; + newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem; + if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);} +void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}} + +/* Create basic types: */ +cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} +cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} +cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} +cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;} +cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;} +cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;} +cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} +cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} + +/* Create Arrays: */ +cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} + +/* Duplication */ +cJSON *cJSON_Duplicate(cJSON *item,int recurse) +{ + cJSON *newitem,*cptr,*nptr=0,*newchild; + /* Bail on bad ptr */ + if (!item) return 0; + /* Create new item */ + newitem=cJSON_New_Item(); + if (!newitem) return 0; + /* Copy over all vars */ + newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble; + if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}} + if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}} + /* If non-recursive, then we're done! */ + if (!recurse) return newitem; + /* Walk the ->next chain for the child. */ + cptr=item->child; + while (cptr) + { + newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */ + if (!newchild) {cJSON_Delete(newitem);return 0;} + if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */ + else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */ + cptr=cptr->next; + } + return newitem; +} + +void cJSON_Minify(char *json) +{ + char *into=json; + while (*json) + { + if (*json==' ') json++; + else if (*json=='\t') json++; // Whitespace characters. + else if (*json=='\r') json++; + else if (*json=='\n') json++; + else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; // double-slash comments, to end of line. + else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} // multiline comments. + else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} // string literals, which are \" sensitive. + else *into++=*json++; // All other characters. + } + *into=0; // and null-terminate. +} \ No newline at end of file diff --git a/extlibs/cjson/cJSON.h b/extlibs/cjson/cJSON.h new file mode 100644 index 000000000..867b7c32f --- /dev/null +++ b/extlibs/cjson/cJSON.h @@ -0,0 +1,143 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef cJSON__h +#define cJSON__h + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* cJSON Types: */ +#define cJSON_False 0 +#define cJSON_True 1 +#define cJSON_NULL 2 +#define cJSON_Number 3 +#define cJSON_String 4 +#define cJSON_Array 5 +#define cJSON_Object 6 + +#define cJSON_IsReference 256 + +/* The cJSON structure: */ +typedef struct cJSON { + struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + + int type; /* The type of the item, as above. */ + + char *valuestring; /* The item's string, if type==cJSON_String */ + int valueint; /* The item's number, if type==cJSON_Number */ + double valuedouble; /* The item's number, if type==cJSON_Number */ + + char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ +} cJSON; + +typedef struct cJSON_Hooks { + void *(*malloc_fn)(size_t sz); + void (*free_fn)(void *ptr); +} cJSON_Hooks; + +/* Supply malloc, realloc and free functions to cJSON */ +extern void cJSON_InitHooks(cJSON_Hooks* hooks); + + +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ +extern cJSON *cJSON_Parse(const char *value); +/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ +extern char *cJSON_Print(cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ +extern char *cJSON_PrintUnformatted(cJSON *item); +/* Delete a cJSON entity and all subentities. */ +extern void cJSON_Delete(cJSON *c); + +/* Returns the number of items in an array (or object). */ +extern int cJSON_GetArraySize(cJSON *array); +/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ +extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); +/* Get item "string" from object. Case insensitive. */ +extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); + +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +extern const char *cJSON_GetErrorPtr(void); + +/* These calls create a cJSON item of the appropriate type. */ +extern cJSON *cJSON_CreateNull(void); +extern cJSON *cJSON_CreateTrue(void); +extern cJSON *cJSON_CreateFalse(void); +extern cJSON *cJSON_CreateBool(int b); +extern cJSON *cJSON_CreateNumber(double num); +extern cJSON *cJSON_CreateString(const char *string); +extern cJSON *cJSON_CreateArray(void); +extern cJSON *cJSON_CreateObject(void); + +/* These utilities create an Array of count items. */ +extern cJSON *cJSON_CreateIntArray(const int *numbers,int count); +extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count); +extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count); +extern cJSON *cJSON_CreateStringArray(const char **strings,int count); + +/* Append item to the specified array/object. */ +extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); +/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ +extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); + +/* Remove/Detatch items from Arrays/Objects. */ +extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); +extern void cJSON_DeleteItemFromArray(cJSON *array,int which); +extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); +extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); + +/* Update array items. */ +extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); +extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); + +/* Duplicate a cJSON item */ +extern cJSON *cJSON_Duplicate(cJSON *item,int recurse); +/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will +need to be released. With recurse!=0, it will duplicate any children connected to the item. +The item->next and ->prev pointers are always zero on return from Duplicate. */ + +/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ +extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); + +extern void cJSON_Minify(char *json); + +/* Macros for creating things quickly. */ +#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) +#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) +#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) +#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) +#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) +#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) + +/* When assigning an integer value, it needs to be propagated to valuedouble too. */ +#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/extra_options.scons b/extra_options.scons new file mode 100644 index 000000000..dc2e48ec2 --- /dev/null +++ b/extra_options.scons @@ -0,0 +1,35 @@ +###################################################################### +# This script manages extra build options +# +###################################################################### +import os +import platform + +Import('env') + +target_os = env.get('TARGET_OS') +target_arch = env.get('TARGET_ARCH') +src_dir = env.get('SRC_DIR') + +if target_os == 'arduino': + # Add 'NET' build option, let user select board network connection type + vars = Variables() + vars.Add(EnumVariable('NET', 'Network connection type', 'Ethernet', ['Ethernet', 'Wifi'])) + vars.Update(env) + Help(vars.GenerateHelpText(env)) + +# check 'cereal' library, temporarily put it here +if not os.path.exists(src_dir + '/extlibs/cereal'): + print ''' +*********************************** Error: ************************************** +* 'Cereal' library doesn't exist. please download cereal to extlibs directory * +* add apply the patch as following: * +* $ git clone https://github.com/USCiLab/cereal.git /extlibs/cereal* +* $ cd /extlibs/cereal * +* $ git reset --hard 7121e91e6ab8c3e6a6516d9d9c3e6804e6f65245 * +* $ git apply ../../resource/patches/cereal_gcc46.patch * +********************************************************************************* +''' + Exit(1) +else: + env.AppendUnique(CPPPATH = [src_dir + '/extlibs/cereal/include']) diff --git a/resource/README.setup.txt b/resource/README.setup.txt new file mode 100644 index 000000000..d248d66da --- /dev/null +++ b/resource/README.setup.txt @@ -0,0 +1,266 @@ +****************************************************************** + + Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. + +-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +=============================================================================== +== NOTICE - Transition to SCONS == +=============================================================================== + +The IoTivity build system is transitioning to SCONS. Although the +makefiles are still available (until v1.0) and some developers are +still using them, they are currently no longer supported. To learn more +about building using SCONS see Readme.scons.txt in the repository root +directory. The build steps used in continuous integration can be found +in auto_build.sh which is also in the the repository root directory. + +=============================================================================== +== Rich Stack & Lite Stack == +=============================================================================== + +The OIC-RESOURCE repository (referred as "") contains two SDKs +with underlying code (i.e. "stack"). The two SDKs are referred to as "Rich SDK" +(or "C++ SDK") and "Lite SDK" (or "C SDK"). The associated stacks are referred +to as "Rich Stack" (or "C++ Stack") and "Lite Stack" (or "C Stack"), +respectively. The Rich Stack-SDK pair requires that the Lite Stack-SDK pair is +built under it. + +For a list of artifact locations for all possible build processes in the +OIC-RESOURCE repository, please refer to: +/artifact_output_locations.txt. + +=============================================================================== + +The Rich Stack is intended ONLY for Linux Ubuntu 12.04 operating system. +To build Rich Stack, please follow these requirements: +- GCC compiler version is 4.6 +- Pre-install the "gnu-libc" libraries package. +- You have pre-built the Lite Stack for Linux Ubuntu 12.04. +- You have installed and pre-built Boost 1.54. +- To compile Rich Unit Tests, you must have Google Test 1.7.0 and must also + create/append "local.properties" file at /csdk/ with the + following specified: + + GTEST_DIR= + +The Lite Stack is intended ONLY for Linux Ubuntu 12.04, Arduino ATMega 2560 with +Arduino Framework 1.0.5, and Arduino Due with Arduino Framework 1.5.7. +Tip: Use Cutecom in Ubuntu 12.04 to view logs from Arduino ATMega 2560 and +Arduino Due. + +To build Lite Stack, please follow these requirements for Linux Ubuntu 12.04: +- GCC compiler version is 4.6 +- Pre-install the "gnu-libc" libraries package. + +To build Lite Stack, please follow these requirements for Arduino ATMega 2560: +- Arduino Framework 1.0.5 is installed. (Newer versions of the Arduino + Framework for Arduino ATMega 2560 have not been tested.) +- AVR-GCC compiler version is 4.5.3 (Distributed with Arduino 1.0.5, no further + action necessary if framework was obtained from + http://arduino.cc/en/Main/OldSoftwareReleases. Note: Frameworks obtained from + apt-get have had different compiler versions.) +- Unzip the Time Library from here to your Arduino Directory Structure: + http://playground.arduino.cc/code/time +- Apply patch "arduino-1.0.5_linux.patch" at + /tools/arduino/patches to your Arduino Directory Structure at + location . +- Create/Append "local.properties" file at location + /resource/csdk/ with the following specified: + + ARDUINO_DIR := + ARDUINO_TOOLS_DIR := $(ARDUINO_DIR)/hardware/tools/avr/bin + +To build Lite Stack, please follow these requirements for Arduino Due: +- Arduino Framework 1.5.7 is installed. (Newer versions of the Arduino + Framework for Arduino Due have not been tested.) +- AVR-GCC compiler version is 4.8.3 (Distributed with Arduino 1.5.7, no further + action necessary if framework was obtained from + http://arduino.cc/en/Main/OldSoftwareReleases. Note: Frameworks obtained from + apt-get have had different compiler versions.) +- Unzip the Time Library from here to your Arduino Directory Structure: + http://www.pjrc.com/teensy/td_libs_Time.html +- Apply patch "arduino-1.5.7_linux.patch" at + /tools/arduino/patches to your Arduino Directory Structure at + location . +- Create/Append "local.properties" file at location + /resource/csdk/ with the following specified: + + ARDUINO_DIR := + ARDUINO_TOOLS_DIR := $(ARDUINO_DIR)/hardware/tools/avr/bin + +Note: If you are building Unit Tests for Linux, building for Arduino Mega, and +building for Arduino Due you may find it useful to set the "local.properties" +file to look like this: + +GTEST_DIR= + +ifeq ($(PLATFORM), arduinomega) + #Location of arduino sdk for Arduino Mega + ARDUINO_DIR := + ARDUINO_TOOLS_DIR := $(ARDUINO_DIR)/hardware/tools/avr/bin +else + #Location of arduino sdk for Arduino Due + ARDUINO_DIR := + ARDUINO_TOOLS_DIR := $(ARDUINO_DIR)/hardware/tools/gcc-arm-none-eabi-4.8.3-2014q1/bin +endif + +=============================================================================== + +Instructions for Common Build Processes: + +NOTE: 'GNU Make' is required to utilize the build script at location: +/buildScript.mk. + +======================================= +== All Targets - Linux, ATMega & Due == +======================================= + +- All Modules, including OCICUC, in Release & Debug (Lite Stack, Lite Unit + Tests, Lite Examples, Rich Stack, Rich Unit Tests, Rich Examples, Rich + OCICUC) for linux, Arduino ATMega 2560 with Ethernet Shield, Arduino ATMega + ATMega 2560 with WiFi Shield, Arduino Due with Ethernet Shield and Arduino + Due with WiFi Shield: + (This will be what is used on the Build Server(s) to limit regression.) + + make -f buildScript.mk all_dev + +======================================= +== All Targets - Linux & ATMega 2560 == +======================================= + +- All Modules in Release (Lite Stack, Lite Unit Tests, Lite Examples, Rich + Stack, Rich Unit Tests, Rich Examples) for Linux & Arduino ATMega 2560 with + Ethernet Shield: + + make -f buildScript.mk all + +- All Modules in Debug (Lite Stack, Lite Unit Tests, Lite Examples, Rich Stack, + Rich Examples) for Linux & Arduino ATMega 2560 with Ethernet Shield: + + make -f buildScript.mk all_debug + +======================================= +== All Targets - Linux & Due == +======================================= + +- All Modules in Release (Lite Stack, Lite Unit Tests, Lite Examples, Rich + Stack, Rich Unit Tests, Rich Examples) for Linux & Arduino Due with Ethernet + Shield: + + make -f buildScript.mk complement + +- All Modules in Debug (Lite Stack, Lite Unit Tests, Lite Examples, Rich Stack, + Rich Unit Tests, Rich Examples) for Linux & Arduino Due with Ethernet Shield: + + make -f buildScript.mk complement_debug + +======================================= +== All Targets - Linux Only == +======================================= + +- All Modules, without OCICUC, in Release (Lite Stack, Lite Unit Tests, Lite + Examples, Rich Stack, Rich Unit Tests, Rich Examples) for linux: + + make -f buildScript.mk linux + +- All Modules, without OCICUC, in Debug (Lite Stack, Lite Unit Tests, Lite + Examples, Rich Stack, Rich Unit Tests, Rich Examples) for linux: + + make -f buildScript.mk linux_debug + +- All Rich Stack Modules in Release, without OCICUC, (Lite Stack, Rich Stack, + Rich Unit Tests, Rich Examples) for Linux: + + make -f buildScript.mk linux_ub + +- All Rich Stack Modules in Debug, without OCICUC, (Lite Stack, Rich Stack, + Rich Unit Tests, Rich Examples) for Linux: + + make -f buildScript.mk linux_ub_debug + +- All Rich Stack Modules, including OCICUC, in Release & Debug (Lite Stack, + Rich Stack, Rich Unit Tests, Rich Examples, Rich OCICUC) for linux: + + make -f buildScript.mk linux_ub_dev + +- All Lite Stack Modules in Release (Lite Stack, Lite Unit Tests, Lite + Examples) for Linux: + + make -f buildScript.mk linux_tb + +- All Lite Stack Modules in Debug (Lite Stack, Lite Unit Tests, Lite Examples) + for Linux: + + make -f buildScript.mk linux_tb_debug + +======================================= +== All Targets - Mega Only == +======================================= + +- All Lite Stack Modules in Release (Lite Stack, Lite Unit Tests, Lite + Examples) for Arduino ATMega 2560 with Ethernet Shield: + + make -f buildScript.mk arduinomega + +- All Lite Stack Modules in Debug (Lite Stack, Lite Unit Tests, Lite Examples) + for Arduino ATMega 2560 with Ethernet Shield: + + make -f buildScript.mk arduinomega_debug + +- All Lite Stack Modules in Release (Lite Stack, Lite Unit Tests, Lite + Examples) for Arduino ATMega 2560 with WiFi Shield: + + make -f buildScript.mk arduinomega_wifi + +- All Lite Stack Modules in Debug (Lite Stack, Lite Unit Tests, Lite Examples) + for Arduino ATMega 2560 with WiFi Shield: + + make -f buildScript.mk arduinomega_wifi_debug + +======================================= +== All Targets - Due Only == +======================================= + +- All Lite Stack Modules in Release (Lite Stack, Lite Unit Tests, Lite + Examples) for Arduino Due with Ethernet Shield: + + make -f buildScript.mk arduinodue_all + +- All Lite Stack Modules in Debug (Lite Stack, Lite Unit Tests, Lite Examples) + Examples) for Arduino Due with Ethernet Shield: + + make -f buildScript.mk arduinodue_all_debug + +- All Lite Stack Modules in Release (Lite Stack, Lite Unit Tests, Lite + Examples) for Arduino Due with WiFi Shield: + + make -f buildScript.mk arduinodue_wifi + +- All Lite Stack Modules in Debug (Lite Stack, Lite Unit Tests, Lite Examples) + for Arduino Due with WiFi Shield: + + make -f buildScript.mk arduinodue_wifi_debug + +======================================= +== Clean All Targets == +======================================= + +- Clean All: + + make -f buildScript.mk clean + diff --git a/resource/SConscript b/resource/SConscript new file mode 100644 index 000000000..e1ad14e21 --- /dev/null +++ b/resource/SConscript @@ -0,0 +1,29 @@ +## +# 'resource' sub-project main build script +# +## + +Import('env') + +target_os = env.get('TARGET_OS') + +# Build libcoap +SConscript('csdk/libcoap/SConscript') + +# Build liboctbstack +SConscript('csdk/SConscript') + +if target_os == 'android': + SConscript('android/SConscript') + +if target_os != 'arduino': + # Build liboc_logger + SConscript('oc_logger/SConscript') + + # Build liboc + SConscript('src/SConscript') + + # Build examples + SConscript('examples/SConscript') +else: + SConscript('csdk/stack/samples/arduino/SimpleClientServer/ocserver/SConscript') \ No newline at end of file diff --git a/resource/android/OCAndroid.cpp b/resource/android/OCAndroid.cpp new file mode 100644 index 000000000..a43d578ae --- /dev/null +++ b/resource/android/OCAndroid.cpp @@ -0,0 +1,104 @@ +//****************************************************************** +// +// Copyright 2014 MediaTek All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include +#include "OCAndroid.h" + +namespace OC { + template + void from_string(const std::string& s, T& result) { + std::stringstream ss(s); + ss >> result; // TODO handle errors + } + + /* + template + std::string to_string(T value) + { + std::ostringstream os ; + os << value ; + return os.str() ; + } + */ + +} + +namespace std { + + int stoi(const string& s) + { + int ret; + int &ref = ret; + OC::from_string(s, ref); + return ret; + } + + double stod(const std::string& s) + { + double ret; + double &ref = ret; + OC::from_string(s, ref); + return ret; + } + + long long stoll(const std::string& s) + { + long long ret; + long long int &ref = ret; + OC::from_string(s, ref); + return ret; + } + + unsigned long long stoull(const std::string& s) + { + unsigned long long ret; + unsigned long long &ref = ret; + OC::from_string(s, ref); + return ret; + } + + long double stold(const string& s) + { + long double ret; + long double &ref = ret; + OC::from_string(s, ref); + return ret; + } + + std::string to_string(int t) { + std::ostringstream os; + os << t; + return os.str(); + } + + std::string to_string(double t) { + std::ostringstream os; + os << t; + return os.str(); + } + + std::string to_string(uint32_t t) + { + std::ostringstream os; + os << t; + return os.str(); + } + +} // std diff --git a/resource/android/SConscript b/resource/android/SConscript new file mode 100644 index 000000000..35e361644 --- /dev/null +++ b/resource/android/SConscript @@ -0,0 +1,30 @@ +## +# Android Compatibility (static library) build script +## +Import('env') + +# Add third party libraries +lib_env = env.Clone() +#SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env') + +compatibilitylib_env = lib_env.Clone() +###################################################################### +# Build flags +###################################################################### +compatibilitylib_env.AppendUnique(CPPPATH = ['../include/']) + +target_os = env.get('TARGET_OS') + +if target_os == 'android': + compatibilitylib_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions']) + #oclib_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')]) + compatibilitylib_env.AppendUnique(LIBS = ['gnustl_static']) + +###################################################################### +# Source files and Targets +###################################################################### +compatibilitylib_src = ['OCAndroid.cpp'] + +if target_os == 'android': + static_compatibilitylib = compatibilitylib_env.StaticLibrary('compatibility', compatibilitylib_src) + compatibilitylib_env.InstallTarget(static_compatibilitylib, 'libcompatibility') diff --git a/resource/artifact_output_locations.txt b/resource/artifact_output_locations.txt new file mode 100644 index 000000000..d9234a03a --- /dev/null +++ b/resource/artifact_output_locations.txt @@ -0,0 +1,191 @@ +****************************************************************** + + Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. + +-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +=============================================================================== +==== UB Stack & TB Stack - Artifact Output Locations ==== +=============================================================================== + +This file contains the file location for every artifact from every possible +build process in the OIC-RESOURCE repository. + +Please refer to the readme file at /README for more information. + +=============================================================================== +==== Linux - Release & Debug ==== +=============================================================================== + +TB Stack: + release: + /csdk/libcoap/linux/release/libcoap.a + /csdk/linux/release/liboctbstack.a + debug: + /csdk/libcoap/linux/debug/libcoap.a + /csdk/linux/debug/liboctbstack.a + +TB Unit Tests: + release: + /csdk/stack/test/linux/release/ocserver + /csdk/stack/test/linux/release/occlient + debug: + /csdk/stack/test/linux/debug/ocserver + /csdk/stack/test/linux/debug/occlient + +TB Examples: + release: + /csdk/stack/samples/linux/SimpleClientServer/release/ocserver + /csdk/stack/samples/linux/SimpleClientServer/release/occlient + /csdk/stack/samples/linux/SimpleClientServer/release/ocservercoll + /csdk/stack/samples/linux/SimpleClientServer/release/occlientcoll + debug: + /csdk/stack/samples/linux/SimpleClientServer/debug/ocserver + /csdk/stack/samples/linux/SimpleClientServer/debug/occlient + /csdk/stack/samples/linux/SimpleClientServer/debug/ocservercoll + /csdk/stack/samples/linux/SimpleClientServer/debug/occlientcoll + +UB Stack: + release: + /release/obj/liboc.a + debug: + /debug/obj/liboc.a + +UB Examples: + release: + /examples/release/fridgeclient + /examples/release/fridgeserver + /examples/release/garageclient + /examples/release/garageserver + /examples/release/presenceclient + /examples/release/presenceserver + /examples/release/roomclient + /examples/release/roomserver + /examples/release/simpleclient + /examples/release/simpleclientserver + /examples/release/simpleserver + debug: + /examples/debug/fridgeclient + /examples/debug/fridgeserver + /examples/debug/garageclient + /examples/debug/garageserver + /examples/debug/presenceclient + /examples/debug/presenceserver + /examples/debug/roomclient + /examples/debug/roomserver + /examples/debug/simpleclient + /examples/debug/simpleclientserver + /examples/debug/simpleserver + +UB OCICUC: + /examples/ocicuc/client + /examples/ocicuc/monoprocess + /examples/ocicuc/server + + +=============================================================================== +==== Arduino ATMega 2560 - Release & Debug - Ethernet Shield ==== +=============================================================================== + +TB Stack: + Ethernet Shield: + release: + /csdk/libcoap/arduinomega/ethernet_shield/release/libcoap.a + /csdk/arduinomega/ethernet_shield/release/liboctbstack.a + debug: + /csdk/libcoap/arduinomega/ethernet_shield/debug/libcoap.a + /csdk/arduinomega/ethernet_shield/debug/liboctbstack.a + +TB Examples: + Ethernet Shield: + release: + /csdk/stack/samples/arduino/SimpleClientServer/ocserver/arduinomega/ethernet_shield/release/ocserver.hex + debug: + /csdk/stack/samples/arduino/SimpleClientServer/ocserver/arduinomega/ethernet_shield/debug/ocserver.hex + +=============================================================================== +==== Arduino ATMega 2560 - Release & Debug - WiFi Shield ==== +=============================================================================== + +TB Stack: + WiFi Shield: + release: + /csdk/libcoap/arduinomega/wifi_shield/release/libcoap.a + /csdk/arduinomega/wifi_shield/release/liboctbstack.a + debug: + /csdk/libcoap/arduinomega/wifi_shield/debug/libcoap.a + /csdk/arduinomega/wifi_shield/debug/liboctbstack.a + +TB Examples: + WiFi Shield: + release: + /csdk/stack/samples/arduino/SimpleClientServer/ocserver/arduinomega/wifi_shield/release/ocserver.hex + debug: + /csdk/stack/samples/arduino/SimpleClientServer/ocserver/arduinomega/wifi_shield/debug/ocserver.hex + +=============================================================================== +==== Arduino Due - Release & Debug - Ethernet Shield ==== +=============================================================================== + +TB Stack: + Ethernet Shield: + release: + /csdk/libcoap/arduinodue/ethernet_shield/release/libcoap.a + /csdk/arduinodue/ethernet_shield/release/liboctbstack.a + debug: + /csdk/libcoap/arduinodue/ethernet_shield/debug/libcoap.a + /csdk/arduinodue/ethernet_shield/debug/liboctbstack.a + +TB Examples: + Ethernet Shield: + release: + /csdk/stack/samples/arduino/SimpleClientServer/ocserver/arduinodue/ethernet_shield/release/ocserver.hex + debug: + /csdk/stack/samples/arduino/SimpleClientServer/ocserver/arduinodue/ethernet_shield/debug/ocserver.hex + +=============================================================================== +==== Arduino Due - Release & Debug - WiFi Shield ==== +=============================================================================== + +TB Stack: + WiFi Shield: + release: + /csdk/libcoap/arduinodue/wifi_shield/release/libcoap.a + /csdk/arduinodue/wifi_shield/release/liboctbstack.a + debug: + /csdk/libcoap/arduinodue/wifi_shield/debug/libcoap.a + /csdk/arduinodue/wifi_shield/debug/liboctbstack.a + +TB Examples: + WiFi Shield: + release: + /csdk/stack/samples/arduino/SimpleClientServer/ocserver/arduinodue/wifi_shield/release/ocserver.hex + debug: + /csdk/stack/samples/arduino/SimpleClientServer/ocserver/arduinodue/wifi_shield/debug/ocserver.hex + + + + + + + + + + + + + diff --git a/resource/buildScript.mk b/resource/buildScript.mk new file mode 100644 index 000000000..64afad186 --- /dev/null +++ b/resource/buildScript.mk @@ -0,0 +1,531 @@ +# //****************************************************************** +# // +# // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# // +# // Licensed under the Apache License, Version 2.0 (the "License"); +# // you may not use this file except in compliance with the License. +# // You may obtain a copy of the License at +# // +# // http://www.apache.org/licenses/LICENSE-2.0 +# // +# // Unless required by applicable law or agreed to in writing, software +# // distributed under the License is distributed on an "AS IS" BASIS, +# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# // See the License for the specific language governing permissions and +# // limitations under the License. +# // +# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# + +# This makefile build-script requires the following for each platform: +# Note: Refer to READMEs at "/" & "/csdk/" for +# more information. +# +# Linux: +# OS: Ubuntu 12.04 +# GCC Version: 4.6.1 +# +# Arduino ATMega 2560: +# Framework Version: Arduino 1.0.5 +# AVR-GCC Version: 4.5.3 +# +# Arduino Due: +# Framework Version: Arduino 1.5.7 +# AVR-GCC Version: 4.8.3 + +# Header Description: +# ====NAME/TITLE - BUILD TYPE - OUT DIRECTORY==== + +############################################################################### +#### TB Stack, TB Unit Tests, TB Examples, UB Stack, #### +#### & UB Examples - Linux & Arduino Mega #### +#### Note: Default "all" target builds Release only "all" of Linux & #### +#### Release only "all" of Arduino Mega with Ethernet Shield. #### +############################################################################### + +all: all_release + +all_all: all_release all_debug + +dev: linux_ub_dev arduinomega_all_dev + +all_release: linux_release arduinomega_release + +all_debug: linux_debug arduinomega_debug + +############################################################################### +#### TB Stack, TB Unit Tests, TB Examples, UB Stack, #### +#### & UB Examples - Linux & Arduino Due #### +#### Note: Default "all" target builds Release only "all" of Linux & #### +#### Release only "all" of Arduino Due with Ethernet Shield. #### +############################################################################### + +complement: complement_release + +complement_all: complement_release complement_debug + +complement_dev: linux_ub_dev arduinodue_all_dev + +complement_release: linux_release arduinodue_release + +complement_debug: linux_debug arduinodue_debug + +############################################################################### +#### TB Stack, TB Unit Tests, TB Examples, UB Stack, UB Examples, #### +#### & OCICUC - Linux, Arduino Mega and Arduino Due #### +#### Note: The "all_dev" target is intended for use on the build #### +#### server(s). This includes "all" targets for Release & Debug for #### +#### Linux, "all" Release & Debug for Arduino Mega with Ethernet #### +#### Shield & WiFi Shield, and "all" Release & Debug for Arduino #### +#### Due with Ethernet Shield & Wifi Shield. #### +############################################################################### + +all_dev: linux_ub_dev arduinomega_all_dev arduinodue_all_dev + +############################################################################### +## TB Stack, TB Unit Tests, TB Examples, UB Stack, & UB Examples - Linux Only # +############################################################################### + +linux: linux_tb_release + +linux_all: linux_release linux_debug + +linux_release: linux_tb_release linux_ub_release + +linux_debug: linux_tb_debug linux_ub_debug + +############################################################################### +#### TB Stack, TB Unit Tests, & TB Examples - Linux Only #### +############################################################################### + +linux_tb: linux_tb_release + +linux_tb_all: linux_tb_release linux_tb_debug + +linux_tb_release: linux_tb_stack_release linux_tb_unittests_release linux_tb_examples_release + +linux_tb_debug: linux_tb_stack_debug linux_tb_unittests_debug linux_tb_examples_debug + +############################################################################### +#### UB Stack, TB Stack, & UB Examples - Linux Only #### +############################################################################### + +linux_ub: linux_ub_release + +linux_ub_all: linux_ub_release linux_ub_debug + +linux_ub_release: linux_tb_stack_release linux_ub_unittests_release linux_ub_stack_release linux_ub_examples_release + +linux_ub_debug: linux_tb_stack_debug linux_ub_unittests_debug linux_ub_stack_debug linux_ub_examples_debug + +############################################################################### +#### TB Stack - Linux Only #### +############################################################################### + +linux_tb_stack: linux_tb_stack_release + +linux_tb_stack_all: linux_tb_stack_release linux_tb_stack_debug + +linux_tb_stack_debug: + @echo "=====BUILD LIBCOAP FOR LINUX - DEBUG - /csdk/libcoap/linux/debug/=====" + $(MAKE) -C csdk/libcoap "BUILD=debug" "PLATFORM=linux" + @echo "=====BUILD TB STACK FOR LINUX - DEBUG - /csdk/linux/debug/=====" + $(MAKE) -C csdk/ "buildScript_all" "BUILD=debug" "PLATFORM=linux" + +linux_tb_stack_release: + @echo "=====BUILD LIBCOAP FOR LINUX - RELEASE - /csdk/libcoap/linux/release/=====" + $(MAKE) -C csdk/libcoap "BUILD=release" "PLATFORM=linux" + @echo "=====BUILD TB STACK FOR LINUX - RELEASE - /csdk/linux/release/=====" + $(MAKE) -C csdk/ "buildScript_all" "BUILD=release" "PLATFORM=linux" + +############################################################################### +#### TB Unit Tests - Linux Only #### +############################################################################### + +linux_tb_unittests: linux_tb_unittests_release + +linux_tb_unittests_all: linux_tb_unittests_release linux_tb_unittests_debug + +linux_tb_unittests_release: linux_tb_stack_release + @echo "=====BUILD TB UNITTESTS FOR LINUX - RELEASE - /csdk/stack/test/linux/release/=====" + $(MAKE) -C csdk/stack/test/linux/ "BUILD=release" + +linux_tb_unittests_debug: linux_tb_stack_debug + @echo "=====BUILD TB UNITTESTS FOR LINUX - DEBUG - /csdk/stack/test/linux/debug/=====" + $(MAKE) -C csdk/stack/test/linux/ "BUILD=debug" + +############################################################################### +#### TB Examples - Linux Only #### +############################################################################### + +linux_tb_examples: linux_tb_stack_release linux_tb_examples_release + +linux_tb_examples_all: linux_tb_stack_release linux_tb_examples_debug + +linux_tb_examples_release: linux_tb_stack_release + @echo "=====BUILD TB SAMPLE APPS FOR LINUX - RELEASE - /csdk/stack/samples/linux/SimpleClientServer/release/=====" + $(MAKE) -C csdk/stack/samples/linux/SimpleClientServer "PLATFORM=linux" "BUILD=release" + $(MAKE) -C csdk/stack/samples/linux/secure "PLATFORM=linux" "BUILD=release" + +linux_tb_examples_debug: linux_tb_stack_debug + @echo "=====BUILD TB SAMPLE APPS FOR LINUX - DEBUG - /csdk/stack/samples/linux/SimpleClientServer/debug/=====" + $(MAKE) -C csdk/stack/samples/linux/SimpleClientServer "PLATFORM=linux" "BUILD=debug" + $(MAKE) -C csdk/stack/samples/linux/secure "PLATFORM=linux" "BUILD=debug" + +############################################################################### +#### UB Stack (& TB Stack as prerequisite) - Linux Only #### +############################################################################### + +linux_ub_stack: linux_ub_stack_release + +linux_ub_stack_all: linux_ub_stack_release linux_ub_stack_debug + +linux_ub_stack_release: linux_tb_stack_release + @echo "=====BUILD UB STACK FOR LINUX - RELEASE - /release/=====" + $(MAKE) -C ./ "buildScript_all" "BUILD=release" + +linux_ub_stack_debug: linux_tb_stack_debug + @echo "=====BUILD UB STACK FOR LINUX - DEBUG - /debug/=====" + $(MAKE) -C ./ "buildScript_all" "BUILD=debug" + +############################################################################### +#### UB Unit Tests (& TB Stack as prequisite) - Linux Only #### +############################################################################### + +linux_ub_unittests: linux_ub_unittests_release + +linux_ub_unittests_all: linux_ub_unittests_release linux_ub_unittests_debug + +linux_ub_unittests_release: linux_ub_stack_release + @echo "=====BUILD UB UNIT TESTS FOR LINUX - RELEASE - /unittests/release=====" + $(MAKE) -C unittests/ "BUILD=release" + +linux_ub_unittests_debug: linux_ub_stack_debug + @echo "=====BUILD UB UNIT TESTS FOR LINUX - DEBUG - /unittests/debug=====" + $(MAKE) -C unittests/ "BUILD=debug" + +############################################################################### +#### UB Examples (& UB Stack as prerequisite) - Linux Only #### +############################################################################### + +linux_ub_examples: linux_ub_examples_release + +linux_ub_examples_all: linux_ub_examples_release linux_ub_examples_debug + +linux_ub_examples_release: linux_ub_stack_release + @echo "=====BUILD UB SAMPLE APPS FOR LINUX - RELEASE - /examples/release/=====" + $(MAKE) -C examples/ "buildScript_all" "BUILD=release" + +linux_ub_examples_debug: linux_ub_stack_debug + @echo "=====BUILD UB SAMPLE APPS FOR LINUX - DEBUG - /examples/debug/=====" + $(MAKE) -C examples/ "buildScript_all" "BUILD=debug" + +############################################################################### +#### TB Stack, TB Unit Tests, TB Examples, UB Stack, UB Examples, #### +#### UB Unit Tests, & OCICUC - Linux Only #### +############################################################################### + +linux_ub_dev: linux_ub_stack_all linux_ub_unittests_all linux_ub_examples_all linux_tb_examples_all + @echo "=====BUILD UB OCICUC - /examples/ocicuc/=====" + $(MAKE) -C examples/ocicuc/ + +############################################################################### +#TB Stack, TB Unit Tests, & TB Examples - Arduino Mega Only - Ethernet & WiFi # +############################################################################### + +arduinomega: arduinomega_release + +arduinomega_all: arduinomega_release arduinomega_debug + +arduinomega_all_dev: arduinomega_release_dev arduinomega_debug_dev + +arduinomega_release: arduinomega_ethernet_release + +arduinomega_debug: arduinomega_ethernet_debug + +arduinomega_release_dev: arduinomega_ethernet_release arduinomega_wifi_release + +arduinomega_debug_dev: arduinomega_ethernet_debug arduinomega_wifi_debug + +############################################################################### +## TB Stack, TB Unit Tests, & TB Examples - Arduino Mega Only - Ethernet Only # +############################################################################### + +arduinomega_ethernet: arduinomega_ethernet_release + +arduinomega_ethernet_all: arduinomega_ethernet_release arduinomega_ethernet_debug + +arduinomega_ethernet_release: arduinomega_stack_ethernet_release arduinomega_samples_ethernet_release + +arduinomega_ethernet_debug: arduinomega_stack_ethernet_debug arduinomega_samples_ethernet_debug + +############################################################################### +## TB Stack, TB Unit Tests, & TB Examples - Arduino Mega Only - Ethernet Only # +############################################################################### + +arduinomega_wifi: arduinomega_wifi_release + +arduinomega_wifi_all: arduinomega_wifi_release arduinomega_wifi_debug + +arduinomega_wifi_release: arduinomega_stack_wifi_release arduinomega_samples_wifi_release + +arduinomega_wifi_debug: arduinomega_stack_wifi_debug arduinomega_samples_wifi_debug + +############################################################################### +#### TB Stack - Arduino Mega Only - Ethernet Only #### +############################################################################### + +arduinomega_stack_ethernet: arduinomega_stack_ethernet_release + +arduinomega_stack_ethernet_all: arduinomega_stack_ethernet_release arduinomega_stack_ethernet_debug + +arduinomega_stack_ethernet_release: + @echo "=====BUILD C STACK FOR ARDUINO ATMEGA 2560 - RELEASE - ETHERNET SHIELD======" + @echo "=====BUILD LIBCOAP - RELEASE - /csdk/libcoap/arduinomega/ethernet_shield/release/=====" + $(MAKE) -C csdk/libcoap "BUILD=release" "PLATFORM=arduinomega" "ARDUINOWIFI=0" + @echo "=====BUILD TB STACK - RELEASE - /csdk/arduinomega/ethernet_shield/release/=====" + $(MAKE) -C csdk "buildScript_all" "BUILD=release" "PLATFORM=arduinomega" "ARDUINOWIFI=0" + +arduinomega_stack_ethernet_debug: + @echo "=====BUILD C STACK FOR ARDUINO ATMEGA 2560 - DEBUG - ETHERNET SHIELD======" + @echo "=====BUILD LIBCOAP - DEBUG - /csdk/libcoap/arduinomega/ethernet_shield/debug/=====" + $(MAKE) -C csdk/libcoap "BUILD=debug" "PLATFORM=arduinomega" "ARDUINOWIFI=0" + @echo "=====BUILD TB STACK - DEBUG - /csdk/arduinomega/ethernet_shield/debug/=====" + $(MAKE) -C csdk "buildScript_all" "BUILD=debug" "PLATFORM=arduinomega" "ARDUINOWIFI=0" + +############################################################################### +#### TB Stack - Arduino Mega Only - WiFi Only #### +############################################################################### + +arduinomega_stack_wifi: arduinomega_stack_wifi_release + +arduinomega_stack_wifi_all: arduinomega_stack_wifi_release arduinomega_stack_wifi_debug + +arduinomega_stack_wifi_release: + @echo "=====BUILD C STACK FOR ARDUINO ATMEGA 2560 - RELEASE - WiFi SHIELD======" + @echo "=====BUILD LIBCOAP - RELEASE - /csdk/libcoap/arduinomega/wifi_shield/release/=====" + $(MAKE) -C csdk/libcoap "BUILD=release" "PLATFORM=arduinomega" "ARDUINOWIFI=1" + @echo "=====BUILD TB STACK - RELEASE - /csdk/arduinomega/wifi_shield/release/=====" + $(MAKE) -C csdk "buildScript_all" "BUILD=release" "PLATFORM=arduinomega" "ARDUINOWIFI=1" + +arduinomega_stack_wifi_debug: + @echo "=====BUILD C STACK FOR ARDUINO ATMEGA 2560 - DEBUG - WiFi SHIELD======" + @echo "=====BUILD LIBCOAP - DEBUG - /csdk/libcoap/arduinomega/wifi_shield/debug/=====" + $(MAKE) -C csdk/libcoap "BUILD=debug" "PLATFORM=arduinomega" "ARDUINOWIFI=1" + @echo "=====BUILD TB STACK - DEBUG - /csdk/arduinomega/wifi_shield/debug/=====" + $(MAKE) -C csdk "buildScript_all" "BUILD=debug" "PLATFORM=arduinomega" "ARDUINOWIFI=1" + +############################################################################### +#### TB Examples - Arduino Mega Only - Ethernet Only #### +############################################################################### + +arduinomega_samples_ethernet: arduinomega_samples_ethernet_release + +arduinomega_samples_ethernet_all: arduinomega_samples_ethernet_release arduinomega_samples_ethernet_debug + +arduinomega_samples_ethernet_release: arduinomega_stack_ethernet_release + @echo "=====BUILD TB SAMPLE APPS FOR ARDUINO ATMEGA 2560 - RELEASE - ETHERNET SHIELD=====" + @echo "=====BUILD OCSERVER - RELEASE - /csdk/stack/samples/arduino/SimpleClientServer/ocserver/arduinomega/ethernet_shield/release/=====" + $(MAKE) -C csdk/stack/samples/arduino/SimpleClientServer/ocserver "BUILD=release" "PLATFORM=arduinomega" "ARDUINOWIFI=0" + +arduinomega_samples_ethernet_debug: arduinomega_stack_ethernet_debug + @echo "=====BUILD TB SAMPLE APPS FOR ARDUINO ATMEGA 2560 - DEBUG - ETHERNET SHIELD=====" + @echo "=====BUILD OCSERVER - DEBUG - /csdk/stack/samples/arduino/SimpleClientServer/ocserver/arduinomega/ethernet_shield/debug/=====" + $(MAKE) -C csdk/stack/samples/arduino/SimpleClientServer/ocserver "BUILD=debug" "PLATFORM=arduinomega" "ARDUINOWIFI=0" + +############################################################################### +#### TB Examples - Arduino Mega Only - WiFi Only #### +############################################################################### + +arduinomega_samples_wifi: arduinomega_samples_wifi_release + +arduinomega_samples_wifi_all: arduinomega_samples_wifi_release arduinomega_samples_wifi_debug + +arduinomega_samples_wifi_release: arduinomega_stack_wifi_release + @echo "=====BUILD TB SAMPLE APPS FOR ARDUINO ATMEGA 2560 - RELEASE - WIFI SHIELD=====" + @echo "=====BUILD OCSERVER - RELEASE - /csdk/stack/samples/arduino/SimpleClientServer/ocserver/arduinomega/wifi_shield/release/=====" + $(MAKE) -C csdk/stack/samples/arduino/SimpleClientServer/ocserver "BUILD=release" "PLATFORM=arduinomega" "ARDUINOWIFI=1" + +arduinomega_samples_wifi_debug: arduinomega_stack_wifi_debug + @echo "=====BUILD TB SAMPLE APPS FOR ARDUINO ATMEGA 2560 - DEBUG - WIFI SHIELD=====" + @echo "=====BUILD OCSERVER - DEBUG - /csdk/stack/samples/arduino/SimpleClientServer/ocserver/arduinomega/wifi_shield/debug/=====" + $(MAKE) -C csdk/stack/samples/arduino/SimpleClientServer/ocserver "BUILD=debug" "PLATFORM=arduinomega" "ARDUINOWIFI=1" + + +############################################################################### +#TB Stack, TB Unit Tests, & TB Examples - Arduino Due Only - Ethernet & WiFi ## +############################################################################### + +arduinodue: arduinodue_release + +arduinodue_all: arduinodue_release arduinodue_debug + +arduinodue_all_dev: arduinodue_release_dev arduinodue_debug_dev + +arduinodue_release: arduinodue_ethernet_release + +arduinodue_debug: arduinodue_ethernet_debug + +arduinodue_release_dev: arduinodue_ethernet_release arduinodue_wifi_release + +arduinodue_debug_dev: arduinodue_ethernet_debug arduinodue_wifi_debug + +############################################################################### +## TB Stack, TB Unit Tests, & TB Examples - Arduino Due Only - Ethernet Only ## +############################################################################### + +arduinodue_ethernet: arduinodue_ethernet_release + +arduinodue_ethernet_all: arduinodue_ethernet_release arduinodue_ethernet_debug + +arduinodue_ethernet_release: arduinodue_stack_ethernet_release arduinodue_samples_ethernet_release + +arduinodue_ethernet_debug: arduinodue_stack_ethernet_debug arduinodue_samples_ethernet_debug + +############################################################################### +## TB Stack, TB Unit Tests, & TB Examples - Arduino Due Only - Ethernet Only ## +############################################################################### + +arduinodue_wifi: arduinodue_wifi_release + +arduinodue_wifi_all: arduinodue_wifi_release arduinodue_wifi_debug + +arduinodue_wifi_release: arduinodue_stack_wifi_release arduinodue_samples_wifi_release + +arduinodue_wifi_debug: arduinodue_stack_wifi_debug arduinodue_samples_wifi_debug + +############################################################################### +#### TB Stack - Arduino Due Only - Ethernet Only #### +############################################################################### + +arduinodue_stack_ethernet: arduinodue_stack_ethernet_release + +arduinodue_stack_ethernet_all: arduinodue_stack_ethernet_release arduinodue_stack_ethernet_debug + +arduinodue_stack_ethernet_release: + @echo "=====BUILD C STACK FOR ARDUINO DUE - RELEASE - ETHERNET SHIELD======" + @echo "=====BUILD LIBCOAP - RELEASE - /csdk/libcoap/arduinodue/ethernet_shield/release/=====" + $(MAKE) -C csdk/libcoap "BUILD=release" "PLATFORM=arduinodue" "ARDUINOWIFI=0" + @echo "=====BUILD TB STACK - RELEASE - /csdk/arduinodue/ethernet_shield/release/=====" + $(MAKE) -C csdk "buildScript_all" "BUILD=release" "PLATFORM=arduinodue" "ARDUINOWIFI=0" + +arduinodue_stack_ethernet_debug: + @echo "=====BUILD C STACK FOR ARDUINO DUE - DEBUG - ETHERNET SHIELD======" + @echo "=====BUILD LIBCOAP - DEBUG - /csdk/libcoap/arduinodue/ethernet_shield/debug/=====" + $(MAKE) -C csdk/libcoap "BUILD=debug" "PLATFORM=arduinodue" "ARDUINOWIFI=0" + @echo "=====BUILD TB STACK - DEBUG - /csdk/arduinodue/ethernet_shield/debug/=====" + $(MAKE) -C csdk "buildScript_all" "BUILD=debug" "PLATFORM=arduinodue" "ARDUINOWIFI=0" + +############################################################################### +#### TB Stack - Arduino Due Only - WiFi Only #### +############################################################################### + +arduinodue_stack_wifi: arduinodue_stack_wifi_release + +arduinodue_stack_wifi_all: arduinodue_stack_wifi_release arduinodue_stack_wifi_debug + +arduinodue_stack_wifi_release: + @echo "=====BUILD C STACK FOR ARDUINO DUE - RELEASE - WiFi SHIELD======" + @echo "=====BUILD LIBCOAP - RELEASE - /csdk/libcoap/arduinodue/wifi_shield/release/=====" + $(MAKE) -C csdk/libcoap "BUILD=release" "PLATFORM=arduinodue" "ARDUINOWIFI=1" + @echo "=====BUILD TB STACK - RELEASE - /csdk/arduinodue/wifi_shield/release/=====" + $(MAKE) -C csdk "buildScript_all" "BUILD=release" "PLATFORM=arduinodue" "ARDUINOWIFI=1" + +arduinodue_stack_wifi_debug: + @echo "=====BUILD C STACK FOR ARDUINO DUE - DEBUG - WiFi SHIELD======" + @echo "=====BUILD LIBCOAP - DEBUG - /csdk/libcoap/arduinodue/wifi_shield/debug/=====" + $(MAKE) -C csdk/libcoap "BUILD=debug" "PLATFORM=arduinodue" "ARDUINOWIFI=1" + @echo "=====BUILD TB STACK - DEBUG - /csdk/arduinodue/wifi_shield/debug/=====" + $(MAKE) -C csdk "buildScript_all" "BUILD=debug" "PLATFORM=arduinodue" "ARDUINOWIFI=1" + +############################################################################### +#### TB Examples - Arduino Due Only - Ethernet Only #### +############################################################################### + +arduinodue_samples_ethernet: arduinodue_samples_ethernet_release + +arduinodue_samples_ethernet_all: arduinodue_samples_ethernet_release arduinodue_samples_ethernet_debug + +arduinodue_samples_ethernet_release: arduinodue_stack_ethernet_release + @echo "=====BUILD TB SAMPLE APPS FOR ARDUINO DUE - RELEASE - ETHERNET SHIELD=====" + @echo "=====BUILD OCSERVER - RELEASE - /csdk/stack/samples/arduino/SimpleClientServer/ocserver/arduinodue/ethernet_shield/release/=====" + $(MAKE) -C csdk/stack/samples/arduino/SimpleClientServer/ocserver "BUILD=release" "PLATFORM=arduinodue" "ARDUINOWIFI=0" + +arduinodue_samples_ethernet_debug: arduinodue_stack_ethernet_debug + @echo "=====BUILD TB SAMPLE APPS FOR ARDUINO DUE - DEBUG - ETHERNET SHIELD=====" + @echo "=====BUILD OCSERVER - DEBUG - /csdk/stack/samples/arduino/SimpleClientServer/ocserver/arduinodue/ethernet_shield/debug/=====" + $(MAKE) -C csdk/stack/samples/arduino/SimpleClientServer/ocserver "BUILD=debug" "PLATFORM=arduinodue" "ARDUINOWIFI=0" + +############################################################################### +#### TB Examples - Arduino Due Only - WiFi Only #### +############################################################################### + +arduinodue_samples_wifi: arduinodue_samples_wifi_release + +arduinodue_samples_wifi_all: arduinodue_samples_wifi_release arduinodue_samples_wifi_debug + +arduinodue_samples_wifi_release: arduinodue_stack_wifi_release + @echo "=====BUILD TB SAMPLE APPS FOR ARDUINO DUE - RELEASE - WIFI SHIELD=====" + @echo "=====BUILD OCSERVER - RELEASE - /csdk/stack/samples/arduino/SimpleClientServer/ocserver/arduinodue/wifi_shield/release/=====" + $(MAKE) -C csdk/stack/samples/arduino/SimpleClientServer/ocserver "BUILD=release" "PLATFORM=arduinodue" "ARDUINOWIFI=1" + +arduinodue_samples_wifi_debug: arduinodue_stack_wifi_debug + @echo "=====BUILD TB SAMPLE APPS FOR ARDUINO DUE - DEBUG - WIFI SHIELD=====" + @echo "=====BUILD OCSERVER - DEBUG - /csdk/stack/samples/arduino/SimpleClientServer/ocserver/arduinodue/wifi_shield/debug/=====" + $(MAKE) -C csdk/stack/samples/arduino/SimpleClientServer/ocserver "BUILD=debug" "PLATFORM=arduinodue" "ARDUINOWIFI=1" + +############################################################################### +#### Clean All - Linux Only - Ethernet Only #### +############################################################################### + +linux_clean: + -rm -rf -C csdk/libcoap/linux + -rm -rf -C csdk/linux + $(MAKE) -C csdk/stack/test/linux "clean" + $(MAKE) -C csdk/stack/samples/linux/SimpleClientServer "clean" + $(MAKE) -C csdk/stack/samples/linux/secure "clean" + $(MAKE) -C . "clean" + +############################################################################### +#### Clean All - Arduino Mega Only - Ethernet & WiFi #### +############################################################################### + +arduinomega_clean: + -rm -rf csdk/libcoap/arduinomega + -rm -rf csdk/arduinomega + -rm -rf csdk/stack/test/arduino/arduinomega + -rm -rf csdk/stack/samples/arduino/SimpleClientServer/ocserver/arduinomega + +############################################################################### +#### Clean All - Arduino Due Only - Ethernet & WiFi #### +############################################################################### + +arduinodue_clean: + -rm -rf csdk/libcoap/arduinodue + -rm -rf csdk/arduinodue + -rm -rf csdk/stack/test/arduino/arduinodue + -rm -rf csdk/stack/samples/arduino/SimpleClientServer/ocserver/arduinodue + + +############################################################################### +#### Clean All - Linux, Arduino Mega & Arduino Due - Ethernet & WiFi #### +############################################################################### +clean: + $(MAKE) -C csdk "clean" "deepclean" + $(MAKE) -C csdk/stack/test/linux "clean" + $(MAKE) -C csdk/stack/samples/linux/SimpleClientServer "clean" + $(MAKE) -C csdk/stack/samples/linux/secure "clean" + $(MAKE) -C csdk/stack/samples/arduino/SimpleClientServer/ocserver "clean" + $(MAKE) -C . "clean" + $(MAKE) -C unittests/ "clean" + $(MAKE) -C examples/ "clean" + $(MAKE) -C oc_logger/ "clean" + +############################################################################### +### You must specify arduinomega or arduinodue when using an arduino target.### +############################################################################### +arduino: + $(error "You must specify "arduinomega" or "arduinodue" when trying to\ + build arduino targets.") diff --git a/resource/csdk/README b/resource/csdk/README new file mode 100644 index 000000000..fb924383b --- /dev/null +++ b/resource/csdk/README @@ -0,0 +1,62 @@ +------------------------------------------------------------------------------- + NOTICE - Transition to SCONS +------------------------------------------------------------------------------- + +The IoTivity build system is transitioning to SCONS. Although the +makefiles are still available (until v1.0) and some developers are +still using them, they are currently no longer supported. To learn more +about building using SCONS see Readme.scons.txt in the repository root +directory. The build steps used in continuous integration can be found +in auto_build.sh which is also in the the repository root directory. + +------------------------------------------------------------------------------- +**Linux** +------------------------------------------------------------------------------- +To make octbstack.a in release mode: + + make + +To make octbstack.a in debug mode: + + make BUILD=debug + +------------------------------------------------------------------------------- +**Arduino** +------------------------------------------------------------------------------- +Touch (i.e. create) file named "local.properties" at this directory level with +the following definition(s): + + ARDUINO_DIR = /arduino-1.0.5 + ARDUINO_TOOLS_DIR = (location of avr-g++ and other avr tools) + +To make octbstack.a in release mode: + make PLATFORM=arduinomega (For Arduino Due, use ) + +To make octbstack.a in debug mode: + make PLATFORM=arduinomega BUILD=debug (For Arduino Due, use ) + +To make octbstack.a with Arduino WiFi Shield support: + make PLATFORM=arduinomega ARDUINOWIFI=1 (For Arduino Due, use ) + +Dependencies: + 1) Patch the Wiznet Ethernet library with the patch available at : + oic-utilities/tb/arduino_linux_ethernet_socket_cpp.patch + 2) Arduino builds are dependent on latest Time library. Download it from here: + http://www.pjrc.com/teensy/td_libs_Time.html + 3) Arduino Due has been tested with Arduino 1.5.7 framework. + 4) For Arduino Due, binary tools are located in: + /hardware/tools/gcc-arm-none-eabi-4.8.3-2014q1/bin + 5) For Arduino WiFi, update the WiFi shield with the firmware patches provided + by Intel. +------------------------------------------------------------------------------- +**Clean-Up** +------------------------------------------------------------------------------- +To clean only stack modules: + + make clean + +To clean stack modules and libcoap (i.e. networking) modules & its +dependencies: + + make deepclean + diff --git a/resource/csdk/SConscript b/resource/csdk/SConscript new file mode 100644 index 000000000..65d02a192 --- /dev/null +++ b/resource/csdk/SConscript @@ -0,0 +1,84 @@ +## +# liboctbstack (share library) build script +## + +Import('env') + +lib_env = env.Clone() +SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env') + +liboctbstack_env = lib_env.Clone() + +target_os = env.get('TARGET_OS') +# As in the source code, it includes arduino Time library (C++) +# It requires compile the .c with g++ +if target_os == 'arduino': + liboctbstack_env.Replace(CC = env.get('CXX')) + liboctbstack_env.Replace(CFLAGS = env.get('CXXFLAGS')) + +###################################################################### +# Build flags +###################################################################### +liboctbstack_env.PrependUnique(CPPPATH = [ + '../../extlibs/cjson/', + 'ocsocket/include', + 'logger/include', + 'ocrandom/include', + 'ocmalloc/include', + 'libcoap', + 'occoap/include', + 'stack/include', + 'stack/include/internal', + '../oc_logger/include' + ]) + +if target_os not in ['arduino', 'windows', 'winrt']: + liboctbstack_env.AppendUnique(CPPDEFINES = ['WITH_POSIX']) + liboctbstack_env.AppendUnique(CFLAGS = ['-std=c99']) + +if target_os not in ['windows', 'winrt']: + liboctbstack_env.AppendUnique(CFLAGS = ['-Wall']) + +if target_os == 'android': + liboctbstack_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')]) + liboctbstack_env.AppendUnique(LIBS = ['coap', 'm']) + +if target_os == 'arduino': + liboctbstack_env.AppendUnique(CPPDEFINES = ['NDEBUG', 'WITH_ARDUINO']) +else: + liboctbstack_env.AppendUnique(CFLAGS = ['-fPIC']) + +if target_os in ['darwin', 'ios']: + liboctbstack_env.AppendUnique(CPPDEFINES = ['_DARWIN_C_SOURCE']) + liboctbstack_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')]) + liboctbstack_env.AppendUnique(LIBS = ['coap']) + +if not env.get('RELEASE'): + liboctbstack_env.AppendUnique(CPPDEFINES = ['TB_LOG']) + +###################################################################### +# Source files and Targets +###################################################################### +OCTBSTACK_SRC = 'stack/src/' +liboctbstack_src = [ + '../../extlibs/cjson/cJSON.c', + 'occoap/src/occoap.c', + 'occoap/src/occoaphelper.c', + OCTBSTACK_SRC + 'ocstack.c', + OCTBSTACK_SRC + 'occlientcb.c', + OCTBSTACK_SRC + 'ocresource.c', + OCTBSTACK_SRC + 'ocobserve.c', + OCTBSTACK_SRC + 'ocserverrequest.c', + OCTBSTACK_SRC + 'occollection.c', + OCTBSTACK_SRC + 'ocsecurity.c', + OCTBSTACK_SRC + 'oicgroup.c' + ] +if target_os == 'arduino': + static_liboctbstack = liboctbstack_env.StaticLibrary('octbstack', liboctbstack_src) + liboctbstack_env.InstallTarget(static_liboctbstack, 'liboctbstack') +else: + static_liboctbstack = liboctbstack_env.StaticLibrary('octbstack', liboctbstack_src) + shared_liboctbstack = liboctbstack_env.SharedLibrary('octbstack', liboctbstack_src) + liboctbstack_env.InstallTarget([static_liboctbstack, shared_liboctbstack], 'liboctbstack') + + diff --git a/resource/csdk/arduinodue.properties b/resource/csdk/arduinodue.properties new file mode 100644 index 000000000..959b25641 --- /dev/null +++ b/resource/csdk/arduinodue.properties @@ -0,0 +1,70 @@ +#Source directories +SDIR_ARD_CORE_1 = $(ARDUINO_DIR)/hardware/arduino/sam/cores/arduino +SDIR_ARD_CORE_2 = $(ARDUINO_DIR)/hardware/arduino/sam/cores/arduino/USB +SDIR_ARD_CORE_3 = $(ARDUINO_DIR)/hardware/arduino/sam/variants/arduino_due_x +SDIR_ARD_CORE_4 = $(ARDUINO_DIR)/hardware/arduino/sam/cores/arduino/avr +SDIR_ARD_SPI = $(ARDUINO_DIR)/hardware/arduino/sam/libraries/SPI +SDIR_ARD_ETH = $(ARDUINO_DIR)/libraries/Ethernet/src +SDIR_ARD_ETH_UTIL = $(ARDUINO_DIR)/libraries/Ethernet/src/utility +SDIR_ARD_WIFI = $(ARDUINO_DIR)/libraries/WiFi/src +SDIR_ARD_WIFI_UTIL = $(ARDUINO_DIR)/libraries/WiFi/src/utility +SDIR_ARD_TIME = $(ARDUINO_DIR)/libraries/Time/Time + +SDIR_ARD_PLATFORM = $(SDIR_ARD_CORE_1):$(SDIR_ARD_CORE_2):$(SDIR_ARD_CORE_3):$(SDIR_ARD_CORE_4):$(SDIR_ARD_SPI):\ + $(SDIR_ARD_TIME) + +#include directories +IDIR_ARD_CORE_1 = $(ARDUINO_DIR)/hardware/arduino/sam/cores/arduino +IDIR_ARD_CORE_2 = $(ARDUINO_DIR)/hardware/arduino/sam/system/libsam +IDIR_ARD_CORE_3 = $(ARDUINO_DIR)/hardware/arduino/sam/system/CMSIS/CMSIS/Include +IDIR_ARD_CORE_4 = $(ARDUINO_DIR)/hardware/arduino/sam/system/CMSIS/Device/ATMEL +IDIR_ARD_CORE_5 = $(ARDUINO_DIR)/hardware/arduino/sam/variants/arduino_due_x +IDIR_ARD_SPI = $(ARDUINO_DIR)/hardware/arduino/sam/libraries/SPI +IDIR_ARD_ETH = $(ARDUINO_DIR)/libraries/Ethernet/src +IDIR_ARD_ETH_UTIL = $(ARDUINO_DIR)/libraries/Ethernet/src/utility +INCD_ARD_WIFI = $(ARDUINO_DIR)/libraries/WiFi/src +INCD_ARD_WIFI_UTIL = $(ARDUINO_DIR)/libraries/WiFi/src/utility +INCD_ARD_TIME = $(ARDUINO_DIR)/libraries/Time/Time + + +INC_DIR_PLATFORM = -I$(IDIR_ARD_CORE_1) -I$(IDIR_ARD_CORE_2) -I$(IDIR_ARD_CORE_3) -I$(IDIR_ARD_CORE_4) -I$(IDIR_ARD_CORE_5) \ + -I$(IDIR_ARD_SPI) -I$(INCD_ARD_TIME) + +#Compiler/Linker flags +CFLAGS_PLATFORM = -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions \ + -Dprintf=iprintf -mcpu=cortex-m3 -DF_CPU=84000000L -DARDUINO=157 -DARDUINO_SAM_DUE -DARDUINO_ARCH_SAM \ + -D__SAM3X8E__ -mthumb -DUSB_VID=0x2341 -DUSB_PID=0x003e -DUSBCON -DUSB_MANUFACTURER="Unknown" \ + -DWITH_ARDUINO -DNDEBUG + +#Compilers +CXX=$(ARDUINO_TOOLS_DIR)/arm-none-eabi-g++ +CC=$(ARDUINO_TOOLS_DIR)/arm-none-eabi-gcc +AR=$(ARDUINO_TOOLS_DIR)/arm-none-eabi-ar +RANLIB=$(ARDUINO_TOOLS_DIR)/arm-none-eabi-ranlib +AVR_PROGRAMMER=$(ARDUINO_TOOLS_DIR)/bossac + +#Needed object files +CORE_COBJ = hooks.o dtostrf.o iar_calls_sam3.o WInterrupts.o wiring.o wiring_digital.o wiring_analog.o wiring_shift.o\ + wiring_pulse.o USARTClass.o USBCore.o RingBuffer.o cortex_handlers.o +CORE_CPPOBJ = itoa.o main.o Stream.o WMath.o WString.o Print.o IPAddress.o HID.o UARTClass.o CDC.o Reset.o cxxabi-compat.o +ETH_CPPOBJ = Dhcp.o Dns.o Ethernet.o EthernetUdp.o EthernetClient.o +ETH_UTIL_CPPOBJ = socket.o w5100.o +WIFI_COBJ = WiFi.o WiFiClient.o WiFiServer.o WiFiUdp.o server_drv.o spi_drv.o wifi_drv.o +VARIANT_OBJ = variant.o +SPI_OBJ = SPI.o +SYSCALLS_SAM3_OBJ = syscalls_sam3.o + +PLATFORM_OBJS = $(SYSCALLS_SAM3_OBJ) $(SPI_OBJ) $(VARIANT_OBJ) $(CORE_COBJ) $(CORE_CPPOBJ) + +#Include sources/objects corresponding to WiFi or Ethernet shield +ifeq ($(ARDUINOWIFI),1) + INC_DIR_PLATFORM += -I$(INCD_ARD_WIFI) -I$(INCD_ARD_WIFI_UTIL) + SDIR_ARD_PLATFORM += :$(SDIR_ARD_WIFI):$(SDIR_ARD_WIFI_UTIL) + PLATFORM_OBJS += $(WIFI_COBJ) +else + INC_DIR_PLATFORM += -I$(IDIR_ARD_ETH) -I$(IDIR_ARD_ETH_UTIL) + SDIR_ARD_PLATFORM += :$(SDIR_ARD_ETH):$(SDIR_ARD_ETH_UTIL) + PLATFORM_OBJS += $(ETH_CPPOBJ) $(ETH_UTIL_CPPOBJ) +endif + + diff --git a/resource/csdk/arduinomega.properties b/resource/csdk/arduinomega.properties new file mode 100644 index 000000000..2b76cee4d --- /dev/null +++ b/resource/csdk/arduinomega.properties @@ -0,0 +1,56 @@ + +#Source directories +SDIR_ARD_CORE = $(ARDUINO_DIR)/hardware/arduino/cores/arduino +SDIR_ARD_SPI = $(ARDUINO_DIR)/libraries/SPI +SDIR_ARD_ETH = $(ARDUINO_DIR)/libraries/Ethernet +SDIR_ARD_ETH_UTIL = $(ARDUINO_DIR)/libraries/Ethernet/utility +SDIR_ARD_WIFI = $(ARDUINO_DIR)/libraries/WiFi +SDIR_ARD_WIFI_UTIL = $(ARDUINO_DIR)/libraries/WiFi/utility +SDIR_ARD_TIME = $(ARDUINO_DIR)/libraries/Time/Time +SDIR_ARD_PLATFORM = $(SDIR_ARD_CORE):$(SDIR_ARD_SPI):$(SDIR_ARD_TIME) + +#include directories +INCD_ARD_CORE = -I$(ARDUINO_DIR)/hardware/arduino/cores/arduino +INCD_ARD_VARIANT = -I$(ARDUINO_DIR)/hardware/arduino/variants/mega +INCD_ARD_SPI = -I$(ARDUINO_DIR)/libraries/SPI +INCD_ARD_ETH = -I$(ARDUINO_DIR)/libraries/Ethernet +INCD_ARD_ETH_UTIL = -I$(ARDUINO_DIR)/libraries/Ethernet/utility +INCD_ARD_WIFI = -I$(ARDUINO_DIR)/libraries/WiFi +INCD_ARD_WIFI_UTIL = -I$(ARDUINO_DIR)/libraries/WiFi/utility +INCD_ARD_TIME = -I$(ARDUINO_DIR)/libraries/Time/Time + +INC_DIR_PLATFORM = $(INCD_ARD_CORE) $(INCD_ARD_VARIANT) $(INCD_ARD_SPI) $(INCD_ARD_TIME) + +#Compiler/Linker flags +CFLAGS_PLATFORM = -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=156 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR -DWITH_ARDUINO \ + -MMD -std=c++0x -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions -felide-constructors -DATMEGA2560 -DNDEBUG + +#Compilers +CXX=$(ARDUINO_TOOLS_DIR)/avr-g++ +CC=$(ARDUINO_TOOLS_DIR)/avr-gcc +AR=$(ARDUINO_TOOLS_DIR)/avr-ar +RANLIB=$(ARDUINO_TOOLS_DIR)/avr-ranlib +AVR_OBJCOPY=$(ARDUINO_TOOLS_DIR)/avr-objcopy +AVR_PROGRAMMER=$(ARDUINO_TOOLS_DIR)/../../avrdude + +#Needed object files +CORE_COBJ = WInterrupts.o wiring.o wiring_digital.o +CORE_CPPOBJ = main.o Stream.o WMath.o WString.o HardwareSerial.o Print.o SPI.o IPAddress.o +ETH_CPPOBJ = Dhcp.o Dns.o Ethernet.o EthernetUdp.o +ETH_UTIL_CPPOBJ = socket.o w5100.o +WIFI_COBJ = WiFi.o WiFiClient.o WiFiServer.o WiFiUdp.o server_drv.o spi_drv.o wifi_drv.o +OCDEPENDENT_CPPOBJ = wiring_analog.o + +PLATFORM_OBJS = $(CORE_COBJ) $(CORE_CPPOBJ) $(OCDEPENDENT_CPPOBJ) + +#Include sources/objects corresponding to WiFi or Ethernet shield +ifeq ($(ARDUINOWIFI),1) + INC_DIR_PLATFORM += $(INCD_ARD_WIFI) $(INCD_ARD_WIFI_UTIL) + SDIR_ARD_PLATFORM += :$(SDIR_ARD_WIFI):$(SDIR_ARD_WIFI_UTIL) + PLATFORM_OBJS += $(WIFI_COBJ) +else + INC_DIR_PLATFORM += $(INCD_ARD_ETH) $(INCD_ARD_ETH_UTIL) + SDIR_ARD_PLATFORM += :$(SDIR_ARD_ETH):$(SDIR_ARD_ETH_UTIL) + PLATFORM_OBJS += $(ETH_CPPOBJ) $(ETH_UTIL_CPPOBJ) +endif + diff --git a/resource/csdk/connectivity/RELEASE v0.1 b/resource/csdk/connectivity/RELEASE v0.1 new file mode 100644 index 000000000..c1f3f2709 --- /dev/null +++ b/resource/csdk/connectivity/RELEASE v0.1 @@ -0,0 +1,69 @@ +Project Name: IoTivity +Release Version No. / Label Name: CA_v0.1 +API Version: CA_v0.4 + +Release Description: +Connectivity Abstraction provides a unified approach to send different OIC messages across multiple transports. + +Scope of Release: +1. Supported APIs ( please check below APIs) +2. Samples to test Supported APIs. +3. OIC Coding guidelines followed based on the current CSDK source. +4. Multi-Threaded Connectivity abstraction +5. Executed Open Source Verification and Prevent analysis. + +The following Connectivity Abstraction API features are supported in this release: + +Supported APIs +CAInitialize() +CATerminate() +CAStartListeningServer() +CAStartDiscoveryServer() +CARegisterHandler() +CAhandleRequestResponse() +FindResource() +SendRequest() +SendResponse() +SelectNetwork() +UnselectNetwork() + +Non Supported APIs +SendNotification() +AdvertizeResource() +CAGenerateToken() +CADestryToken() +CAGetNetworkInfo() + +Type of Release: Source, +Platform OS: Ubuntu 12.0.4 and above: + +Connectivity: WIFI only +Preconditions: +1)gcc 4.6.3 and above. +2)glib library (sudo apt-get install libglib2.0-dev) +3)libcoap.a library ( do make @lib/libcoap-4.1.1) + +Known and Open Issues: +1) OIC Log, OIC malloc will be removed once name changes applied to OIC Bases code +2) Support only WIFI Interface. +3) URI length is 16 characters. + +Nature of Release: Partial + +How to Build: +Follow below steps to execute CA Client / server in different systems +Step 1: Build Libcoap library +Make File Location @connectivity\lib\libcoap-4.1.1 +Step 2: Build CA library +Make File Location @connectivity\build\linux +Step 3: Samples +Make File Location @connectivity\samples\linux + +NOTE: sample.sh script can be used @connectivity\samples\linux for 3 steps together + +Execution: +linux$ export LD_LIBRARY_PATH=../../build/out/ +linux$ ./out/sample_main + +Client Option : d, f, h Client +Server Option : s, h diff --git a/resource/csdk/connectivity/api/cacommon.h b/resource/csdk/connectivity/api/cacommon.h new file mode 100644 index 000000000..7e4cda167 --- /dev/null +++ b/resource/csdk/connectivity/api/cacommon.h @@ -0,0 +1,265 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +/** + * @file cacommon.h + * @brief This file contains the common data structures between Resource , CA and adapters + */ +#ifndef __CA_COMMON_H_ +#define __CA_COMMON_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + @brief IP Address Length + */ +#define CA_IPADDR_SIZE 16 + +/** + @brief Mac Address Length for BT + */ +#define CA_MACADDR_SIZE 18 + +/** + @brief Max Header Options data length + */ +#define CA_MAX_HEADER_OPTION_DATA_LENGTH 16 + +/** + @brief CAPayload_t + */ +typedef char* CAPayload_t; + +/** + @brief CAURI_t + */ +typedef char* CAURI_t; + +/** + @brief CAToken_t + */ +typedef char* CAToken_t; + +/** + @brief CABool_t + */ +typedef enum +{ + CA_FALSE = 0, CA_TRUE +} CABool_t; + +/** + @brief CAConnectivityType_t + */ +typedef enum +{ + CA_ETHERNET = (1 << 0), CA_WIFI = (1 << 1), CA_EDR = (1 << 2), CA_LE = (1 << 3) +} CAConnectivityType_t; + +/** + @brief CANetworkStatus_t + */ +typedef enum +{ + CA_INTERFACE_UP, CA_INTERFACE_DOWN +} CANetworkStatus_t; + +/** + @brief Address of the local or remote endpoint + */ +typedef union +{ + /** + @brief BT Information + */ + struct + { + /** @brief Bluettoth Mac Address **/ + char btMacAddress[CA_MACADDR_SIZE]; + } BT; + /** + @brief IP Information + */ + struct + { + /** Ip address of the interface**/ + char ipAddress[CA_IPADDR_SIZE]; + /** port information**/ + uint32_t port; + } IP; +} CAAddress_t; + +/** + @brief CAQualityOfService + */ +typedef enum +{ + CA_LOW_QOS = 0, CA_MEDIUM_QOS, CA_HIGH_QOS, CA_NA_QOS // No Quality is defined, let the stack decide +} CAQualityOfService_t; + +/** + @brief CAMethod_t + */ +typedef enum +{ + CA_GET = 1, CA_POST, CA_PUT, CA_DELETE +} CAMethod_t; + +/** + @brief RemoteEndpoint information for connectivities + */ +typedef struct +{ + /** Resource URI information **/ + CAURI_t resourceUri; + /** Remote Endpoint address **/ + CAAddress_t addressInfo; + /** Connectivity of the endpoint**/ + CAConnectivityType_t connectivityType; +} CARemoteEndpoint_t; + +/** + @brief Local Connectivity information + */ +typedef struct +{ + /** address of the interface **/ + CAAddress_t addressInfo; + /** Connectivity type that localconnectivity avaialble **/ + CAConnectivityType_t type; +} CALocalConnectivityt_t; + +/** + @brief Enums for CA return values + */ +typedef enum +{ + /* Success status code - START HERE */ + CA_STATUS_OK = 0, + CA_STATUS_INVALID_PARAM, + CA_DESTINATION_NOT_REACHABLE, + CA_SEND_FAILED, + CA_RECEVIE_FAILED, + CA_MEMORY_ALLOC_FAILED, + CA_REQUEST_TIMEOUT, + CA_DESTINATION_DISCONNECTED, + CA_STATUS_FAILED, + CA_NOT_SUPPORTED +/* Error status code - END HERE */ +} CAResult_t; + +/** + @brief Enums for CA Response values + */ +typedef enum +{ + /* Success status code - START HERE */ + CA_CREATED = 201, + CA_DELETED = 202, + CA_VALID = 203, + CA_CONTENT = 205, + CA_BAD_REQ = 400, + CA_BAD_OPT = 402, + CA_NOT_FOUND = 404 +/* Error status code - END HERE */ +} CAResponseResult_t; + +/** + @brief Transport Protocol IDs + */ +typedef enum +{ + CA_INVALID_ID = (1 << 0), CA_COAP_ID = (1 << 1) +} CATransportProtocolID_t; + +/** + * @brief Header options structure to be filled + * + * This structure is used to hold header information. + */ +typedef struct +{ + /** The protocol ID this option applies to**/ + CATransportProtocolID_t protocolID; + /** The header option ID which will be added to communication packets**/ + uint16_t optionID; + /** its length 191**/ + uint16_t optionLength; + /** optional data values**/ + uint8_t optionData[CA_MAX_HEADER_OPTION_DATA_LENGTH]; +} CAHeaderOption_t; + +/** + * @brief Request Information to be sent + * + * This structure is used to hold request information + */ + +/** + * @brief Base Information received + * + * This structure is used to hold request & response base information + */ +typedef struct +{ + /**Qos for the request **/ + CAQualityOfService_t qos; + /** Token for CA**/ + CAToken_t token; + /** Header Options for the request **/ + CAHeaderOption_t * options; + /** Number of Header options**/ + uint8_t numOptions; + /** payload of the request **/ + CAPayload_t payload; +} CAInfo_t; + +typedef struct +{ + /** Name of the Method Allowed **/ + CAMethod_t method; + /** Base Information **/ + CAInfo_t info; +} CARequestInfo_t; + +/** + * @brief Response Information received + * + * This structure is used to hold response information + */ +typedef struct +{ + /**Response Result by Resource Model**/ + CAResponseResult_t result; + /**Base Information **/ + CAInfo_t info; +} CAResponseInfo_t; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif //#ifndef __CA_COMMON_H_ diff --git a/resource/csdk/connectivity/api/cainterface.h b/resource/csdk/connectivity/api/cainterface.h new file mode 100644 index 000000000..8619f92f7 --- /dev/null +++ b/resource/csdk/connectivity/api/cainterface.h @@ -0,0 +1,207 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +/** + * @file cainterface.h + * @brief This file contains the APIs for Resource Model to use + */ + +#ifndef __CA_INTERFACE_H_ +#define __CA_INTERFACE_H_ + +/** + * Connectivity Abstraction Interface Description APIs. + */ +#include "cacommon.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @brief Callback function type for request delivery. + * requestInfo contains different parameters for resource model to understand about the request. + * @param object [OUT] Endpoint object from which the request is received. It contains endpoint + * address based on the connectivity type. + * @param requestInfo [OUT] Identifier which needs to be sent with request. + */ +typedef void (*CARequestCallback)(CARemoteEndpoint_t* object, CARequestInfo_t* requestInfo); + +/** + * @brief Callback function type for response delivery. + * responseInfor contains different parameters for resource model to understand about the request. + * @param object [OUT] Endpoint object from which the response is received. + * @param responseInfo [OUT] Identifier which needs to be mapped with response. + */ +typedef void (*CAResponseCallback)(CARemoteEndpoint_t* object, CAResponseInfo_t* responseInfo); + +/** + * @brief Initialize the connectivity abstraction module. + * It will initialize adapters, thread pool and other modules based on the platform compilation options. + * + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAInitialize(); + +/** + * @brief Terminate the connectivity abstraction module. + * All threads, data structures are destroyed for next initializations. + */ +void CATerminate(); + +/** + * @brief Starts listening servers. + * This API is used by resource hosting server for listening multicast requests. + * based on the adapters configurations , different kinds of servers are started. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStartListeningServer(); + +/** + * @brief Starts discovery servers. + * This API is used by resource required clients for listening multicast requests. + * based on the adapters configurations , different kinds of servers are started. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStartDiscoveryServer(); + +/** + * @brief Register request callbacks and response callbacks. + * requests and responses are delivered these callbacks . + * @see CARequestCallback CAResponseCallback + * @param ReqHandler [IN] Request callback ( for GET,PUT ..etc) + * @param RespHandler [IN] Response Handler Callback + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CARegisterHandler(CARequestCallback ReqHandler, CAResponseCallback RespHandler); + +/** + * @brief Create a Remote endpoint if the URI is available already. + * for FindResource-> unicast requests , this API is used. + * FindResource(URI)-> CACreateRemoteEndpoint , CASendRequest(GET) + * @param uri [IN] Absolute URI of the resource to be used to generate the Remote endpoint + * for ex : coap://10.11.12.13:4545/resource_uri ( for IP) + * coap://10:11:12:13:45:45/resource_uri ( for BT) + * @param object [OUT ] Endpoint object which contains the above parsed data + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CACreateRemoteEndpoint(const CAURI_t uri, CARemoteEndpoint_t** object); + +/** + * @brief API Destroy the remote endpoint created + * @param object [IN] endpoint object created with CACreateRemoteEndpoint + */ +void CADestroyRemoteEndpoint(CARemoteEndpoint_t* object); + +/** + * @brief Generating the token for the requests/response. + * Token memory is created and destroyed by the calle. + * @param token [OUT] token for the request + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAGenerateToken(CAToken_t* token); + +/** + * @brief Destroy the token generated by CAGenerateToken + * @param token [IN] token for the request + */ +void CADestroyToken(CAToken_t token); + +/** + * @brief Find the resource in the network. This API internally sends multicast messages on the + * all connectivity adapters. Responses are delivered via response callbacks. + * + * @param resourceUri [IN] Uri to send multicast search request + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAFindResource(const CAURI_t resourceUri); + +/** + * @brief Send control Request on a resource + * @param object [IN] Remote Endpoint where the payload need to be sent. + * This Remote endpoint is delivered with Request or response callback. + * @param requestInfo [IN ] information for the request. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CASendRequest(const CARemoteEndpoint_t* object, CARequestInfo_t* requestInfo); + +/** + * @brief Sendi the response + * @param object [IN] Remote Endpoint where the payload need to be sent. + * This Remote endpoint is delivered with Request or response callback + * @param responseInfo [IN ] information for the response + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CASendResponse(const CARemoteEndpoint_t* object, CAResponseInfo_t* responseInfo); + +/** + * @brief Send notification to the remote object + * @param object [IN] Remote Endpoint where the payload need to be sent. + * This Remote endpoint is delivered with Request or response callback. + * @param responseInfo [IN ] information for the response. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CASendNotification(const CARemoteEndpoint_t* object, CAResponseInfo_t* responseInfo); + +/** + * @brief for advertise the resource + * @param resourceUri [IN] URI to be advertised + * @param options [IN] header options information + * @param numOptions [IN] number of options + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAAdvertiseResource(const CAURI_t resourceUri, CAHeaderOption_t* options, + uint8_t numOptions); + +/** + * @brief Select network to use + * @param interestedNetwork [IN] Connectivity Type enum + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CASelectNetwork(const uint32_t interestedNetwork); + +/** + * @brief Select network to unuse + * @param nonInterestedNetwork [IN] Connectivity Type enum + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAUnSelectNetwork(const uint32_t nonInterestedNetwork); + +/** + * @brief Get network information + * It should be destroyed by the caller as its Get Information. + * @param info [OUT] LocalConnectivity objects + * @param size [OUT] No Of Array objects + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAGetNetworkInformation(CALocalConnectivityt_t **info, uint32_t* size); + +/** + * @brief for usage of singled threaded application. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAHandleRequestResponse(); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/resource/csdk/connectivity/build/linux/Makefile b/resource/csdk/connectivity/build/linux/Makefile new file mode 100644 index 000000000..7fb550ab0 --- /dev/null +++ b/resource/csdk/connectivity/build/linux/Makefile @@ -0,0 +1,161 @@ +#/****************************************************************** +# * +# * Copyright 2014 Samsung Electronics All Rights Reserved. +# * +# * +# * +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# * +#******************************************************************/ + +# override with `make BUILD=debug` +# default to release build +# default to build for linux +BUILD = release +PLATFORM = linux +TRANSPORT = ALL +OBJ_DIR = ./$(BUILD) +VERSION_MAJOR = 0 +VERSION_MINOR = 1 +VERSION_PATCH = 0 + +COMMON_MAKE = common.mk + +include $(COMMON_MAKE) + +#Modify below values to enable/disable the Adapter +#Suffix "NO_" to disable given adapter +EDR = NO_EDR_ADAPTER +WIFI = WIFI_ADAPTER +LE = NO_LE_ADAPTER +ETHERNET = NO_ETHERNET_ADAPTER + +#Add Pre processor definitions +DEFINE_FLAG = -D$(EDR) -D$(LE) -D$(WIFI) -D$(ETHERNET) + +#Add Debug flags here +DEBUG_FLAG = -DTB_LOG + +## +## definitions +## +LIB_PREFIX = CA +ETHERNET_ADAPTER = ethernet_adapter +WIFI_ADAPTER = wifi_adapter +BT_ADAPTER = bt_edr_adapter +BLE_ADAPTER = bt_le_adapter +ETHERNET_ADAPTER_PATH = $(PROJECT_SRC_PATH)/$(ETHERNET_ADAPTER)/$(PLATFORM) +WIFI_ADAPTER_PATH = $(PROJECT_SRC_PATH)/$(WIFI_ADAPTER)/$(PLATFORM) +BT_ADAPTER_PATH = $(PROJECT_SRC_PATH)/$(BT_ADAPTER)/$(PLATFORM) +BLE_ADAPTER_PATH = $(PROJECT_SRC_PATH)/$(BLE_ADAPTER)/$(PLATFORM) +TARGET = lib$(PROJECT_NAME).so.$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH) +TARGET_ALIAS = lib$(PROJECT_NAME).so + +## +## libcoap +## +libcoap_build_dir = $(PROJECT_LIB_PATH)/libcoap-4.1.1 + +LDFLAGS:=-L$(libcoap_build_dir) +LDLIBS:=-lcoap + +BUILD_FLAG.debug = $(DEFINE_FLAG) $(DEBUG_FLAG) +BUILD_FLAG.release = $(DEFINE_FLAG) +BUILD_FLAG = $(BUILD_FLAG.$(BUILD)) + +DEBUG_DIR = ./debug +RELEASE_DIR = ./release + +## +## file declaration +## +COMPONENT_SRCS = \ +logger.c oic_malloc.c oic_logger.c oic_console_logger.c \ +caconnectivitymanager.c caremotehandler.c cainterfacecontroller.c camessagehandler.c \ +canetworkconfigurator.c caedradapter.c caleadapter.c \ +caethernetadapter.c cawifiadapter.c \ +caprotocolmessage.c cawificore.c \ +uqueue.c uarraylist.c umutex.c uthreadpool.c \ + +COMPONENT_OBJS = $(COMPONENT_SRCS:%.c=$(OBJ_DIR)/%.o) + +## +## compiler flags +## +CFLAGS = -g -c -Wall -fPIC `pkg-config --cflags glib-2.0` + +LFLAGS = -ldl -lpthread `pkg-config --libs glib-2.0` + +IFLAGS = -I$(PROJECT_COMMON_INC_PATH) \ + -I$(PROJECT_API_PATH) \ + -I$(PROJECT_INC_PATH) \ + -I$(ETHERNET_ADAPTER_PATH) \ + -I$(WIFI_ADAPTER_PATH) \ + -I$(BT_ADAPTER_PATH) \ + -I$(BLE_ADAPTER_PATH) \ + -I$(libcoap_build_dir) + +DFLAGS = -DLINUX \ + -DWITH_POSIX \ + $(BUILD_FLAG)\ +## +## compile and link rules +## +vpath %.c $(PROJECT_COMMON_SRC_PATH) +vpath %.c $(ETHERNET_ADAPTER_PATH) +vpath %.c $(WIFI_ADAPTER_PATH) +vpath %.c $(BT_ADAPTER_PATH) +vpath %.c $(BLE_ADAPTER_PATH) +vpath %.c $(PROJECT_SRC_PATH) + +$(OBJ_DIR)/%.o: %.c + @$(MAKE_OBJ_PATH) + @$(CC) -o $@ $(CFLAGS) $(DFLAGS) $(IFLAGS) $< + +all : $(TARGET) + @echo " " + @echo "======================" + @echo " Success!!" + @echo "======================" + +$(TARGET) : $(COMPONENT_OBJS) + @$(MAKE_PROJECT_OUT_PATH) + @$(CC) -shared -Wl,-soname,$(TARGET) -o $@ $(COMPONENT_OBJS) $(LFLAGS) $(LDFLAGS) $(LDLIBS) + @$(MV) $(TARGET) $(PROJECT_OUT_PATH)/. + @$(CD) $(PROJECT_OUT_PATH); $(MAKE_TARGET_ALIAS) + +clean : + @$(RM) $(DEBUG_DIR) $(RELEASE_DIR)\ + $(PROJECT_OUT_PATH) + +install : + @$(MAKE_PROJECT_OUT_PATH) + +## +## macros +## +define MAKE_OBJ_PATH + @if [ ! -d $(OBJ_DIR) ]; then \ + mkdir $(OBJ_DIR); \ + fi +endef + +define MAKE_TARGET_ALIAS + if [ ! -f $(TARGET_ALIAS) ]; then \ + $(LN) -s $(TARGET) $(TARGET_ALIAS); \ + fi +endef + +.PHONY: all clean install + + diff --git a/resource/csdk/connectivity/build/linux/common.mk b/resource/csdk/connectivity/build/linux/common.mk new file mode 100644 index 000000000..fe665854b --- /dev/null +++ b/resource/csdk/connectivity/build/linux/common.mk @@ -0,0 +1,59 @@ +#/****************************************************************** +# * +# * Copyright 2014 Samsung Electronics All Rights Reserved. +# * +# * +# * +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# * +#******************************************************************/ + +## +## Definitions +## +SHELL = /bin/bash +PROJECT_NAME = connectivity_abstraction +PROJECT_ROOT_PATH = ../.. +PROJECT_API_PATH = $(PROJECT_ROOT_PATH)/api +PROJECT_INC_PATH = $(PROJECT_ROOT_PATH)/inc +PROJECT_SRC_PATH = $(PROJECT_ROOT_PATH)/src +PROJECT_COMMON_INC_PATH = $(PROJECT_ROOT_PATH)/common/inc +PROJECT_COMMON_SRC_PATH = $(PROJECT_ROOT_PATH)/common/src +PROJECT_COMMON_PATH = $(PROJECT_ROOT_PATH)/common +PROJECT_OUT_PATH = $(PROJECT_ROOT_PATH)/build/out +PROJECT_LIB_PATH = $(PROJECT_ROOT_PATH)/lib + +## +## macro +## +define MAKE_PROJECT_OUT_PATH + @if [ ! -d $(PROJECT_OUT_PATH) ]; then \ + mkdir $(PROJECT_OUT_PATH); \ + fi +endef + + +## +## Commands +## +CC = gcc +CXX = g++ +RM = rm -rf +CP = cp +MV = mv +AR = ar +LD = ld +LN = ln +CD = cd +RANLIB = ranlib + diff --git a/resource/csdk/connectivity/common/inc/logger.h b/resource/csdk/connectivity/common/inc/logger.h new file mode 100644 index 000000000..b19b03703 --- /dev/null +++ b/resource/csdk/connectivity/common/inc/logger.h @@ -0,0 +1,178 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef _U_LOGGER_H_ +#define _U_LOGGER_H_ + +#include +#include +#include +#include "oic_logger.h" +#include "oic_console_logger.h" + +#ifdef __ANDROID__ +#include +#elif defined ARDUINO +#include "Arduino.h" +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +// Use the PCF macro to wrap strings stored in FLASH on the Arduino +// Example: OC_LOG(INFO, TAG, PCF("Entering function")); +#ifdef ARDUINO +#define PCF(str) ((PROGMEM const char *)(F(str))) +#else +#define PCF(str) str +#endif + +// Max buffer size used in variable argument log function +#define MAX_LOG_V_BUFFER_SIZE (256) + +// Log levels +typedef enum +{ + DEBUG = 0, INFO, WARNING, ERROR, FATAL +} LogLevel; + +#ifndef ARDUINO + +/** + * Configure logger to use a context that defines a custom logger function + * + * @param ctx - pointer to oc_log_ctx_t struct that defines custom logging functions + */ +void OICLogConfig(oic_log_ctx_t *ctx); + +/** + * Initialize the logger. Optional on Android and Linux. Configures serial port on Arduino + */ +void OICLogInit(); + +/** + * Called to Free dyamically allocated resources used with custom logging. + * Not necessary if default logging is used + * + */ +void OICLogShutdown(); + +/** + * Output a log string with the specified priority level. + * Only defined for Linux and Android + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param logStr - log string + */ +void OICLog(LogLevel level, const char * tag, const char * logStr); + +/** + * Output a variable argument list log string with the specified priority level. + * Only defined for Linux and Android + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param format - variadic log string + */ +void OICLogv(LogLevel level, const char * tag, const char * format, ...); + +/** + * Output the contents of the specified buffer (in hex) with the specified priority level. + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param buffer - pointer to buffer of bytes + * @param bufferSize - max number of byte in buffer + */ +void OICLogBuffer(LogLevel level, const char * tag, const uint8_t * buffer, uint16_t bufferSize); +#else +/** + * Initialize the serial logger for Arduino + * Only defined for Arduino + */ +void OICLogInit(); + +/** + * Output a log string with the specified priority level. + * Only defined for Arduino. Uses PROGMEM strings + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param logStr - log string + */ +void OICLog(LogLevel level, PROGMEM const char * tag, PROGMEM const char * logStr); + +/** + * Output the contents of the specified buffer (in hex) with the specified priority level. + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param buffer - pointer to buffer of bytes + * @param bufferSize - max number of byte in buffer + */ +void OICLogBuffer(LogLevel level, PROGMEM const char * tag, const uint8_t * buffer, uint16_t bufferSize); + +/** + * Output a variable argument list log string with the specified priority level. + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param format - variadic log string + */ +void OICLogv(LogLevel level, const char * tag, const char * format, ...); +#endif + +#ifdef TB_LOG +// These macros are defined for Linux, Android, and Arduino +#define OIC_LOG_INIT() OICLogInit() +#define OIC_LOG(level, tag, logStr) OICLog((level), (tag), (logStr)) +#define OIC_LOG_BUFFER(level, tag, buffer, bufferSize) OICLogBuffer((level), (tag), (buffer), (bufferSize)) + +#ifdef ARDUINO +#define OIC_LOG_CONFIG(ctx) +#define OIC_LOG_SHUTDOWN() +// Use full namespace for logInit to avoid function name collision +#define OIC_LOG_INIT() OICLogInit() +// Don't define variable argument log function for Arduino +#define OIC_LOG_V(level, tag, ...) OICLogv((level), (tag), __VA_ARGS__) +#else +#define OIC_LOG_CONFIG(ctx) OICLogConfig((ctx)) +#define OIC_LOG_SHUTDOWN() OICLogShutdown() +// Define variable argument log function for Linux and Android +#define OIC_LOG_V(level, tag, ...) OICLogv((level), (tag), __VA_ARGS__) +#endif + +#else +#define OIC_LOG_CONFIG(ctx) +#define OIC_LOG_SHUTDOWN() +#define OIC_LOG(level, tag, logStr) +#define OIC_LOG_V(level, tag, ...) +#define OIC_LOG_BUFFER(level, tag, buffer, bufferSize) +#define OIC_LOG_INIT() +#endif + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif /* _U_LOGGER_H_ */ diff --git a/resource/csdk/connectivity/common/inc/oic_console_logger.h b/resource/csdk/connectivity/common/inc/oic_console_logger.h new file mode 100644 index 000000000..6ff5894ec --- /dev/null +++ b/resource/csdk/connectivity/common/inc/oic_console_logger.h @@ -0,0 +1,44 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef __OIC_CONSOLE_LOGGER_ +#define __OIC_CONSOLE_LOGGER_ + +#include "oic_logger_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +oic_log_ctx_t *oic_make_console_logger(); + +int oic_console_logger_init(oic_log_ctx_t *ctx, void *world); +void oic_console_logger_destroy(oic_log_ctx_t *ctx); +void oic_console_logger_flush(oic_log_ctx_t *ctx); +void oic_console_logger_set_level(oic_log_ctx_t *ctx, const int level); +size_t oic_console_logger_write(oic_log_ctx_t *ctx, const int level, const char *msg); +int oic_console_logger_set_module(oic_log_ctx_t *ctx, const char *module_name); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/resource/csdk/connectivity/common/inc/oic_logger.h b/resource/csdk/connectivity/common/inc/oic_logger.h new file mode 100644 index 000000000..df738c23e --- /dev/null +++ b/resource/csdk/connectivity/common/inc/oic_logger.h @@ -0,0 +1,48 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef __OIC_LOGGER_H_ +#define __OIC_LOGGER_H_ + +#include "oic_logger_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Basic interface: */ +oic_log_ctx_t *oic_log_make_ctx(void* world, const oic_log_level level, oic_log_init_t init, + oic_log_destroy_t destroy, oic_log_flush_t flush, oic_log_set_level_t set_level, + oic_log_write_level_t write_level, oic_log_set_module_t set_module); + +void oic_log_destroy(oic_log_ctx_t *ctx); + +void oic_log_flush(oic_log_ctx_t *ctx); +void oic_log_set_level(oic_log_ctx_t *ctx, const oic_log_level ll); +size_t oic_log_write(oic_log_ctx_t *ctx, const char *msg); +size_t oic_log_write_level(oic_log_ctx_t *ctx, const oic_log_level ll, const char *msg); +int oic_log_set_module(oic_log_ctx_t *ctx, const char *module_name); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/resource/csdk/connectivity/common/inc/oic_logger_types.h b/resource/csdk/connectivity/common/inc/oic_logger_types.h new file mode 100644 index 000000000..f372a4ced --- /dev/null +++ b/resource/csdk/connectivity/common/inc/oic_logger_types.h @@ -0,0 +1,86 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef __OIC_LOGGER_TYPES_H_ +#define __OIC_LOGGER_TYPES_H_ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef enum +{ + __OIC_LOG_MIN__ = -1, + OIC_LOG_ALL = 0, + OIC_LOG_FATAL, + OIC_LOG_ERROR, + OIC_LOG_WARNING, + OIC_LOG_INFO, + OIC_LOG_DEBUG, + OIC_LOG_DISABLED, + __OIC_LOG_MAX__ +} oic_log_level; + +typedef struct _oic_log_ctx +{ + void* ctx; + + oic_log_level log_level; + + char* module_name; + + /* Required interface: */ + int (*init)(struct _oic_log_ctx *, void *); + void (*destroy)(struct _oic_log_ctx *); + void (*flush)(struct _oic_log_ctx *); + void (*set_level)(struct _oic_log_ctx *, const int); + size_t (*write_level)(struct _oic_log_ctx *, const int, const char *); + int (*set_module)(struct _oic_log_ctx *, const char *); + + /* Optional interface (if one is implemented, all must be implemented): */ + int (*lock)(struct _oic_log_ctx *); + int (*unlock)(struct _oic_log_ctx *); + int (*try_lock)(struct _oic_log_ctx *); + int (*locked_destroy)(struct _oic_log_ctx *); + +} oic_log_ctx_t; + +/* Notice that these are all passed the /top level/ ctx-- it's "public" with respect to + these functions, they have full access to fiddle with the structure all they want (but, + generally should avoid doing that); I could certainly be convinced to go the other direction, + and have most functions only take the inner context: */ +typedef int (*oic_log_init_t)(oic_log_ctx_t *, void *); +typedef void (*oic_log_destroy_t)(oic_log_ctx_t *); +typedef void (*oic_log_flush_t)(oic_log_ctx_t *); +typedef void (*oic_log_set_level_t)(oic_log_ctx_t *, const int); +typedef size_t (*oic_log_write_level_t)(oic_log_ctx_t *, const int, const char *); +typedef int (*oic_log_set_module_t)(oic_log_ctx_t *, const char *); +typedef int (*oic_log_lock_t)(oic_log_ctx_t *); +typedef int (*oic_log_unlock_t)(oic_log_ctx_t *); +typedef int (*oic_log_try_lock_t)(oic_log_ctx_t *); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/resource/csdk/connectivity/common/inc/oic_malloc.h b/resource/csdk/connectivity/common/inc/oic_malloc.h new file mode 100644 index 000000000..ae06f14f0 --- /dev/null +++ b/resource/csdk/connectivity/common/inc/oic_malloc.h @@ -0,0 +1,84 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef _OIC_MALLOC_H_ +#define _OIC_MALLOC_H_ + +// The purpose of this module is to allow custom dynamic memory allocation +// code to easily be added to the TB Stack by redefining the OICMalloc and +// OICFree functions. Examples of when this might be needed are on TB +// platforms that do not support dynamic allocation or if a memory pool +// needs to be added. +// +// Note that these functions are intended to be used ONLY within the TB +// stack and NOT by the application code. The application should be +// responsible for its own dynamic allocation. + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus +//----------------------------------------------------------------------------- +// Defines +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Typedefs +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Function prototypes +//----------------------------------------------------------------------------- + +/** + * Allocates a block of size bytes, returning a pointer to the beginning of + * the allocated block. + * + * NOTE: This function is intended to be used internally by the TB Stack. + * It is not intended to be used by applications. + * + * @param size - Size of the memory block in bytes, where size > 0 + * + * @return + * on success, a pointer to the allocated memory block + * on failure, a null pointer is returned + */ +void *OICMalloc(size_t size); + +/** + * Deallocate a block of memory previously allocated by a call to OCMalloc + * + * NOTE: This function is intended to be used internally by the TB Stack. + * It is not intended to be used by applications. + * + * @param ptr - Pointer to block of memory previously allocated by OCMalloc. + * If ptr is a null pointer, the function does nothing. + */ +void OICFree(void *ptr); + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif /* _OIC_MALLOC_H_ */ diff --git a/resource/csdk/connectivity/common/inc/uarraylist.h b/resource/csdk/connectivity/common/inc/uarraylist.h new file mode 100644 index 000000000..b26734e22 --- /dev/null +++ b/resource/csdk/connectivity/common/inc/uarraylist.h @@ -0,0 +1,116 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +#ifndef __U_ARRAYLIST_H_ +#define __U_ARRAYLIST_H_ + +#include +#include "cacommon.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * Use this default size when initialized + */ +#define U_ARRAYLIST_DEFAULT_SIZE 1 + +/** + * @struct u_arraylist_t + * @brief array list structure + */ +typedef struct u_arraylist_t +{ + void **data; + uint32_t length; + uint32_t size; +} u_arraylist_t; + +/** + * @brief API to creates array list and initializes the elements. + * @return u_arraylist_t if Success, NULL otherwise + */ +u_arraylist_t* u_arraylist_create(); + +/** + * @brief Resets and deletes the array list + * application should free the memory of data in array list + * @param u_arraylist_t- u_arraylist pointer + * @return CAResult_t + * CA_STATUS_OK if Success, CA_STATUS_FAILED otherwise + */ +CAResult_t u_arraylist_free(u_arraylist_t *list); + +/** + * @brief Returns the data of the index from the array list + * @param u_arraylist + * [IN] pointer of array list + * @param index + * [IN] index of array list + * @return void pointer of the data + */ +void* u_arraylist_get(const u_arraylist_t *list, uint32_t index); + +/** + * @brief Add data in the array list + * @param u_arraylist + * [IN] pointer of array list + * @param data + * [IN] pointer of data + * @return CAResult_t + * CA_STATUS_OK if Success, CA_STATUS_FAILED otherwise + */ +CAResult_t u_arraylist_add(u_arraylist_t *list, void *data); + +/** + * @brief Remove the data of the index from the array list + * @param u_arraylist + * [IN] pointer of array list + * @param index + * [IN] index of array list + * @return void pointer of the data + */ +void* u_arraylist_remove(u_arraylist_t *list, uint32_t index); + +/** + * @brief Returns the length of the array list + * @param u_arraylist + * [IN] pointer of array list + * @return length of the array list + */ +uint32_t u_arraylist_length(const u_arraylist_t *list); + +/** + * @brief Returns whether the data exists or not + * @param u_arraylist + * [IN] pointer of array list + * @param data + * [IN] pointer of data + * @return 1 if exists, 0 otherwise + */ +uint8_t u_arraylist_contains(const u_arraylist_t *list, void *data); + +#ifdef __cplusplus +} +#endif + +#endif /* _U_ARRAYLIST_H_ */ diff --git a/resource/csdk/connectivity/common/inc/umutex.h b/resource/csdk/connectivity/common/inc/umutex.h new file mode 100644 index 000000000..30f833602 --- /dev/null +++ b/resource/csdk/connectivity/common/inc/umutex.h @@ -0,0 +1,143 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ +/** + * @file umutex.h + * @brief This file provides APIs related to mutex and semaphores + */ + +#ifndef __UMUTEX_H_ +#define __UMUTEX_H_ + +#include "cacommon.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +typedef void *u_mutex; +typedef void *u_cond; + +/** + * @fn u_mutex_init + * @brief Initializes the thread system for using other mutex related APIs + * + */ +void u_mutex_init(void); + +/** + * @fn u_mutex_new + * @brief Creates new mutex + * + * @return Reference to newly created mutex, otherwise NULL. + * + * @see u_mutex_Init + */ +u_mutex u_mutex_new(void); + +/** + * @fn u_mutex_lock + * @brief Lock the mutex + * + * @param mutex The mutex to be locked + * + */ +void u_mutex_lock(u_mutex mutex); + +/** + * @fn u_mutex_trylock + * @brief Checks if the mutex can be locked + * + * @param mutex The mutex to be locked + * + * @return CA_TRUE if the mutex is not locked currently, otherwise CA_FALSE. + * + */ +CABool_t u_mutex_trylock(u_mutex mutex); + +/** + * @fn u_mutex_unlock + * @brief Unlock the mutex + * + * @param mutex The mutex to be unlocked + * + */ +void u_mutex_unlock(u_mutex mutex); + +/** + * @fn u_mutex_free + * @brief Free the mutex + * + * @param mutex The mutex to be freed + * + */ +void u_mutex_free(u_mutex mutex); + +/** + * @fn u_cond_new + * @brief Creates new condition + * + * @return Reference to newly created @u_cond, otherwise NULL. + * + * @see u_mutex_Init + */ +u_cond u_cond_new(void); + +/** + * @fn u_cond_signal + * @brief One of threads is woken up if multiple threads are waiting for @cond + * + * @param cond The condtion to be signaled + * + */ +void u_cond_signal(u_cond cond); + +/** + * @fn u_cond_broadcast + * @brief All of threads are woken up if multiple threads are waiting for @cond + * + * @param cond The condtion to be signaled + * + */ +void u_cond_broadcast(u_cond cond); + +/** + * @fn u_cond_wait + * @brief Waits untill this thread woken up on @cond + * + * @param cond The condtion to be wait for to signal + * @param mutex The mutex which is currently locked from calling thread + * + */ +void u_cond_wait(u_cond cond, u_mutex mutex); + +/** + * @fn u_cond_free + * @brief Free the condition + * + * @param mutex The condition to be freed + * + */ +void u_cond_free(u_cond cond); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif //__UMUTEX_H_ diff --git a/resource/csdk/connectivity/common/inc/uqueue.h b/resource/csdk/connectivity/common/inc/uqueue.h new file mode 100644 index 000000000..b40be81a0 --- /dev/null +++ b/resource/csdk/connectivity/common/inc/uqueue.h @@ -0,0 +1,147 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +/** + * @file uqueue.h + * @brief This file contains the APIs for queue to be implemented + */ +#ifndef __U_QUEUE_H_ +#define __U_QUEUE_H_ + +#include "cacommon.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** + * @struct u_queue_message + * @brief Queue message format + */ +typedef struct u_queue_message_t +{ + /* Pointer to message*/ + void *msg; + /* message size */ + uint32_t size; +} u_queue_message_t; + +typedef struct u_queue_element_t u_queue_element; + +/** + * @struct u_queue_element + * @brief Queue element format + */ +struct u_queue_element_t +{ + /* pointer to queue message */ + u_queue_message_t* message; + /* Pointer to next queue element*/ + u_queue_element* next; +}; + +/** + * @struct u_queue_t + * @brief Queue structure + */ +typedef struct u_queue_t +{ + /* Head of the queue */ + u_queue_element* element; + /* Number of messages in Queue*/ + uint32_t count; +} u_queue_t; + +/** + * @brief API to creates queue and initializes the elements. + * @return u_queue_t pointer if Success, NULL otherwise + */ +u_queue_t* u_queue_create(); + +/** + * @fn u_queue_delete + * @brief Resets and deletes the queue + * @param queue- queue pointer + * @return CAResult_t - CA_STATUS_OK, if Success + * @return CA_STATUS_FAILED - otherwise + */ +CAResult_t u_queue_delete(u_queue_t* queue); + +/** + * @fn u_queue_add_element + * @brief Adds message at the end of the queue + * @param queue - pointer to queue + * @param message - Pointer to message + * @return CAResult_t - CA_STATUS_OK, if Success + * @return CA_STATUS_FAILED - otherwise + */ +CAResult_t u_queue_add_element(u_queue_t* queue, u_queue_message_t *message); + +/** + * @fn u_queue_get_element + * @brief Returns the first message in the queue and removes queue element. + * Head is moved to next element. + * @param queue - pointer to queue + * @return pointer to Message, if Success + * @return NULL - otherwise + */ +u_queue_message_t* u_queue_get_element(u_queue_t* queue); + +/** + * @fn u_queueRemoveElement + * @brief Removes head element of the queue + * @param queue - pointer to queue + * @return CAResult_t - CA_STATUS_OK, if Success + * @return CA_STATUS_FAILED - otherwise + */ +CAResult_t u_queue_remove_element(u_queue_t* queue); + +/** + * @fn u_queue_get_size + * Returns number of elements in queue + * Input : queue - pointer to queue + * Return : number of elements in queue + */ +uint32_t u_queue_get_size(u_queue_t* queue); + +/** + * @fn u_queue_reset + * @brief Removes all the messages from Queue and reset message count + * @param queue - pointer to queue + * @return CAResult_t - CA_STATUS_OK, if Success + * @return CA_STATUS_FAILED - otherwise + */ +CAResult_t u_queue_reset(u_queue_t* queue); + +/** + * @fn u_queue_get_head + * @brief Returns the first message in queue, but not remove the element + * @param queue - pointer to queue + * @return pointer to Message, if Success + * @return NULL - otherwise + */ +u_queue_message_t* u_queue_get_head(u_queue_t* queue); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* _U_QUEUE_H_ */ diff --git a/resource/csdk/connectivity/common/inc/uthreadpool.h b/resource/csdk/connectivity/common/inc/uthreadpool.h new file mode 100644 index 000000000..fefb8522a --- /dev/null +++ b/resource/csdk/connectivity/common/inc/uthreadpool.h @@ -0,0 +1,94 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ +/** + * @file uthreadpool.h + * @brief This file provides APIs related to thread pool + */ + +#ifndef __UTHREAD_POOL_H_ +#define __UTHREAD_POOL_H_ + +#include +#include +#include +#include + +#include "cacommon.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** + * @var u_thread_func + * @brief Callback type can be registered to thread pool. + */ +typedef void (*u_thread_func)(void *); + +/** + * @struct u_thread_msg_t + * @brief Structure to maintain the data which needs to send to task function. + */ +typedef struct +{ + void *data; + u_thread_func func; +} u_thread_msg_t; + +/** + * @var u_thread_pool_t + * @brief Thread pool type. + */ +typedef void *u_thread_pool_t; + +/** + * This function creates a newly allocated thread pool. + * + * @param num_of_threads The number of worker thread used in this pool. + * @param thread_pool_handle Handle to newly create thread pool. + * @return Error code, CA_STATUS_OK if success, else error number. + */ +CAResult_t u_thread_pool_init(uint32_t num_of_threads, u_thread_pool_t *thread_pool_handle); + +/** + * This function adds a routine to be executed by the thread pool at some future time. + * + * @param pool The thread pool structure. + * @param routine The routine to be executed. + * @param data The data to be passed to the routine. + * + * @return CA_STATUS_OK on success. + * @return Error on failure. + */ +CAResult_t u_thread_pool_add_task(u_thread_pool_t thread_pool, void (*routine)(void *), void *data); + +/** + * This function stops all the worker threads (stop & exit). And frees all the allocated memory. + * Function will return only after joining all threads executing the currently scheduled tasks. + * + * @param pool The thread pool structure. + */ +void u_thread_pool_free(u_thread_pool_t thread_pool); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* __UTHREAD_POOL_H_ */ diff --git a/resource/csdk/connectivity/common/src/logger.c b/resource/csdk/connectivity/common/src/logger.c new file mode 100644 index 000000000..03b6f8591 --- /dev/null +++ b/resource/csdk/connectivity/common/src/logger.c @@ -0,0 +1,379 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "logger.h" +#include "string.h" +#include "oic_logger.h" +#include "oic_console_logger.h" + +static oic_log_ctx_t *logCtx = 0; + +static oic_log_level LEVEL_XTABLE[] = +{ OIC_LOG_DEBUG, OIC_LOG_INFO, OIC_LOG_WARNING, OIC_LOG_ERROR, OIC_LOG_FATAL }; + +static const uint16_t LINE_BUFFER_SIZE = (16 * 2) + 16 + 1; // Show 16 bytes, 2 chars/byte, spaces between bytes, null termination + +// Convert LogLevel to platform-specific severity level. Store in PROGMEM on Arduino +#ifdef __ANDROID__ +static android_LogPriority LEVEL[] = +{ ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL}; +#elif defined __linux__ +static const char * LEVEL[] __attribute__ ((unused)) = +{ "DEBUG", "INFO", "WARNING", "ERROR", "FATAL"}; +#elif defined ARDUINO +#include + +PROGMEM const char level0[] = "DEBUG"; +PROGMEM const char level1[] = "INFO"; +PROGMEM const char level2[] = "WARNING"; +PROGMEM const char level3[] = "ERROR"; +PROGMEM const char level4[] = "FATAL"; + +PROGMEM const char * const LEVEL[] = +{ level0, level1, level2, level3, level4}; + +static void OICLogString(LogLevel level, PROGMEM const char * tag, PROGMEM const char * logStr); +#ifdef ARDUINO_ARCH_AVR +//Mega2560 and other 8-bit AVR microcontrollers +#define GET_PROGMEM_BUFFER(buffer, addr) { strcpy_P(buffer, (char*)pgm_read_word(addr));} +#elif defined ARDUINO_ARCH_SAM +//Arduino Due and other 32-bit ARM micro-controllers +#define GET_PROGMEM_BUFFER(buffer, addr) { strcpy_P(buffer, (char*)pgm_read_dword(addr));} +#else +#define GET_PROGMEM_BUFFER(buffer, addr) { buffer[0] = '\0';} +#endif +#endif // __ANDROID__ +#ifndef ARDUINO + +void OICLogConfig(oic_log_ctx_t *ctx) +{ + logCtx = ctx; +} + +void OICLogInit() +{ + +} + +void OICLogShutdown() +{ +#ifdef __linux__ + if (logCtx && logCtx->destroy) + { + logCtx->destroy(logCtx); + } +#endif +} + +/** + * Output a log string with the specified priority level. + * Only defined for Linux and Android + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param logStr - log string + */ +void OICLog(LogLevel level, const char * tag, const char * logStr) +{ + if (!logStr || !tag) + { + return; + } + +#ifdef __ANDROID__ + __android_log_write(LEVEL[level], tag, logStr); +#elif defined __linux__ + if (logCtx && logCtx->write_level) + { + logCtx->write_level(logCtx, LEVEL_XTABLE[level], logStr); + + } + else + { + printf("%s: %s: %s\n", LEVEL[level], tag, logStr); + } +#endif +} + +/** + * Output a variable argument list log string with the specified priority level. + * Only defined for Linux and Android + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param format - variadic log string + */ +void OICLogv(LogLevel level, const char * tag, const char * format, ...) +{ + if (!format || !tag) + { + return; + } + char buffer[MAX_LOG_V_BUFFER_SIZE]; + memset(buffer, 0, sizeof buffer); + va_list args; + va_start(args, format); + vsnprintf(buffer, sizeof buffer - 1, format, args); + va_end(args); + OICLog(level, tag, buffer); +} + +/** + * Output the contents of the specified buffer (in hex) with the specified priority level. + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param buffer - pointer to buffer of bytes + * @param bufferSize - max number of byte in buffer + */ +void OICLogBuffer(LogLevel level, const char * tag, const uint8_t * buffer, uint16_t bufferSize) +{ + if (!buffer || !tag || (bufferSize == 0)) + { + return; + } + + char lineBuffer[LINE_BUFFER_SIZE]; + memset(lineBuffer, 0, sizeof lineBuffer); + int lineIndex = 0; + int i; + for (i = 0; i < bufferSize; i++) + { + // Format the buffer data into a line + snprintf(&lineBuffer[lineIndex*3], sizeof(lineBuffer)-lineIndex*3, "%02X ", buffer[i]); + lineIndex++; + // Output 16 values per line + if (((i + 1) % 16) == 0) + { + OICLog(level, tag, lineBuffer); + memset(lineBuffer, 0, sizeof lineBuffer); + lineIndex = 0; + } + } + // Output last values in the line, if any + if (bufferSize % 16) + { + OICLog(level, tag, lineBuffer); + } +} + +#else +/** + * Initialize the serial logger for Arduino + * Only defined for Arduino + */ +void OICLogInit() +{ + Serial.begin(115200); +} + +/** + * Output a log string with the specified priority level. + * Only defined for Arduino. Only uses PROGMEM strings + * for the tag parameter + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param logStr - log string + */ +void OICLogString(LogLevel level, PROGMEM const char * tag, const char * logStr) +{ + if (!logStr || !tag) + { + return; + } + + char buffer[LINE_BUFFER_SIZE]; + + GET_PROGMEM_BUFFER(buffer, &(LEVEL[level])); + Serial.print(buffer); + + char c; + Serial.print(F(": ")); + while ((c = pgm_read_byte(tag))) + { + Serial.write(c); + tag++; + } + Serial.print(F(": ")); + + Serial.println(logStr); +} + +/** + * Output the contents of the specified buffer (in hex) with the specified priority level. + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param buffer - pointer to buffer of bytes + * @param bufferSize - max number of byte in buffer + */ +void OICLogBuffer(LogLevel level, PROGMEM const char * tag, const uint8_t * buffer, uint16_t bufferSize) +{ + if (!buffer || !tag || (bufferSize == 0)) + { + return; + } + + char lineBuffer[LINE_BUFFER_SIZE] = + { 0}; + uint8_t lineIndex = 0; + for (uint8_t i = 0; i < bufferSize; i++) + { + // Format the buffer data into a line + snprintf(&lineBuffer[lineIndex*3], sizeof(lineBuffer)-lineIndex*3, "%02X ", buffer[i]); + lineIndex++; + // Output 16 values per line + if (((i+1)%16) == 0) + { + OICLogString(level, tag, lineBuffer); + memset(lineBuffer, 0, sizeof lineBuffer); + lineIndex = 0; + } + } + // Output last values in the line, if any + if (bufferSize % 16) + { + OICLogString(level, tag, lineBuffer); + } +} + +/** + * Output a log string with the specified priority level. + * Only defined for Arduino. Uses PROGMEM strings + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param logStr - log string + */ +void OICLog(LogLevel level, PROGMEM const char * tag, PROGMEM const char * logStr) +{ + if (!logStr || !tag) + { + return; + } + + char buffer[LINE_BUFFER_SIZE]; + + GET_PROGMEM_BUFFER(buffer, &(LEVEL[level])); + Serial.print(buffer); + + char c; + Serial.print(F(": ")); + while ((c = pgm_read_byte(tag))) + { + Serial.write(c); + tag++; + } + Serial.print(F(": ")); + + while ((c = pgm_read_byte(logStr))) + { + Serial.write(c); + logStr++; + } + Serial.println(); +} + +/** + * Output a variable argument list log string with the specified priority level. + * Only defined for Arduino as depicted below. + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param format - variadic log string + */ +void OICLogv(LogLevel level, PROGMEM const char * tag, const char * format, ...) +{ + char buffer[LINE_BUFFER_SIZE]; + va_list ap; + va_start(ap, format); + + GET_PROGMEM_BUFFER(buffer, &(LEVEL[level])); + Serial.print(buffer); + + char c; + Serial.print(F(": ")); + + while ((c = pgm_read_byte(tag))) + { + Serial.write(c); + tag++; + } + Serial.print(F(": ")); + + vsnprintf(buffer, sizeof(buffer), format, ap); + for(char *p = &buffer[0]; *p; p++) // emulate cooked mode for newlines + { + if(*p == '\n') + { + Serial.write('\r'); + } + Serial.write(*p); + } + Serial.println(); + va_end(ap); +} +/** + * Output a variable argument list log string with the specified priority level. + * Only defined for Arduino as depicted below. + * + * @param level - DEBUG, INFO, WARNING, ERROR, FATAL + * @param tag - Module name + * @param format - variadic log string + */ +void OICLogv(LogLevel level, PROGMEM const char * tag, const __FlashStringHelper *format, ...) +{ + char buffer[LINE_BUFFER_SIZE]; + va_list ap; + va_start(ap, format); + + GET_PROGMEM_BUFFER(buffer, &(LEVEL[level])); + Serial.print(buffer); + + char c; + Serial.print(F(": ")); + + while ((c = pgm_read_byte(tag))) + { + Serial.write(c); + tag++; + } + Serial.print(F(": ")); + +#ifdef __AVR__ + vsnprintf_P(buffer, sizeof(buffer), (const char *)format, ap); // progmem for AVR +#else + vsnprintf(buffer, sizeof(buffer), (const char *)format, ap); // for the rest of the world +#endif + for(char *p = &buffer[0]; *p; p++) // emulate cooked mode for newlines + { + if(*p == '\n') + { + Serial.write('\r'); + } + Serial.write(*p); + } + Serial.println(); + va_end(ap); +} + +#endif + diff --git a/resource/csdk/connectivity/common/src/oic_console_logger.c b/resource/csdk/connectivity/common/src/oic_console_logger.c new file mode 100644 index 000000000..500f5a68c --- /dev/null +++ b/resource/csdk/connectivity/common/src/oic_console_logger.c @@ -0,0 +1,93 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "oic_logger.h" +#include "oic_console_logger.h" + +#include +#include + +typedef struct +{ + FILE *out; +} oic_console_logger_ctx; + +oic_log_ctx_t *oic_make_console_logger() +{ + return oic_log_make_ctx(NULL, OIC_LOG_ALL, oic_console_logger_init, oic_console_logger_destroy, + oic_console_logger_flush, oic_console_logger_set_level, oic_console_logger_write, + oic_console_logger_set_module); +} + +int oic_console_logger_init(oic_log_ctx_t *ctx, void *world) +{ + oic_console_logger_ctx *my_ctx; + + my_ctx = (oic_console_logger_ctx *) malloc(sizeof(oic_console_logger_ctx)); + + if (0 == my_ctx) + return 0; + + my_ctx->out = stderr; + + ctx->ctx = (void *) my_ctx; + + return 1; +} + +void oic_console_logger_destroy(oic_log_ctx_t *ctx) +{ + oic_console_logger_ctx *lctx = (oic_console_logger_ctx *) ctx->ctx; + + fflush(lctx->out); + + free(lctx); +} + +void oic_console_logger_flush(oic_log_ctx_t *ctx) +{ + oic_console_logger_ctx *lctx = (oic_console_logger_ctx *) ctx->ctx; + + fflush(lctx->out); +} + +void oic_console_logger_set_level(oic_log_ctx_t *ctx, const int level) +{ + /* We don't have any special thing we need to do when a log level changes. */ + return; +} + +size_t oic_console_logger_write(oic_log_ctx_t *ctx, const int level, const char *msg) +{ + oic_console_logger_ctx *lctx = (oic_console_logger_ctx *) ctx->ctx; + + /* A "real" implementation might want to replace the loglevel with a mnemonic: */ + + if (0 == ctx->module_name) + return 1 + fprintf(lctx->out, "%d: %s\n", level, msg); + + return 1 + fprintf(lctx->out, "%d: [%s]: %s\n", level, ctx->module_name, msg); +} + +int oic_console_logger_set_module(oic_log_ctx_t *ctx, const char *module_name) +{ + /* We don't do anything special when the module name changes: */ + return 1; +} diff --git a/resource/csdk/connectivity/common/src/oic_logger.c b/resource/csdk/connectivity/common/src/oic_logger.c new file mode 100644 index 000000000..7c1d7e971 --- /dev/null +++ b/resource/csdk/connectivity/common/src/oic_logger.c @@ -0,0 +1,148 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "oic_logger.h" + +#include +#include + +oic_log_ctx_t *oic_log_make_ctx(void* world, const oic_log_level level, oic_log_init_t init, + oic_log_destroy_t destroy, oic_log_flush_t flush, oic_log_set_level_t set_level, + oic_log_write_level_t write_level, oic_log_set_module_t set_module) +{ + oic_log_ctx_t *log_ctx; + + if (0 == init || 0 == destroy || 0 == flush || 0 == set_level || 0 == write_level + || 0 == set_module) + return 0; + + if (__OIC_LOG_MIN__ > level || __OIC_LOG_MAX__ < level) + return 0; + + log_ctx = (oic_log_ctx_t *) malloc(sizeof(oic_log_ctx_t)); + + if (0 == log_ctx) + return 0; + + log_ctx->ctx = 0; /* we'll get to this in a sec... */ + log_ctx->log_level = level; + log_ctx->module_name = 0; + log_ctx->init = init; + log_ctx->destroy = destroy; + log_ctx->flush = flush; + log_ctx->set_level = set_level; + log_ctx->set_module = set_module; + + log_ctx->write_level = write_level; + + if (0 == log_ctx->init(log_ctx, world)) + { + free(log_ctx); + return 0; + } + + return log_ctx; +} + +void oic_log_destroy(oic_log_ctx_t *ctx) +{ + if (0 == ctx) + return; + + ctx->destroy(ctx); + + if (0 != ctx->module_name) + free(ctx->module_name); + + free(ctx); +} + +int oic_log_init(oic_log_ctx_t *ctx, void *world) +{ + if (0 == ctx) + return 0; + + return ctx->init(ctx, world); +} + +void oic_log_flush(oic_log_ctx_t *ctx) +{ + if (0 == ctx) + { + return; + } + ctx->flush(ctx); +} + +void oic_log_set_level(oic_log_ctx_t *ctx, const oic_log_level ll) +{ + if (0 == ctx) + { + return; + } + ctx->set_level(ctx, ll); +} + +size_t oic_log_write(oic_log_ctx_t *ctx, const char *msg) +{ + if (0 == ctx) + return 0; + + return oic_log_write_level(ctx, ctx->log_level, msg); +} + +size_t oic_log_write_level(oic_log_ctx_t *ctx, const oic_log_level ll, const char *msg) +{ + if (0 == ctx) + return 0; + + ctx->log_level = ll; + + /* Notify: */ + return ctx->write_level(ctx, ll, msg); +} + +int oic_log_set_module(oic_log_ctx_t *ctx, const char *module_name) +{ + char *mn; + size_t l; + + if (0 == ctx) + return 0; + + /* Swap pointers so that module data's not erased in the event of failure: */ + l = strlen(module_name); + + mn = (char *) malloc(1 + l); + + if (0 == mn) + return 0; + + memcpy(mn, module_name, 1 + l); + + if (0 != ctx->module_name) + free(ctx->module_name); + + ctx->module_name = mn; + + /* Notify: */ + return ctx->set_module(ctx, ctx->module_name); +} + diff --git a/resource/csdk/connectivity/common/src/oic_malloc.c b/resource/csdk/connectivity/common/src/oic_malloc.c new file mode 100644 index 000000000..8136c972f --- /dev/null +++ b/resource/csdk/connectivity/common/src/oic_malloc.c @@ -0,0 +1,89 @@ +//****************************************************************** +// +// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include +#include "oic_malloc.h" + +// Enable extra debug logging for malloc. Comment out to disable +//#define ENABLE_MALLOC_DEBUG (1) + +#ifdef ENABLE_MALLOC_DEBUG +#include "logger.h" +#define TAG PCF("OICMalloc") +#endif + +//----------------------------------------------------------------------------- +// Typedefs +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Private variables +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Macros +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Internal API function +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Private internal function prototypes +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Public APIs +//----------------------------------------------------------------------------- + +void *OICMalloc(size_t size) +{ +#ifdef ENABLE_MALLOC_DEBUG + void *ptr = 0; + + if (0 == size) + { + return NULL; + } + + ptr = malloc(size); + OIC_LOG_V(INFO, TAG, "malloc: ptr=%p, size=%u", ptr, size); + return ptr; +#else + if (0 == size) + { + return NULL; + } + return malloc(size); +#endif +} + +void OICFree(void *ptr) +{ +#ifdef ENABLE_MALLOC_DEBUG + OIC_LOG_V(INFO, TAG, "free: ptr=%p", ptr); +#endif + + free(ptr); +} + diff --git a/resource/csdk/connectivity/common/src/uarraylist.c b/resource/csdk/connectivity/common/src/uarraylist.c new file mode 100644 index 000000000..a618e51e2 --- /dev/null +++ b/resource/csdk/connectivity/common/src/uarraylist.c @@ -0,0 +1,149 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +#include +#include +#include "uarraylist.h" +#include "logger.h" +#include "oic_malloc.h" + +#define TAG PCF("UARRAYLIST") + +u_arraylist_t *u_arraylist_create() +{ + u_arraylist_t *list = NULL; + + if (!(list = (u_arraylist_t*) OICMalloc(sizeof(u_arraylist_t)))) + { + return NULL; + } + + list->size = U_ARRAYLIST_DEFAULT_SIZE; + list->length = 0; + + if (!(list->data = (void*) OICMalloc(list->size * sizeof(void*)))) + { + OICFree(list); + return NULL; + } + + return list; +} + +CAResult_t u_arraylist_free(u_arraylist_t *list) +{ + OICFree(list->data); + OICFree(list); + + list = NULL; + + return CA_STATUS_OK; +} + +void *u_arraylist_get(const u_arraylist_t *list, uint32_t index) +{ + if (index >= list->length) + { + return NULL; + } + + if (list->data) + { + return list->data[index]; + } + + return NULL; +} + +CAResult_t u_arraylist_add(u_arraylist_t *list, void *data) +{ + uint32_t new_size = 0; + + if (list->size <= list->length) + { + + new_size = list->size + 1; + if (!(list->data = (void **) realloc(list->data, new_size * sizeof(void *)))) + { + return -1; + } + + (void) memset(list->data + list->size, 0, (new_size - list->size) * sizeof(void *)); + list->size = new_size; + } + + list->data[list->length] = data; + list->length++; + + return 0; +} + +void *u_arraylist_remove(u_arraylist_t *list, uint32_t index) +{ + void *removed = NULL; + + if (index >= list->length) + { + return NULL; + } + + removed = list->data[index]; + + if (index < list->length - 1) + { + memmove(&list->data[index], &list->data[index + 1], + (list->length - index - 1) * sizeof(void *)); + } + + list->size--; + list->length--; + + if (!(list->data = (void **) realloc(list->data, list->size * sizeof(void *)))) + { + return NULL; + } + + return removed; +} + +uint32_t u_arraylist_length(const u_arraylist_t *list) +{ + return list->length; +} + +uint8_t u_arraylist_contains(const u_arraylist_t *list, void *data) +{ + uint32_t i = 0; + + for (i = 0; i < u_arraylist_length(list); i++) + { + if (data == u_arraylist_get(list, i)) + { + return 1; + } + else + { + continue; + } + } + + return 0; +} + diff --git a/resource/csdk/connectivity/common/src/umutex.c b/resource/csdk/connectivity/common/src/umutex.c new file mode 100644 index 000000000..657545354 --- /dev/null +++ b/resource/csdk/connectivity/common/src/umutex.c @@ -0,0 +1,169 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ +/** + * @file umutex.c + * @brief This file provides APIs related to mutex and semaphores + */ + +#include "umutex.h" +#include + +#include "logger.h" +#define TAG PCF("UMUTEX") + +void u_mutex_init(void) +{ + /*Initialize the glib thread system if it is not. GMutex works only if the threadsystem is initialized*/ + if (!g_thread_supported()) + { + g_thread_init(NULL); + } +} + +u_mutex u_mutex_new(void) +{ + if (!g_thread_supported()) + { + return NULL; + } + + GMutex *mutexLock = g_mutex_new(); + return (u_mutex) mutexLock; +} + +void u_mutex_lock(u_mutex mutex) +{ + if (NULL == mutex) + { + OIC_LOG_V(ERROR, TAG ,"Invalid mutex !"); + return; + } + + GMutex *mutexLock = (GMutex*) mutex; + g_mutex_lock(mutexLock); +} + +CABool_t u_mutex_trylock(u_mutex mutex) +{ + if (NULL == mutex) + { + OIC_LOG_V(ERROR, TAG,"Invalid mutex !"); + return CA_FALSE; + } + + GMutex *mutexLock = (GMutex*) mutex; + gboolean ret = g_mutex_trylock(mutexLock); + if (TRUE == ret) + { + return CA_TRUE; + } + + return CA_FALSE; +} + +void u_mutex_unlock(u_mutex mutex) +{ + if (NULL == mutex) + { + OIC_LOG_V(ERROR, TAG,"Invalid mutex !"); + return; + } + + GMutex *mutexLock = (GMutex*) mutex; + g_mutex_unlock(mutexLock); +} + +void u_mutex_free(u_mutex mutex) +{ + if (NULL == mutex) + { + OIC_LOG_V(ERROR, TAG,"Invalid mutex !"); + return; + } + + GMutex *mutexLock = (GMutex*) mutex; + g_mutex_free(mutexLock); +} + +u_cond u_cond_new(void) +{ + if (!g_thread_supported()) + { + return NULL; + } + + GCond *condition = g_cond_new(); + return (u_cond) condition; +} + +void u_cond_signal(u_cond cond) +{ + if (NULL == cond) + { + OIC_LOG_V(ERROR, TAG,"Invalid condition !"); + return; + } + + GCond *condition = (GCond*) cond; + g_cond_signal(condition); +} + +void u_cond_broadcast(u_cond cond) +{ + if (NULL == cond) + { + OIC_LOG_V(ERROR, TAG,"Invalid condition !"); + return; + } + + GCond *condition = (GCond*) cond; + g_cond_broadcast(condition); +} + +void u_cond_wait(u_cond cond, u_mutex mutex) +{ + if (NULL == mutex) + { + OIC_LOG_V(ERROR, TAG,"Invalid mutex !"); + return; + } + + if (NULL == cond) + { + OIC_LOG_V(ERROR, TAG,"Invalid condition !"); + return; + } + + GMutex *mutexLock = (GMutex*) mutex; + GCond *condition = (GCond*) cond; + g_cond_wait(condition, mutexLock); +} + +void u_cond_free(u_cond cond) +{ + if (NULL == cond) + { + OIC_LOG_V(ERROR, TAG,"Invalid condition !"); + return; + } + + GCond *condition = (GCond*) cond; + g_cond_free(condition); +} + diff --git a/resource/csdk/connectivity/common/src/uqueue.c b/resource/csdk/connectivity/common/src/uqueue.c new file mode 100644 index 000000000..5b048307e --- /dev/null +++ b/resource/csdk/connectivity/common/src/uqueue.c @@ -0,0 +1,247 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +#include +#include +#include + +#include "logger.h" +#include "uqueue.h" +#include "oic_malloc.h" + +#define NO_MESSAGES 0 +#define TAG PCF("UQUEUE") + +u_queue_t* u_queue_create() +{ + u_queue_t* queuePtr = (u_queue_t*) OICMalloc(sizeof(u_queue_t)); + if (NULL == queuePtr) + { + OIC_LOG(DEBUG, TAG, "QueueCreate FAIL"); + return NULL; + } + + queuePtr->count = NO_MESSAGES; + queuePtr->element = NULL; + + return queuePtr; +} + +CAResult_t u_queue_add_element(u_queue_t* queue, u_queue_message_t *message) +{ + u_queue_element* element = NULL; + u_queue_element* ptr = NULL; + + if (NULL == queue) + { + OIC_LOG(DEBUG, TAG, "QueueAddElement FAIL, Invalid Queue"); + return CA_STATUS_FAILED; + } + + if (NULL == message) + { + OIC_LOG(DEBUG, TAG, "QueueAddElement : FAIL, NULL Message"); + return CA_STATUS_FAILED; + } + + element = (u_queue_element*) OICMalloc(sizeof(u_queue_element)); + if (NULL == element) + { + OIC_LOG(DEBUG, TAG, "QueueAddElement FAIL, memory allocation failed"); + return CA_MEMORY_ALLOC_FAILED; + } + + element->message = message; + element->next = NULL; + + ptr = queue->element; + + if (NULL != ptr) + { + while (NULL != ptr->next) + { + ptr = ptr->next; + } + + ptr->next = element; + queue->count++; + + OIC_LOG_V(DEBUG, TAG, "Queue Count : %d", queue->count); + } + else + { + if (NO_MESSAGES != queue->count) + { + OIC_LOG(DEBUG, TAG, "QueueAddElement : FAIL, count is not zero"); + + /* error in queue, free the allocated memory*/ + OICFree(element); + return CA_STATUS_FAILED; + } + + queue->element = element; + queue->count++; + OIC_LOG_V(DEBUG, TAG, "Queue Count : %d", queue->count); + + return CA_STATUS_OK; + } + + return CA_STATUS_OK; +} + +u_queue_message_t* u_queue_get_element(u_queue_t* queue) +{ + u_queue_element* next = NULL; + u_queue_element* element = NULL; + u_queue_message_t* message = NULL; + + if (NULL == queue) + { + OIC_LOG(DEBUG, TAG, "QueueAddElement FAIL, Invalid Queue"); + return NULL; + } + + element = queue->element; + + if (NULL == element) + { + OIC_LOG(DEBUG, TAG, "QueueGetElement : FAIL, no messages"); + return NULL; + } + + next = element->next; + queue->element = next; + queue->count--; + + message = element->message; + OICFree(element); + return message; +} + +CAResult_t u_queue_remove_element(u_queue_t* queue) +{ + u_queue_element* next = NULL; + u_queue_element* remove = NULL; + + if (NULL == queue) + { + OIC_LOG(DEBUG, TAG, "QueueRemoveElement FAIL, Invalid Queue"); + return CA_STATUS_FAILED; + } + + remove = queue->element; + + if (NULL == remove) + { + OIC_LOG(DEBUG, TAG, "QueueRemoveElement : no messages"); + return CA_STATUS_OK; + } + + next = remove->next; + + OICFree(remove->message); + OICFree(remove); + + queue->element = next; + queue->count--; + + return CA_STATUS_OK; +} + +uint32_t u_queue_get_size(u_queue_t* queue) +{ + if (NULL == queue) + { + OIC_LOG(DEBUG, TAG, "QueueGetSize FAIL, Invalid Queue"); + return NO_MESSAGES; + } + + return queue->count; +} + +CAResult_t u_queue_reset(u_queue_t* queue) +{ + CAResult_t error = CA_STATUS_FAILED; + + if (NULL == queue) + { + OIC_LOG(DEBUG, TAG, "QueueReset FAIL, Invalid Queue"); + return CA_STATUS_FAILED; + } + + if (NO_MESSAGES == queue->count) + { + OIC_LOG(DEBUG, TAG, "QueueReset, no elements in the queue"); + return CA_STATUS_OK; + } + + while (NULL != queue->element) + { + error = u_queue_remove_element(queue); + if (error == CA_STATUS_FAILED) + break; + } + + if (NO_MESSAGES != queue->count) + { + OIC_LOG(DEBUG, TAG, "QueueReset : FAIL, count is non zero"); + return CA_STATUS_FAILED; + } + + return CA_STATUS_OK; + +} + +CAResult_t u_queue_delete(u_queue_t* queue) +{ + CAResult_t error = CA_STATUS_FAILED; + + if (NULL == queue) + { + OIC_LOG(DEBUG, TAG, "QueueDelete FAIL, Invalid Queue"); + return CA_STATUS_FAILED; + } + + error = u_queue_reset(queue); + if (error != CA_STATUS_OK) + { + OIC_LOG(DEBUG, TAG, "QueueDelete : FAIL, error in QueueReset"); + return error; + } + + OICFree(queue); + return (CA_STATUS_OK); +} + +u_queue_message_t* u_queue_get_head(u_queue_t* queue) +{ + if (NULL == queue) + { + OIC_LOG(DEBUG, TAG, "QueueGetHead FAIL, Invalid Queue"); + return NULL; + } + + if (NULL == queue->element) + { + OIC_LOG(DEBUG, TAG, "QueueGetHead : no messages in queue"); + return NULL; + } + return queue->element->message; +} diff --git a/resource/csdk/connectivity/common/src/uthreadpool.c b/resource/csdk/connectivity/common/src/uthreadpool.c new file mode 100644 index 000000000..477d5fd67 --- /dev/null +++ b/resource/csdk/connectivity/common/src/uthreadpool.c @@ -0,0 +1,116 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ +/** + * @file uthreadpool.c + * @brief This file provides APIs related to thread pool + */ + +#include "uthreadpool.h" +#include "logger.h" +#include "oic_malloc.h" +#define TAG PCF("UTHREADPOOL") + +/** + * @var gThreadpool + * @brief Glib thread pool. + */ +static GThreadPool *gThreadpool; + +/** + * @fn run + * @brief function which is registed to glib thread pool. + */ +static void run(void *thread_data, void *user_data); + +CAResult_t u_thread_pool_init(uint32_t num_of_threads, u_thread_pool_t *thread_pool) +{ + OIC_LOG_V(DEBUG, TAG, "IN"); + + GError *error = NULL; + gThreadpool = g_thread_pool_new(run, NULL, num_of_threads, FALSE, &error); + if (NULL == gThreadpool) + { + OIC_LOG_V(ERROR, TAG, "Error: g_thread_pool_new failed!"); + if (NULL != error) + { + OIC_LOG_V(ERROR, TAG, "Error is: %s", error->message); + g_error_free(error); + } + return CA_STATUS_FAILED; + } + *thread_pool = (u_thread_pool_t) gThreadpool; + + OIC_LOG_V(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; +} + +CAResult_t u_thread_pool_add_task(u_thread_pool_t thread_pool, void (*routine)(void *), void *data) +{ + OIC_LOG_V(DEBUG, TAG, "IN"); + + gboolean result = FALSE; + if (NULL == routine) + { + OIC_LOG_V(ERROR, TAG, "Error: routine is NULL!"); + return CA_STATUS_FAILED; + } + + u_thread_msg_t *message = (u_thread_msg_t *) OICMalloc(sizeof(u_thread_msg_t)); + message->data = data; + message->func = routine; + result = g_thread_pool_push((GThreadPool *) thread_pool, (void *) message, NULL); + if (FALSE == result) + { + OIC_LOG_V(ERROR, TAG, "Error: Failed to push the task to threadpool!"); + return CA_STATUS_FAILED; + } + + OIC_LOG_V(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; +} + +void u_thread_pool_free(u_thread_pool_t thread_pool) +{ + OIC_LOG_V(DEBUG, TAG, "IN"); + + GThreadPool *threadpool = (GThreadPool *) thread_pool; + g_thread_pool_free(threadpool, TRUE, TRUE); + + OIC_LOG_V(DEBUG, TAG, "OUT"); +} + +void run(void *thread_data, void *user_data) +{ + u_thread_msg_t *message = (u_thread_msg_t *) thread_data; + + if (message && message->func) + { + OIC_LOG_V(DEBUG, TAG, "Calling routine with data as parameter"); + message->func(message->data); + } + else + { + OIC_LOG_V(ERROR, TAG, "Error: Invalid task data"); + return; + } + + //Free message + OICFree(message); + message = NULL; +} diff --git a/resource/csdk/connectivity/inc/caadapterinterface.h b/resource/csdk/connectivity/inc/caadapterinterface.h new file mode 100644 index 000000000..67a44cb35 --- /dev/null +++ b/resource/csdk/connectivity/inc/caadapterinterface.h @@ -0,0 +1,187 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +/** + * @file caadapterinterface.h + * @brief This file contains the APIs for adapters to be implemented + */ +#ifndef __CA_ADAPTER_INTERFACE_H_ +#define __CA_ADAPTER_INTERFACE_H_ + +#include "cacommon.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @brief Starting connectivity adapters and each adapter have transport specific behavior. + * Transport Specific Behavior: + * WIFI/ETH connectivity Starts unicast server on all available IPs and defined port number as per specification. + * EDR will not start any specific servers. + * LE will not start any specific servers. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +typedef CAResult_t (*CAAdapterStart)(); + +/** + * @brief Starting listening server for receiving multicast search requests + * Transport Specific Behavior: + * WIFI/ETH Starts multicast server on all available IPs and defined port number and as per specification. + * EDR Starts RFCOMM Server with prefixed UUID as per specification. + * LE Start GATT Server with prefixed UUID and Characteristics as per OIC Specification. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +typedef CAResult_t (*CAAdapterStartListeningServer)(); + +/** + * @brief for starting discovery servers for receiving multicast advertisements + * Transport Specific Behavior: + * WIFI/ETH Starts multicast server on all available IPs and defined port number as per OIC Specification. + * EDR Starts RFCOMM Server with prefixed UUID as per OIC Specification. + * LE Starts GATT Server with prefixed UUID and Characteristics as per OIC Specification. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +typedef CAResult_t (*CAAdapterStartDiscoveryServer)(); + +/** + * @brief Sends data to the endpoint using the adapter connectivity. + * Note: length must be > 0. + * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference uri and connectivity type) to + * which the unicast data has to be sent. + * @param data [IN] Data which required to be sent. + * @param dataLen [IN] Size of data to be sent. + * @return - The number of bytes sent on the network. Return value equal to zero indicates error. + */ +typedef uint32_t (*CAAdapterSendUnitcastData)(const CARemoteEndpoint_t* endpoint, void* data, + uint32_t dataLen); + +/** + * @brief Sends Multicast data to the endpoint using the adapter connectivity. + * Note: length must be > 0. + * @param data [IN] Data which required to be sent. + * @param dataLen [IN] Size of data to be sent. + * @return - The number of bytes sent on the network. Return value equal to zero indicates error. + */ +typedef uint32_t (*CAAdapterSendMulticastData)(void* data, uint32_t dataLen); + +/** + * @brief Starts notification server on adapters. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +typedef CAResult_t (*CAAdapterStartNotificationRecvServer)(); + +/** + * @brief Send notification information to the given endpoint. + * Note: length must be > 0. + * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference uri and connectivity type) to + * which the unicast data has to be sent. + * @param data [IN] Data which required to be sent. + * @param dataLen [IN] Size of data to be sent. + * @return - The number of bytes sent on the network. Return value equal to zero indicates error. + */ +typedef uint32_t (*CAAdapterSendNotification)(const CARemoteEndpoint_t* endpoint, void* data, + uint32_t dataLen); + +/** + * @brief Get Network Information + * @param info [OUT] Local connectivity information structures + * @param size [OUT] Number of local connectivity structures. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +typedef CAResult_t (*CAAdapterGetNetworkInfo)(CALocalConnectivityt_t** info, uint32_t* size); + +/** + * @brief Read Synchronous API callback. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +typedef CAResult_t (*CAAdapterReadData)(); + +/** + * @brief Stopping the adapters and close socket connections + * Transport Specific Behavior: + * WIFI/ETH Stops all listening servers and close sockets. + * EDR Stops all RFCOMM servers and close sockets. + * LE Stops all GATT servers and close sockets. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +typedef CAResult_t (*CAAdapterStop)(); + +/** + * @brief Terminate the connectivity adapter.Configuration information will be deleted from further use + */ +typedef void (*CAAdapterTerminate)(); + +/** + * @brief Connectivity handler information for adapter + */ +typedef struct +{ + /** Start Transport specific functions*/ + CAAdapterStart startAdapter; + /** Listening Server function address*/ + CAAdapterStartListeningServer startListenServer; + /** Discovery Server function address **/ + CAAdapterStartDiscoveryServer startDiscoverServer; + /** Unicast data function address**/ + CAAdapterSendUnitcastData sendData; + /** Multicast data function address**/ + CAAdapterSendMulticastData sendDataToAll; + /** Notify server function address**/ + CAAdapterStartNotificationRecvServer startNotifyServer; + /** Send Notification function address**/ + CAAdapterSendNotification sendNotification; + /** Get Networking information **/ + CAAdapterGetNetworkInfo GetnetInfo; + /** Read Data function address**/ + CAAdapterReadData readData; + /** Stop Transport specific functions*/ + CAAdapterStop stopAdapter; + /** Terminate function address stored in this pointer**/ + CAAdapterTerminate terminate; + +} CAConnectivityHandler_t; + +/** + * @brief This will be used during the registration of adapters call backs to the common logic + * @see CAConnectivityHandler_t , CAConnectivityType_t + */ +typedef void (*CARegisterConnectivityCallback)(CAConnectivityHandler_t handler, + CAConnectivityType_t cType); + +/** + * @brief This will be used during the recive of network requests and response. + * @see SendUnitcastData(), SendMulticastData() + */ +typedef void (*CANetworkPacketReceivedCallback)(CARemoteEndpoint_t* endPoint, void* data, + uint32_t dataLen); + +/** + * @brief This will be used to intimate network changes to the connectivity common logic layer + * @see SendUnitcastData(), SendMulticastData() + */ +typedef void (*CANetworkChangeCallback)(CALocalConnectivityt_t* info, CANetworkStatus_t status); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // __CA_ADAPTER_INTERFACE_H_ diff --git a/resource/csdk/connectivity/inc/caedradapter.h b/resource/csdk/connectivity/inc/caedradapter.h new file mode 100644 index 000000000..2b68a0761 --- /dev/null +++ b/resource/csdk/connectivity/inc/caedradapter.h @@ -0,0 +1,141 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ +/** + * @file caedradapter.h + * @brief This file contains the APIs for EDR adapters to be implemented + */ +#ifndef __CA_EDRADAPTER_H_ +#define __CA_EDRADAPTER_H_ + +/** + * BT Interface AP + **/ +#include "cacommon.h" +#include "caadapterinterface.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifndef BLUETOOTH_ADAPTER_TAG +#define BLUETOOTH_ADAPTER_TAG "CA_EDR" +#endif //BLUETOOTH_ADAPTER_TAG +/** + * @brief Initialize EDR connectivity interface. + * @param registerCallback [IN] To register EDR interfaces to Connectivity Abstraction Layer + * @param reqRespCallback [IN] sending responses and discovery messages from unicast , multicast servers + * @param netCallback [IN] Intimate the network additions to Connectivity Abstraction Layer. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAInitializeEDR(CARegisterConnectivityCallback registerCallback, + CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback); + +/** + * @brief Starting EDR connectivity adapters .As its peer to peer it doesnot require to start any servers + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStartEDR(); + +/** + * @brief Starting listening server for receiving multicast search requests + * Transport Specific Behavior: + * EDR Starts RFCOMM Server with prefixed UUID as per specification. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStartEDRListeningServer(); + +/** + * @brief for starting discovery servers for receiving multicast advertisements + * Transport Specific Behavior: + * EDR Starts RFCOMM server with prefixed UUID as per OIC Specification. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStartEDRDiscoveryServer(); + +/** + * @brief Sends data to the endpoint using the adapter connectivity. + * Note: length must be > 0. + * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference uri and connectivity type) to + * which the unicast data has to be sent. + * @param data [IN] Data which required to be sent. + * @param dataLen [IN] Size of data to be sent. + * @return - The number of bytes sent on the network. Return value equal to zero indicates error. + */ +uint32_t CASendEDRUnicastData(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen); + +/** + * @brief Sends Multicast data to the endpoint using the EDR connectivity. + * Note: length must be > 0. + * @param data [IN] Data which required to be sent. + * @param dataLen [IN] Size of data to be sent. + * @return - The number of bytes sent on the network. Return value equal to zero indicates error. + */ +uint32_t CASendEDRMulticastData(void* data, uint32_t dataLen); + +/** + * @brief Starts notification server on EDR adapters. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStartEDRNotifyServer(); + +/** + * @brief Send notification information. + * Note: length must be > 0. + * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference uri and connectivity type) to + * which the unicast data has to be sent. + * @param data [IN] Data which required to be sent. + * @param dataLen [IN] Size of data to be sent. + * @return - The number of bytes sent on the network. Return value equal to zero indicates error. + */ +uint32_t CASendEDRNotification(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen); + +/** + * @brief Get EDR Connectivity network information + * @param info [OUT] Local connectivity information structures + * @param size [OUT] Number of local connectivity structures. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAGetEDRInterfaceInformation(CALocalConnectivityt_t** info, uint32_t* size); + +/** + * @brief Read Synchronous API callback. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAReadEDRData(); + +/** + * @brief Stopping the adapters and close socket connections + * EDR Stops all RFCOMM servers and close sockets. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStopEDR(); + +/** + * @brief Terminate the EDR connectivity adapter. + * Configuration information will be deleted from further use + */ +void CATerminateEDR(); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif //__CA_EDRADAPTER_H_ diff --git a/resource/csdk/connectivity/inc/caerrorcode.h b/resource/csdk/connectivity/inc/caerrorcode.h new file mode 100644 index 000000000..80905b45f --- /dev/null +++ b/resource/csdk/connectivity/inc/caerrorcode.h @@ -0,0 +1,65 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +#ifndef __CA_ERROR_CODE_H_ +#define __CA_ERROR_CODE_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * Declares Stack Results & Errors + */ +typedef enum +{ + OC_STACK_OK = 0, + OC_STACK_INVALID_URI, + OC_STACK_INVALID_QUERY, + OC_STACK_INVALID_IP, + OC_STACK_INVALID_PORT, + OC_STACK_INVALID_CALLBACK, + OC_STACK_INVALID_METHOD, + OC_STACK_INVALID_PARAM, + OC_STACK_INVALID_OBSERVE_PARAM, + OC_STACK_NO_MEMORY, + OC_STACK_COMM_ERROR, + OC_STACK_NOTIMPL, + OC_STACK_NO_RESOURCE, /* resource not found*/ + OC_STACK_RESOURCE_ERROR, /*ex: not supported method or interface*/ + OC_STACK_SLOW_RESOURCE, + OC_STACK_NO_OBSERVERS, /* resource has no registered observers */ + OC_STACK_OBSERVER_NOT_FOUND, + OC_STACK_OBSERVER_NOT_ADDED, + OC_STACK_OBSERVER_NOT_REMOVED, +#ifdef WITH_PRESENCE + OC_STACK_PRESENCE_NO_UPDATE, + OC_STACK_PRESENCE_STOPPED, + OC_STACK_PRESENCE_DO_NOT_HANDLE, +#endif + OC_STACK_ERROR +} OCStackResult; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif //#ifndef __CA_ERROR_CODE_H_ diff --git a/resource/csdk/connectivity/inc/caethernetadapter.h b/resource/csdk/connectivity/inc/caethernetadapter.h new file mode 100644 index 000000000..61e8a4de7 --- /dev/null +++ b/resource/csdk/connectivity/inc/caethernetadapter.h @@ -0,0 +1,137 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +/** + * @file caethernetadapter.h + * @brief This file contains the APIs for Ethernet Adapter. + */ +#ifndef __CA_ETHERNET_ADAPTER_H__ +#define __CA_ETHERNET_ADAPTER_H__ + +#include "cacommon.h" +#include "caadapterinterface.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @brief Initialize Ethernet connectivity interface. + * @param registerCallback [IN] To register Ethernet interfaces to Connectivity Abstraction Layer + * @param reqRespCallback [IN] sending responses and discovery messages from unicast , multicast servers + * @param netCallback [IN] Intimate the network additions to Connectivity Abstraction Layer. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAInitializeEthernet(CARegisterConnectivityCallback registerCallback, + CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback); + +/** + * @brief Start Ethernet Interface adapter. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStartEthernet(); + +/** + * @brief Starting listening server for receiving multicast search requests + * Transport Specific Behavior: + * Ethernet Starts Multicast Server on all available IPs and prefixed port number and as per OIC Specification. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStartEthernetListeningServer(); + +/** + * @brief for starting discovery servers for receiving multicast advertisements + * Transport Specific Behavior: + * Ethernet Starts Start multicast server on all available IPs and prefixed port number as per OIC Specification + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStartEthernetDiscoveryServer(); + +/** + * @brief Sends data to the endpoint using the adapter connectivity. + * Note: length must be > 0. + * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference uri and connectivity type) to + * which the unicast data has to be sent. + * @param data [IN] Data which required to be sent. + * @param dataLen [IN] Size of data to be sent. + * @return - The number of bytes sent on the network. Return value equal to zero indicates error. + */ +uint32_t CASendEthernetUnicastData(const CARemoteEndpoint_t* endpoint, void* data, + uint32_t dataLen); + +/** + * @brief Sends Multicast data to the endpoint using the WIFI connectivity. + * Note: length must be > 0. + * @param data [IN] Data which required to be sent. + * @param dataLen [IN] Size of data to be sent. + * @return - The number of bytes sent on the network. Return value equal to zero indicates error. + */ +uint32_t CASendEthernetMulticastData(void* data, uint32_t dataLen); + +/** + * @brief Starts notification server on Ethernet adapters. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStartEthernetNotifyServer(); + +/** + * @brief Send notification information. + * Note: length must be > 0. + * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference uri and connectivity type) to + * which the unicast data has to be sent. + * @param data [IN] Data which required to be sent. + * @param dataLen [IN] Size of data to be sent. + * @return - The number of bytes sent on the network. Return value equal to zero indicates error. + */ +uint32_t CASendEthernetNotification(const CARemoteEndpoint_t* endpoint, void* data, + uint32_t dataLen); +/** + * @brief Get Ethernet Connectivity network information + * @param info [OUT] Local connectivity information structures + * @param size [OUT] Number of local connectivity structures. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAGetEthernetInterfaceInformation(CALocalConnectivityt_t** info, uint32_t* size); + +/** + * @brief Read Synchronous API callback. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAReadEthernetData(); + +/** + * @brief Stopping the adapters and close socket connections + * Ethernet Stops all multicast and unicast servers and close sockets. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStopEthernet(); + +/** + * @brief Terminate the Ethernet connectivity adapter. + * Configuration information will be deleted from further use + */ +void CATerminateEthernet(); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/resource/csdk/connectivity/inc/cainterfacecontroller.h b/resource/csdk/connectivity/inc/cainterfacecontroller.h new file mode 100644 index 000000000..d2af4d256 --- /dev/null +++ b/resource/csdk/connectivity/inc/cainterfacecontroller.h @@ -0,0 +1,52 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ +#ifndef __CA_INTERFACE_CONTROLLER_H_ +#define __CA_INTERFACE_CONTROLLER_H_ + +#include "caadapterinterface.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +void CAInitializeAdapters(); + +void CASetPacketReceivedCallback(CANetworkPacketReceivedCallback callback); + +void CAStartAdapter(CAConnectivityType_t connectivity); + +void CAStopAdapter(CAConnectivityType_t connectivity); + +CAResult_t CASendUnicastData(const CARemoteEndpoint_t* endpoint, void* data, uint32_t length); + +CAResult_t CASendMulticastData(void* data, uint32_t length); + +CAResult_t CAStartListeningServerAdapters(); + +CAResult_t CAStartDiscoveryServerAdapters(); + +void CATerminateAdapters(); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif //#ifndef __CA_INTERFACE_CONTROLLER_H_ diff --git a/resource/csdk/connectivity/inc/caleadapter.h b/resource/csdk/connectivity/inc/caleadapter.h new file mode 100644 index 000000000..a99d16173 --- /dev/null +++ b/resource/csdk/connectivity/inc/caleadapter.h @@ -0,0 +1,138 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +/** + * @file caleadapter.h + * @brief This file contains the APIs for LE adapters to be implemented + */ +#ifndef _CA_LEADAPTER_H_ +#define _CA_LEADAPTER_H_ + +#include "cacommon.h" +#include "caadapterinterface.h" + +/** + * BLE Interface APIs. + */ +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @brief Initialize LE connectivity interface. + * @param registerCallback [IN] To register LE interfaces to Connectivity Abstraction Layer + * @param reqRespCallback [IN] sending responses and discovery messages from unicast , multicast servers + * @param netCallback [IN] Intimate the network additions to Connectivity Abstraction Layer. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAInitializeLE(CARegisterConnectivityCallback registerCallback, + CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback); +/** + * @brief Starting LE connectivity adapters .As its peer to peer it doesnot require to start any servers + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStartLE(); + +/** + * @brief Starting listening server for receiving multicast search requests + * Transport Specific Behavior: + * LE Starts GATT Server with prefixed UUID and Characteristics as per OIC Specification. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStartLEListeningServer(); + +/** + * @brief for starting discovery servers for receiving multicast advertisements + * Transport Specific Behavior: + * LE Starts GATT Server with prefixed UUID and Characteristics as per OIC Specification. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStartLEDiscoveryServer(); + +/** + * @brief Sends data to the endpoint using the adapter connectivity. + * Note: length must be > 0. + * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference uri and connectivity type) to + * which the unicast data has to be sent. + * @param data [IN] Data which required to be sent. + * @param dataLen [IN] Size of data to be sent. + * @return - The number of bytes sent on the network. Return value equal to zero indicates error. + */ +uint32_t CASendLEUnicastData(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen); + +/** + * @brief Sends Multicast data to the endpoint using the LE connectivity. + * Note: length must be > 0. + * @param data [IN] Data which required to be sent. + * @param dataLen [IN] Size of data to be sent. + * @return - The number of bytes sent on the network. Return value equal to zero indicates error. + */ +uint32_t CASendLEMulticastData(void* data, uint32_t dataLen); + +/** + * @brief Starts notification server on EDR adapters. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStartLENotifyServer(); + +/** + * @brief Send notification information. + * Note: length must be > 0. + * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference uri and connectivity type) to + * which the unicast data has to be sent. + * @param data [IN] Data which required to be sent. + * @param dataLen [IN] Size of data to be sent. + * @return - The number of bytes sent on the network. Return value equal to zero indicates error. + */ +uint32_t CASendLENotification(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen); + +/** + * @brief Get LE Connectivity network information + * @param info [OUT] Local connectivity information structures + * @param size [OUT] Number of local connectivity structures. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAGetLEInterfaceInformation(CALocalConnectivityt_t** info, uint32_t* size); + +/** + * @brief Read Synchronous API callback. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAReadLEData(); + +/** + * @brief Stopping the adapters and close socket connections + * LE Stops all GATT servers and close sockets. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStopLE(); + +/** + * @brief Terminate the LE connectivity adapter. + * Configuration information will be deleted from further use + */ +void CATerminateLE(); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif //#ifndef _CA_LEADAPTER_H_ diff --git a/resource/csdk/connectivity/inc/camessagehandler.h b/resource/csdk/connectivity/inc/camessagehandler.h new file mode 100644 index 000000000..597da7bdf --- /dev/null +++ b/resource/csdk/connectivity/inc/camessagehandler.h @@ -0,0 +1,58 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ +#ifndef __CA_MESSAGE_HANDLER_H_ +#define __CA_MESSAGE_HANDLER_H_ + +#include +#include "cacommon.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef enum +{ + SUCCESS = 0, NETWORK_ERROR, FAIL +} CADetachErrorCode; + +typedef void (*CAMessageHandlerCallback)(int32_t id, CADetachErrorCode code); + +int32_t CADetachRequestMessage(const CARemoteEndpoint_t* object, const CARequestInfo_t* request); + +int32_t CADetachResponseMessage(const CARemoteEndpoint_t* object, const CAResponseInfo_t* response); + +int32_t CADetachMessageResourceUri(const CAURI_t resourceUri); + +void CASetMessageHandlerCallback(CAMessageHandlerCallback callback); + +void CASetRequestResponseCallbacks(CARequestCallback ReqHandler, CAResponseCallback RespHandler); + +CAResult_t CAInitializeMessageHandler(); + +void CATerminateMessageHandler(); + +void CAHandleRequestResponseCallbacks(); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif //#ifndef __CA_MESSAGE_HANDLER_H_ diff --git a/resource/csdk/connectivity/inc/canetworkconfigurator.h b/resource/csdk/connectivity/inc/canetworkconfigurator.h new file mode 100644 index 000000000..4117bf7ab --- /dev/null +++ b/resource/csdk/connectivity/inc/canetworkconfigurator.h @@ -0,0 +1,45 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ +#ifndef _NETWORK_CONFIGURATOR_H_ +#define _NETWORK_CONFIGURATOR_H_ + +#include "uarraylist.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +static uint32_t NETWORK_ETHERNET = CA_ETHERNET; +static uint32_t NETWORK_WIFI = CA_WIFI; +static uint32_t NETWORK_EDR = CA_EDR; +static uint32_t NETWORK_LE = CA_LE; + +CAResult_t CAAddNetworkType(uint32_t CAConnectivityType); + +CAResult_t CARemoveNetworkType(uint32_t CAConnectivityType); + +u_arraylist_t* CAGetSelectedNetworkList(); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif //#ifndef _NETWORK_CONFIGURATOR_H_ diff --git a/resource/csdk/connectivity/inc/caprotocolmessage.h b/resource/csdk/connectivity/inc/caprotocolmessage.h new file mode 100644 index 000000000..baeb261b4 --- /dev/null +++ b/resource/csdk/connectivity/inc/caprotocolmessage.h @@ -0,0 +1,80 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ +#ifndef __CA_PROTOCOL_MESSAGE_H_ +#define __CA_PROTOCOL_MESSAGE_H_ + +#include "cacommon.h" +#include "config.h" +#include "coap.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +uint32_t flags = 0; + +uint8_t msgtype = COAP_MESSAGE_CON; /* usually, requests are sent confirmable */ + +coap_block_t block = +{ .num = 0, .m = 0, .szx = 6}; + +typedef uint32_t code_t; + +/** + * function for generate + */ +coap_pdu_t* CAGeneratePdu(const char* uri, const uint32_t code, const CAInfo_t info); +/** + * function for parsing + */ +uint32_t CAGetRequestInfoFromPdu(const coap_pdu_t *pdu, CARequestInfo_t* outReqInfo); + +uint32_t CAGetResponseInfoFromPdu(const coap_pdu_t *pdu, CAResponseInfo_t* outResInfo); + +coap_pdu_t* CACreatePDUforRequest(const code_t code, coap_list_t *options); + +coap_pdu_t* CACreatePDUforRequestWithPayload(const code_t code, coap_list_t *optlist, + const char* payload); + +void CAParseURI(const char* uriInfo, coap_list_t **options); + +void CAParseHeadOption(const uint32_t code, const CAInfo_t info, coap_list_t **optlist); + +coap_list_t* CACreateNewOptionNode(const uint16_t key, const uint32_t length, const uint8_t *data); + +int32_t CAOrderOpts(void *a, void *b); + +void CAGetRequestPDUInfo(const coap_pdu_t *pdu, uint32_t* outCode, CAInfo_t* outInfo); + +coap_pdu_t* CAParsePDU(const char* data, uint32_t* outCode); + +/** + * function for token + */ +CAResult_t CAGenerateTokenInternal(CAToken_t* token); + +void CADestroyTokenInternal(CAToken_t token); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif //#ifndef __CA_PROTOCOL_MESSAGE_H_ diff --git a/resource/csdk/connectivity/inc/caremotehandler.h b/resource/csdk/connectivity/inc/caremotehandler.h new file mode 100644 index 000000000..4c3a984b3 --- /dev/null +++ b/resource/csdk/connectivity/inc/caremotehandler.h @@ -0,0 +1,55 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ +#ifndef __CA_REMOTE_HANDLER_H_ +#define __CA_REMOTE_HANDLER_H_ + +#include +#include +#include + +#include "cacommon.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +CARemoteEndpoint_t* CACloneRemoteEndpoint(const CARemoteEndpoint_t* rep); + +CARemoteEndpoint_t* CACreateRemoteEndpointUriInternal(const CAURI_t uri); + +CARemoteEndpoint_t* CACreateRemoteEndpointInternal(const CAURI_t resourceUri, + const CAAddress_t addr, const CAConnectivityType_t type); + +void CADestroyRemoteEndpointInternal(CARemoteEndpoint_t* rep); + +CARequestInfo_t* CACloneRequestInfo(const CARequestInfo_t* rep); + +void CADestroyRequestInfoInternal(CARequestInfo_t* rep); + +CAResponseInfo_t* CACloneResponseInfo(const CAResponseInfo_t* rep); + +void CADestroyResponseInfoInternal(CAResponseInfo_t* rep); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif //#ifndef __CA_REMOTE_HANDLER_H_ diff --git a/resource/csdk/connectivity/inc/cawifiadapter.h b/resource/csdk/connectivity/inc/cawifiadapter.h new file mode 100644 index 000000000..07ad36aa6 --- /dev/null +++ b/resource/csdk/connectivity/inc/cawifiadapter.h @@ -0,0 +1,135 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +/** + * @file cawifiadapter.h + * @brief This file contains the APIs for WiFi Adapter. + */ +#ifndef __CA_WIFI_ADAPTER_H__ +#define __CA_WIFI_ADAPTER_H__ + +#include "cacommon.h" +#include "caadapterinterface.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @brief API to initialize WiFi Interface. + * @param registerCallback [IN] To register WIFI interfaces to Connectivity Abstraction Layer + * @param reqRespCallback [IN] sending responses and discovery messages from unicast , multicast servers + * @param netCallback [IN] Intimate the network additions to Connectivity Abstraction Layer. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAInitializeWifi(CARegisterConnectivityCallback registerCallback, + CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback); + +/** + * @brief Start WiFi Interface adapter. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStartWIFI(); + +/** + * @brief Starting listening server for receiving multicast search requests + * Transport Specific Behavior: + * WIFI Starts Multicast Server on all available IPs and prefixed port number and as per OIC Specification. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStartWIFIListeningServer(); + +/** + * @brief for starting discovery servers for receiving multicast advertisements + * Transport Specific Behavior: + * WIFI Starts Start multicast server on all available IPs and prefixed port number as per OIC Specification + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStartWIFIDiscoveryServer(); + +/** + * @brief Sends data to the endpoint using the adapter connectivity. + * Note: length must be > 0. + * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference uri and connectivity type) to + * which the unicast data has to be sent. + * @param data [IN] Data which required to be sent. + * @param dataLen [IN] Size of data to be sent. + * @return - The number of bytes sent on the network. Return value equal to zero indicates error. + */ +uint32_t CASendWIFIUnicastData(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen); + +/** + * @brief Sends Multicast data to the endpoint using the WIFI connectivity. + * Note: length must be > 0. + * @param data [IN] Data which required to be sent. + * @param dataLen [IN] Size of data to be sent. + * @return - The number of bytes sent on the network. Return value equal to zero indicates error. + */ +uint32_t CASendWIFIMulticastData(void* data, uint32_t dataLen); + +/** + * @brief Starts notification server on WIFI adapters. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStartWIFINotifyRecvServers(); + +/** + * @brief Send notification information. + * Note: length must be > 0. + * @param endpoint [IN] Remote Endpoint information (like ipaddress , port, reference uri and connectivity type) to + * which the unicast data has to be sent. + * @param data [IN] Data which required to be sent. + * @param dataLen [IN] Size of data to be sent. + * @return - The number of bytes sent on the network. Return value equal to zero indicates error. + */ +uint32_t CASendWIFINotification(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen); +/** + * @brief Get WIFI Connectivity network information + * @param info [OUT] Local connectivity information structures + * @param size [OUT] Number of local connectivity structures. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAGetWIFIInterfaceInformation(CALocalConnectivityt_t** info, uint32_t* size); + +/** + * @brief Read Synchronous API callback. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAReadWIFIData(); + +/** + * @brief Stopping the adapters and close socket connections + * WIFI Stops all multicast and unicast servers and close sockets. + * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStopWIFI(); + +/** + * @brief Terminate the WIFI connectivity adapter. + * Configuration information will be deleted from further use + */ +void CATerminateWIfI(); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif//#ifndef __CA_WIFI_ADAPTER_H__ diff --git a/resource/csdk/connectivity/inc/cawificore.h b/resource/csdk/connectivity/inc/cawificore.h new file mode 100644 index 000000000..64e7a200c --- /dev/null +++ b/resource/csdk/connectivity/inc/cawificore.h @@ -0,0 +1,83 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +/** + * @file cawificore.h + * @brief This file contains the APIs for Wi-Fi communications. + */ +#ifndef __CA_WIFICORE_H_ +#define __CA_WIFICORE_H_ + +#include "cacommon.h" +#include "config.h" +#include "coap.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef void (*CAPacketReceiveCallback)(const char* address, const char* data); + +void CAWiFiInitialize(); + +void CAWiFiTerminate(); + +int32_t CAWiFiSendUnicastMessage(const char* address, const char* data, int32_t length); + +int32_t CAWiFiSendMulticastMessage(const char* m_address, const char* data); + +int32_t CAWiFiStartUnicastServer(const char* address, int32_t port); + +int32_t CAWiFiStartMulticastServer(const char* m_address, int32_t port); + +int32_t CAWiFiStopUnicastServer(int32_t server_id); + +int32_t CAWiFiStopMulticastServer(int32_t server_id); + +void CAWiFiSetCallback(CAPacketReceiveCallback callback); + +void* CAUnicastReceiveThread(void* data); + +void* CAUnicastSendThread(void* data); + +void CASendUnicastMessage(char* address, void* data); + +int32_t CASendUnicastMessageImpl(const char* address, const char* data, int32_t lengh); + +void CAStopUnicastSendThread(); + +void* CAMulticastReceiveThread(void* data); + +void* CAMulticastSendThread(void* data); + +void CASendMulticastMessage(void* data); + +int32_t CASendMulticastMessageImpl(const char* msg); + +void CAStopMulticastSendThread(); + +void CAGetLocalAddress(char* addressBuffer); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/resource/csdk/connectivity/inc/cawifiethernetadapter.h b/resource/csdk/connectivity/inc/cawifiethernetadapter.h new file mode 100644 index 000000000..45dcab85c --- /dev/null +++ b/resource/csdk/connectivity/inc/cawifiethernetadapter.h @@ -0,0 +1,137 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +/** + * @file cawifiethernetadapter.h + * @brief This file contains the APIs for WiFi/Ethernet Adapter. + */ +#ifndef __CA_WIFI_ETHERNET_ADAPTER_H__ +#define __CA_WIFI_ETHERNET_ADAPTER_H__ + +#include "cacommon.h" +#include "caadapterinterface.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @brief API to initialize WiFi Interface. + * @param registerCallback to register WIFI interfaces to things communication + * @param reqRespCallback for sending responses and discovery messages from unicast , multicast servers + * @param netCallback to intimate the network additions to things communication + * @return Error Code + */ +CAResult_t CAInitializeWifi(CARegisterConnectivityCallback registerCallback, + CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback); + +/** + * @brief API to Start WiFi Interface. + * @return Error Code + */ +CAResult_t CAStartWIFI(); + +/** + * @brief starting listening server + * Transport Specific Behaviour + * IP :- Start Multicast Server on all available IPs and prefixed port number and as per OIC Specification. + * @return Error Code CAResult_t. + */ +CAResult_t CAStartWIFIListeningServer(); + +/** + * @brief for starting discovery servers. + * Transport Specific Behaviour + * IP :- Start Multicast Server on all available IPs and prefixed port number as per OIC Specification. + * @return CAResult_t. + * CA_STATUS_OK = 0 else ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStartWIFIDiscoveryServer(); + +/** + * @brief Send Multicast Data interface API callback. + * Note: length must be > 0 + * @param endpoint - Endpoint information (like ipaddress , port, reference uri and connectivity type) to which the multicast data has to be sent. + * @param data - void pointer data which will be sent via client + * @param dataLen - size of data to be sent + * @return - Will return the number of bytes sent on the network. Return value equal to zero indicates error. + */ +uint32_t CASendWIFIUnicastData(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen); + +/** + * @brief API to send data to a group of remote addresses. + * @param endpoint - Endpoint information (like ipaddress , port, reference uri and connectivity type) to which the multicast data has to be sent. + * @param data - void pointer data which will be sent via client + * @param dataLen - size of data to be sent + * @return - size of data sent or -1 on error + */ +uint32_t CASendWIFIMulticastData(void* data, uint32_t dataLen); + +/** + * @brief Start Notification Server interface API callback. + * + * @return CAResult_t. + * CA_STATUS_OK = 0 else ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAStartWIFINotifyRecvServers(); + +/** + * @brief Send Notification Data interface API callback. + * Note: length must be > 0 + * @param endpoint - remote endpoint having endpoint details + * @param data - data to be sent + * @param dataLen - length of data to be sent + * @return Will return the number of bytes sent on the network. Return value equal to zero indicates error. + */ +uint32_t CASendWIFINotification(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen); +/** + * @brief Get Network Information + * + * @return CAResult_t. + * CA_STATUS_OK = 0 else ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAGetWIFIInterfaceInformation(CALocalConnectivityt_t** info, uint32_t* size); + +/** + * @brief Read Synchronous API callback. + * @return Error Code CAResult_t. + * @return CAResult_t. + * CA_STATUS_OK = 0 else ERROR CODES ( CAResult_t error codes in cacommon.h) + */ +CAResult_t CAReadWIFIData(); + +/** + * @brief API to Stop WiFi Interface. + * @return CAResult_t + */ +CAResult_t CAStopWIFI(); + +/** + * @brief API to terminate WiFi Interface. + * @return none. + */ +void CATerminateWifi(); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/.gitignore b/resource/csdk/connectivity/lib/libcoap-4.1.1/.gitignore new file mode 100644 index 000000000..10301e28b --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/.gitignore @@ -0,0 +1 @@ +*.a diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/ChangeLog b/resource/csdk/connectivity/lib/libcoap-4.1.1/ChangeLog new file mode 100644 index 000000000..404e33113 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/ChangeLog @@ -0,0 +1,159 @@ +2014-02-04 Olaf Bergmann + + * resource.c (coap_print_link): This function now takes an offset + where printing starts. This is used for generating blocks on the + fly. + + * net.c (wellknown_response): Added support for Block2 options + when generating a response for .well-known/core. + + * block.h (coap_opt_block_num): Fixed handling of zero-length + options. COAP_OPT_BLOCK_LAST now returns NULL when the option + value's length is zero. + +2014-01-07 Olaf Bergmann + + * resource.c (coap_print_link): Output partial resource + descriptions. The function now provides a sliding window over the + textual representation of the resource. Output starts at the given + offset and ends at the buffer's upper bound. The meaning of the + return value has changed to allow distinguishing whether or not + the resource description has been truncated at the buffer's upper + bound. + (print_wellknown): Support for the new coap_print_link(). An + additional parameter now is used to provide the offset into the + resource description. The meaning of the return value has been + adjusted accordingly. + +2013-12-23 Olaf Bergmann + + * configure.in: merged with LWIP port from chrysn + . This + introduces new compiler flags WITH_POSIX and WITH_LWIP to + distinguish target platforms. + +2013-09-03 Olaf Bergmann + + * option.h (coap_option_setb): increased size of option type + argument + + * tests/test_error_response.c (t_init_error_response_tests): new + tests for error response generation + + * tests/test_pdu.c (t_encode_pdu5): fixed number for option Accept + + * net.c (coap_new_error_response): fixed option size calculation + +2013-07-04 Olaf Bergmann + + * net.c (coap_new_context): register critical Accept option + + * pdu.c: option codes for Accept and Size1 according to coap-18 + +2013-02-01 Olaf Bergmann + + * coap_time.h (coap_clock_init_impl): fix invalid preprocessor + directive. #warning is now only used for gcc only (close sf bug #15) + + * net.c (wellknown_response): applied patch from chrysn to + fix bug in generation of .well-known/core representation + +2013-01-21 Olaf Bergmann + + * option.h: renamed option field in coap_opt_iterator_t to + next_option to detect erroneous use in old code + +2013-01-18 Olaf Bergmann + + * configure.in: new option --with-tests to enable unit tests + + * tests/testdriver.c: unit tests for parser functions + + * pdu.c (coap_pdu_parse): new PDU parser for Klaus-encoding + according to coap-13 + + * net.c (coap_read): call coap_pdu_parse() to check PDU integrity + + * option.c: Klaus-encoding for coap-13, including new option + iterator interface + +2012-11-20 Olaf Bergmann + + * net.c (next_option_safe): made option parsing more robust in + presence of option jumps + + * pdu.h: new option codes from draft-ietf-core-coap-12 + + * option.c (coap_opt_setlength): new function to set option length + + * uri.c (make_decoded_option): use coap_opt_setlength() instead of + obsolete macro COAP_OPT_SETLENGTH. + +2012-11-19 Olaf Bergmann + + * uri.c (make_decoded_option): use coap_opt_encode() instead of writing + +2012-11-03 Olaf Bergmann + + * net.c (coap_read): read new option encoding + +2012-11-01 Olaf Bergmann + + * option.c (coap_opt_size, coap_opt_value, coap_opt_length): + several functions to access fields of options (possibly preceeded + by option jump) + +2012-10-25 Olaf Bergmann + + * option.c (coap_opt_encode): new function for option encoding + with option jumps + +2012-03-23 Olaf Bergmann + + * examples/client.c (clear_obs): clear observation relationship after + user-specified duration + +2012-03-21 Olaf Bergmann + + * resource.c (print_wellknown): filtering by attributes + +2012-03-19 Olaf Bergmann + + * pdu.c (coap_add_option): allow more than 15 options. + +2012-03-15 Olaf Bergmann + + * examples/client.c (cmdline_uri): split path and query here to + make it easier to include these options in subsequent requests for + block transfer. + +2012-03-14 Olaf Bergmann + + * examples/etsi_iot_01.c: Support for POST, PUT, DELETE on /test + +2012-03-13 Olaf Bergmann + + * encode.c (coap_encode_var_bytes): more efficient coding for 0 + +2012-03-11 Olaf Bergmann + + * examples/etsi_iot_01.c: Test cases for 1st ETSI CoAP Plugtest, + March 24/25, 2012 in Paris, France. + +2012-03-10 Olaf Bergmann + + * block.c: support for block transfer. + +2012-03-07 Olaf Bergmann + + * examples/client.c (usage): new command line options + -B to set timeout after which the main loop is left. + -e to specify a payload (incompatible with -f) + (message_handler): bugfixes + + * resource.h: (coap_method_handler_t): new API for method handlers. + + +Copyright 2012 Olaf Bergmann, TZI +Copying and distribution of this file, with or without modification, are +permitted provided the copyright notice and this notice are preserved. diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/LICENSE.BSD b/resource/csdk/connectivity/lib/libcoap-4.1.1/LICENSE.BSD new file mode 100644 index 000000000..2fc333a5d --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/LICENSE.BSD @@ -0,0 +1,26 @@ +Copyright (c) 2010--2011, Olaf Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + o Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + o Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/LICENSE.GPL b/resource/csdk/connectivity/lib/libcoap-4.1.1/LICENSE.GPL new file mode 100644 index 000000000..d8cf7d463 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/LICENSE.GPL @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/Makefile b/resource/csdk/connectivity/lib/libcoap-4.1.1/Makefile new file mode 100644 index 000000000..23475f8e8 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/Makefile @@ -0,0 +1,113 @@ +# Makefile for libcoap +# +# Copyright (C) 2010--2013 Olaf Bergmann +# +# This file is part of the CoAP library libcoap. Please see +# README for terms of use. + +# the library's version +VERSION:=4.1.1 + +# tools + +RANLIB=ranlib +SHELL = /bin/sh +MKDIR = mkdir +ETAGS = /bin/false + +abs_builddir = /connectivity/connectivity/src/bt_edr_adapter/libcoap-4.1.1 +top_builddir = . +package = libcoap-4.1.1 + +# files and flags +SOURCES:= pdu.c net.c debug.c encode.c uri.c coap_list.c resource.c hashkey.c \ + str.c option.c async.c subscribe.c block.c +OBJECTS:= $(patsubst %.c, %.o, $(SOURCES)) +HEADERS:=coap.h config.h debug.h pdu.h net.h encode.h uri.h coap_list.h mem.h \ + str.h option.h bits.h uthash.h utlist.h resource.h hashkey.h async.h \ + subscribe.h block.h address.h prng.h coap_time.h t_list.h +CFLAGS:=-Wall -Wextra -std=c99 -pedantic -g -O2 +CPPFLAGS:= -DWITH_POSIX +DISTDIR=$(top_builddir)/$(package) +SUBDIRS:=#examples #doc tests +FILES:=ChangeLog README LICENSE.BSD LICENSE.GPL Makefile.in configure configure.in config.h.in $(SOURCES) $(HEADERS) +LIB:=libcoap.a +LDSOFLAGS=-shared +LDFLAGS:= +ARFLAGS:=cru +examples:=examples +doc:=doc + + +ifdef BUILD_SO + MACHINE?=$(shell $(CC) -dumpmachine) + ifeq ($(findstring Darwin, $(MACHINE)), Darwin) + LDSOFLAGS=-dynamiclib + LIBSO=libcoap.dylib + endif + ifeq ($(findstring Windows, $(MACHINE)), Windows) + LIBSO=libcoap.dll + endif + # more platforms go here + ifndef LIBSO + LIBSO=libcoap.so + endif + ifndef PICFLAG + CFLAGS+=-fPIC + else + CFLAGS+=$(PICFLAG) + endif +endif + +.PHONY: all dirs clean distclean .gitignore doc TAGS + +.SUFFIXES: +.SUFFIXES: .c .o + +all: $(LIB) $(LIBSO) dirs + +check: + echo DISTDIR: $(DISTDIR) + echo top_builddir: $(top_builddir) + $(MAKE) -C examples check + +dirs: $(SUBDIRS) + for dir in $^; do \ + $(MAKE) -C $$dir ; \ + done + +$(LIB): $(OBJECTS) + $(AR) $(ARFLAGS) $@ $^ + $(RANLIB) $@ + +$(LIBSO): $(OBJECTS) + $(LD) $(LDSOFLAGS) $(LDFLAGS) -o $@ $^ + +clean: + @rm -f $(PROGRAM) main.o $(LIB) $(LIBSO) $(OBJECTS) + for dir in $(SUBDIRS); do \ + $(MAKE) -C $$dir clean ; \ + done + +doc: + $(MAKE) -C doc + +distclean: clean + @rm -rf $(DISTDIR) + @rm -f *~ $(DISTDIR).tar.gz + +dist: $(FILES) $(SUBDIRS) + test -d $(DISTDIR) || mkdir $(DISTDIR) + cp $(FILES) $(DISTDIR) + for dir in $(SUBDIRS); do \ + $(MAKE) -C $$dir dist; \ + done + tar czf $(package).tar.gz $(DISTDIR) + +TAGS: + $(ETAGS) -o $@.new $(SOURCES) + $(ETAGS) -a -o $@.new $(HEADERS) + mv $@.new $@ + +.gitignore: + echo "core\n*~\n*.[oa]\n*.gz\n*.cap\n$(PROGRAM)\n$(DISTDIR)\n.gitignore" >$@ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/Makefile.in b/resource/csdk/connectivity/lib/libcoap-4.1.1/Makefile.in new file mode 100644 index 000000000..d9b1c555a --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/Makefile.in @@ -0,0 +1,113 @@ +# Makefile for libcoap +# +# Copyright (C) 2010--2013 Olaf Bergmann +# +# This file is part of the CoAP library libcoap. Please see +# README for terms of use. + +# the library's version +VERSION:=@PACKAGE_VERSION@ + +# tools +@SET_MAKE@ +RANLIB=@RANLIB@ +SHELL = /bin/sh +MKDIR = mkdir +ETAGS = @ETAGS@ + +abs_builddir = @abs_builddir@ +top_builddir = @top_builddir@ +package = @PACKAGE_TARNAME@-@PACKAGE_VERSION@ + +# files and flags +SOURCES:= pdu.c net.c debug.c encode.c uri.c coap_list.c resource.c hashkey.c \ + str.c option.c async.c subscribe.c block.c +OBJECTS:= $(patsubst %.c, %.o, $(SOURCES)) +HEADERS:=coap.h config.h debug.h pdu.h net.h encode.h uri.h coap_list.h mem.h \ + str.h option.h bits.h uthash.h utlist.h resource.h hashkey.h async.h \ + subscribe.h block.h address.h prng.h coap_time.h t_list.h +CFLAGS:=-Wall -Wextra -std=c99 -pedantic @CFLAGS@ +CPPFLAGS:=@CPPFLAGS@ +DISTDIR=$(top_builddir)/$(package) +SUBDIRS:=examples doc tests +FILES:=ChangeLog README LICENSE.BSD LICENSE.GPL Makefile.in configure configure.in config.h.in $(SOURCES) $(HEADERS) +LIB:=libcoap.a +LDSOFLAGS=-shared +LDFLAGS:=@LIBS@ +ARFLAGS:=cru +examples:=examples +doc:=doc +@BUILD_SO@ + +ifdef BUILD_SO + MACHINE?=$(shell $(CC) -dumpmachine) + ifeq ($(findstring Darwin, $(MACHINE)), Darwin) + LDSOFLAGS=-dynamiclib + LIBSO=libcoap.dylib + endif + ifeq ($(findstring Windows, $(MACHINE)), Windows) + LIBSO=libcoap.dll + endif + # more platforms go here + ifndef LIBSO + LIBSO=libcoap.so + endif + ifndef PICFLAG + CFLAGS+=-fPIC + else + CFLAGS+=$(PICFLAG) + endif +endif + +.PHONY: all dirs clean distclean .gitignore doc TAGS + +.SUFFIXES: +.SUFFIXES: .c .o + +all: $(LIB) $(LIBSO) dirs + +check: + echo DISTDIR: $(DISTDIR) + echo top_builddir: $(top_builddir) + $(MAKE) -C examples check + +dirs: $(SUBDIRS) + for dir in $^; do \ + $(MAKE) -C $$dir ; \ + done + +$(LIB): $(OBJECTS) + $(AR) $(ARFLAGS) $@ $^ + $(RANLIB) $@ + +$(LIBSO): $(OBJECTS) + $(LD) $(LDSOFLAGS) $(LDFLAGS) -o $@ $^ + +clean: + @rm -f $(PROGRAM) main.o $(LIB) $(LIBSO) $(OBJECTS) + for dir in $(SUBDIRS); do \ + $(MAKE) -C $$dir clean ; \ + done + +doc: + $(MAKE) -C doc + +distclean: clean + @rm -rf $(DISTDIR) + @rm -f *~ $(DISTDIR).tar.gz + +dist: $(FILES) $(SUBDIRS) + test -d $(DISTDIR) || mkdir $(DISTDIR) + cp $(FILES) $(DISTDIR) + for dir in $(SUBDIRS); do \ + $(MAKE) -C $$dir dist; \ + done + tar czf $(package).tar.gz $(DISTDIR) + +TAGS: + $(ETAGS) -o $@.new $(SOURCES) + $(ETAGS) -a -o $@.new $(HEADERS) + mv $@.new $@ + +.gitignore: + echo "core\n*~\n*.[oa]\n*.gz\n*.cap\n$(PROGRAM)\n$(DISTDIR)\n.gitignore" >$@ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/README b/resource/csdk/connectivity/lib/libcoap-4.1.1/README new file mode 100644 index 000000000..5faa3dc49 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/README @@ -0,0 +1,27 @@ +libcoap: A C implementation of IETF Core Application protocol + +Copyright (C) 2010--2013 by Olaf Bergmann + +ABOUT LIBCOAP + +libcoap is a C implementation of a lightweight application-protocol +for devices that are constrained their resources such as computing +power, RF range, memory, bandwith, or network packet sizes. This +protocol, CoAP, is developed in the IETF working group "Constrained +RESTful Environments (core)", see . + +PACKAGE CONTENTS + +This directory contains a protocol parser and basic networking +functions for platform with support for malloc() and BSD-style +sockets. The examples directory contains a client and a server to +demonstrate the use of this library. + +LICENSE INFORMATION + +This library is published as open-source software without any warranty +of any kind. Use is permitted under the terms of the GNU General +Public License (GPL), Version 2 or higher, OR the revised BSD +license. Please refer to LICENSE.GPL oder LICENSE.BSD for further +details. + diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/address.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/address.h new file mode 100644 index 000000000..24ebce74d --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/address.h @@ -0,0 +1,176 @@ +/* address.h -- representation of network addresses + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file address.h + * @brief representation of network addresses + */ + +#ifndef _COAP_ADDRESS_H_ +#define _COAP_ADDRESS_H_ + +#include "config.h" + +#ifdef HAVE_ASSERT_H +#include +#else +#ifndef assert +#warning "assertions are disabled" +# define assert(x) +#endif +#endif + +#include +#include + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef WITH_LWIP +#include + +typedef struct coap_address_t +{ + uint16_t port; + ip_addr_t addr; +}coap_address_t; + +/* FIXME oversimplification: just assuming it's an ipv4 address instead of + * looking up the appropraite lwip function */ + +#define _coap_address_equals_impl(A, B) ((A)->addr.addr == (B)->addr.addr && A->port == B->port) + +/* FIXME sure there is something in lwip */ + +#define _coap_is_mcast_impl(Address) 0 + +#endif /* WITH_LWIP */ +#ifdef WITH_CONTIKI +#include "uip.h" + +typedef struct coap_address_t +{ + unsigned char size; + uip_ipaddr_t addr; + unsigned short port; +}coap_address_t; + +#define _coap_address_equals_impl(A,B) \ + ((A)->size == (B)->size \ + && (A)->port == (B)->port \ + && uip_ipaddr_cmp(&((A)->addr),&((B)->addr))) + +#define _coap_is_mcast_impl(Address) uip_is_addr_mcast(&((Address)->addr)) +#endif /* WITH_CONTIKI */ +#ifdef WITH_POSIX + +/** multi-purpose address abstraction */ +typedef struct coap_address_t +{ + socklen_t size; /**< size of addr */ + union + { + struct sockaddr sa; + struct sockaddr_storage st; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + }addr; +}coap_address_t; + +static inline int +_coap_address_equals_impl(const coap_address_t *a, + const coap_address_t *b) +{ + if (a->size != b->size || a->addr.sa.sa_family != b->addr.sa.sa_family) + return 0; + + /* need to compare only relevant parts of sockaddr_in6 */ + switch (a->addr.sa.sa_family) + { + case AF_INET: + return + a->addr.sin.sin_port == b->addr.sin.sin_port && + memcmp(&a->addr.sin.sin_addr, &b->addr.sin.sin_addr, + sizeof(struct in_addr)) == 0; + case AF_INET6: + return a->addr.sin6.sin6_port == b->addr.sin6.sin6_port && + memcmp(&a->addr.sin6.sin6_addr, &b->addr.sin6.sin6_addr, + sizeof(struct in6_addr)) == 0; + default: /* fall through and signal error */ + ; + } + return 0; +} + +static inline int +_coap_is_mcast_impl(const coap_address_t *a) +{ + if (!a) + { + printf("[COAP] address - coap_address_t is false\n"); + return 0; + } + switch (a->addr.sa.sa_family) + { + case AF_INET: + printf("[COAP] address - local address : %s\n", a->addr.sin.sin_addr.s_addr); + return IN_MULTICAST(a->addr.sin.sin_addr.s_addr); + case AF_INET6: + return IN6_IS_ADDR_MULTICAST(&a->addr.sin6.sin6_addr); + default: /* fall through and signal error */ + printf("[COAP] address - sa_family is default value\n"); + ; + } + return 0; +} +#endif /* WITH_POSIX */ + +/** + * Resets the given coap_address_t object @p addr to its default + * values. In particular, the member size must be initialized to the + * available size for storing addresses. + * + * @param addr The coap_address_t object to initialize. + */ +static inline void coap_address_init(coap_address_t *addr) +{ + assert(addr); + memset(addr, 0, sizeof(coap_address_t)); +#ifndef WITH_LWIP + /* lwip has constandt address sizes and doesn't need the .size part */ + addr->size = sizeof(addr->addr); +#endif +} + +/** + * Compares given address objects @p a and @p b. This function returns + * @c 1 if addresses are equal, @c 0 otherwise. The parameters @p a + * and @p b must not be @c NULL; + */ +static inline int coap_address_equals(const coap_address_t *a, const coap_address_t *b) +{ + assert(a); + assert(b); + return _coap_address_equals_impl(a, b); +} + +/** + * Checks if given address @p a denotes a multicast address. This + * function returns @c 1 if @p a is multicast, @c 0 otherwise. + */ +static inline int coap_is_mcast(const coap_address_t *a) +{ + return a && _coap_is_mcast_impl(a); +} + +#endif /* _COAP_ADDRESS_H_ */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/async.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/async.c new file mode 100644 index 000000000..8c6ec2627 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/async.c @@ -0,0 +1,105 @@ +/* async.c -- state management for asynchronous messages + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file async.c + * @brief state management for asynchronous messages + */ + +#ifndef WITHOUT_ASYNC + +#include "config.h" + +#include "utlist.h" + +#include "mem.h" +#include "debug.h" +#include "async.h" + +coap_async_state_t * +coap_register_async(coap_context_t *context, coap_address_t *peer, coap_pdu_t *request, + unsigned char flags, void *data) +{ + coap_async_state_t *s; + coap_tid_t id; + + coap_transaction_id(peer, request, &id); + LL_SEARCH_SCALAR(context->async_state, s, id, id); + + if (s != NULL) + { + /* We must return NULL here as the caller must know that he is + * responsible for releasing @p data. */ + debug("asynchronous state for transaction %d already registered\n", id); + return NULL; + } + + /* store information for handling the asynchronous task */ + s = (coap_async_state_t *) coap_malloc(sizeof(coap_async_state_t) + + request->hdr->token_length); + if (!s) + { + coap_log(LOG_CRIT, "coap_register_async: insufficient memory\n"); + return NULL; + } + + memset(s, 0, sizeof(coap_async_state_t) + request->hdr->token_length); + + /* set COAP_ASYNC_CONFIRM according to request's type */ + s->flags = flags & ~COAP_ASYNC_CONFIRM; + if (request->hdr->type == COAP_MESSAGE_CON) + s->flags |= COAP_ASYNC_CONFIRM; + + s->appdata = data; + + memcpy(&s->peer, peer, sizeof(coap_address_t)); + + if (request->hdr->token_length) + { + s->tokenlen = request->hdr->token_length; + memcpy(s->token, request->hdr->token, request->hdr->token_length); + } + + memcpy(&s->id, &id, sizeof(coap_tid_t)); + + coap_touch_async(s); + + LL_PREPEND(context->async_state, s); + + return s; +} + +coap_async_state_t * +coap_find_async(coap_context_t *context, coap_tid_t id) +{ + coap_async_state_t *tmp; + LL_SEARCH_SCALAR(context->async_state, tmp, id, id); + return tmp; +} + +int coap_remove_async(coap_context_t *context, coap_tid_t id, coap_async_state_t **s) +{ + coap_async_state_t *tmp = coap_find_async(context, id); + + if (tmp) + LL_DELETE(context->async_state, tmp); + + *s = tmp; + return tmp != NULL; +} + +void coap_free_async(coap_async_state_t *s) +{ + if (s && (s->flags & COAP_ASYNC_RELEASE_DATA) != 0) + coap_free(s->appdata); + coap_free(s); +} + +#else +void does_not_exist(); /* make some compilers happy */ +#endif /* WITHOUT_ASYNC */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/async.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/async.h new file mode 100644 index 000000000..9f6c7b02c --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/async.h @@ -0,0 +1,148 @@ +/* async.h -- state management for asynchronous messages + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file async.h + * @brief state management for asynchronous messages + */ + +#ifndef _COAP_ASYNC_H_ +#define _COAP_ASYNC_H_ + +#include "config.h" +#include "net.h" + +#ifndef WITHOUT_ASYNC + +/** + * @defgroup coap_async Asynchronous Messaging + * @{ + * Structure for managing asynchronous state of CoAP resources. A + * coap_resource_t object holds a list of coap_async_state_t objects + * that can be used to generate a separate response in case a result + * of an operation cannot be delivered in time, or the resource has + * been explicitly subscribed to with the option @c observe. + */ +typedef struct coap_async_state_t +{ + unsigned char flags; /**< holds the flags to control behaviour */ + + /** + * Holds the internal time when the object was registered with a + * resource. This field will be updated whenever + * coap_register_async() is called for a specific resource. + */ + coap_tick_t created; + + /** + * This field can be used to register opaque application data with + * the asynchronous state object. */ + void *appdata; + + unsigned short message_id; /**< id of last message seen */ + coap_tid_t id; /**< transaction id */ + + struct coap_async_state_t *next; /**< internally used for linking */ + + coap_address_t peer; /**< the peer to notify */ + size_t tokenlen; /**< length of the token */ + unsigned char token[]; /**< the token to use in a response */ +} coap_async_state_t; + +/* Definitions for Async Status Flags These flags can be used to + * control the behaviour of asynchronous response generation. */ +#define COAP_ASYNC_CONFIRM 0x01 /**< send confirmable response */ +#define COAP_ASYNC_SEPARATE 0x02 /**< send separate response */ +#define COAP_ASYNC_OBSERVED 0x04 /**< the resource is being observed */ + +/** release application data on destruction */ +#define COAP_ASYNC_RELEASE_DATA 0x08 + +/** + * Allocates a new coap_async_state_t object and fills its fields + * according to the given @p request. The @p flags are used to control + * generation of empty ACK responses to stop retransmissions and to + * release registered @p data when the resource is deleted by + * coap_free_async(). This function returns a pointer to the registered + * coap_async_t object or @c NULL on error. Note that this function will + * return @c NULL in case that an object with the same identifier is + * already registered. + * + * @param context The context to use. + * @param peer The remote peer that is to be asynchronously notified. + * @param request The request that is handled asynchronously. + * @param flags Flags to control state management. + * @param data Opaque application data to register. Note that the + * storage occupied by @p data is released on destruction + * only if flag COAP_ASYNC_RELEASE_DATA is set. + * + * @return A pointer to the registered coap_async_state_t object or + * @c NULL in case of an error. + */ +coap_async_state_t * +coap_register_async(coap_context_t *context, coap_address_t *peer, coap_pdu_t *request, + unsigned char flags, void *data); + +/** + * Removes the state object identified by @p id from @p context. The + * removed object is returned in @p s, if found. Otherwise, @p s is + * undefined. This function returns @c 1 if the object was removed, @c + * 0 otherwise. Note that the storage allocated for the stored object + * is not released by this functions. You will have to call + * coap_free_async() to do so. + * + * @param context The context where the async object is registered. + * @param id The identifier of the asynchronous transaction. + * @param s Will be set to the object identified by @p id + * after removal. + * + * @return @c 1 if object was removed and @p s updated, or @c 0 if no + * object was found with the given id. @p s is valid only if the + * return value is @c 1. + */ +int coap_remove_async(coap_context_t *context, coap_tid_t id, coap_async_state_t **s); + +/** + * Releases the memory that was allocated by coap_async_state_init() + * for the object @p s. The registered application data will be + * released automatically if COAP_ASYNC_RELEASE_DATA is set. + * + * @param s The object to delete. + */ +void +coap_free_async(coap_async_state_t *state); + +/** + * Retrieves the object identified by @p id from the list of asynchronous + * transactions that are registered with @p context. This function returns + * a pointer to that object or @c NULL if not found. + * + * @param context The context where the asynchronous objects are + * registered with. + * @param id The id of the object to retrieve. + * + * @return A pointer to the object identified by @p id or @c NULL if + * not found. + */ +coap_async_state_t *coap_find_async(coap_context_t *context, coap_tid_t id); + +/** + * Updates the time stamp of @p s. + * + * @param s The state object to update. + */ +static inline void coap_touch_async(coap_async_state_t *s) +{ + coap_ticks(&s->created); +} + +/** @} */ + +#endif /* WITHOUT_ASYNC */ + +#endif /* _COAP_ASYNC_H_ */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/bits.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/bits.h new file mode 100644 index 000000000..487af392d --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/bits.h @@ -0,0 +1,79 @@ +/* + * bits.h -- bit vector manipulation + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file bits.h + * @brief bit vector manipulation + */ + +#ifndef _BITS_H_ +#define _BITS_H_ + +#include +#include + +/** + * Sets the bit @p bit in bit-vector @p vec. This function returns @c + * 1 if bit was set or @c -1 on error (i.e. when the given bit does + * not fit in the vector). + * + * @param vec The bit-vector to change. + * @param size The size of @p vec in bytes. + * @param bit The bit to set in @p vec. + * + * @return @c -1 if @p bit does not fit into @p vec, @c 1 otherwise. + */ +inline static int bits_setb(uint8_t *vec, size_t size, uint8_t bit) +{ + if (size <= (bit >> 3)) + return -1; + + *(vec + (bit >> 3)) |= (uint8_t)(1 << (bit & 0x07)); + return 1; +} + +/** + * Clears the bit @p bit from bit-vector @p vec. This function returns + * @c 1 if bit was cleared or @c -1 on error (i.e. when the given bit + * does not fit in the vector). + * + * @param vec The bit-vector to change. + * @param size The size of @p vec in bytes. + * @param bit The bit to clear from @p vec. + * + * @return @c -1 if @p bit does not fit into @p vec, @c 1 otherwise. + */ +inline static int bits_clrb(uint8_t *vec, size_t size, uint8_t bit) +{ + if (size <= (bit >> 3)) + return -1; + + *(vec + (bit >> 3)) &= (uint8_t)(~(1 << (bit & 0x07))); + return 1; +} + +/** + * Gets the status of bit @p bit from bit-vector @p vec. This function returns + * @c 1 if the bit is set, @c 0 otherwise (even in case of an error).. + * + * @param vec The bit-vector to read from.. + * @param size The size of @p vec in bytes. + * @param bit The bit to get from @p vec. + * + * @return @c 1 if the bit is set, @c 0 otherwise. + */ +inline static int bits_getb(const uint8_t *vec, size_t size, uint8_t bit) +{ + if (size <= (bit >> 3)) + return -1; + + return (*(vec + (bit >> 3)) & (1 << (bit & 0x07))) != 0; +} + +#endif /* _BITS_H_ */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/block.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/block.c new file mode 100644 index 000000000..3ad47e395 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/block.c @@ -0,0 +1,140 @@ +/* block.c -- block transfer + * + * Copyright (C) 2010--2012 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "config.h" + +#if defined(HAVE_ASSERT_H) && !defined(assert) +# include +#endif + +#include "debug.h" +#include "block.h" + +#define min(a,b) ((a) < (b) ? (a) : (b)) + +#ifndef WITHOUT_BLOCK +unsigned int coap_opt_block_num(const coap_opt_t *block_opt) +{ + unsigned int num = 0; + unsigned short len; + + len = coap_opt_length(block_opt); + + if (len == 0) + { + return 0; + } + + if (len > 1) + { + num = coap_decode_var_bytes(COAP_OPT_VALUE(block_opt), COAP_OPT_LENGTH(block_opt) - 1); + } + + return (num << 4) | ((*COAP_OPT_BLOCK_LAST(block_opt) & 0xF0) >> 4); +} + +int coap_get_block(coap_pdu_t *pdu, unsigned short type, coap_block_t *block) +{ + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + + assert(block); + memset(block, 0, sizeof(coap_block_t)); + + if (pdu && (option = coap_check_option(pdu, type, &opt_iter))) + { + block->szx = COAP_OPT_BLOCK_SZX(option); + if (COAP_OPT_BLOCK_MORE(option)) + block->m = 1; + block->num = coap_opt_block_num(option); + return 1; + } + + return 0; +} + +int coap_write_block_opt(coap_block_t *block, unsigned short type, coap_pdu_t *pdu, + size_t data_length) +{ + size_t start, want, avail; + unsigned char buf[3]; + + assert(pdu); + + /* Block2 */ + if (type != COAP_OPTION_BLOCK2) + { + warn("coap_write_block_opt: skipped unknown option\n"); + return -1; + } + + start = block->num << (block->szx + 4); + if (data_length <= start) + { + debug("illegal block requested\n"); + return -2; + } + + avail = pdu->max_size - pdu->length - 4; + want = 1 << (block->szx + 4); + + /* check if entire block fits in message */ + if (want <= avail) + { + block->m = want < data_length - start; + } + else + { + /* Sender has requested a block that is larger than the remaining + * space in pdu. This is ok if the remaining data fits into the pdu + * anyway. The block size needs to be adjusted only if there is more + * data left that cannot be delivered in this message. */ + + if (data_length - start <= avail) + { + + /* it's the final block and everything fits in the message */ + block->m = 0; + } + else + { + unsigned char szx; + + /* we need to decrease the block size */ + if (avail < 16) + { /* bad luck, this is the smallest block size */ + debug("not enough space, even the smallest block does not fit"); + return -3; + } + debug("decrease block size for %d to %d\n", avail, coap_fls(avail) - 5); + szx = block->szx; + block->szx = coap_fls(avail) - 5; + block->m = 1; + block->num <<= szx - block->szx; + } + } + + /* to re-encode the block option */ + coap_add_option(pdu, type, + coap_encode_var_bytes(buf, ((block->num << 4) | (block->m << 3) | block->szx)), buf); + + return 1; +} + +int coap_add_block(coap_pdu_t *pdu, unsigned int len, const unsigned char *data, + unsigned int block_num, unsigned char block_szx) +{ + size_t start; + start = block_num << (block_szx + 4); + + if (len <= start) + return 0; + + return coap_add_data(pdu, min(len - start, (unsigned int)(1 << (block_szx + 4))), data + start); +} +#endif /* WITHOUT_BLOCK */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/block.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/block.h new file mode 100644 index 000000000..64513833d --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/block.h @@ -0,0 +1,138 @@ +/* block.h -- block transfer + * + * Copyright (C) 2010--2012,2014 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef _COAP_BLOCK_H_ +#define _COAP_BLOCK_H_ + +#include "option.h" +#include "encode.h" +#include "pdu.h" + +/** + * @defgroup block Block Transfer + * @{ + */ + +#ifndef COAP_MAX_BLOCK_SZX +/** + * The largest value for the SZX component in a Block option. Note + * that 1 << (COAP_MAX_BLOCK_SZX + 4) should not exceed + * COAP_MAX_PDU_SIZE. + */ +#define COAP_MAX_BLOCK_SZX 4 +#endif /* COAP_MAX_BLOCK_SZX */ + +#if (COAP_MAX_PDU_SIZE - 6) < (1 << (COAP_MAX_BLOCK_SZX + 4)) +#error "COAP_MAX_BLOCK_SZX too large" +#endif + +/** + * Structure of Block options. + */ +typedef struct +{ + unsigned int num :20; /**< block number */ + unsigned int m :1; /**< 1 if more blocks follow, 0 otherwise */ + unsigned int szx :3; /**< block size */ +} coap_block_t; + +/** + * Returns the value of the least significant byte of a Block option @p opt. + * For zero-length options (i.e. num == m == szx == 0), COAP_OPT_BLOCK_LAST + * returns @c NULL. + */ +#define COAP_OPT_BLOCK_LAST(opt) \ + (COAP_OPT_LENGTH(opt) ? (COAP_OPT_VALUE(opt) + (COAP_OPT_LENGTH(opt)-1)) : 0) + +/** Returns the value of the More-bit of a Block option @p opt. */ +#define COAP_OPT_BLOCK_MORE(opt) \ + (COAP_OPT_LENGTH(opt) ? (*COAP_OPT_BLOCK_LAST(opt) & 0x08) : 0) + +/** Returns the value of the SZX-field of a Block option @p opt. */ +#define COAP_OPT_BLOCK_SZX(opt) \ + (COAP_OPT_LENGTH(opt) ? (*COAP_OPT_BLOCK_LAST(opt) & 0x07) : 0) + +/** + * Returns the value of field @c num in the given block option @p + * block_opt. + */ +unsigned int coap_opt_block_num(const coap_opt_t *block_opt); + +/** + * Checks if more than @p num blocks are required to deliver @p data_len + * bytes of data for a block size of 1 << (@p szx + 4). + */ +static inline int coap_more_blocks(size_t data_len, unsigned int num, unsigned short szx) +{ + return ((num + 1) << (szx + 4)) < data_len; +} + +/** Sets the More-bit in @p block_opt */ +static inline void coap_opt_block_set_m(coap_opt_t *block_opt, int m) +{ + if (m) + *(COAP_OPT_VALUE(block_opt) + (COAP_OPT_LENGTH(block_opt) - 1)) |= 0x08; + else + *(COAP_OPT_VALUE(block_opt) + (COAP_OPT_LENGTH(block_opt) - 1)) &= ~0x08; +} + +/** + * Initializes @p block from @p pdu. @p type must be either COAP_OPTION_BLOCK1 + * or COAP_OPTION_BLOCK2. When option @p type was found in @p pdu, @p block + * is initialized with values from this option and the function returns the + * value @c 1. Otherwise, @c 0 is returned. + * + * @param pdu The pdu to search for option @p type. + * @param type The option to search for (must be COAP_OPTION_BLOCK1 or + * COAP_OPTION_BLOCK2) + * @param block The block structure to initilize. + * @return @c 1 on success, @c 0 otherwise. + */ +int coap_get_block(coap_pdu_t *pdu, unsigned short type, coap_block_t *block); + +/** + * Writes a block option of type @p type to message @p pdu. If the + * requested block size is too large to fit in @p pdu, it is reduced + * accordingly. An exception is made for the final block when less + * space is required. The actual length of the resource is specified + * in @p data_length. + * + * This function may change *block to reflect the values written to + * @p pdu. As the function takes into consideration the remaining space + * @p pdu, no more options should be added after coap_write_block_opt() + * has returned. + * + * @param block The block structure to use. On return, this object + * is updated according to the values that have been + * written to @p pdu. + * @param type COAP_OPTION_BLOCK1 or COAP_OPTION_BLOCK2 + * @param pdu The message where the block option should be + * written. + * @param data_length The length of the actual data that will be added + * the @p pdu by calling coap_add_block(). + * @return @c 1 on success, or a negative value on error. + */ +int coap_write_block_opt(coap_block_t *block, unsigned short type, coap_pdu_t *pdu, + size_t data_length); + +/** + * Adds the @p block_num block of size 1 << (@p block_szx + 4) from + * source @p data to @p pdu. + * + * @param pdu The message to add the block + * @param len The length of @p data. + * @param data The source data to fill the block with + * @param block_num The actual block number + * @param block_szx Encoded size of block @p block_number + * @return @c 1 on success, @c 0 otherwise. + */ +int coap_add_block(coap_pdu_t *pdu, unsigned int len, const unsigned char *data, + unsigned int block_num, unsigned char block_szx); +/**@}*/ + +#endif /* _COAP_BLOCK_H_ */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/coap.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/coap.h new file mode 100644 index 000000000..d4bf9c5d9 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/coap.h @@ -0,0 +1,36 @@ +/* coap.h -- main header file for CoAP stack + * + * Copyright (C) 2010--2012 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef _COAP_H_ +#define _COAP_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "config.h" +#include "debug.h" +#include "mem.h" +#include "coap_list.h" +#include "pdu.h" +#include "option.h" +#include "net.h" +#include "encode.h" +#include "str.h" +#include "uri.h" +#include "async.h" +#include "resource.h" +#include "subscribe.h" +#include "block.h" + +#ifdef __cplusplus +} +#endif + +#endif /* _COAP_H_ */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/coap_list.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/coap_list.c new file mode 100644 index 000000000..ba31c5438 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/coap_list.c @@ -0,0 +1,92 @@ +/* coap_list.c -- CoAP list structures + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "config.h" + +#include +#include + +#include "debug.h" +#include "mem.h" +#include "coap_list.h" + +int coap_insert(coap_list_t **queue, coap_list_t *node, int (*order)(void *, void *node)) +{ + coap_list_t *p, *q; + if (!queue || !node) + return 0; + + /* set queue head if empty */ + if (!*queue) + { + *queue = node; + return 1; + } + + /* replace queue head if new node has to be added before the existing queue head */ + q = *queue; + if (order(node->data, q->data) < 0) + { + node->next = q; + *queue = node; + return 1; + } + + /* search for right place to insert */ + do + { + p = q; + q = q->next; + } while (q && order(node->data, q->data) >= 0); + + /* insert new item */ + node->next = q; + p->next = node; + return 1; +} + +int coap_delete(coap_list_t *node) +{ + if (!node) + return 0; + + if (node->delete_func) + node->delete_func(node->data); + coap_free( node->data); + coap_free( node); + + return 1; +} + +void coap_delete_list(coap_list_t *queue) +{ + if (!queue) + return; + + coap_delete_list(queue->next); + coap_delete(queue); +} + +coap_list_t * +coap_new_listnode(void *data, void (*delete_func)(void *)) +{ + coap_list_t *node = coap_malloc( sizeof(coap_list_t) ); + if (!node) + { +#ifndef NDEBUG + coap_log(LOG_CRIT, "coap_new_listnode: malloc\n"); +#endif + return NULL; + } + + memset(node, 0, sizeof(coap_list_t)); + node->data = data; + node->delete_func = delete_func; + return node; +} + diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/coap_list.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/coap_list.h new file mode 100644 index 000000000..0c1334b4a --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/coap_list.h @@ -0,0 +1,45 @@ +/* coap_list.h -- CoAP list structures + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef _COAP_LIST_H_ +#define _COAP_LIST_H_ + +struct coap_linkedlistnode +{ + struct coap_linkedlistnode *next; + void *data; + + /** + * Callback function that is called from coap_delete to release + * additional memory allocated by data Set to NULL if you do not + * need this. Note that data is free'd automatically. */ + void (*delete_func)(void *); +}; + +typedef struct coap_linkedlistnode coap_list_t; + +/** + * Adds node to given queue, ordered by specified order function. Returns 1 + * when insert was successful, 0 otherwise. + */ +int coap_insert(coap_list_t **queue, coap_list_t *node, int (*order)(void *, void *)); + +/* destroys specified node */ +int coap_delete(coap_list_t *node); + +/* removes all items from given queue and frees the allocated storage */ +void coap_delete_list(coap_list_t *queue); + +/** + * Creates a new list node and adds the given data object. The memory allocated + * by data will be released by coap_delete() with the new node. Returns the + * new list node. + */ +coap_list_t *coap_new_listnode(void *data, void (*delete_func)(void *)); + +#endif /* _COAP_LIST_H_ */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/coap_time.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/coap_time.h new file mode 100644 index 000000000..041d9a821 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/coap_time.h @@ -0,0 +1,167 @@ +/* coap_time.h -- Clock Handling + * + * Copyright (C) 2010--2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file coap_time.h + * @brief Clock Handling + */ + +#ifndef _COAP_TIME_H_ +#define _COAP_TIME_H_ + +/* + ** Make sure we can call this stuff from C++. + */ +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "config.h" + + /** + * @defgroup clock Clock Handling + * Default implementation of internal clock. You should redefine this if + * you do not have time() and gettimeofday(). + * @{ + */ + +#ifdef WITH_LWIP + +#include +#include + + /* lwIP provides ms in sys_now */ +#define COAP_TICKS_PER_SECOND 1000 + + typedef uint32_t coap_tick_t; + + static inline void coap_ticks_impl(coap_tick_t *t) + { + *t = sys_now(); + } + + static inline void coap_clock_init_impl(void) + { + } + +#define coap_clock_init coap_clock_init_impl + +#define coap_ticks coap_ticks_impl + +#endif +#ifdef WITH_CONTIKI +#include "clock.h" + + typedef clock_time_t coap_tick_t; + + /** + * This data type is used to represent the difference between two + * clock_tick_t values. This data type must have the same size in + * memory as coap_tick_t to allow wrapping. + */ + typedef int coap_tick_diff_t; + +#define COAP_TICKS_PER_SECOND CLOCK_SECOND + + /** Set at startup to initialize the internal clock (time in seconds). */ + extern clock_time_t clock_offset; + + static inline void + contiki_clock_init_impl(void) + { + clock_init(); + clock_offset = clock_time(); + } + +#define coap_clock_init contiki_clock_init_impl + + static inline void + contiki_ticks_impl(coap_tick_t *t) + { + *t = clock_time(); + } + +#define coap_ticks contiki_ticks_impl + +#endif /* WITH_CONTIKI */ +#ifdef WITH_POSIX + typedef unsigned int coap_tick_t; + + /** + * This data type is used to represent the difference between two + * clock_tick_t values. This data type must have the same size in + * memory as coap_tick_t to allow wrapping. + */ + typedef int coap_tick_diff_t; + +#define COAP_TICKS_PER_SECOND 1024 + + /** Set at startup to initialize the internal clock (time in seconds). */ + extern time_t clock_offset; +#endif /* WITH_POSIX */ + +#ifndef coap_clock_init + static inline void coap_clock_init_impl(void) + { +#ifdef HAVE_TIME_H + clock_offset = time(NULL); +#else +# ifdef __GNUC__ + /* Issue a warning when using gcc. Other prepropressors do + * not seem to have a similar feature. */ +# warning "cannot initialize clock" +# endif + clock_offset = 0; +#endif + } +#define coap_clock_init coap_clock_init_impl +#endif /* coap_clock_init */ + +#ifndef coap_ticks + static inline void coap_ticks_impl(coap_tick_t *t) + { +#ifdef HAVE_SYS_TIME_H + struct timeval tv; + gettimeofday(&tv, NULL); + *t = (tv.tv_sec - clock_offset) * COAP_TICKS_PER_SECOND + + (tv.tv_usec * COAP_TICKS_PER_SECOND / 1000000); +#else +#error "clock not implemented" +#endif + } +#define coap_ticks coap_ticks_impl +#endif /* coap_ticks */ + + /** + * Returns @c 1 if and only if @p a is less than @p b where less is + * defined on a signed data type. + */ + static inline + int coap_time_lt(coap_tick_t a, coap_tick_t b) + { + return ((coap_tick_diff_t)(a - b)) < 0; + } + + /** + * Returns @c 1 if and only if @p a is less than or equal @p b where + * less is defined on a signed data type. + */ + static inline + int coap_time_le(coap_tick_t a, coap_tick_t b) + { + return a == b || coap_time_lt(a, b); + } + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* _COAP_TIME_H_ */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/config.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/config.h new file mode 100644 index 000000000..654c4ea04 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/config.h @@ -0,0 +1,132 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `getaddrinfo' function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `coap' library (-lcoap). */ +/* #undef HAVE_LIBCOAP */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#define HAVE_MALLOC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the `select' function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strnlen' function. */ +#define HAVE_STRNLEN 1 + +/* Define to 1 if you have the `strrchr' function. */ +#define HAVE_STRRCHR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYSLOG_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UNISTD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "libcoap" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "libcoap 4.1.1" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "libcoap" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "4.1.1" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Define to rpl_malloc if the replacement function should be used. */ +/* #undef malloc */ + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* Define to `int' if does not define. */ +/* #undef ssize_t */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/config.h.in b/resource/csdk/connectivity/lib/libcoap-4.1.1/config.h.in new file mode 100644 index 000000000..4a0f3c6a3 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/config.h.in @@ -0,0 +1,131 @@ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define if building universal (internal helper macro) */ +#undef AC_APPLE_UNIVERSAL_BUILD + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_INET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ASSERT_H + +/* Define to 1 if you have the `getaddrinfo' function. */ +#undef HAVE_GETADDRINFO + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `coap' library (-lcoap). */ +#undef HAVE_LIBCOAP + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#undef HAVE_MALLOC + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `memset' function. */ +#undef HAVE_MEMSET + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the `select' function. */ +#undef HAVE_SELECT + +/* Define to 1 if you have the `socket' function. */ +#undef HAVE_SOCKET + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strcasecmp' function. */ +#undef HAVE_STRCASECMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strnlen' function. */ +#undef HAVE_STRNLEN + +/* Define to 1 if you have the `strrchr' function. */ +#undef HAVE_STRRCHR + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYSLOG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UNISTD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# undef WORDS_BIGENDIAN +# endif +#endif + +/* Define to rpl_malloc if the replacement function should be used. */ +#undef malloc + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define to `int' if does not define. */ +#undef ssize_t diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/config.status b/resource/csdk/connectivity/lib/libcoap-4.1.1/config.status new file mode 100644 index 000000000..4984732a8 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/config.status @@ -0,0 +1,1020 @@ +#! /bin/bash +# Generated by configure. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=${CONFIG_SHELL-/bin/bash} +export SHELL +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by libcoap $as_me 4.1.1, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +# Files that config.status was made for. +config_files=" Makefile doc/Makefile doc/Doxyfile examples/Makefile tests/Makefile" +config_headers=" config.h" + +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to the package provider." + +ac_cs_config="" +ac_cs_version="\ +libcoap config.status 4.1.1 +configured by ./configure, generated by GNU Autoconf 2.69, + with options \"$ac_cs_config\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='/connectivity/connectivity/src/bt_edr_adapter/libcoap-4.1.1' +srcdir='.' +test -n "$AWK" || AWK=awk +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +if $ac_cs_recheck; then + set X /bin/bash './configure' $ac_configure_extra_args --no-create --no-recursion + shift + $as_echo "running CONFIG_SHELL=/bin/bash $*" >&6 + CONFIG_SHELL='/bin/bash' + export CONFIG_SHELL + exec "$@" +fi + +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; + "doc/Doxyfile") CONFIG_FILES="$CONFIG_FILES doc/Doxyfile" ;; + "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;; + "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +cat >>"$ac_tmp/subs1.awk" <<\_ACAWK && +S["LTLIBOBJS"]="" +S["BUILD_SO"]="" +S["TESTS"]="" +S["LIBOBJS"]="" +S["EGREP"]="/bin/grep -E" +S["GREP"]="/bin/grep" +S["CPP"]="gcc -E" +S["ETAGS"]="/bin/false" +S["DOXYGEN"]=":" +S["RANLIB"]="ranlib" +S["OBJEXT"]="o" +S["EXEEXT"]="" +S["ac_ct_CC"]="gcc" +S["CPPFLAGS"]=" -DWITH_POSIX" +S["LDFLAGS"]="" +S["CFLAGS"]="-g -O2" +S["CC"]="gcc" +S["SET_MAKE"]="" +S["target_alias"]="" +S["host_alias"]="" +S["build_alias"]="" +S["LIBS"]="" +S["ECHO_T"]="" +S["ECHO_N"]="-n" +S["ECHO_C"]="" +S["DEFS"]="-DHAVE_CONFIG_H" +S["mandir"]="${datarootdir}/man" +S["localedir"]="${datarootdir}/locale" +S["libdir"]="${exec_prefix}/lib" +S["psdir"]="${docdir}" +S["pdfdir"]="${docdir}" +S["dvidir"]="${docdir}" +S["htmldir"]="${docdir}" +S["infodir"]="${datarootdir}/info" +S["docdir"]="${datarootdir}/doc/${PACKAGE_TARNAME}" +S["oldincludedir"]="/usr/include" +S["includedir"]="${prefix}/include" +S["localstatedir"]="${prefix}/var" +S["sharedstatedir"]="${prefix}/com" +S["sysconfdir"]="${prefix}/etc" +S["datadir"]="${datarootdir}" +S["datarootdir"]="${prefix}/share" +S["libexecdir"]="${exec_prefix}/libexec" +S["sbindir"]="${exec_prefix}/sbin" +S["bindir"]="${exec_prefix}/bin" +S["program_transform_name"]="s,x,x," +S["prefix"]="/usr/local" +S["exec_prefix"]="${prefix}" +S["PACKAGE_URL"]="" +S["PACKAGE_BUGREPORT"]="" +S["PACKAGE_STRING"]="libcoap 4.1.1" +S["PACKAGE_VERSION"]="4.1.1" +S["PACKAGE_TARNAME"]="libcoap" +S["PACKAGE_NAME"]="libcoap" +S["PATH_SEPARATOR"]=":" +S["SHELL"]="/bin/bash" +_ACAWK +cat >>"$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +D["PACKAGE_NAME"]=" \"libcoap\"" +D["PACKAGE_TARNAME"]=" \"libcoap\"" +D["PACKAGE_VERSION"]=" \"4.1.1\"" +D["PACKAGE_STRING"]=" \"libcoap 4.1.1\"" +D["PACKAGE_BUGREPORT"]=" \"\"" +D["PACKAGE_URL"]=" \"\"" +D["STDC_HEADERS"]=" 1" +D["HAVE_SYS_TYPES_H"]=" 1" +D["HAVE_SYS_STAT_H"]=" 1" +D["HAVE_STDLIB_H"]=" 1" +D["HAVE_STRING_H"]=" 1" +D["HAVE_MEMORY_H"]=" 1" +D["HAVE_STRINGS_H"]=" 1" +D["HAVE_INTTYPES_H"]=" 1" +D["HAVE_STDINT_H"]=" 1" +D["HAVE_UNISTD_H"]=" 1" +D["HAVE_ASSERT_H"]=" 1" +D["HAVE_ARPA_INET_H"]=" 1" +D["HAVE_LIMITS_H"]=" 1" +D["HAVE_NETDB_H"]=" 1" +D["HAVE_NETINET_IN_H"]=" 1" +D["HAVE_STDLIB_H"]=" 1" +D["HAVE_STRING_H"]=" 1" +D["HAVE_STRINGS_H"]=" 1" +D["HAVE_SYS_SOCKET_H"]=" 1" +D["HAVE_SYS_TIME_H"]=" 1" +D["HAVE_TIME_H"]=" 1" +D["HAVE_UNISTD_H"]=" 1" +D["HAVE_SYS_UNISTD_H"]=" 1" +D["HAVE_SYSLOG_H"]=" 1" +D["HAVE_STDLIB_H"]=" 1" +D["HAVE_MALLOC"]=" 1" +D["HAVE_MEMSET"]=" 1" +D["HAVE_SELECT"]=" 1" +D["HAVE_SOCKET"]=" 1" +D["HAVE_STRCASECMP"]=" 1" +D["HAVE_STRRCHR"]=" 1" +D["HAVE_GETADDRINFO"]=" 1" +D["HAVE_STRNLEN"]=" 1" + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+[_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ][_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]*([\t (]|$)/ { + line = $ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} + ac_datarootdir_hack=' + s&@datadir@&${datarootdir}&g + s&@docdir@&${datarootdir}/doc/${PACKAGE_TARNAME}&g + s&@infodir@&${datarootdir}/info&g + s&@localedir@&${datarootdir}/locale&g + s&@mandir@&${datarootdir}/man&g + s&\${datarootdir}&${prefix}/share&g' ;; +esac +ac_sed_extra="/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +} + +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + + esac + +done # for ac_tag + + +as_fn_exit 0 diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/configure b/resource/csdk/connectivity/lib/libcoap-4.1.1/configure new file mode 100644 index 000000000..b6f5dadb5 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/configure @@ -0,0 +1,5411 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for libcoap 4.1.1. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='libcoap' +PACKAGE_TARNAME='libcoap' +PACKAGE_VERSION='4.1.1' +PACKAGE_STRING='libcoap 4.1.1' +PACKAGE_BUGREPORT='' +PACKAGE_URL='' + +ac_unique_file="coap.h" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='LTLIBOBJS +BUILD_SO +TESTS +LIBOBJS +EGREP +GREP +CPP +ETAGS +DOXYGEN +RANLIB +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +SET_MAKE +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +with_contiki +with_debug +with_async +with_block +with_observe +with_query_filter +with_tests +with_shared +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures libcoap 4.1.1 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/libcoap] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of libcoap 4.1.1:";; + esac + cat <<\_ACEOF + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-contiki build libcoap for the Contiki OS + --without-debug disable all debug output and assertions + --without-async disable handling of asynchronous transactions and + observe + --without-block disable block transfer + --without-observe disable resource observation + --without-query-filter disable support for filters on /.well-known/core + --with-tests enable unit tests (requires cunit) + --with-shared build shared library + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +libcoap configure 4.1.1 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by libcoap $as_me 4.1.1, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + +# First check for Contiki build to quit configure before any other test + +# Check whether --with-contiki was given. +if test "${with_contiki+set}" = set; then : + withval=$with_contiki; cp -p Makefile.contiki Makefile + cp -p config.h.contiki config.h + { $as_echo "$as_me:${as_lineno-$LINENO}: Contiki build prepared" >&5 +$as_echo "$as_me: Contiki build prepared" >&6;} + exit 0 +fi + + +# Checks for programs. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +# Extract the first word of "doxygen", so it can be a program name with args. +set dummy doxygen; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_DOXYGEN+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $DOXYGEN in + [\\/]* | ?:[\\/]*) + ac_cv_path_DOXYGEN="$DOXYGEN" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_DOXYGEN="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_DOXYGEN" && ac_cv_path_DOXYGEN=":" + ;; +esac +fi +DOXYGEN=$ac_cv_path_DOXYGEN +if test -n "$DOXYGEN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DOXYGEN" >&5 +$as_echo "$DOXYGEN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "etags", so it can be a program name with args. +set dummy etags; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ETAGS+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ETAGS in + [\\/]* | ?:[\\/]*) + ac_cv_path_ETAGS="$ETAGS" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ETAGS="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_ETAGS" && ac_cv_path_ETAGS="/bin/false" + ;; +esac +fi +ETAGS=$ac_cv_path_ETAGS +if test -n "$ETAGS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ETAGS" >&5 +$as_echo "$ETAGS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; + +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) + +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error $? "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac + + +# Checks for libraries. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for coap_new_pdu in -lcoap" >&5 +$as_echo_n "checking for coap_new_pdu in -lcoap... " >&6; } +if ${ac_cv_lib_coap_coap_new_pdu+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcoap $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char coap_new_pdu (); +int +main () +{ +return coap_new_pdu (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_coap_coap_new_pdu=yes +else + ac_cv_lib_coap_coap_new_pdu=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_coap_coap_new_pdu" >&5 +$as_echo "$ac_cv_lib_coap_coap_new_pdu" >&6; } +if test "x$ac_cv_lib_coap_coap_new_pdu" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBCOAP 1 +_ACEOF + + LIBS="-lcoap $LIBS" + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5 +$as_echo_n "checking for library containing gethostbyname... " >&6; } +if ${ac_cv_search_gethostbyname+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +for ac_lib in '' nsl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_gethostbyname=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_gethostbyname+:} false; then : + break +fi +done +if ${ac_cv_search_gethostbyname+:} false; then : + +else + ac_cv_search_gethostbyname=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5 +$as_echo "$ac_cv_search_gethostbyname" >&6; } +ac_res=$ac_cv_search_gethostbyname +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5 +$as_echo_n "checking for library containing socket... " >&6; } +if ${ac_cv_search_socket+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char socket (); +int +main () +{ +return socket (); + ; + return 0; +} +_ACEOF +for ac_lib in '' socket; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_socket=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_socket+:} false; then : + break +fi +done +if ${ac_cv_search_socket+:} false; then : + +else + ac_cv_search_socket=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5 +$as_echo "$ac_cv_search_socket" >&6; } +ac_res=$ac_cv_search_socket +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + +# configuration options that may change compile flags + +# Check whether --with-debug was given. +if test "${with_debug+set}" = set; then : + withval=$with_debug; CPPFLAGS="${CPPFLAGS} -DNDEBUG" +fi + + + +# Check whether --with-async was given. +if test "${with_async+set}" = set; then : + withval=$with_async; CPPFLAGS="${CPPFLAGS} -DWITHOUT_ASYNC" +fi + + + +# Check whether --with-block was given. +if test "${with_block+set}" = set; then : + withval=$with_block; CPPFLAGS="${CPPFLAGS} -DWITHOUT_BLOCK" +fi + + + +# Check whether --with-observe was given. +if test "${with_observe+set}" = set; then : + withval=$with_observe; CPPFLAGS="${CPPFLAGS} -DWITHOUT_OBSERVE" +fi + + + +# Check whether --with-query-filter was given. +if test "${with_query_filter+set}" = set; then : + withval=$with_query_filter; CPPFLAGS="${CPPFLAGS} -DWITHOUT_QUERY_FILTER" +fi + + + +# Check whether --with-tests was given. +if test "${with_tests+set}" = set; then : + withval=$with_tests; TESTS="tests" +fi + + + +# Check whether --with-shared was given. +if test "${with_shared+set}" = set; then : + withval=$with_shared; BUILD_SO="BUILD_SO=1" +fi + + +# disambiguate between autoconf generated setups and contiki / lwip setups +# which use explicit config.h.* files +CPPFLAGS="${CPPFLAGS} -DWITH_POSIX" + +# Checks for header files. +for ac_header in assert.h arpa/inet.h limits.h netdb.h netinet/in.h stdlib.h string.h strings.h sys/socket.h sys/time.h time.h unistd.h sys/unistd.h syslog.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +# Checks for typedefs, structures, and compiler characteristics. +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default" +if test "x$ac_cv_type_ssize_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define ssize_t int +_ACEOF + +fi + + +# Checks for library functions. +for ac_header in stdlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" +if test "x$ac_cv_header_stdlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDLIB_H 1 +_ACEOF + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 +$as_echo_n "checking for GNU libc compatible malloc... " >&6; } +if ${ac_cv_func_malloc_0_nonnull+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_malloc_0_nonnull=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if defined STDC_HEADERS || defined HAVE_STDLIB_H +# include +#else +char *malloc (); +#endif + +int +main () +{ +return ! malloc (0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_malloc_0_nonnull=yes +else + ac_cv_func_malloc_0_nonnull=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 +$as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } +if test $ac_cv_func_malloc_0_nonnull = yes; then : + +$as_echo "#define HAVE_MALLOC 1" >>confdefs.h + +else + $as_echo "#define HAVE_MALLOC 0" >>confdefs.h + + case " $LIBOBJS " in + *" malloc.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS malloc.$ac_objext" + ;; +esac + + +$as_echo "#define malloc rpl_malloc" >>confdefs.h + +fi + + +for ac_func in memset select socket strcasecmp strrchr getaddrinfo strnlen +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + +ac_config_headers="$ac_config_headers config.h" + + +ac_config_files="$ac_config_files Makefile doc/Makefile doc/Doxyfile examples/Makefile tests/Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by libcoap $as_me 4.1.1, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +libcoap config.status 4.1.1 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; + "doc/Doxyfile") CONFIG_FILES="$CONFIG_FILES doc/Doxyfile" ;; + "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;; + "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/configure.in b/resource/csdk/connectivity/lib/libcoap-4.1.1/configure.in new file mode 100644 index 000000000..77f6c8f37 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/configure.in @@ -0,0 +1,98 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. +# +# Copyright (C) 2010--2014 Olaf Bergmann +# +# This file is part of the CoAP library libcoap. Please see +# README for terms of use. + +AC_PREREQ([2.65]) +AC_INIT([libcoap], [4.1.1]) +AC_CONFIG_SRCDIR([coap.h]) + +# First check for Contiki build to quit configure before any other test +AC_ARG_WITH(contiki, + [AS_HELP_STRING([--with-contiki],[build libcoap for the Contiki OS])], + [cp -p Makefile.contiki Makefile + cp -p config.h.contiki config.h + AC_MSG_NOTICE([Contiki build prepared]) + exit 0], + []) + +# Checks for programs. +AC_PROG_MAKE_SET +AC_PROG_CC +AC_PROG_RANLIB +AC_PATH_PROG(DOXYGEN, doxygen, [:]) +AC_PATH_PROG(ETAGS, etags, [/bin/false]) + +AC_C_BIGENDIAN + +# Checks for libraries. +AC_CHECK_LIB([coap], [coap_new_pdu]) + +AC_SEARCH_LIBS([gethostbyname], [nsl]) +AC_SEARCH_LIBS([socket], [socket]) + +# configuration options that may change compile flags +AC_ARG_WITH(debug, + [AS_HELP_STRING([--without-debug],[disable all debug output and assertions])], + [CPPFLAGS="${CPPFLAGS} -DNDEBUG"], + []) + +AC_ARG_WITH(async, + [AS_HELP_STRING([--without-async],[disable handling of asynchronous transactions and observe])], + [CPPFLAGS="${CPPFLAGS} -DWITHOUT_ASYNC"], + []) + +AC_ARG_WITH(block, + [AS_HELP_STRING([--without-block],[disable block transfer])], + [CPPFLAGS="${CPPFLAGS} -DWITHOUT_BLOCK"], + []) + +AC_ARG_WITH(observe, + [AS_HELP_STRING([--without-observe],[disable resource observation])], + [CPPFLAGS="${CPPFLAGS} -DWITHOUT_OBSERVE"], + []) + +AC_ARG_WITH(query-filter, + [AS_HELP_STRING([--without-query-filter],[disable support for filters on /.well-known/core])], + [CPPFLAGS="${CPPFLAGS} -DWITHOUT_QUERY_FILTER"], + []) + +AC_ARG_WITH(tests, + [AS_HELP_STRING([--with-tests],[enable unit tests (requires cunit)])], + [TESTS="tests"], + []) + +AC_ARG_WITH(shared, + [AS_HELP_STRING([--with-shared],[build shared library])], + [BUILD_SO="BUILD_SO=1"], + []) + +# disambiguate between autoconf generated setups and contiki / lwip setups +# which use explicit config.h.* files +CPPFLAGS="${CPPFLAGS} -DWITH_POSIX" + +# Checks for header files. +AC_CHECK_HEADERS([assert.h arpa/inet.h limits.h netdb.h netinet/in.h stdlib.h string.h strings.h sys/socket.h sys/time.h time.h unistd.h sys/unistd.h syslog.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_TYPE_SIZE_T +AC_TYPE_SSIZE_T + +# Checks for library functions. +AC_FUNC_MALLOC +AC_CHECK_FUNCS([memset select socket strcasecmp strrchr getaddrinfo strnlen]) + +AC_SUBST(TESTS) +AC_SUBST(BUILD_SO) + +AC_CONFIG_HEADERS([config.h]) + +AC_CONFIG_FILES([Makefile + doc/Makefile + doc/Doxyfile + examples/Makefile + tests/Makefile]) +AC_OUTPUT diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/debug.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/debug.c new file mode 100644 index 000000000..eedf24763 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/debug.c @@ -0,0 +1,391 @@ +/* debug.c -- debug utilities + * + * Copyright (C) 2010--2012 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "config.h" + +#if defined(HAVE_ASSERT_H) && !defined(assert) +# include +#endif + +#include +#include +#include +#include + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_TIME_H +#include +#endif + +#include "debug.h" +#include "net.h" + +#ifdef WITH_CONTIKI +# ifndef DEBUG +# define DEBUG DEBUG_PRINT +# endif /* DEBUG */ +#include "net/uip-debug.h" +#endif + +static coap_log_t maxlog = LOG_WARNING; /* default maximum log level */ + +coap_log_t coap_get_log_level() +{ + return maxlog; +} + +void coap_set_log_level(coap_log_t level) +{ + maxlog = level; +} + +/* this array has the same order as the type log_t */ +static char *loglevels[] = +{ "EMRG", "ALRT", "CRIT", "ERR", "WARN", "NOTE", "INFO", "DEBG" }; + +#ifdef HAVE_TIME_H + +static inline size_t print_timestamp(char *s, size_t len, coap_tick_t t) +{ + struct tm *tmp; + time_t now = clock_offset + (t / COAP_TICKS_PER_SECOND); + tmp = localtime(&now); + return strftime(s, len, "%b %d %H:%M:%S", tmp); +} + +#else /* alternative implementation: just print the timestamp */ + +static inline size_t +print_timestamp(char *s, size_t len, coap_tick_t t) +{ +#ifdef HAVE_SNPRINTF + return snprintf(s, len, "%u.%03u", + (unsigned int)(clock_offset + (t / COAP_TICKS_PER_SECOND)), + (unsigned int)(t % COAP_TICKS_PER_SECOND)); +#else /* HAVE_SNPRINTF */ + /* @todo do manual conversion of timestamp */ + return 0; +#endif /* HAVE_SNPRINTF */ +} + +#endif /* HAVE_TIME_H */ + +#ifndef NDEBUG + +#ifndef HAVE_STRNLEN +/** + * A length-safe strlen() fake. + * + * @param s The string to count characters != 0. + * @param maxlen The maximum length of @p s. + * + * @return The length of @p s. + */ +static inline size_t +strnlen(const char *s, size_t maxlen) +{ + size_t n = 0; + while(*s++ && n < maxlen) + ++n; + return n; +} +#endif /* HAVE_STRNLEN */ + +unsigned int print_readable(const unsigned char *data, unsigned int len, unsigned char *result, + unsigned int buflen, int encode_always) +{ + const unsigned char hex[] = "0123456789ABCDEF"; + unsigned int cnt = 0; + assert(data || len == 0); + + if (buflen == 0 || len == 0) + return 0; + + while (len) + { + if (!encode_always && isprint(*data)) + { + if (cnt == buflen) + break; + *result++ = *data; + ++cnt; + } + else + { + if (cnt + 4 < buflen) + { + *result++ = '\\'; + *result++ = 'x'; + *result++ = hex[(*data & 0xf0) >> 4]; + *result++ = hex[*data & 0x0f]; + cnt += 4; + } + else + break; + } + + ++data; + --len; + } + + *result = '\0'; + return cnt; +} + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +size_t coap_print_addr(const struct coap_address_t *addr, unsigned char *buf, size_t len) +{ +#ifdef HAVE_ARPA_INET_H + const void *addrptr = NULL; + in_port_t port; + unsigned char *p = buf; + + switch (addr->addr.sa.sa_family) + { + case AF_INET: + addrptr = &addr->addr.sin.sin_addr; + port = ntohs(addr->addr.sin.sin_port); + break; + case AF_INET6: + if (len < 7) /* do not proceed if buffer is even too short for [::]:0 */ + return 0; + + *p++ = '['; + + addrptr = &addr->addr.sin6.sin6_addr; + port = ntohs(addr->addr.sin6.sin6_port); + + break; + default: + memcpy(buf, "(unknown address type)", min(22, len)); + return min(22, len); + } + + if (inet_ntop(addr->addr.sa.sa_family, addrptr, (char *) p, len) == 0) + { + perror("coap_print_addr"); + return 0; + } + + p += strnlen((char *) p, len); + + if (addr->addr.sa.sa_family == AF_INET6) + { + if (p < buf + len) + { + *p++ = ']'; + } + else + return 0; + } + + p += snprintf((char *) p, buf + len - p + 1, ":%d", port); + + return buf + len - p; +#else /* HAVE_ARPA_INET_H */ +# if WITH_CONTIKI + unsigned char *p = buf; + uint8_t i; +# if WITH_UIP6 + const unsigned char hex[] = "0123456789ABCDEF"; + + if (len < 41) + return 0; + + *p++ = '['; + + for (i=0; i < 16; i += 2) + { + if (i) + { + *p++ = ':'; + } + *p++ = hex[(addr->addr.u8[i] & 0xf0) >> 4]; + *p++ = hex[(addr->addr.u8[i] & 0x0f)]; + *p++ = hex[(addr->addr.u8[i+1] & 0xf0) >> 4]; + *p++ = hex[(addr->addr.u8[i+1] & 0x0f)]; + } + *p++ = ']'; +# else /* WITH_UIP6 */ +# warning "IPv4 network addresses will not be included in debug output" + + if (len < 21) + return 0; +# endif /* WITH_UIP6 */ + if (buf + len - p < 6) + return 0; + +#ifdef HAVE_SNPRINTF + p += snprintf((char *)p, buf + len - p + 1, ":%d", uip_htons(addr->port)); +#else /* HAVE_SNPRINTF */ + /* @todo manual conversion of port number */ +#endif /* HAVE_SNPRINTF */ + + return p - buf; +# else /* WITH_CONTIKI */ + /* TODO: output addresses manually */ +# warning "inet_ntop() not available, network addresses will not be included in debug output" +# endif /* WITH_CONTIKI */ + return 0; +#endif +} + +#ifndef WITH_CONTIKI +void coap_show_pdu(const coap_pdu_t *pdu) +{ + unsigned char buf[COAP_MAX_PDU_SIZE]; /* need some space for output creation */ + int encode = 0, have_options = 0; + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + + fprintf(COAP_DEBUG_FD, "v:%d t:%d tkl:%d c:%d id:%u", pdu->hdr->version, pdu->hdr->type, + pdu->hdr->token_length, pdu->hdr->code, ntohs(pdu->hdr->id)); + + /* show options, if any */ + coap_option_iterator_init((coap_pdu_t *) pdu, &opt_iter, COAP_OPT_ALL); + + while ((option = coap_option_next(&opt_iter))) + { + if (!have_options) + { + have_options = 1; + fprintf(COAP_DEBUG_FD, " o: ["); + } + else + { + fprintf(COAP_DEBUG_FD, ","); + } + + if (opt_iter.type == COAP_OPTION_URI_PATH || opt_iter.type == COAP_OPTION_PROXY_URI + || opt_iter.type == COAP_OPTION_URI_HOST + || opt_iter.type == COAP_OPTION_LOCATION_PATH + || opt_iter.type == COAP_OPTION_LOCATION_QUERY + || opt_iter.type == COAP_OPTION_URI_PATH || opt_iter.type == COAP_OPTION_URI_QUERY) + { + encode = 0; + } + else + { + encode = 1; + } + + if (print_readable(COAP_OPT_VALUE(option), COAP_OPT_LENGTH(option), buf, sizeof(buf), + encode)) + fprintf(COAP_DEBUG_FD, " %d:'%s'", opt_iter.type, buf); + } + + if (have_options) + fprintf(COAP_DEBUG_FD, " ]"); + + if (pdu->data) + { + assert(pdu->data < (unsigned char *) pdu->hdr + pdu->length); + print_readable(pdu->data, (unsigned char *) pdu->hdr + pdu->length - pdu->data, buf, + sizeof(buf), 0); + fprintf(COAP_DEBUG_FD, " d:%s", buf); + } + fprintf(COAP_DEBUG_FD, "\n"); + fflush(COAP_DEBUG_FD); +} + +#else /* WITH_CONTIKI */ + +void +coap_show_pdu(const coap_pdu_t *pdu) +{ + unsigned char buf[80]; /* need some space for output creation */ + + PRINTF("v:%d t:%d oc:%d c:%d id:%u", + pdu->hdr->version, pdu->hdr->type, + pdu->hdr->optcnt, pdu->hdr->code, uip_ntohs(pdu->hdr->id)); + + /* show options, if any */ + if (pdu->hdr->optcnt) + { + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + coap_option_iterator_init((coap_pdu_t *)pdu, &opt_iter, COAP_OPT_ALL); + + PRINTF(" o:"); + while ((option = coap_option_next(&opt_iter))) + { + + if (print_readable(COAP_OPT_VALUE(option), + COAP_OPT_LENGTH(option), + buf, sizeof(buf), 0)) + PRINTF(" %d:%s", opt_iter.type, buf); + } + } + + if (pdu->data < (unsigned char *)pdu->hdr + pdu->length) + { + print_readable(pdu->data, + (unsigned char *)pdu->hdr + pdu->length - pdu->data, + buf, sizeof(buf), 0 ); + PRINTF(" d:%s", buf); + } + PRINTF("\r\n"); +} +#endif /* WITH_CONTIKI */ + +#endif /* NDEBUG */ + +#ifndef WITH_CONTIKI +void coap_log_impl(coap_log_t level, const char *format, ...) +{ + char timebuf[32]; + coap_tick_t now; + va_list ap; + FILE *log_fd; + + if (maxlog < level) + return; + + log_fd = level <= LOG_CRIT ? COAP_ERR_FD : COAP_DEBUG_FD; + + coap_ticks(&now); + if (print_timestamp(timebuf, sizeof(timebuf), now)) + fprintf(log_fd, "%s ", timebuf); + + if (level <= LOG_DEBUG) + fprintf(log_fd, "%s ", loglevels[level]); + + va_start(ap, format); + vfprintf(log_fd, format, ap); + va_end(ap); + fflush(log_fd); +} +#else /* WITH_CONTIKI */ +void +coap_log_impl(coap_log_t level, const char *format, ...) +{ + char timebuf[32]; + coap_tick_t now; + va_list ap; + + if (maxlog < level) + return; + + coap_ticks(&now); + if (print_timestamp(timebuf,sizeof(timebuf), now)) + PRINTF("%s ", timebuf); + + if (level <= LOG_DEBUG) + PRINTF("%s ", loglevels[level]); + + va_start(ap, format); + PRINTF(format, ap); + va_end(ap); +} +#endif /* WITH_CONTIKI */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/debug.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/debug.h new file mode 100644 index 000000000..708ffc24a --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/debug.h @@ -0,0 +1,75 @@ +/* debug.h -- debug utilities + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef _COAP_DEBUG_H_ +#define _COAP_DEBUG_H_ + +#include "config.h" + +#ifndef COAP_DEBUG_FD +#define COAP_DEBUG_FD stdout +#endif + +#ifndef COAP_ERR_FD +#define COAP_ERR_FD stderr +#endif + +#ifdef HAVE_SYSLOG_H +#include +typedef short coap_log_t; +#else +/** Pre-defined log levels akin to what is used in \b syslog. */ +typedef enum +{ LOG_EMERG=0, LOG_ALERT, LOG_CRIT, LOG_WARNING, + LOG_NOTICE, LOG_INFO, LOG_DEBUG +}coap_log_t; +#endif + +/** Returns the current log level. */ +coap_log_t coap_get_log_level(); + +/** Sets the log level to the specified value. */ +void coap_set_log_level(coap_log_t level); + +/** + * Writes the given text to @c COAP_ERR_FD (for @p level <= @c + * LOG_CRIT) or @c COAP_DEBUG_FD (for @p level >= @c LOG_WARNING). The + * text is output only when @p level is below or equal to the log + * level that set by coap_set_log_level(). + */ +void coap_log_impl(coap_log_t level, const char *format, ...); + +#ifndef coap_log +#define coap_log(...) coap_log_impl(__VA_ARGS__) +#endif + +#ifndef NDEBUG + +/* A set of convenience macros for common log levels. */ +#define info(...) coap_log(LOG_INFO, __VA_ARGS__) +#define warn(...) coap_log(LOG_WARNING, __VA_ARGS__) +#define debug(...) coap_log(LOG_DEBUG, __VA_ARGS__) + +#include "pdu.h" +void coap_show_pdu(const coap_pdu_t *); + +struct coap_address_t; +size_t coap_print_addr(const struct coap_address_t *, unsigned char *, size_t); + +#else + +#define debug(...) +#define info(...) +#define warn(...) + +#define coap_show_pdu(x) +#define coap_print_addr(...) + +#endif + +#endif /* _COAP_DEBUG_H_ */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/encode.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/encode.c new file mode 100644 index 000000000..9e70ea8ce --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/encode.c @@ -0,0 +1,50 @@ +/* encode.c -- encoding and decoding of CoAP data types + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef NDEBUG +# include +#endif + +#include "config.h" +#include "encode.h" + +/* Carsten suggested this when fls() is not available: */ +int coap_fls(unsigned int i) +{ + int n; + for (n = 0; i; n++) + i >>= 1; + return n; +} + +unsigned int coap_decode_var_bytes(unsigned char *buf, unsigned int len) +{ + unsigned int i, n = 0; + for (i = 0; i < len; ++i) + n = (n << 8) + buf[i]; + + return n; +} + +unsigned int coap_encode_var_bytes(unsigned char *buf, unsigned int val) +{ + unsigned int n, i; + + for (n = 0, i = val; i && n < sizeof(val); ++n) + i >>= 8; + + i = n; + while (i--) + { + buf[i] = val & 0xff; + val >>= 8; + } + + return n; +} + diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/encode.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/encode.h new file mode 100644 index 000000000..e58cad649 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/encode.h @@ -0,0 +1,52 @@ +/* encode.h -- encoding and decoding of CoAP data types + * + * Copyright (C) 2010--2012 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef _COAP_ENCODE_H_ +#define _COAP_ENCODE_H_ + +#if (BSD >= 199103) || defined(WITH_CONTIKI) +# include +#else +# include +#endif + +#define Nn 8 /* duplicate definition of N if built on sky motes */ +#define E 4 +#define HIBIT (1 << (Nn - 1)) +#define EMASK ((1 << E) - 1) +#define MMASK ((1 << Nn) - 1 - EMASK) +#define MAX_VALUE ( (1 << Nn) - (1 << E) ) * (1 << ((1 << E) - 1)) + +#define COAP_PSEUDOFP_DECODE_8_4(r) (r < HIBIT ? r : (r & MMASK) << (r & EMASK)) + +#ifndef HAVE_FLS +/* include this only if fls() is not available */ +extern int coap_fls(unsigned int i); +#else +#define coap_fls(i) fls(i) +#endif + +/* ls and s must be integer variables */ +#define COAP_PSEUDOFP_ENCODE_8_4_DOWN(v,ls) (v < HIBIT ? v : (ls = coap_fls(v) - Nn, (v >> ls) & MMASK) + ls) +#define COAP_PSEUDOFP_ENCODE_8_4_UP(v,ls,s) (v < HIBIT ? v : (ls = coap_fls(v) - Nn, (s = (((v + ((1<> ls) & MMASK)), s == 0 ? HIBIT + ls + 1 : s + ls)) + +/** + * Decodes multiple-length byte sequences. buf points to an input byte + * sequence of length len. Returns the decoded value. + */ +unsigned int coap_decode_var_bytes(unsigned char *buf, unsigned int len); + +/** + * Encodes multiple-length byte sequences. buf points to an output + * buffer of sufficient length to store the encoded bytes. val is + * the value to encode. Returns the number of bytes used to encode + * val or 0 on error. + */ +unsigned int coap_encode_var_bytes(unsigned char *buf, unsigned int val); + +#endif /* _COAP_ENCODE_H_ */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/examples/Makefile b/resource/csdk/connectivity/lib/libcoap-4.1.1/examples/Makefile new file mode 100644 index 000000000..9f93ca3d8 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/examples/Makefile @@ -0,0 +1,61 @@ +# Makefile for libcoap +# +# Copyright (C) 2010,2011 Olaf Bergmann +# +# This file is part of the CoAP library libcoap. Please see +# README for terms of use. + +# the library's version +VERSION:=4.1.1 + +# tools + +SHELL = /bin/sh +MKDIR = mkdir + +abs_builddir = /connectivity/connectivity/src/bt_edr_adapter/libcoap-4.1.1/examples +top_builddir = .. +top_srcdir = .. +# files and flags +PROGRAMS:=coap-server coap-client rd etsi_iot_01 #tiny +SOURCES:= tiny.c client.c server.c rd.c etsi_iot_01.c +OBJECTS:= $(patsubst %.c, %.o, $(SOURCES)) +#CFLAGS:=-g -Wall -ansi -pedantic -I.. +CFLAGS:=-g -Wall -g -O2 +CPPFLAGS:=-I$(top_srcdir) -DWITH_POSIX +DISTDIR?=$(top_builddir)/libcoap-4.1.1 +FILES:=Makefile.in $(SOURCES) +LDFLAGS:=-L$(top_builddir) +LDLIBS:=-lcoap +libcoap =$(top_builddir)/libcoap.a + +.PHONY: clean distclean + +.SUFFIXES: +.SUFFIXES: .c .o + +all: $(PROGRAMS) + +check: + echo DISTDIR: $(DISTDIR) + echo top_builddir: $(top_builddir) + +tiny: tiny.o $(libcoap) + $(CC) -o $@ $< $(LDFLAGS) + +coap-client: client.o $(libcoap) + $(CC) -o $@ $< $(LDFLAGS) $(LDLIBS) + +coap-server: server.o $(libcoap) + $(CC) -o $@ $< $(LDFLAGS) $(LDLIBS) + +clean: + @rm -f $(PROGRAMS) $(OBJECTS) + +distclean: clean + @rm -rf $(DISTDIR) + @rm -f *~ + +dist: $(FILES) + test -d $(DISTDIR)/examples || mkdir $(DISTDIR)/examples + cp $(FILES) $(DISTDIR)/examples diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/examples/Makefile.in b/resource/csdk/connectivity/lib/libcoap-4.1.1/examples/Makefile.in new file mode 100644 index 000000000..80445adb0 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/examples/Makefile.in @@ -0,0 +1,61 @@ +# Makefile for libcoap +# +# Copyright (C) 2010,2011 Olaf Bergmann +# +# This file is part of the CoAP library libcoap. Please see +# README for terms of use. + +# the library's version +VERSION:=@PACKAGE_VERSION@ + +# tools +@SET_MAKE@ +SHELL = /bin/sh +MKDIR = mkdir + +abs_builddir = @abs_builddir@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +# files and flags +PROGRAMS:=coap-server coap-client rd etsi_iot_01 #tiny +SOURCES:= tiny.c client.c server.c rd.c etsi_iot_01.c +OBJECTS:= $(patsubst %.c, %.o, $(SOURCES)) +#CFLAGS:=-g -Wall -ansi -pedantic -I.. +CFLAGS:=-g -Wall @CFLAGS@ +CPPFLAGS:=-I$(top_srcdir) @CPPFLAGS@ +DISTDIR?=$(top_builddir)/@PACKAGE_TARNAME@-@PACKAGE_VERSION@ +FILES:=Makefile.in $(SOURCES) +LDFLAGS:=-L$(top_builddir) +LDLIBS:=-lcoap @LIBS@ +libcoap =$(top_builddir)/libcoap.a + +.PHONY: clean distclean + +.SUFFIXES: +.SUFFIXES: .c .o + +all: $(PROGRAMS) + +check: + echo DISTDIR: $(DISTDIR) + echo top_builddir: $(top_builddir) + +tiny: tiny.o $(libcoap) + $(CC) -o $@ $< $(LDFLAGS) + +coap-client: client.o $(libcoap) + $(CC) -o $@ $< $(LDFLAGS) $(LDLIBS) + +coap-server: server.o $(libcoap) + $(CC) -o $@ $< $(LDFLAGS) $(LDLIBS) + +clean: + @rm -f $(PROGRAMS) $(OBJECTS) + +distclean: clean + @rm -rf $(DISTDIR) + @rm -f *~ + +dist: $(FILES) + test -d $(DISTDIR)/examples || mkdir $(DISTDIR)/examples + cp $(FILES) $(DISTDIR)/examples diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/examples/client.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/examples/client.c new file mode 100644 index 000000000..72a090874 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/examples/client.c @@ -0,0 +1,1270 @@ +/* coap-client -- simple CoAP client + * + * Copyright (C) 2010--2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "coap.h" + +int flags = 0; + +static unsigned char _token_data[8]; +str the_token = +{ 0, _token_data }; + +#define FLAGS_BLOCK 0x01 + +static coap_list_t *optlist = NULL; +/* Request URI. + * TODO: associate the resources with transaction id and make it expireable */ +static coap_uri_t uri; +static str proxy = +{ 0, NULL }; +static unsigned short proxy_port = COAP_DEFAULT_PORT; + +/* reading is done when this flag is set */ +static int ready = 0; + +static str output_file = +{ 0, NULL }; /* output file name */ +static FILE *file = NULL; /* output file stream */ + +static str payload = +{ 0, NULL }; /* optional payload to send */ + +unsigned char msgtype = COAP_MESSAGE_CON; /* usually, requests are sent confirmable */ + +typedef unsigned char method_t; +method_t method = 1; /* the method we are using in our requests */ + +coap_block_t block = +{ .num = 0, .m = 0, .szx = 6 }; + +unsigned int wait_seconds = 90; /* default timeout in seconds */ +coap_tick_t max_wait; /* global timeout (changed by set_timeout()) */ + +unsigned int obs_seconds = 30; /* default observe time */ +coap_tick_t obs_wait = 0; /* timeout for current subscription */ + +#define min(a,b) ((a) < (b) ? (a) : (b)) + +static inline void set_timeout(coap_tick_t *timer, const unsigned int seconds) +{ + coap_ticks(timer); + *timer += seconds * COAP_TICKS_PER_SECOND; +} + +int append_to_output(const unsigned char *data, size_t len) +{ + size_t written; + + if (!file) + { + if (!output_file.s || (output_file.length && output_file.s[0] == '-')) + file = stdout; + else + { + if (!(file = fopen((char *) output_file.s, "w"))) + { + perror("fopen"); + return -1; + } + } + } + + do + { + written = fwrite(data, 1, len, file); + len -= written; + data += written; + } while (written && len); + fflush(file); + + return 0; +} + +void close_output() +{ + if (file) + { + + /* add a newline before closing in case were writing to stdout */ + if (!output_file.s || (output_file.length && output_file.s[0] == '-')) + fwrite("\n", 1, 1, file); + + fflush(file); + fclose(file); + } +} + +coap_pdu_t * +new_ack(coap_context_t *ctx, coap_queue_t *node) +{ + coap_pdu_t *pdu = coap_new_pdu(); + + if (pdu) + { + pdu->hdr->type = COAP_MESSAGE_ACK; + pdu->hdr->code = 0; + pdu->hdr->id = node->pdu->hdr->id; + } + + return pdu; +} + +coap_pdu_t * +new_response(coap_context_t *ctx, coap_queue_t *node, unsigned int code) +{ + coap_pdu_t *pdu = new_ack(ctx, node); + + if (pdu) + pdu->hdr->code = code; + + return pdu; +} + +coap_pdu_t * +coap_new_request(coap_context_t *ctx, method_t m, coap_list_t *options) +{ + coap_pdu_t *pdu; + coap_list_t *opt; + + if (!(pdu = coap_new_pdu())) + return NULL; + + pdu->hdr->type = msgtype; + pdu->hdr->id = coap_new_message_id(ctx); + pdu->hdr->code = m; + + pdu->hdr->token_length = the_token.length; + if (!coap_add_token(pdu, the_token.length, the_token.s)) + { + debug("cannot add token to request\n"); + } + + coap_show_pdu(pdu); + + for (opt = options; opt; opt = opt->next) + { + coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option *)opt->data), + COAP_OPTION_LENGTH(*(coap_option *)opt->data), + COAP_OPTION_DATA(*(coap_option *)opt->data)); + } + + if (payload.length) + { + if ((flags & FLAGS_BLOCK) == 0) + coap_add_data(pdu, payload.length, payload.s); + else + coap_add_block(pdu, payload.length, payload.s, block.num, block.szx); + } + + return pdu; +} + +coap_tid_t clear_obs(coap_context_t *ctx, const coap_address_t *remote) +{ + coap_list_t *option; + coap_pdu_t *pdu; + coap_tid_t tid = COAP_INVALID_TID; + + /* create bare PDU w/o any option */ + pdu = coap_new_request(ctx, COAP_REQUEST_GET, NULL); + + if (pdu) + { + /* FIXME: add token */ + /* add URI components from optlist */ + for (option = optlist; option; option = option->next) + { + switch (COAP_OPTION_KEY(*(coap_option *)option->data)) + { + case COAP_OPTION_URI_HOST: + case COAP_OPTION_URI_PORT: + case COAP_OPTION_URI_PATH: + case COAP_OPTION_URI_QUERY: + coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option *)option->data), + COAP_OPTION_LENGTH(*(coap_option *)option->data), + COAP_OPTION_DATA(*(coap_option *)option->data)); + break; + default: + ; /* skip other options */ + } + } + + if (pdu->hdr->type == COAP_MESSAGE_CON) + tid = coap_send_confirmed(ctx, remote, pdu); + else + tid = coap_send(ctx, remote, pdu); + + if (tid == COAP_INVALID_TID) + { + debug("clear_obs: error sending new request"); + coap_delete_pdu(pdu); + } + else if (pdu->hdr->type != COAP_MESSAGE_CON) + coap_delete_pdu(pdu); + } + return tid; +} + +int resolve_address(const str *server, struct sockaddr *dst) +{ + + struct addrinfo *res, *ainfo; + struct addrinfo hints; + static char addrstr[256]; + int error, len = -1; + + memset(addrstr, 0, sizeof(addrstr)); + if (server->length) + memcpy(addrstr, server->s, server->length); + else + memcpy(addrstr, "localhost", 9); + + memset((char *) &hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_DGRAM; + hints.ai_family = AF_UNSPEC; + + error = getaddrinfo(addrstr, "", &hints, &res); + + if (error != 0) + { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error)); + return error; + } + + for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) + { + switch (ainfo->ai_family) + { + case AF_INET6: + case AF_INET: + len = ainfo->ai_addrlen; + memcpy(dst, ainfo->ai_addr, len); + goto finish; + default: + ; + } + } + + finish: freeaddrinfo(res); + return len; +} + +static inline coap_opt_t * +get_block(coap_pdu_t *pdu, coap_opt_iterator_t *opt_iter) +{ + coap_opt_filter_t f; + + assert(pdu); + + memset(f, 0, sizeof(coap_opt_filter_t)); + coap_option_setb(f, COAP_OPTION_BLOCK1); + coap_option_setb(f, COAP_OPTION_BLOCK2); + + coap_option_iterator_init(pdu, opt_iter, f); + return coap_option_next(opt_iter); +} + +#define HANDLE_BLOCK1(Pdu) \ + ((method == COAP_REQUEST_PUT || method == COAP_REQUEST_POST) && \ + ((flags & FLAGS_BLOCK) == 0) && \ + ((Pdu)->hdr->code == COAP_RESPONSE_CODE(201) || \ + (Pdu)->hdr->code == COAP_RESPONSE_CODE(204))) + +inline int check_token(coap_pdu_t *received) +{ + return received->hdr->token_length == the_token.length + && memcmp(received->hdr->token, the_token.s, the_token.length) == 0; +} + +void message_handler(struct coap_context_t *ctx, const coap_address_t *remote, coap_pdu_t *sent, + coap_pdu_t *received, const coap_tid_t id) +{ + + coap_pdu_t *pdu = NULL; + coap_opt_t *block_opt; + coap_opt_iterator_t opt_iter; + unsigned char buf[4]; + coap_list_t *option; + size_t len; + unsigned char *databuf; + coap_tid_t tid; + +#ifndef NDEBUG + if (LOG_DEBUG <= coap_get_log_level()) + { + debug( + "** process incoming %d.%02d response:\n", (received->hdr->code >> 5), received->hdr->code & 0x1F); + coap_show_pdu(received); + } +#endif + + /* check if this is a response to our original request */ + if (!check_token(received)) + { + /* drop if this was just some message, or send RST in case of notification */ + if (!sent + && (received->hdr->type == COAP_MESSAGE_CON + || received->hdr->type == COAP_MESSAGE_NON)) + coap_send_rst(ctx, remote, received); + return; + } + + switch (received->hdr->type) + { + case COAP_MESSAGE_CON: + /* acknowledge received response if confirmable (TODO: check Token) */ + coap_send_ack(ctx, remote, received); + break; + case COAP_MESSAGE_RST: + info("got RST\n"); + return; + default: + ; + } + + /* output the received data, if any */ + if (received->hdr->code == COAP_RESPONSE_CODE(205)) + { + + /* set obs timer if we have successfully subscribed a resource */ + if (sent && coap_check_option(received, COAP_OPTION_SUBSCRIPTION, &opt_iter)) + { + debug("observation relationship established, set timeout to %d\n", obs_seconds); + set_timeout(&obs_wait, obs_seconds); + } + + /* Got some data, check if block option is set. Behavior is undefined if + * both, Block1 and Block2 are present. */ + block_opt = get_block(received, &opt_iter); + if (!block_opt) + { + /* There is no block option set, just read the data and we are done. */ + if (coap_get_data(received, &len, &databuf)) + append_to_output(databuf, len); + } + else + { + unsigned short blktype = opt_iter.type; + + /* TODO: check if we are looking at the correct block number */ + if (coap_get_data(received, &len, &databuf)) + append_to_output(databuf, len); + + if (COAP_OPT_BLOCK_MORE(block_opt)) + { + /* more bit is set */ + debug( + "found the M bit, block size is %u, block nr. %u\n", COAP_OPT_BLOCK_SZX(block_opt), coap_opt_block_num(block_opt)); + + /* create pdu with request for next block */ + pdu = coap_new_request(ctx, method, NULL); /* first, create bare PDU w/o any option */ + if (pdu) + { + /* add URI components from optlist */ + for (option = optlist; option; option = option->next) + { + switch (COAP_OPTION_KEY(*(coap_option *)option->data)) + { + case COAP_OPTION_URI_HOST: + case COAP_OPTION_URI_PORT: + case COAP_OPTION_URI_PATH: + case COAP_OPTION_URI_QUERY: + coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option *)option->data), + COAP_OPTION_LENGTH(*(coap_option *)option->data), + COAP_OPTION_DATA(*(coap_option *)option->data)); + break; + default: + ; /* skip other options */ + } + } + + /* finally add updated block option from response, clear M bit */ + /* blocknr = (blocknr & 0xfffffff7) + 0x10; */ + debug("query block %d\n", (coap_opt_block_num(block_opt) + 1)); + coap_add_option(pdu, blktype, + coap_encode_var_bytes(buf, + ((coap_opt_block_num(block_opt) + 1) << 4) + | COAP_OPT_BLOCK_SZX(block_opt)), buf); + + if (received->hdr->type == COAP_MESSAGE_CON) + tid = coap_send_confirmed(ctx, remote, pdu); + else + tid = coap_send(ctx, remote, pdu); + + if (tid == COAP_INVALID_TID) + { + debug("message_handler: error sending new request"); + coap_delete_pdu(pdu); + } + else + { + set_timeout(&max_wait, wait_seconds); + if (received->hdr->type != COAP_MESSAGE_CON) + coap_delete_pdu(pdu); + } + + return; + } + } + } + } + else + { /* no 2.05 */ + + /* check if an error was signaled and output payload if so */ + if (COAP_RESPONSE_CLASS(received->hdr->code) >= 4) + { + fprintf(stderr, "%d.%02d", (received->hdr->code >> 5), received->hdr->code & 0x1F); + if (coap_get_data(received, &len, &databuf)) + { + fprintf(stderr, " "); + while (len--) + fprintf(stderr, "%c", *databuf++); + } + fprintf(stderr, "\n"); + } + + } + + /* finally send new request, if needed */ + if (pdu && coap_send(ctx, remote, pdu) == COAP_INVALID_TID) + { + debug("message_handler: error sending response"); + } + coap_delete_pdu(pdu); + + /* our job is done, we can exit at any time */ + ready = coap_check_option(received, COAP_OPTION_SUBSCRIPTION, &opt_iter) == NULL; +} + +void usage(const char *program, const char *version) +{ + const char *p; + + p = strrchr(program, '/'); + if (p) + program = ++p; + + fprintf(stderr, "%s v%s -- a small CoAP implementation\n" + "(c) 2010-2013 Olaf Bergmann \n\n" + "usage: %s [-A type...] [-t type] [-b [num,]size] [-B seconds] [-e text]\n" + "\t\t[-g group] [-m method] [-N] [-o file] [-P addr[:port]] [-p port]\n" + "\t\t[-s duration] [-O num,text] [-T string] [-v num] URI\n\n" + "\tURI can be an absolute or relative coap URI,\n" + "\t-A type...\taccepted media types as comma-separated list of\n" + "\t\t\tsymbolic or numeric values\n" + "\t-t type\t\tcontent type for given resource for PUT/POST\n" + "\t-b [num,]size\tblock size to be used in GET/PUT/POST requests\n" + "\t \t\t(value must be a multiple of 16 not larger than 1024)\n" + "\t \t\tIf num is present, the request chain will start at\n" + "\t \t\tblock num\n" + "\t-B seconds\tbreak operation after waiting given seconds\n" + "\t\t\t(default is %d)\n" + "\t-e text\t\tinclude text as payload (use percent-encoding for\n" + "\t\t\tnon-ASCII characters)\n" + "\t-f file\t\tfile to send with PUT/POST (use '-' for STDIN)\n" + "\t-g group\tjoin the given multicast group\n" + "\t-m method\trequest method (get|put|post|delete), default is 'get'\n" + "\t-N\t\tsend NON-confirmable message\n" + "\t-o file\t\toutput received data to this file (use '-' for STDOUT)\n" + "\t-p port\t\tlisten on specified port\n" + "\t-s duration\tsubscribe for given duration [s]\n" + "\t-v num\t\tverbosity level (default: 3)\n" + "\t-O num,text\tadd option num with contents text to request\n" + "\t-P addr[:port]\tuse proxy (automatically adds Proxy-Uri option to\n" + "\t\t\trequest)\n" + "\t-T token\tinclude specified token\n" + "\n" + "examples:\n" + "\tcoap-client -m get coap://[::1]/\n" + "\tcoap-client -m get coap://[::1]/.well-known/core\n" + "\tcoap-client -m get -T cafe coap://[::1]/time\n" + "\techo 1000 | coap-client -m put -T cafe coap://[::1]/time -f -\n", program, version, + program, wait_seconds); +} + +int join(coap_context_t *ctx, char *group_name) +{ + struct ipv6_mreq mreq; + struct addrinfo *reslocal = NULL, *resmulti = NULL, hints, *ainfo; + int result = -1; + + /* we have to resolve the link-local interface to get the interface id */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_DGRAM; + + result = getaddrinfo("::", NULL, &hints, &reslocal); + if (result < 0) + { + fprintf(stderr, "join: cannot resolve link-local interface: %s\n", gai_strerror(result)); + goto finish; + } + + /* get the first suitable interface identifier */ + for (ainfo = reslocal; ainfo != NULL; ainfo = ainfo->ai_next) + { + if (ainfo->ai_family == AF_INET6) + { + mreq.ipv6mr_interface = ((struct sockaddr_in6 *) ainfo->ai_addr)->sin6_scope_id; + break; + } + } + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_DGRAM; + + /* resolve the multicast group address */ + result = getaddrinfo(group_name, NULL, &hints, &resmulti); + + if (result < 0) + { + fprintf(stderr, "join: cannot resolve multicast address: %s\n", gai_strerror(result)); + goto finish; + } + + for (ainfo = resmulti; ainfo != NULL; ainfo = ainfo->ai_next) + { + if (ainfo->ai_family == AF_INET6) + { + mreq.ipv6mr_multiaddr = ((struct sockaddr_in6 *) ainfo->ai_addr)->sin6_addr; + break; + } + } + + result = setsockopt(ctx->sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *) &mreq, sizeof(mreq)); + if (result < 0) + perror("join: setsockopt"); + + finish: freeaddrinfo(resmulti); + freeaddrinfo(reslocal); + + return result; +} + +int order_opts(void *a, void *b) +{ + if (!a || !b) + return a < b ? -1 : 1; + + if (COAP_OPTION_KEY(*(coap_option *)a) < COAP_OPTION_KEY(*(coap_option *)b)) + return -1; + + return COAP_OPTION_KEY(*(coap_option *)a) == COAP_OPTION_KEY(*(coap_option *)b); +} + +coap_list_t * +new_option_node(unsigned short key, unsigned int length, unsigned char *data) +{ + coap_option *option; + coap_list_t *node; + + option = coap_malloc(sizeof(coap_option) + length); + if (!option) + goto error; + + COAP_OPTION_KEY(*option) = key; + COAP_OPTION_LENGTH(*option) = length; + memcpy(COAP_OPTION_DATA(*option), data, length); + + /* we can pass NULL here as delete function since option is released automatically */ + node = coap_new_listnode(option, NULL); + + if (node) + return node; + + error: perror("new_option_node: malloc"); + coap_free( option); + return NULL; +} + +typedef struct +{ + unsigned char code; + char *media_type; +} content_type_t; + +void cmdline_content_type(char *arg, unsigned short key) +{ + static content_type_t content_types[] = + { + { 0, "plain" }, + { 0, "text/plain" }, + { 40, "link" }, + { 40, "link-format" }, + { 40, "application/link-format" }, + { 41, "xml" }, + { 42, "binary" }, + { 42, "octet-stream" }, + { 42, "application/octet-stream" }, + { 47, "exi" }, + { 47, "application/exi" }, + { 50, "json" }, + { 50, "application/json" }, + { 255, NULL } }; + coap_list_t *node; + unsigned char i, value[10]; + int valcnt = 0; + unsigned char buf[2]; + char *p, *q = arg; + + while (q && *q) + { + p = strchr(q, ','); + + if (isdigit(*q)) + { + if (p) + *p = '\0'; + value[valcnt++] = atoi(q); + } + else + { + for (i = 0; + content_types[i].media_type + && strncmp(q, content_types[i].media_type, p ? p - q : strlen(q)) != 0; + ++i) + ; + + if (content_types[i].media_type) + { + value[valcnt] = content_types[i].code; + valcnt++; + } + else + { + warn("W: unknown content-type '%s'\n", arg); + } + } + + if (!p || key == COAP_OPTION_CONTENT_TYPE) + break; + + q = p + 1; + } + + for (i = 0; i < valcnt; ++i) + { + node = new_option_node(key, coap_encode_var_bytes(buf, value[i]), buf); + if (node) + coap_insert(&optlist, node, order_opts); + } +} + +void cmdline_uri(char *arg) +{ + unsigned char portbuf[2]; +#define BUFSIZE 40 + unsigned char _buf[BUFSIZE]; + unsigned char *buf = _buf; + size_t buflen; + int res; + + if (proxy.length) + { /* create Proxy-Uri from argument */ + size_t len = strlen(arg); + while (len > 270) + { + coap_insert(&optlist, + new_option_node(COAP_OPTION_PROXY_URI, 270, (unsigned char *) arg), order_opts); + len -= 270; + arg += 270; + } + + coap_insert(&optlist, new_option_node(COAP_OPTION_PROXY_URI, len, (unsigned char *) arg), + order_opts); + } + else + { /* split arg into Uri-* options */ + coap_split_uri((unsigned char *) arg, strlen(arg), &uri); + + if (uri.port != COAP_DEFAULT_PORT) + { + coap_insert(&optlist, + new_option_node(COAP_OPTION_URI_PORT, coap_encode_var_bytes(portbuf, uri.port), + portbuf), order_opts); + } + + if (uri.path.length) + { + buflen = BUFSIZE; + res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); + + while (res--) + { + coap_insert(&optlist, + new_option_node(COAP_OPTION_URI_PATH, COAP_OPT_LENGTH(buf), + COAP_OPT_VALUE(buf)), order_opts); + + buf += COAP_OPT_SIZE(buf); + } + } + + if (uri.query.length) + { + buflen = BUFSIZE; + buf = _buf; + res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen); + + while (res--) + { + coap_insert(&optlist, + new_option_node(COAP_OPTION_URI_QUERY, COAP_OPT_LENGTH(buf), + COAP_OPT_VALUE(buf)), order_opts); + + buf += COAP_OPT_SIZE(buf); + } + } + } +} + +int cmdline_blocksize(char *arg) +{ + unsigned short size; + + again: size = 0; + while (*arg && *arg != ',') + size = size * 10 + (*arg++ - '0'); + + if (*arg == ',') + { + arg++; + block.num = size; + goto again; + } + + if (size) + block.szx = (coap_fls(size >> 4) - 1) & 0x07; + + flags |= FLAGS_BLOCK; + return 1; +} + +/* Called after processing the options from the commandline to set + * Block1 or Block2 depending on method. */ +void set_blocksize() +{ + static unsigned char buf[4]; /* hack: temporarily take encoded bytes */ + unsigned short opt; + + if (method != COAP_REQUEST_DELETE) + { + opt = method == COAP_REQUEST_GET ? COAP_OPTION_BLOCK2 : COAP_OPTION_BLOCK1; + + coap_insert(&optlist, + new_option_node(opt, coap_encode_var_bytes(buf, (block.num << 4 | block.szx)), buf), + order_opts); + } +} + +void cmdline_subscribe(char *arg) +{ + obs_seconds = atoi(optarg); + coap_insert(&optlist, new_option_node(COAP_OPTION_SUBSCRIPTION, 0, NULL), order_opts); +} + +int cmdline_proxy(char *arg) +{ + char *proxy_port_str = strrchr((const char *) arg, ':'); /* explicit port ? */ + if (proxy_port_str) + { + char *ipv6_delimiter = strrchr((const char *) arg, ']'); + if (!ipv6_delimiter) + { + if (proxy_port_str == strchr((const char *) arg, ':')) + { + /* host:port format - host not in ipv6 hexadecimal string format */ + *proxy_port_str++ = '\0'; /* split */ + proxy_port = atoi(proxy_port_str); + } + } + else + { + arg = strchr((const char *) arg, '['); + if (!arg) + return 0; + arg++; + *ipv6_delimiter = '\0'; /* split */ + if (ipv6_delimiter + 1 == proxy_port_str++) + { + /* [ipv6 address]:port */ + proxy_port = atoi(proxy_port_str); + } + } + } + + proxy.length = strlen(arg); + if ((proxy.s = coap_malloc(proxy.length + 1)) == NULL) + { + proxy.length = 0; + return 0; + } + + memcpy(proxy.s, arg, proxy.length + 1); + return 1; +} + +inline void cmdline_token(char *arg) +{ + strncpy((char *) the_token.s, arg, min(sizeof(_token_data), strlen(arg))); + the_token.length = strlen(arg); +} + +void cmdline_option(char *arg) +{ + unsigned int num = 0; + + while (*arg && *arg != ',') + { + num = num * 10 + (*arg - '0'); + ++arg; + } + if (*arg == ',') + ++arg; + + coap_insert(&optlist, new_option_node(num, strlen(arg), (unsigned char *) arg), order_opts); +} + +extern int check_segment(const unsigned char *s, size_t length); +extern void decode_segment(const unsigned char *seg, size_t length, unsigned char *buf); + +int cmdline_input(char *text, str *buf) +{ + int len; + len = check_segment((unsigned char *) text, strlen(text)); + + if (len < 0) + return 0; + + buf->s = (unsigned char *) coap_malloc(len); + if (!buf->s) + return 0; + + buf->length = len; + decode_segment((unsigned char *) text, strlen(text), buf->s); + return 1; +} + +int cmdline_input_from_file(char *filename, str *buf) +{ + FILE *inputfile = NULL; + ssize_t len; + int result = 1; + struct stat statbuf; + + if (!filename || !buf) + return 0; + + if (filename[0] == '-' && !filename[1]) + { /* read from stdin */ + buf->length = 20000; + buf->s = (unsigned char *) coap_malloc(buf->length); + if (!buf->s) + return 0; + + inputfile = stdin; + } + else + { + /* read from specified input file */ + if (stat(filename, &statbuf) < 0) + { + perror("cmdline_input_from_file: stat"); + return 0; + } + + buf->length = statbuf.st_size; + buf->s = (unsigned char *) coap_malloc(buf->length); + if (!buf->s) + return 0; + + inputfile = fopen(filename, "r"); + if (!inputfile) + { + perror("cmdline_input_from_file: fopen"); + coap_free(buf->s); + return 0; + } + } + + len = fread(buf->s, 1, buf->length, inputfile); + + if (len < buf->length) + { + if (ferror(inputfile) != 0) + { + perror("cmdline_input_from_file: fread"); + coap_free(buf->s); + buf->length = 0; + buf->s = NULL; + result = 0; + } + else + { + buf->length = len; + } + } + + if (inputfile != stdin) + fclose(inputfile); + + return result; +} + +method_t cmdline_method(char *arg) +{ + static char *methods[] = + { 0, "get", "post", "put", "delete", 0 }; + unsigned char i; + + for (i = 1; methods[i] && strcasecmp(arg, methods[i]) != 0; ++i) + ; + + return i; /* note that we do not prevent illegal methods */ +} + +coap_context_t * +get_context(const char *node, const char *port) +{ + coap_context_t *ctx = NULL; + int s; + struct addrinfo hints; + struct addrinfo *result, *rp; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */ + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV | AI_ALL; + + s = getaddrinfo(node, port, &hints, &result); + if (s != 0) + { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); + return NULL; + } + + /* iterate through results until success */ + for (rp = result; rp != NULL; rp = rp->ai_next) + { + coap_address_t addr; + + if (rp->ai_addrlen <= sizeof(addr.addr)) + { + coap_address_init(&addr); + addr.size = rp->ai_addrlen; + memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen); + + ctx = coap_new_context(&addr); + if (ctx) + { + /* TODO: output address:port for successful binding */ + goto finish; + } + } + } + + fprintf(stderr, "no context available for interface '%s'\n", node); + + finish: freeaddrinfo(result); + return ctx; +} + +int main(int argc, char **argv) +{ + coap_context_t *ctx = NULL; + coap_address_t dst; + static char addr[INET6_ADDRSTRLEN]; + void *addrptr = NULL; + fd_set readfds; + struct timeval tv; + int result; + coap_tick_t now; + coap_queue_t *nextpdu; + coap_pdu_t *pdu; + static str server; + unsigned short port = COAP_DEFAULT_PORT; + char port_str[NI_MAXSERV] = "0"; + int opt, res; + char *group = NULL; + coap_log_t log_level = LOG_WARNING; + coap_tid_t tid = COAP_INVALID_TID; + + while ((opt = getopt(argc, argv, "Nb:e:f:g:m:p:s:t:o:v:A:B:O:P:T:")) != -1) + { + switch (opt) + { + case 'b': + cmdline_blocksize(optarg); + break; + case 'B': + wait_seconds = atoi(optarg); + break; + case 'e': + if (!cmdline_input(optarg, &payload)) + payload.length = 0; + break; + case 'f': + if (!cmdline_input_from_file(optarg, &payload)) + payload.length = 0; + break; + case 'g': + group = optarg; + break; + case 'p': + strncpy(port_str, optarg, NI_MAXSERV - 1); + port_str[NI_MAXSERV - 1] = '\0'; + break; + case 'm': + method = cmdline_method(optarg); + break; + case 'N': + msgtype = COAP_MESSAGE_NON; + break; + case 's': + cmdline_subscribe(optarg); + break; + case 'o': + output_file.length = strlen(optarg); + output_file.s = (unsigned char *) coap_malloc(output_file.length + 1); + + if (!output_file.s) + { + fprintf(stderr, "cannot set output file: insufficient memory\n"); + exit(-1); + } + else + { + /* copy filename including trailing zero */ + memcpy(output_file.s, optarg, output_file.length + 1); + } + break; + case 'A': + cmdline_content_type(optarg, COAP_OPTION_ACCEPT); + break; + case 't': + cmdline_content_type(optarg, COAP_OPTION_CONTENT_TYPE); + break; + case 'O': + cmdline_option(optarg); + break; + case 'P': + if (!cmdline_proxy(optarg)) + { + fprintf(stderr, "error specifying proxy address\n"); + exit(-1); + } + break; + case 'T': + cmdline_token(optarg); + break; + case 'v': + log_level = strtol(optarg, NULL, 10); + break; + default: + usage(argv[0], PACKAGE_VERSION); + exit(1); + } + } + + coap_set_log_level(log_level); + + if (optind < argc) + cmdline_uri(argv[optind]); + else + { + usage(argv[0], PACKAGE_VERSION); + exit(1); + } + + if (proxy.length) + { + server = proxy; + port = proxy_port; + } + else + { + server = uri.host; + port = uri.port; + } + + /* resolve destination address where server should be sent */ + res = resolve_address(&server, &dst.addr.sa); + + if (res < 0) + { + fprintf(stderr, "failed to resolve address\n"); + exit(-1); + } + + dst.size = res; + dst.addr.sin.sin_port = htons(port); + + /* add Uri-Host if server address differs from uri.host */ + + switch (dst.addr.sa.sa_family) + { + case AF_INET: + addrptr = &dst.addr.sin.sin_addr; + + /* create context for IPv4 */ + ctx = get_context("0.0.0.0", port_str); + break; + case AF_INET6: + addrptr = &dst.addr.sin6.sin6_addr; + + /* create context for IPv6 */ + ctx = get_context("::", port_str); + break; + default: + ; + } + + if (!ctx) + { + coap_log(LOG_EMERG, "cannot create context\n"); + return -1; + } + + coap_register_option(ctx, COAP_OPTION_BLOCK2); + coap_register_response_handler(ctx, message_handler); + + /* join multicast group if requested at command line */ + if (group) + join(ctx, group); + + /* construct CoAP message */ + + if (!proxy.length && addrptr + && (inet_ntop(dst.addr.sa.sa_family, addrptr, addr, sizeof(addr)) != 0) + && (strlen(addr) != uri.host.length || memcmp(addr, uri.host.s, uri.host.length) != 0)) + { + /* add Uri-Host */ + + coap_insert(&optlist, new_option_node(COAP_OPTION_URI_HOST, uri.host.length, uri.host.s), + order_opts); + } + + /* set block option if requested at commandline */ + if (flags & FLAGS_BLOCK) + set_blocksize(); + + if (!(pdu = coap_new_request(ctx, method, optlist))) + return -1; + +#ifndef NDEBUG + if (LOG_DEBUG <= coap_get_log_level()) + { + debug("sending CoAP request:\n"); + coap_show_pdu(pdu); + } +#endif + + if (pdu->hdr->type == COAP_MESSAGE_CON) + tid = coap_send_confirmed(ctx, &dst, pdu); + else + tid = coap_send(ctx, &dst, pdu); + + if (pdu->hdr->type != COAP_MESSAGE_CON || tid == COAP_INVALID_TID) + coap_delete_pdu(pdu); + + set_timeout(&max_wait, wait_seconds); + debug("timeout is set to %d seconds\n", wait_seconds); + + while (!(ready && coap_can_exit(ctx))) + { + FD_ZERO(&readfds); + FD_SET(ctx->sockfd, &readfds); + + nextpdu = coap_peek_next(ctx); + + coap_ticks(&now); + while (nextpdu && nextpdu->t <= now - ctx->sendqueue_basetime) + { + coap_retransmit(ctx, coap_pop_next(ctx)); + nextpdu = coap_peek_next(ctx); + } + + if (nextpdu && nextpdu->t < min(obs_wait ? obs_wait : max_wait, max_wait) - now) + { + /* set timeout if there is a pdu to send */ + tv.tv_usec = ((nextpdu->t) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND; + tv.tv_sec = (nextpdu->t) / COAP_TICKS_PER_SECOND; + } + else + { + /* check if obs_wait fires before max_wait */ + if (obs_wait && obs_wait < max_wait) + { + tv.tv_usec = ((obs_wait - now) % COAP_TICKS_PER_SECOND) * 1000000 + / COAP_TICKS_PER_SECOND; + tv.tv_sec = (obs_wait - now) / COAP_TICKS_PER_SECOND; + } + else + { + tv.tv_usec = ((max_wait - now) % COAP_TICKS_PER_SECOND) * 1000000 + / COAP_TICKS_PER_SECOND; + tv.tv_sec = (max_wait - now) / COAP_TICKS_PER_SECOND; + } + } + + result = select(ctx->sockfd + 1, &readfds, 0, 0, &tv); + + if (result < 0) + { /* error */ + perror("select"); + } + else if (result > 0) + { /* read from socket */ + if (FD_ISSET(ctx->sockfd, &readfds)) + { + coap_read(ctx); /* read received data */ + coap_dispatch(ctx); /* and dispatch PDUs from receivequeue */ + } + } + else + { /* timeout */ + coap_ticks(&now); + if (max_wait <= now) + { + info("timeout\n"); + break; + } + if (obs_wait && obs_wait <= now) + { + debug("clear observation relationship\n"); + clear_obs(ctx, &dst); /* FIXME: handle error case COAP_TID_INVALID */ + + /* make sure that the obs timer does not fire again */ + obs_wait = 0; + obs_seconds = 0; + } + } + } + + close_output(); + + coap_free_context(ctx); + + return 0; +} diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/examples/etsi_iot_01.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/examples/etsi_iot_01.c new file mode 100644 index 000000000..83f582e21 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/examples/etsi_iot_01.c @@ -0,0 +1,796 @@ +/* CoAP server for first ETSI CoAP plugtest, March 2012 + * + * Copyright (C) 2012--2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "uthash.h" +#include "coap.h" + +#define COAP_RESOURCE_CHECK_TIME_SEC 1 + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/* temporary storage for dynamic resource representations */ +static int quit = 0; + +#define COAP_OPT_BLOCK_SZX_MAX 6 /**< allowed maximum for block szx value */ + +#define REQUIRE_ETAG 0x01 /* flag for coap_payload_t: require ETag option */ +typedef struct +{ + UT_hash_handle hh; + coap_key_t resource_key; /* foreign key that points into resource space */ + unsigned int flags; /* some flags to control behavior */ + size_t max_data; /* maximum size allocated for @p data */ + uint16_t media_type; /* media type for this object */ + size_t length; /* length of data */ + unsigned char data[]; /* the actual contents */ +} coap_payload_t; + +coap_payload_t *test_resources = NULL; + +/** + * This structure is used to store URIs for dynamically allocated + * resources, usually by POST or PUT. + */ +typedef struct +{ + UT_hash_handle hh; + coap_key_t resource_key; /* foreign key that points into resource space */ + size_t length; /* length of data */ + unsigned char data[]; /* the actual contents */ +} coap_dynamic_uri_t; + +coap_dynamic_uri_t *test_dynamic_uris = NULL; + +/* This variable is used to mimic long-running tasks that require + * asynchronous responses. */ +static coap_async_state_t *async = NULL; + +/* SIGINT handler: set quit to 1 for graceful termination */ +void handle_sigint(int signum) +{ + quit = 1; +} + +#define INDEX "libcoap server for ETSI CoAP Plugtest, March 2012, Paris\n" \ + "Copyright (C) 2012 Olaf Bergmann \n\n" + +coap_payload_t * +coap_new_payload(size_t size) +{ + coap_payload_t *p; + p = (coap_payload_t *) coap_malloc(sizeof(coap_payload_t) + size); + if (p) + { + memset(p, 0, sizeof(coap_payload_t)); + p->max_data = size; + } + + return p; +} + +static inline coap_payload_t * +coap_find_payload(const coap_key_t key) +{ + coap_payload_t *p; + HASH_FIND(hh, test_resources, key, sizeof(coap_key_t), p); + return p; +} + +static inline void coap_add_payload(const coap_key_t key, coap_payload_t *payload, + coap_dynamic_uri_t *uri) +{ + assert(payload); + + memcpy(payload->resource_key, key, sizeof(coap_key_t)); + HASH_ADD(hh, test_resources, resource_key, sizeof(coap_key_t), payload); + + if (uri) + { + memcpy(uri->resource_key, key, sizeof(coap_key_t)); + HASH_ADD(hh, test_dynamic_uris, resource_key, sizeof(coap_key_t), uri); + } +} + +static inline void coap_delete_payload(coap_payload_t *payload) +{ + if (payload) + { + coap_dynamic_uri_t *uri; + HASH_FIND(hh, test_dynamic_uris, payload->resource_key, sizeof(coap_key_t), uri); + if (uri) + { + HASH_DELETE(hh, test_dynamic_uris, uri); + coap_free(uri); + } + } + + HASH_DELETE(hh, test_resources, payload); + coap_free(payload); +} + +void hnd_get_index(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, + coap_pdu_t *request, str *token, coap_pdu_t *response) +{ + unsigned char buf[3]; + + response->hdr->code = COAP_RESPONSE_CODE(205); + + coap_add_option(response, COAP_OPTION_CONTENT_TYPE, + coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); + + coap_add_option(response, COAP_OPTION_MAXAGE, coap_encode_var_bytes(buf, 0x2ffff), buf); + + coap_add_data(response, strlen(INDEX), (unsigned char *) INDEX); +} + +void hnd_get_resource(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, + coap_pdu_t *request, str *token, coap_pdu_t *response) +{ + coap_key_t etag; + unsigned char buf[2]; + coap_payload_t *test_payload; + coap_block_t block; + + test_payload = coap_find_payload(resource->key); + if (!test_payload) + { + response->hdr->code = COAP_RESPONSE_CODE(500); + + return; + } + + response->hdr->code = COAP_RESPONSE_CODE(205); + + coap_add_option(response, COAP_OPTION_CONTENT_TYPE, + coap_encode_var_bytes(buf, test_payload->media_type), buf); + + /* add etag for the resource */ + if (test_payload->flags & REQUIRE_ETAG) + { + memset(etag, 0, sizeof(etag)); + coap_hash(test_payload->data, test_payload->length, etag); + coap_add_option(response, COAP_OPTION_ETAG, sizeof(etag), etag); + } + + if (request) + { + int res; + + if (coap_get_block(request, COAP_OPTION_BLOCK2, &block)) + { + res = coap_write_block_opt(&block, COAP_OPTION_BLOCK2, response, test_payload->length); + + switch (res) + { + case -2: /* illegal block */ + response->hdr->code = COAP_RESPONSE_CODE(400); + goto error; + case -1: /* should really not happen */ + assert(0); + /* fall through if assert is a no-op */ + case -3: /* cannot handle request */ + response->hdr->code = COAP_RESPONSE_CODE(500); + goto error; + default: /* everything is good */ + ; + } + + coap_add_block(response, test_payload->length, test_payload->data, block.num, + block.szx); + } + else + { + if (!coap_add_data(response, test_payload->length, test_payload->data)) + { + /* set initial block size, will be lowered by + * coap_write_block_opt) automatically */ + block.szx = 6; + coap_write_block_opt(&block, COAP_OPTION_BLOCK2, response, test_payload->length); + + coap_add_block(response, test_payload->length, test_payload->data, block.num, + block.szx); + } + } + } + else + { /* this is a notification, block is 0 */ + /* FIXME: need to store block size with subscription */ + } + + return; + + error: coap_add_data(response, strlen(coap_response_phrase(response->hdr->code)), + (unsigned char *) coap_response_phrase(response->hdr->code)); +} + +/* DELETE handler for dynamic resources created by POST /test */ +void hnd_delete_resource(coap_context_t *ctx, struct coap_resource_t *resource, + coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response) +{ + coap_payload_t *payload; + + payload = coap_find_payload(resource->key); + + if (payload) + coap_delete_payload(payload); + + coap_delete_resource(ctx, resource->key); + + response->hdr->code = COAP_RESPONSE_CODE(202); +} + +void hnd_post_test(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, + coap_pdu_t *request, str *token, coap_pdu_t *response) +{ + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + coap_payload_t *test_payload; + size_t len; + size_t l = 6 + sizeof(void *); + coap_dynamic_uri_t *uri; + unsigned char *data; + +#define BUFSIZE 20 + int res; + unsigned char _buf[BUFSIZE]; + unsigned char *buf = _buf; + size_t buflen = BUFSIZE; + + coap_get_data(request, &len, &data); + + /* allocate storage for resource and to hold URI */ + test_payload = coap_new_payload(len); + uri = (coap_dynamic_uri_t *) coap_malloc(sizeof(coap_dynamic_uri_t) + l); + if (!(test_payload && uri)) + { + coap_log(LOG_CRIT, "cannot allocate new resource under /test"); + response->hdr->code = COAP_RESPONSE_CODE(500); + coap_free(test_payload); + coap_free(uri); + } + else + { + coap_resource_t *r; + + memset(uri, 0, sizeof(coap_dynamic_uri_t)); + uri->length = min(l, snprintf((char *)uri->data, l, "test/%p", test_payload)); + test_payload->length = len; + + memcpy(test_payload->data, data, len); + + r = coap_resource_init(uri->data, uri->length, 0); + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_resource); + coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_resource); + + /* set media_type if available */ + option = coap_check_option(request, COAP_OPTION_CONTENT_TYPE, &opt_iter); + if (option) + { + test_payload->media_type = coap_decode_var_bytes(COAP_OPT_VALUE(option), + COAP_OPT_LENGTH(option)); + } + + coap_add_resource(ctx, r); + coap_add_payload(r->key, test_payload, uri); + + /* add Location-Path */ + res = coap_split_path(uri->data, uri->length, buf, &buflen); + + while (res--) + { + coap_add_option(response, COAP_OPTION_LOCATION_PATH, COAP_OPT_LENGTH(buf), + COAP_OPT_VALUE(buf)); + + buf += COAP_OPT_SIZE(buf); + } + + response->hdr->code = COAP_RESPONSE_CODE(201); + } + +} + +void hnd_put_test(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, + coap_pdu_t *request, str *token, coap_pdu_t *response) +{ + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + coap_payload_t *payload; + size_t len; + unsigned char *data; + + response->hdr->code = COAP_RESPONSE_CODE(204); + + coap_get_data(request, &len, &data); + + payload = coap_find_payload(resource->key); + if (payload && payload->max_data < len) + { /* need more storage */ + coap_delete_payload(payload); + payload = NULL; + /* bug: when subsequent coap_new_payload() fails, our old contents + is gone */ + } + + if (!payload) + { /* create new payload */ + payload = coap_new_payload(len); + if (!payload) + goto error; + + coap_add_payload(resource->key, payload, NULL); + } + payload->length = len; + memcpy(payload->data, data, len); + + option = coap_check_option(request, COAP_OPTION_CONTENT_TYPE, &opt_iter); + if (option) + { + /* set media type given in request */ + payload->media_type = coap_decode_var_bytes(COAP_OPT_VALUE(option), + COAP_OPT_LENGTH(option)); + } + else + { + /* set default value */ + payload->media_type = COAP_MEDIATYPE_TEXT_PLAIN; + } + /* FIXME: need to change attribute ct of resource. + To do so, we need dynamic management of the attribute value + */ + + return; + error: + warn("cannot modify resource\n"); + response->hdr->code = COAP_RESPONSE_CODE(500); +} + +void hnd_delete_test(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, + coap_pdu_t *request, str *token, coap_pdu_t *response) +{ + /* the ETSI validation tool does not like empty resources... */ +#if 0 + coap_payload_t *payload; + payload = coap_find_payload(resource->key); + + if (payload) + payload->length = 0; +#endif + + response->hdr->code = COAP_RESPONSE_CODE(202); +} + +void hnd_get_query(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, + coap_pdu_t *request, str *token, coap_pdu_t *response) +{ + coap_opt_iterator_t opt_iter; + coap_opt_filter_t f; + coap_opt_t *q; + size_t len, L; + unsigned char buf[70]; + + response->hdr->code = COAP_RESPONSE_CODE(205); + + coap_add_option(response, COAP_OPTION_CONTENT_TYPE, + coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); + + coap_option_filter_clear(f); + coap_option_setb(f, COAP_OPTION_URI_QUERY); + + coap_option_iterator_init(request, &opt_iter, f); + + len = 0; + while ((len < sizeof(buf)) && (q = coap_option_next(&opt_iter))) + { + L = min(sizeof(buf) - len, 11); + memcpy(buf + len, "Uri-Query: ", L); + len += L; + + L = min(sizeof(buf) - len, COAP_OPT_LENGTH(q)); + memcpy(buf + len, COAP_OPT_VALUE(q), L); + len += L; + + if (len < sizeof(buf)) + buf[len++] = '\n'; + } + + coap_add_data(response, len, buf); +} + +/* handler for TD_COAP_CORE_16 */ +void hnd_get_separate(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, + coap_pdu_t *request, str *token, coap_pdu_t *response) +{ + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + coap_opt_filter_t f; + unsigned long delay = 5; + + if (async) + { + if (async->id != request->hdr->id) + { + coap_opt_filter_t f; + coap_option_filter_clear(f); + response->hdr->code = COAP_RESPONSE_CODE(503); + } + return; + } + + /* search for option delay in query list */ + coap_option_filter_clear(f); + coap_option_setb(f, COAP_OPTION_URI_QUERY); + + coap_option_iterator_init(request, &opt_iter, f); + + while ((option = coap_option_next(&opt_iter))) + { + if (strncmp("delay=", (char *) COAP_OPT_VALUE(option), 6) == 0) + { + int i; + unsigned long d = 0; + + for (i = 6; i < COAP_OPT_LENGTH(option); ++i) + d = d * 10 + COAP_OPT_VALUE(option)[i] - '0'; + + /* don't allow delay to be less than COAP_RESOURCE_CHECK_TIME*/ + delay = d < COAP_RESOURCE_CHECK_TIME_SEC ? COAP_RESOURCE_CHECK_TIME_SEC : d; + debug("set delay to %lu\n", delay); + break; + } + } + + async = coap_register_async(ctx, peer, request, COAP_ASYNC_SEPARATE, + (void *) (COAP_TICKS_PER_SECOND * delay)); +} + +void check_async(coap_context_t *ctx, coap_tick_t now) +{ + coap_pdu_t *response; + coap_async_state_t *tmp; + unsigned char buf[2]; + size_t size = sizeof(coap_hdr_t) + 8; + + if (!async || now < async->created + (unsigned long) async->appdata) + return; + + size += async->tokenlen; + + response = coap_pdu_init(async->flags & COAP_ASYNC_CONFIRM ? COAP_MESSAGE_CON : COAP_MESSAGE_NON, + COAP_RESPONSE_CODE(205), 0, size); + if (!response) + { + debug("check_async: insufficient memory, we'll try later\n"); + async->appdata = (void *) ((unsigned long) async->appdata + 15 * COAP_TICKS_PER_SECOND); + return; + } + + response->hdr->id = coap_new_message_id(ctx); + + if (async->tokenlen) + coap_add_token(response, async->tokenlen, async->token); + + coap_add_option(response, COAP_OPTION_CONTENT_TYPE, + coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); + + coap_add_data(response, 4, (unsigned char *) "done"); + + if (coap_send(ctx, &async->peer, response) == COAP_INVALID_TID) + { + debug("check_async: cannot send response for message %d\n", response->hdr->id); + } + coap_delete_pdu(response); + + coap_remove_async(ctx, async->id, &tmp); + coap_free_async(async); + async = NULL; +} + +coap_payload_t * +make_large(char *filename) +{ + coap_payload_t *payload; + FILE *inputfile = NULL; + struct stat statbuf; + + if (!filename) + return NULL; + + /* read from specified input file */ + if (stat(filename, &statbuf) < 0) + { + warn("cannot stat file %s\n", filename); + return NULL; + } + + payload = coap_new_payload(statbuf.st_size); + if (!payload) + return NULL; + + inputfile = fopen(filename, "r"); + if (!inputfile) + { + warn("cannot read file %s\n", filename); + coap_free(payload); + return NULL; + } + + payload->length = fread(payload->data, 1, statbuf.st_size, inputfile); + payload->media_type = 41; + + fclose(inputfile); + + return payload; +} + +void init_resources(coap_context_t *ctx) +{ + coap_resource_t *r; + coap_payload_t *test_payload; + + test_payload = coap_new_payload(200); + if (!test_payload) + coap_log(LOG_CRIT, "cannot allocate resource /test"); + else + { + test_payload->length = 13; + memcpy(test_payload->data, "put data here", test_payload->length); + /* test_payload->media_type is 0 anyway */ + + r = coap_resource_init((unsigned char *) "test", 4, 0); + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_resource); + coap_register_handler(r, COAP_REQUEST_POST, hnd_post_test); + coap_register_handler(r, COAP_REQUEST_PUT, hnd_put_test); + coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_test); + + coap_add_attr(r, (unsigned char *) "ct", 2, (unsigned char *) "0", 1, 0); + coap_add_attr(r, (unsigned char *) "rt", 2, (unsigned char *) "test", 4, 0); + coap_add_attr(r, (unsigned char *) "if", 2, (unsigned char *) "core#b", 6, 0); +#if 0 + coap_add_attr(r, (unsigned char *)"obs", 3, NULL, 0, 0); +#endif + coap_add_resource(ctx, r); + coap_add_payload(r->key, test_payload, NULL); + } + + /* TD_COAP_BLOCK_01 + * TD_COAP_BLOCK_02 */ + test_payload = make_large("etsi_iot_01_largedata.txt"); + if (!test_payload) + coap_log(LOG_CRIT, "cannot allocate resource /large\n"); + else + { + r = coap_resource_init((unsigned char *) "large", 5, 0); + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_resource); + + coap_add_attr(r, (unsigned char *) "ct", 2, (unsigned char *) "41", 2, 0); + coap_add_attr(r, (unsigned char *) "rt", 2, (unsigned char *) "large", 5, 0); + coap_add_resource(ctx, r); + + test_payload->flags |= REQUIRE_ETAG; + + coap_add_payload(r->key, test_payload, NULL); + } + + /* For TD_COAP_CORE_12 */ + test_payload = coap_new_payload(20); + if (!test_payload) + coap_log(LOG_CRIT, "cannot allocate resource /seg1/seg2/seg3\n"); + else + { + test_payload->length = 10; + memcpy(test_payload->data, "segsegseg!", test_payload->length); + /* test_payload->media_type is 0 anyway */ + + r = coap_resource_init((unsigned char *) "seg1/seg2/seg3", 14, 0); + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_resource); + + coap_add_attr(r, (unsigned char *) "ct", 2, (unsigned char *) "0", 1, 0); + coap_add_resource(ctx, r); + + coap_add_payload(r->key, test_payload, NULL); + } + + /* For TD_COAP_CORE_13 */ + r = coap_resource_init((unsigned char *) "query", 5, 0); + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_query); + + coap_add_attr(r, (unsigned char *) "ct", 2, (unsigned char *) "0", 1, 0); + coap_add_resource(ctx, r); + + /* For TD_COAP_CORE_16 */ + r = coap_resource_init((unsigned char *) "separate", 8, 0); + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_separate); + + coap_add_attr(r, (unsigned char *) "ct", 2, (unsigned char *) "0", 1, 0); + coap_add_attr(r, (unsigned char *) "rt", 2, (unsigned char *) "separate", 8, 0); + coap_add_resource(ctx, r); +} + +void usage(const char *program, const char *version) +{ + const char *p; + + p = strrchr(program, '/'); + if (p) + program = ++p; + + fprintf(stderr, "%s v%s -- ETSI CoAP plugtest server\n" + "(c) 2012 Olaf Bergmann \n\n" + "usage: %s [-A address] [-p port]\n\n" + "\t-A address\tinterface address to bind to\n" + "\t-p port\t\tlisten on specified port\n" + "\t-v num\t\tverbosity level (default: 3)\n", program, version, program); +} + +coap_context_t * +get_context(const char *node, const char *port) +{ + coap_context_t *ctx = NULL; + int s; + struct addrinfo hints; + struct addrinfo *result, *rp; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */ + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; + + s = getaddrinfo(node, port, &hints, &result); + if (s != 0) + { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); + return NULL; + } + + /* iterate through results until success */ + for (rp = result; rp != NULL; rp = rp->ai_next) + { + coap_address_t addr; + + if (rp->ai_addrlen <= sizeof(addr.addr)) + { + coap_address_init(&addr); + addr.size = rp->ai_addrlen; + memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen); + + ctx = coap_new_context(&addr); + if (ctx) + { + /* TODO: output address:port for successful binding */ + goto finish; + } + } + } + + fprintf(stderr, "no context available for interface '%s'\n", node); + + finish: freeaddrinfo(result); + return ctx; +} + +int main(int argc, char **argv) +{ + coap_context_t *ctx; + fd_set readfds; + struct timeval tv, *timeout; + int result; + coap_tick_t now; + coap_queue_t *nextpdu; + char addr_str[NI_MAXHOST] = "::"; + char port_str[NI_MAXSERV] = "5683"; + int opt; + coap_log_t log_level = LOG_WARNING; + + while ((opt = getopt(argc, argv, "A:p:v:")) != -1) + { + switch (opt) + { + case 'A': + strncpy(addr_str, optarg, NI_MAXHOST - 1); + addr_str[NI_MAXHOST - 1] = '\0'; + break; + case 'p': + strncpy(port_str, optarg, NI_MAXSERV - 1); + port_str[NI_MAXSERV - 1] = '\0'; + break; + case 'v': + log_level = strtol(optarg, NULL, 10); + break; + default: + usage(argv[0], PACKAGE_VERSION); + exit(1); + } + } + + coap_set_log_level(log_level); + + ctx = get_context(addr_str, port_str); + if (!ctx) + return -1; + + coap_register_option(ctx, COAP_OPTION_BLOCK2); + + init_resources(ctx); + + signal(SIGINT, handle_sigint); + + while (!quit) + { + FD_ZERO(&readfds); + FD_SET(ctx->sockfd, &readfds); + + nextpdu = coap_peek_next(ctx); + + coap_ticks(&now); + while (nextpdu && nextpdu->t <= now) + { + coap_retransmit(ctx, coap_pop_next(ctx)); + nextpdu = coap_peek_next(ctx); + } + + if (nextpdu && nextpdu->t <= now + COAP_RESOURCE_CHECK_TIME_SEC) + { + /* set timeout if there is a pdu to send before our automatic timeout occurs */ + tv.tv_usec = ((nextpdu->t - now) % COAP_TICKS_PER_SECOND) * 1000000 + / COAP_TICKS_PER_SECOND; + tv.tv_sec = (nextpdu->t - now) / COAP_TICKS_PER_SECOND; + timeout = &tv; + } + else + { + tv.tv_usec = 0; + tv.tv_sec = COAP_RESOURCE_CHECK_TIME_SEC; + timeout = &tv; + } + result = select(FD_SETSIZE, &readfds, 0, 0, timeout); + + if (result < 0) + { /* error */ + if (errno != EINTR) + perror("select"); + } + else if (result > 0) + { /* read from socket */ + if (FD_ISSET(ctx->sockfd, &readfds)) + { + coap_read(ctx); /* read received data */ + coap_dispatch(ctx); /* and dispatch PDUs from receivequeue */ + } + } + else + { /* timeout */ + /* coap_check_resource_list( ctx ); */ + } + + /* check if we have to send asynchronous responses */ + check_async(ctx, now); + } + + coap_free_context(ctx); + + return 0; +} diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/examples/rd.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/examples/rd.c new file mode 100644 index 000000000..0cc97d27c --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/examples/rd.c @@ -0,0 +1,750 @@ +/* coap -- simple implementation of the Constrained Application Protocol (CoAP) + * as defined in draft-ietf-core-coap + * + * Copyright (C) 2010--2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file rd.c + * @brief CoRE resource directory + * + * @see http://tools.ietf.org/id/draft-shelby-core-resource-directory + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "utlist.h" +#include "resource.h" +#include "coap.h" + +#define COAP_RESOURCE_CHECK_TIME 2 + +#define RD_ROOT_STR ((unsigned char *)"rd") +#define RD_ROOT_SIZE 2 + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +typedef struct rd_t +{ + UT_hash_handle hh; /**< hash handle (for internal use only) */ + coap_key_t key; /**< the actual key bytes for this resource */ + + size_t etag_len; /**< actual length of @c etag */ + unsigned char etag[8]; /**< ETag for current description */ + + str data; /**< points to the resource description */ +} rd_t; + +rd_t *resources = NULL; + +inline rd_t * +rd_new() +{ + rd_t *rd; + rd = (rd_t *) coap_malloc(sizeof(rd_t)); + if (rd) + memset(rd, 0, sizeof(rd_t)); + + return rd; +} + +inline void rd_delete(rd_t *rd) +{ + if (rd) + { + coap_free(rd->data.s); + coap_free(rd); + } +} + +/* temporary storage for dynamic resource representations */ +static int quit = 0; + +/* SIGINT handler: set quit to 1 for graceful termination */ +void handle_sigint(int signum) +{ + quit = 1; +} + +void hnd_get_resource(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, + coap_pdu_t *request, str *token, coap_pdu_t *response) +{ + rd_t *rd = NULL; + unsigned char buf[3]; + + HASH_FIND(hh, resources, resource->key, sizeof(coap_key_t), rd); + + response->hdr->code = COAP_RESPONSE_CODE(205); + + coap_add_option(response, COAP_OPTION_CONTENT_TYPE, + coap_encode_var_bytes(buf, COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), buf); + + if (rd && rd->etag_len) + coap_add_option(response, COAP_OPTION_ETAG, rd->etag_len, rd->etag); + + if (rd && rd->data.s) + coap_add_data(response, rd->data.length, rd->data.s); +} + +void hnd_put_resource(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, + coap_pdu_t *request, str *token, coap_pdu_t *response) +{ +#if 1 + response->hdr->code = COAP_RESPONSE_CODE(501); +#else /* FIXME */ + coap_opt_iterator_t opt_iter; + coap_opt_t *token, *etag; + coap_pdu_t *response; + size_t size = sizeof(coap_hdr_t); + int type = (request->hdr->type == COAP_MESSAGE_CON) + ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON; + rd_t *rd = NULL; + unsigned char code; /* result code */ + unsigned char *data; + str tmp; + + HASH_FIND(hh, resources, resource->key, sizeof(coap_key_t), rd); + if (rd) + { + /* found resource object, now check Etag */ + etag = coap_check_option(request, COAP_OPTION_ETAG, &opt_iter); + if (!etag || (COAP_OPT_LENGTH(etag) != rd->etag_len) + || memcmp(COAP_OPT_VALUE(etag), rd->etag, rd->etag_len) != 0) + { + + if (coap_get_data(request, &tmp.length, &data)) + { + + tmp.s = (unsigned char *)coap_malloc(tmp.length); + if (!tmp.s) + { + debug("hnd_put_rd: cannot allocate storage for new rd\n"); + code = COAP_RESPONSE_CODE(503); + goto finish; + } + + coap_free(rd->data.s); + rd->data.s = tmp.s; + rd->data.length = tmp.length; + memcpy(rd->data.s, data, rd->data.length); + } + } + + if (etag) + { + rd->etag_len = min(COAP_OPT_LENGTH(etag), sizeof(rd->etag)); + memcpy(rd->etag, COAP_OPT_VALUE(etag), rd->etag_len); + } + + code = COAP_RESPONSE_CODE(204); + /* FIXME: update lifetime */ + + } + else + { + + code = COAP_RESPONSE_CODE(503); + } + + finish: + /* FIXME: do not create a new response but use the old one instead */ + response = coap_pdu_init(type, code, request->hdr->id, size); + + if (!response) + { + debug("cannot create response for message %d\n", request->hdr->id); + return; + } + + if (request->hdr->token_length) + coap_add_token(response, request->hdr->token_length, request->hdr->token); + + if (coap_send(ctx, peer, response) == COAP_INVALID_TID) + { + debug("hnd_get_rd: cannot send response for message %d\n", + request->hdr->id); + } + coap_delete_pdu(response); +#endif +} + +void hnd_delete_resource(coap_context_t *ctx, struct coap_resource_t *resource, + coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response) +{ + rd_t *rd = NULL; + + HASH_FIND(hh, resources, resource->key, sizeof(coap_key_t), rd); + if (rd) + { + HASH_DELETE(hh, resources, rd); + rd_delete(rd); + } + /* FIXME: link attributes for resource have been created dynamically + * using coap_malloc() and must be released. */ + coap_delete_resource(ctx, resource->key); + + response->hdr->code = COAP_RESPONSE_CODE(202); +} + +void hnd_get_rd(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, + coap_pdu_t *request, str *token, coap_pdu_t *response) +{ + unsigned char buf[3]; + + response->hdr->code = COAP_RESPONSE_CODE(205); + + coap_add_option(response, COAP_OPTION_CONTENT_TYPE, + coap_encode_var_bytes(buf, COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), buf); + + coap_add_option(response, COAP_OPTION_MAXAGE, coap_encode_var_bytes(buf, 0x2ffff), buf); +} + +int parse_param(unsigned char *search, size_t search_len, unsigned char *data, size_t data_len, + str *result) +{ + + if (result) + memset(result, 0, sizeof(str)); + + if (!search_len) + return 0; + + while (search_len <= data_len) + { + + /* handle parameter if found */ + if (memcmp(search, data, search_len) == 0) + { + data += search_len; + data_len -= search_len; + + /* key is only valid if we are at end of string or delimiter follows */ + if (!data_len || *data == '=' || *data == '&') + { + while (data_len && *data != '=') + { + ++data; + --data_len; + } + + if (data_len > 1 && result) + { + /* value begins after '=' */ + + result->s = ++data; + while (--data_len && *data != '&') + { + ++data; + result->length++; + } + } + + return 1; + } + } + + /* otherwise proceed to next */ + while (--data_len && *data++ != '&') + ; + } + + return 0; +} + +void add_source_address(struct coap_resource_t *resource, coap_address_t *peer) +{ +#define BUFSIZE 64 + char *buf; + size_t n = 1; + + buf = (char *) coap_malloc(BUFSIZE); + if (!buf) + return; + + buf[0] = '"'; + + switch (peer->addr.sa.sa_family) + { + + case AF_INET: + /* FIXME */ + break; + + case AF_INET6: + n += snprintf(buf + n, BUFSIZE - n, "[%02x%02x:%02x%02x:%02x%02x:%02x%02x" + ":%02x%02x:%02x%02x:%02x%02x:%02x%02x]", peer->addr.sin6.sin6_addr.s6_addr[0], + peer->addr.sin6.sin6_addr.s6_addr[1], peer->addr.sin6.sin6_addr.s6_addr[2], + peer->addr.sin6.sin6_addr.s6_addr[3], peer->addr.sin6.sin6_addr.s6_addr[4], + peer->addr.sin6.sin6_addr.s6_addr[5], peer->addr.sin6.sin6_addr.s6_addr[6], + peer->addr.sin6.sin6_addr.s6_addr[7], peer->addr.sin6.sin6_addr.s6_addr[8], + peer->addr.sin6.sin6_addr.s6_addr[9], peer->addr.sin6.sin6_addr.s6_addr[10], + peer->addr.sin6.sin6_addr.s6_addr[11], peer->addr.sin6.sin6_addr.s6_addr[12], + peer->addr.sin6.sin6_addr.s6_addr[13], peer->addr.sin6.sin6_addr.s6_addr[14], + peer->addr.sin6.sin6_addr.s6_addr[15]); + + if (peer->addr.sin6.sin6_port != htons(COAP_DEFAULT_PORT)) + { + n += snprintf(buf + n, BUFSIZE - n, ":%d", peer->addr.sin6.sin6_port); + } + break; + default: + ; + } + + if (n < BUFSIZE) + buf[n++] = '"'; + + coap_add_attr(resource, (unsigned char *) "A", 1, (unsigned char *) buf, n, + COAP_ATTR_FLAGS_RELEASE_VALUE); +#undef BUFSIZE +} + +rd_t * +make_rd(coap_address_t *peer, coap_pdu_t *pdu) +{ + rd_t *rd; + unsigned char *data; + coap_opt_iterator_t opt_iter; + coap_opt_t *etag; + + rd = rd_new(); + + if (!rd) + { + debug("hnd_get_rd: cannot allocate storage for rd\n"); + return NULL; + } + + if (coap_get_data(pdu, &rd->data.length, &data)) + { + rd->data.s = (unsigned char *) coap_malloc(rd->data.length); + if (!rd->data.s) + { + debug("hnd_get_rd: cannot allocate storage for rd->data\n"); + rd_delete(rd); + return NULL; + } + memcpy(rd->data.s, data, rd->data.length); + } + + etag = coap_check_option(pdu, COAP_OPTION_ETAG, &opt_iter); + if (etag) + { + rd->etag_len = min(COAP_OPT_LENGTH(etag), sizeof(rd->etag)); + memcpy(rd->etag, COAP_OPT_VALUE(etag), rd->etag_len); + } + + return rd; +} + +void hnd_post_rd(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, + coap_pdu_t *request, str *token, coap_pdu_t *response) +{ + coap_resource_t *r; + coap_opt_iterator_t opt_iter; + coap_opt_t *query; +#define LOCSIZE 68 + unsigned char *loc; + size_t loc_size; + str h = + { 0, NULL }, ins = + { 0, NULL }, rt = + { 0, NULL }, lt = + { 0, NULL }; /* store query parameters */ + unsigned char *buf; + + loc = (unsigned char *) coap_malloc(LOCSIZE); + if (!loc) + { + response->hdr->code = COAP_RESPONSE_CODE(500); + return; + } + memcpy(loc, RD_ROOT_STR, RD_ROOT_SIZE); + + loc_size = RD_ROOT_SIZE; + loc[loc_size++] = '/'; + + /* store query parameters for later use */ + query = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter); + if (query) + { + parse_param((unsigned char *) "h", 1, COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), &h); + parse_param((unsigned char *) "ins", 3, COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), + &ins); + parse_param((unsigned char *) "lt", 2, COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), <); + parse_param((unsigned char *) "rt", 2, COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), &rt); + } + + if (h.length) + { /* client has specified a node name */ + memcpy(loc + loc_size, h.s, min(h.length, LOCSIZE - loc_size - 1)); + loc_size += min(h.length, LOCSIZE - loc_size - 1); + + if (ins.length && loc_size > 1) + { + loc[loc_size++] = '-'; + memcpy((char *) (loc + loc_size), ins.s, min(ins.length, LOCSIZE - loc_size - 1)); + loc_size += min(ins.length, LOCSIZE - loc_size - 1); + } + + } + else + { /* generate node identifier */ + loc_size += snprintf((char *) (loc + loc_size), LOCSIZE - loc_size - 1, "%x", + request->hdr->id); + + if (loc_size > 1) + { + if (ins.length) + { + loc[loc_size++] = '-'; + memcpy((char *) (loc + loc_size), ins.s, min(ins.length, LOCSIZE - loc_size - 1)); + loc_size += min(ins.length, LOCSIZE - loc_size - 1); + } + else + { + coap_tick_t now; + coap_ticks(&now); + + loc_size += snprintf((char *) (loc + loc_size), LOCSIZE - loc_size - 1, "-%x", now); + } + } + } + + /* TODO: + * - use lt to check expiration + */ + + r = coap_resource_init(loc, loc_size, COAP_RESOURCE_FLAGS_RELEASE_URI); + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_resource); + coap_register_handler(r, COAP_REQUEST_PUT, hnd_put_resource); + coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_resource); + + if (ins.s) + { + buf = (unsigned char *) coap_malloc(ins.length + 2); + if (buf) + { + /* add missing quotes */ + buf[0] = '"'; + memcpy(buf + 1, ins.s, ins.length); + buf[ins.length + 1] = '"'; + coap_add_attr(r, (unsigned char *) "ins", 3, buf, ins.length + 2, + COAP_ATTR_FLAGS_RELEASE_VALUE); + } + } + + if (rt.s) + { + buf = (unsigned char *) coap_malloc(rt.length + 2); + if (buf) + { + /* add missing quotes */ + buf[0] = '"'; + memcpy(buf + 1, rt.s, rt.length); + buf[rt.length + 1] = '"'; + coap_add_attr(r, (unsigned char *) "rt", 2, buf, rt.length + 2, + COAP_ATTR_FLAGS_RELEASE_VALUE); + } + } + + add_source_address(r, peer); + + { + rd_t *rd; + rd = make_rd(peer, request); + if (rd) + { + coap_hash_path(loc, loc_size, rd->key); + HASH_ADD(hh, resources, key, sizeof(coap_key_t), rd); + } + else + { + /* FIXME: send error response and delete r */ + } + } + + coap_add_resource(ctx, r); + + /* create response */ + + response->hdr->code = COAP_RESPONSE_CODE(201); + + { /* split path into segments and add Location-Path options */ + unsigned char _b[LOCSIZE]; + unsigned char *b = _b; + size_t buflen = sizeof(_b); + int nseg; + + nseg = coap_split_path(loc, loc_size, b, &buflen); + while (nseg--) + { + coap_add_option(response, COAP_OPTION_LOCATION_PATH, COAP_OPT_LENGTH(b), + COAP_OPT_VALUE(b)); + b += COAP_OPT_SIZE(b); + } + } +} + +void init_resources(coap_context_t *ctx) +{ + coap_resource_t *r; + + r = coap_resource_init(RD_ROOT_STR, RD_ROOT_SIZE, 0); + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_rd); + coap_register_handler(r, COAP_REQUEST_POST, hnd_post_rd); + + coap_add_attr(r, (unsigned char *) "ct", 2, (unsigned char *) "40", 2, 0); + coap_add_attr(r, (unsigned char *) "rt", 2, (unsigned char *) "\"core-rd\"", 9, 0); + coap_add_attr(r, (unsigned char *) "ins", 2, (unsigned char *) "\"default\"", 9, 0); + + coap_add_resource(ctx, r); + +} + +void usage(const char *program, const char *version) +{ + const char *p; + + p = strrchr(program, '/'); + if (p) + program = ++p; + + fprintf(stderr, "%s v%s -- CoRE Resource Directory implementation\n" + "(c) 2011-2012 Olaf Bergmann \n\n" + "usage: %s [-A address] [-p port]\n\n" + "\t-A address\tinterface address to bind to\n" + "\t-p port\t\tlisten on specified port\n" + "\t-v num\t\tverbosity level (default: 3)\n", program, version, program); +} + +coap_context_t * +get_context(const char *node, const char *port) +{ + coap_context_t *ctx = NULL; + int s; + struct addrinfo hints; + struct addrinfo *result, *rp; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */ + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; + + s = getaddrinfo(node, port, &hints, &result); + if (s != 0) + { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); + return NULL; + } + + /* iterate through results until success */ + for (rp = result; rp != NULL; rp = rp->ai_next) + { + coap_address_t addr; + + if (rp->ai_addrlen <= sizeof(addr.addr)) + { + coap_address_init(&addr); + addr.size = rp->ai_addrlen; + memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen); + + ctx = coap_new_context(&addr); + if (ctx) + { + /* TODO: output address:port for successful binding */ + goto finish; + } + } + } + + fprintf(stderr, "no context available for interface '%s'\n", node); + + finish: freeaddrinfo(result); + return ctx; +} + +int join(coap_context_t *ctx, char *group_name) +{ + struct ipv6_mreq mreq; + struct addrinfo *reslocal = NULL, *resmulti = NULL, hints, *ainfo; + int result = -1; + + /* we have to resolve the link-local interface to get the interface id */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_DGRAM; + + result = getaddrinfo("::", NULL, &hints, &reslocal); + if (result < 0) + { + perror("join: cannot resolve link-local interface"); + goto finish; + } + + /* get the first suitable interface identifier */ + for (ainfo = reslocal; ainfo != NULL; ainfo = ainfo->ai_next) + { + if (ainfo->ai_family == AF_INET6) + { + mreq.ipv6mr_interface = ((struct sockaddr_in6 *) ainfo->ai_addr)->sin6_scope_id; + break; + } + } + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_DGRAM; + + /* resolve the multicast group address */ + result = getaddrinfo(group_name, NULL, &hints, &resmulti); + + if (result < 0) + { + perror("join: cannot resolve multicast address"); + goto finish; + } + + for (ainfo = resmulti; ainfo != NULL; ainfo = ainfo->ai_next) + { + if (ainfo->ai_family == AF_INET6) + { + mreq.ipv6mr_multiaddr = ((struct sockaddr_in6 *) ainfo->ai_addr)->sin6_addr; + break; + } + } + + result = setsockopt(ctx->sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *) &mreq, sizeof(mreq)); + if (result < 0) + perror("join: setsockopt"); + + finish: freeaddrinfo(resmulti); + freeaddrinfo(reslocal); + + return result; +} + +int main(int argc, char **argv) +{ + coap_context_t *ctx; + fd_set readfds; + struct timeval tv, *timeout; + int result; + coap_tick_t now; + coap_queue_t *nextpdu; + char addr_str[NI_MAXHOST] = "::"; + char port_str[NI_MAXSERV] = "5683"; + char *group = NULL; + int opt; + coap_log_t log_level = LOG_WARNING; + + while ((opt = getopt(argc, argv, "A:g:p:v:")) != -1) + { + switch (opt) + { + case 'A': + strncpy(addr_str, optarg, NI_MAXHOST - 1); + addr_str[NI_MAXHOST - 1] = '\0'; + break; + case 'g': + group = optarg; + break; + case 'p': + strncpy(port_str, optarg, NI_MAXSERV - 1); + port_str[NI_MAXSERV - 1] = '\0'; + break; + case 'v': + log_level = strtol(optarg, NULL, 10); + break; + default: + usage(argv[0], PACKAGE_VERSION); + exit(1); + } + } + + coap_set_log_level(log_level); + + ctx = get_context(addr_str, port_str); + if (!ctx) + return -1; + + if (group) + join(ctx, group); + + init_resources(ctx); + + signal(SIGINT, handle_sigint); + + while (!quit) + { + FD_ZERO(&readfds); + FD_SET(ctx->sockfd, &readfds); + + nextpdu = coap_peek_next(ctx); + + coap_ticks(&now); + while (nextpdu && nextpdu->t <= now) + { + coap_retransmit(ctx, coap_pop_next(ctx)); + nextpdu = coap_peek_next(ctx); + } + + if (nextpdu && nextpdu->t <= now + COAP_RESOURCE_CHECK_TIME) + { + /* set timeout if there is a pdu to send before our automatic timeout occurs */ + tv.tv_usec = ((nextpdu->t - now) % COAP_TICKS_PER_SECOND) * 1000000 + / COAP_TICKS_PER_SECOND; + tv.tv_sec = (nextpdu->t - now) / COAP_TICKS_PER_SECOND; + timeout = &tv; + } + else + { + tv.tv_usec = 0; + tv.tv_sec = COAP_RESOURCE_CHECK_TIME; + timeout = &tv; + } + result = select(FD_SETSIZE, &readfds, 0, 0, timeout); + + if (result < 0) + { /* error */ + if (errno != EINTR) + perror("select"); + } + else if (result > 0) + { /* read from socket */ + if (FD_ISSET(ctx->sockfd, &readfds)) + { + coap_read(ctx); /* read received data */ + coap_dispatch(ctx); /* and dispatch PDUs from receivequeue */ + } + } + else + { /* timeout */ + /* coap_check_resource_list( ctx ); */ + } + } + + coap_free_context(ctx); + + return 0; +} diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/examples/server.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/examples/server.c new file mode 100644 index 000000000..0d3e0555d --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/examples/server.c @@ -0,0 +1,456 @@ +/* coap -- simple implementation of the Constrained Application Protocol (CoAP) + * as defined in draft-ietf-core-coap + * + * Copyright (C) 2010--2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "resource.h" +#include "coap.h" + +#define COAP_RESOURCE_CHECK_TIME 2 + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/* temporary storage for dynamic resource representations */ +static int quit = 0; + +/* changeable clock base (see handle_put_time()) */ +static time_t my_clock_base = 0; + +struct coap_resource_t *time_resource = NULL; + +#ifndef WITHOUT_ASYNC +/* This variable is used to mimic long-running tasks that require + * asynchronous responses. */ +static coap_async_state_t *async = NULL; +#endif /* WITHOUT_ASYNC */ + +/* SIGINT handler: set quit to 1 for graceful termination */ +void handle_sigint(int signum) +{ + quit = 1; +} + +#define INDEX "This is a test server made with libcoap (see http://libcoap.sf.net)\n" \ + "Copyright (C) 2010--2013 Olaf Bergmann \n\n" + +void hnd_get_index(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, + coap_pdu_t *request, str *token, coap_pdu_t *response) +{ + unsigned char buf[3]; + + response->hdr->code = COAP_RESPONSE_CODE(205); + + coap_add_option(response, COAP_OPTION_CONTENT_TYPE, + coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); + + coap_add_option(response, COAP_OPTION_MAXAGE, coap_encode_var_bytes(buf, 0x2ffff), buf); + + coap_add_data(response, strlen(INDEX), (unsigned char *) INDEX); +} + +void hnd_get_time(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, + coap_pdu_t *request, str *token, coap_pdu_t *response) +{ + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + unsigned char buf[40]; + size_t len; + time_t now; + coap_tick_t t; + coap_subscription_t *subscription; + + /* FIXME: return time, e.g. in human-readable by default and ticks + * when query ?ticks is given. */ + + /* if my_clock_base was deleted, we pretend to have no such resource */ + response->hdr->code = my_clock_base ? COAP_RESPONSE_CODE(205) : COAP_RESPONSE_CODE(404); + + if (request != NULL && coap_check_option(request, COAP_OPTION_OBSERVE, &opt_iter)) + { + subscription = coap_add_observer(resource, peer, token); + if (subscription) + { + subscription->non = request->hdr->type == COAP_MESSAGE_NON; + coap_add_option(response, COAP_OPTION_OBSERVE, 0, NULL); + } + } + if (resource->dirty == 1) + coap_add_option(response, COAP_OPTION_OBSERVE, coap_encode_var_bytes(buf, ctx->observe), + buf); + + if (my_clock_base) + coap_add_option(response, COAP_OPTION_CONTENT_FORMAT, + coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); + + coap_add_option(response, COAP_OPTION_MAXAGE, coap_encode_var_bytes(buf, 0x01), buf); + + if (my_clock_base) + { + + /* calculate current time */ + coap_ticks(&t); + now = my_clock_base + (t / COAP_TICKS_PER_SECOND); + + if (request != NULL + && (option = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter)) + && memcmp(COAP_OPT_VALUE(option), "ticks", min(5, COAP_OPT_LENGTH(option))) == 0) + { + /* output ticks */ + len = snprintf((char *) buf, min(sizeof(buf), response->max_size - response->length), + "%u", (unsigned int) now); + coap_add_data(response, len, buf); + + } + else + { /* output human-readable time */ + struct tm *tmp; + tmp = gmtime(&now); + len = strftime((char *) buf, min(sizeof(buf), response->max_size - response->length), + "%b %d %H:%M:%S", tmp); + coap_add_data(response, len, buf); + } + } +} + +void hnd_put_time(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, + coap_pdu_t *request, str *token, coap_pdu_t *response) +{ + coap_tick_t t; + size_t size; + unsigned char *data; + + /* FIXME: re-set my_clock_base to clock_offset if my_clock_base == 0 + * and request is empty. When not empty, set to value in request payload + * (insist on query ?ticks). Return Created or Ok. + */ + + /* if my_clock_base was deleted, we pretend to have no such resource */ + response->hdr->code = my_clock_base ? COAP_RESPONSE_CODE(204) : COAP_RESPONSE_CODE(201); + + resource->dirty = 1; + + coap_get_data(request, &size, &data); + + if (size == 0) /* re-init */ + my_clock_base = clock_offset; + else + { + my_clock_base = 0; + coap_ticks(&t); + while (size--) + my_clock_base = my_clock_base * 10 + *data++; + my_clock_base -= t / COAP_TICKS_PER_SECOND; + } +} + +void hnd_delete_time(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, + coap_pdu_t *request, str *token, coap_pdu_t *response) +{ + my_clock_base = 0; /* mark clock as "deleted" */ + + /* type = request->hdr->type == COAP_MESSAGE_CON */ + /* ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON; */ +} + +#ifndef WITHOUT_ASYNC +void hnd_get_async(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, + coap_pdu_t *request, str *token, coap_pdu_t *response) +{ + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + unsigned long delay = 5; + size_t size; + + if (async) + { + if (async->id != request->hdr->id) + { + coap_opt_filter_t f; + coap_option_filter_clear(f); + response->hdr->code = COAP_RESPONSE_CODE(503); + } + return; + } + + option = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter); + if (option) + { + unsigned char *p = COAP_OPT_VALUE(option); + + delay = 0; + for (size = COAP_OPT_LENGTH(option); size; --size, ++p) + delay = delay * 10 + (*p - '0'); + } + + async = coap_register_async(ctx, peer, request, COAP_ASYNC_SEPARATE | COAP_ASYNC_CONFIRM, + (void *) (COAP_TICKS_PER_SECOND * delay)); +} + +void check_async(coap_context_t *ctx, coap_tick_t now) +{ + coap_pdu_t *response; + coap_async_state_t *tmp; + + size_t size = sizeof(coap_hdr_t) + 8; + + if (!async || now < async->created + (unsigned long) async->appdata) + return; + + response = coap_pdu_init(async->flags & COAP_ASYNC_CONFIRM ? COAP_MESSAGE_CON : COAP_MESSAGE_NON, + COAP_RESPONSE_CODE(205), 0, size); + if (!response) + { + debug("check_async: insufficient memory, we'll try later\n"); + async->appdata = (void *) ((unsigned long) async->appdata + 15 * COAP_TICKS_PER_SECOND); + return; + } + + response->hdr->id = coap_new_message_id(ctx); + + if (async->tokenlen) + coap_add_token(response, async->tokenlen, async->token); + + coap_add_data(response, 4, (unsigned char *) "done"); + + if (coap_send(ctx, &async->peer, response) == COAP_INVALID_TID) + { + debug("check_async: cannot send response for message %d\n", response->hdr->id); + } + coap_delete_pdu(response); + coap_remove_async(ctx, async->id, &tmp); + coap_free_async(async); + async = NULL; +} +#endif /* WITHOUT_ASYNC */ + +void init_resources(coap_context_t *ctx) +{ + coap_resource_t *r; + + r = coap_resource_init(NULL, 0, 0); + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_index); + + coap_add_attr(r, (unsigned char *) "ct", 2, (unsigned char *) "0", 1, 0); + coap_add_attr(r, (unsigned char *) "title", 5, (unsigned char *) "\"General Info\"", 14, 0); + coap_add_resource(ctx, r); + + /* store clock base to use in /time */ + my_clock_base = clock_offset; + + r = coap_resource_init((unsigned char *) "time", 4, 0); + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_time); + coap_register_handler(r, COAP_REQUEST_PUT, hnd_put_time); + coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_time); + + coap_add_attr(r, (unsigned char *) "ct", 2, (unsigned char *) "0", 1, 0); + coap_add_attr(r, (unsigned char *) "title", 5, (unsigned char *) "\"Internal Clock\"", 16, 0); + coap_add_attr(r, (unsigned char *) "rt", 2, (unsigned char *) "\"Ticks\"", 7, 0); + r->observable = 1; + coap_add_attr(r, (unsigned char *) "if", 2, (unsigned char *) "\"clock\"", 7, 0); + + coap_add_resource(ctx, r); + time_resource = r; + +#ifndef WITHOUT_ASYNC + r = coap_resource_init((unsigned char *) "async", 5, 0); + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_async); + + coap_add_attr(r, (unsigned char *) "ct", 2, (unsigned char *) "0", 1, 0); + coap_add_resource(ctx, r); +#endif /* WITHOUT_ASYNC */ +} + +void usage(const char *program, const char *version) +{ + const char *p; + + p = strrchr(program, '/'); + if (p) + program = ++p; + + fprintf(stderr, "%s v%s -- a small CoAP implementation\n" + "(c) 2010,2011 Olaf Bergmann \n\n" + "usage: %s [-A address] [-p port]\n\n" + "\t-A address\tinterface address to bind to\n" + "\t-p port\t\tlisten on specified port\n" + "\t-v num\t\tverbosity level (default: 3)\n", program, version, program); +} + +coap_context_t * +get_context(const char *node, const char *port) +{ + coap_context_t *ctx = NULL; + int s; + struct addrinfo hints; + struct addrinfo *result, *rp; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */ + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; + + s = getaddrinfo(node, port, &hints, &result); + if (s != 0) + { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); + return NULL; + } + + /* iterate through results until success */ + for (rp = result; rp != NULL; rp = rp->ai_next) + { + coap_address_t addr; + + if (rp->ai_addrlen <= sizeof(addr.addr)) + { + coap_address_init(&addr); + addr.size = rp->ai_addrlen; + memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen); + + ctx = coap_new_context(&addr); + if (ctx) + { + /* TODO: output address:port for successful binding */ + goto finish; + } + } + } + + fprintf(stderr, "no context available for interface '%s'\n", node); + + finish: freeaddrinfo(result); + return ctx; +} + +int main(int argc, char **argv) +{ + coap_context_t *ctx; + fd_set readfds; + struct timeval tv, *timeout; + int result; + coap_tick_t now; + coap_queue_t *nextpdu; + char addr_str[NI_MAXHOST] = "::"; + char port_str[NI_MAXSERV] = "5683"; + int opt; + coap_log_t log_level = LOG_WARNING; + + while ((opt = getopt(argc, argv, "A:p:v:")) != -1) + { + switch (opt) + { + case 'A': + strncpy(addr_str, optarg, NI_MAXHOST - 1); + addr_str[NI_MAXHOST - 1] = '\0'; + break; + case 'p': + strncpy(port_str, optarg, NI_MAXSERV - 1); + port_str[NI_MAXSERV - 1] = '\0'; + break; + case 'v': + log_level = strtol(optarg, NULL, 10); + break; + default: + usage(argv[0], PACKAGE_VERSION); + exit(1); + } + } + + coap_set_log_level(log_level); + + ctx = get_context(addr_str, port_str); + if (!ctx) + return -1; + + init_resources(ctx); + + signal(SIGINT, handle_sigint); + + while (!quit) + { + FD_ZERO(&readfds); + FD_SET(ctx->sockfd, &readfds); + + nextpdu = coap_peek_next(ctx); + + coap_ticks(&now); + while (nextpdu && nextpdu->t <= now - ctx->sendqueue_basetime) + { + coap_retransmit(ctx, coap_pop_next(ctx)); + nextpdu = coap_peek_next(ctx); + } + + if (nextpdu && nextpdu->t <= COAP_RESOURCE_CHECK_TIME) + { + /* set timeout if there is a pdu to send before our automatic timeout occurs */ + tv.tv_usec = ((nextpdu->t) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND; + tv.tv_sec = (nextpdu->t) / COAP_TICKS_PER_SECOND; + timeout = &tv; + } + else + { + tv.tv_usec = 0; + tv.tv_sec = COAP_RESOURCE_CHECK_TIME; + timeout = &tv; + } + result = select(FD_SETSIZE, &readfds, 0, 0, timeout); + + if (result < 0) + { /* error */ + if (errno != EINTR) + perror("select"); + } + else if (result > 0) + { /* read from socket */ + if (FD_ISSET(ctx->sockfd, &readfds)) + { + coap_read(ctx); /* read received data */ + coap_dispatch(ctx); /* and dispatch PDUs from receivequeue */ + } + } + else + { /* timeout */ + if (time_resource) + { + time_resource->dirty = 1; + } + } + +#ifndef WITHOUT_ASYNC + /* check if we have to send asynchronous responses */ + check_async(ctx, now); +#endif /* WITHOUT_ASYNC */ + +#ifndef WITHOUT_OBSERVE + /* check if we have to send observe notifications */ + coap_check_notify(ctx); +#endif /* WITHOUT_OBSERVE */ + } + + coap_free_context(ctx); + + return 0; +} diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/examples/tiny.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/examples/tiny.c new file mode 100644 index 000000000..9ccee12a9 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/examples/tiny.c @@ -0,0 +1,157 @@ +/* tiny -- tiny sender + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../coap.h" + +static coap_tid_t id; + +coap_pdu_t * +make_pdu(unsigned int value) +{ + coap_pdu_t *pdu; + unsigned char enc; + static unsigned char buf[20]; + int len, ls; + + if (!(pdu = coap_new_pdu())) + return NULL; + + pdu->hdr->type = COAP_MESSAGE_NON; + pdu->hdr->code = COAP_REQUEST_POST; + pdu->hdr->id = htons(id++); + + enc = COAP_PSEUDOFP_ENCODE_8_4_DOWN(value,ls); + coap_add_data(pdu, 1, &enc); + + len = snprintf((char *) buf, sizeof(buf), "%u", COAP_PSEUDOFP_DECODE_8_4(enc)); + if (len > 0) + { + coap_add_data(pdu, len, buf); + } + + return pdu; +} + +void usage(const char *program) +{ + const char *p; + + p = strrchr(program, '/'); + if (p) + program = ++p; + + fprintf(stderr, "%s -- tiny fake sensor\n" + "(c) 2010 Olaf Bergmann \n\n" + "usage: %s [group address]\n" + "\n\nSends some fake sensor values to specified multicast group\n", program, program); +} + +coap_context_t * +get_context(const char *node, const char *port) +{ + coap_context_t *ctx = NULL; + int s; + struct addrinfo hints; + struct addrinfo *result, *rp; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */ + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV | AI_ALL; + + s = getaddrinfo(node, port, &hints, &result); + if (s != 0) + { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); + return NULL; + } + + /* iterate through results until success */ + for (rp = result; rp != NULL; rp = rp->ai_next) + { + ctx = coap_new_context(rp->ai_addr, rp->ai_addrlen); + if (ctx) + { + /* TODO: output address:port for successful binding */ + goto finish; + } + } + + fprintf(stderr, "no context available for interface '%s'\n", node); + + finish: freeaddrinfo(result); + return ctx; +} + +int main(int argc, char **argv) +{ + coap_context_t *ctx; + struct timeval tv; + coap_pdu_t *pdu; + struct sockaddr_in6 dst; + int hops = 16; + + if (argc > 1 && strncmp(argv[1], "-h", 2) == 0) + { + usage(argv[0]); + exit(1); + } + + ctx = get_context("::", NULL); + if (!ctx) + return -1; + + id = rand() & INT_MAX; + + memset(&dst, 0, sizeof(struct sockaddr_in6)); + dst.sin6_family = AF_INET6; + inet_pton(AF_INET6, argc > 1 ? argv[1] : "::1", &dst.sin6_addr); + dst.sin6_port = htons(COAP_DEFAULT_PORT); + + if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr)) + { + /* set socket options for multicast */ + + if (setsockopt(ctx->sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *) &hops, sizeof(hops)) + < 0) + perror("setsockopt: IPV6_MULTICAST_HOPS"); + + } + + while (1) + { + + if (!(pdu = make_pdu(rand() & 0xfff))) + return -1; + + coap_send(ctx, (struct sockaddr *) &dst, sizeof(dst), pdu); + coap_delete_pdu(pdu); + + tv.tv_sec = 5; + tv.tv_usec = 0; + + select(0, 0, 0, 0, &tv); + + } + + coap_free_context(ctx); + + return 0; +} diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/hashkey.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/hashkey.c new file mode 100644 index 000000000..a79429200 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/hashkey.c @@ -0,0 +1,31 @@ +/* hashkey.c -- definition of hash key type and helper functions + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "hashkey.h" + +/* Caution: When changing this, update COAP_DEFAULT_WKC_HASHKEY + * accordingly (see int coap_hash_path()); + */ +void coap_hash_impl(const unsigned char *s, unsigned int len, coap_key_t h) +{ + size_t j; + + while (len--) + { + j = sizeof(coap_key_t) - 1; + + while (j) + { + h[j] = ((h[j] << 7) | (h[j - 1] >> 1)) + h[j]; + --j; + } + + h[0] = (h[0] << 7) + h[0] + *s++; + } +} + diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/hashkey.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/hashkey.h new file mode 100644 index 000000000..4732a703d --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/hashkey.h @@ -0,0 +1,57 @@ +/* hashkey.h -- definition of hash key type and helper functions + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file hashkey.h + * @brief definition of hash key type and helper functions + */ + +#ifndef _COAP_HASHKEY_H_ +#define _COAP_HASHKEY_H_ + +#include "str.h" + +typedef unsigned char coap_key_t[4]; + +#ifndef coap_hash +/** + * Calculates a fast hash over the given string @p s of length @p len + * and stores the result into @p h. Depending on the exact + * implementation, this function cannot be used as one-way function to + * check message integrity or simlar. + * + * @param s The string used for hash calculation. + * @param len The length of @p s. + * @param h The result buffer to store the calculated hash key. + */ +void coap_hash_impl(const unsigned char *s, unsigned int len, coap_key_t h); + +#define coap_hash(String,Length,Result) \ + coap_hash_impl((String),(Length),(Result)) + +/* This is used to control the pre-set hash-keys for resources. */ +#define __COAP_DEFAULT_HASH +#else +#undef __COAP_DEFAULT_HASH +#endif /* coap_hash */ + +/** + * Calls coap_hash() with given @c str object as parameter. + * + * @param Str Must contain a pointer to a coap string object. + * @param H A coap_key_t object to store the result. + * + * @hideinitializer + */ +#define coap_str_hash(Str,H) { \ + assert(Str); \ + memset((H), 0, sizeof(coap_key_t)); \ + coap_hash((H), (Str)->s, (Str)->length); \ + } + +#endif /* _COAP_HASHKEY_H_ */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/mem.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/mem.h new file mode 100644 index 000000000..a84405ee8 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/mem.h @@ -0,0 +1,18 @@ +/* mem.h -- CoAP memory handling + * Currently, this is just a dummy for malloc/free + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef _COAP_MEM_H_ +#define _COAP_MEM_H_ + +#include + +#define coap_malloc(size) malloc(size) +#define coap_free(size) free(size) + +#endif /* _COAP_MEM_H_ */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/net.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/net.c new file mode 100644 index 000000000..7138f4ae0 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/net.c @@ -0,0 +1,1805 @@ +/* net.c -- CoAP network interface + * + * Copyright (C) 2010--2014 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "config.h" + +#include +#include +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#elif HAVE_SYS_UNISTD_H +#include +#endif +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef WITH_LWIP +#include +#include +#include +#endif + +#include "debug.h" +#include "mem.h" +#include "str.h" +#include "async.h" +#include "resource.h" +#include "option.h" +#include "encode.h" +#include "block.h" +#include "net.h" + +#if defined(WITH_POSIX) + +time_t clock_offset; + +static inline coap_queue_t * +coap_malloc_node() +{ + return (coap_queue_t *)coap_malloc(sizeof(coap_queue_t)); +} + +static inline void +coap_free_node(coap_queue_t *node) +{ + coap_free(node); +} +#endif /* WITH_POSIX */ +#ifdef WITH_LWIP + +#include + +static void coap_retransmittimer_execute(void *arg); +static void coap_retransmittimer_restart(coap_context_t *ctx); + +static inline coap_queue_t * +coap_malloc_node() +{ + return (coap_queue_t *)memp_malloc(MEMP_COAP_NODE); +} + +static inline void +coap_free_node(coap_queue_t *node) +{ + memp_free(MEMP_COAP_NODE, node); +} + +#endif /* WITH_LWIP */ +#ifdef WITH_CONTIKI +# ifndef DEBUG +# define DEBUG DEBUG_PRINT +# endif /* DEBUG */ + +#include "memb.h" +#include "net/uip-debug.h" + +clock_time_t clock_offset; + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN]) + +void coap_resources_init(); +void coap_pdu_resources_init(); + +unsigned char initialized = 0; +coap_context_t the_coap_context; + +MEMB(node_storage, coap_queue_t, COAP_PDU_MAXCNT); + +PROCESS(coap_retransmit_process, "message retransmit process"); + +static inline coap_queue_t * +coap_malloc_node() +{ + return (coap_queue_t *)memb_alloc(&node_storage); +} + +static inline void +coap_free_node(coap_queue_t *node) +{ + memb_free(&node_storage, node); +} +#endif /* WITH_CONTIKI */ +#ifdef WITH_LWIP + +/** Callback to udp_recv when using lwIP. Gets called by lwIP on arriving + * packages, places a reference in context->pending_package, and calls + * coap_read to process the package. Thus, coap_read needs not be called in + * lwIP main loops. (When modifying this for thread-like operation, ie. if you + * remove the coap_read call from this, make sure that coap_read gets a chance + * to run before this callback is entered the next time.) + */ +static void received_package(void *arg, struct udp_pcb *upcb, struct pbuf *p, ip_addr_t *addr, u16_t port) +{ + struct coap_context_t *context = (coap_context_t *)arg; + + LWIP_ASSERT("pending_package was not cleared.", context->pending_package == NULL); + + context->pending_package = p; /* we don't free it, coap_read has to do that */ + context->pending_address.addr = addr->addr; /* FIXME: this has to become address-type independent, probably there'll be an lwip function for that */ + context->pending_port = port; + + char* data; + coap_read(context, data); +} + +#endif /* WITH_LWIP */ + +int print_wellknown(coap_context_t *, unsigned char *, size_t *, size_t, coap_opt_t *); + +void coap_handle_failed_notify(coap_context_t *, const coap_address_t *, const str *); + +unsigned int coap_adjust_basetime(coap_context_t *ctx, coap_tick_t now) +{ + unsigned int result = 0; + coap_tick_diff_t delta = now - ctx->sendqueue_basetime; + + if (ctx->sendqueue) + { + /* delta < 0 means that the new time stamp is before the old. */ + if (delta <= 0) + { + ctx->sendqueue->t -= delta; + } + else + { + /* This case is more complex: The time must be advanced forward, + * thus possibly leading to timed out elements at the queue's + * start. For every element that has timed out, its relative + * time is set to zero and the result counter is increased. */ + + coap_queue_t *q = ctx->sendqueue; + coap_tick_t t = 0; + while (q && (t + q->t < (coap_tick_t) delta)) + { + t += q->t; + q->t = 0; + result++; + q = q->next; + } + + /* finally adjust the first element that has not expired */ + if (q) + { + q->t = (coap_tick_t) delta - t; + } + } + } + + /* adjust basetime */ + ctx->sendqueue_basetime += delta; + + return result; +} + +int coap_insert_node(coap_queue_t **queue, coap_queue_t *node) +{ + coap_queue_t *p, *q; + if (!queue || !node) + return 0; + + /* set queue head if empty */ + if (!*queue) + { + *queue = node; + return 1; + } + + /* replace queue head if PDU's time is less than head's time */ + q = *queue; + if (node->t < q->t) + { + node->next = q; + *queue = node; + q->t -= node->t; /* make q->t relative to node->t */ + return 1; + } + + /* search for right place to insert */ + do + { + node->t -= q->t; /* make node-> relative to q->t */ + p = q; + q = q->next; + } while (q && q->t <= node->t); + + /* insert new item */ + if (q) + { + q->t -= node->t; /* make q->t relative to node->t */ + } + node->next = q; + p->next = node; + return 1; +} + +int coap_delete_node(coap_queue_t *node) +{ + if (!node) + return 0; + + coap_delete_pdu(node->pdu); + coap_free_node(node); + + return 1; +} + +void coap_delete_all(coap_queue_t *queue) +{ + if (!queue) + return; + + coap_delete_all(queue->next); + coap_delete_node(queue); +} + +coap_queue_t * +coap_new_node() +{ + coap_queue_t *node; + node = coap_malloc_node(); + + if (!node) + { +#ifndef NDEBUG + coap_log(LOG_WARNING, "coap_new_node: malloc\n"); +#endif + return NULL; + } + + memset(node, 0, sizeof *node); + return node; +} + +coap_queue_t * +coap_peek_next(coap_context_t *context) +{ + if (!context || !context->sendqueue) + return NULL; + + return context->sendqueue; +} + +coap_queue_t * +coap_pop_next(coap_context_t *context) +{ + coap_queue_t *next; + + if (!context || !context->sendqueue) + return NULL; + + next = context->sendqueue; + context->sendqueue = context->sendqueue->next; + if (context->sendqueue) + { + context->sendqueue->t += next->t; + } + next->next = NULL; + return next; +} + +#ifdef COAP_DEFAULT_WKC_HASHKEY +/** Checks if @p Key is equal to the pre-defined hash key for.well-known/core. */ +#define is_wkc(Key) \ + (memcmp((Key), COAP_DEFAULT_WKC_HASHKEY, sizeof(coap_key_t)) == 0) +#else +/* Implements a singleton to store a hash key for the .wellknown/core + * resources. */ +int +is_wkc(coap_key_t k) +{ + static coap_key_t wkc; + static unsigned char _initialized = 0; + if (!_initialized) + { + _initialized = coap_hash_path((unsigned char *)COAP_DEFAULT_URI_WELLKNOWN, + sizeof(COAP_DEFAULT_URI_WELLKNOWN) - 1, wkc); + } + return memcmp(k, wkc, sizeof(coap_key_t)) == 0; +} +#endif + +coap_context_t * +coap_new_context(const coap_address_t *listen_addr) +{ +#ifdef WITH_POSIX + coap_context_t *c = coap_malloc( sizeof( coap_context_t ) ); + int reuse = 1; +#endif /* WITH_POSIX */ +#ifdef WITH_LWIP + coap_context_t *c = memp_malloc(MEMP_COAP_CONTEXT); +#endif /* WITH_LWIP */ +#ifdef WITH_CONTIKI + coap_context_t *c; + + if (initialized) + return NULL; +#endif /* WITH_CONTIKI */ + + if (!listen_addr) + { + coap_log(LOG_EMERG, "no listen address specified\n"); + return NULL; + } + + coap_clock_init(); +#ifdef WITH_LWIP + prng_init(LWIP_RAND()); +#else /* WITH_LWIP */ + prng_init((unsigned long)listen_addr ^ clock_offset); +#endif /* WITH_LWIP */ + +#ifndef WITH_CONTIKI + if (!c) + { +#ifndef NDEBUG + coap_log(LOG_EMERG, "coap_init: malloc:\n"); +#endif + return NULL; + } +#endif /* not WITH_CONTIKI */ +#ifdef WITH_CONTIKI + coap_resources_init(); + coap_pdu_resources_init(); + + c = &the_coap_context; + initialized = 1; +#endif /* WITH_CONTIKI */ + + memset(c, 0, sizeof(coap_context_t)); + + /* initialize message id */ + prng((unsigned char *)&c->message_id, sizeof(unsigned short)); + + /* register the critical options that we know */ + coap_register_option(c, COAP_OPTION_IF_MATCH); + coap_register_option(c, COAP_OPTION_URI_HOST); + coap_register_option(c, COAP_OPTION_IF_NONE_MATCH); + coap_register_option(c, COAP_OPTION_URI_PORT); + coap_register_option(c, COAP_OPTION_URI_PATH); + coap_register_option(c, COAP_OPTION_URI_QUERY); + coap_register_option(c, COAP_OPTION_ACCEPT); + coap_register_option(c, COAP_OPTION_PROXY_URI); + coap_register_option(c, COAP_OPTION_PROXY_SCHEME); + coap_register_option(c, COAP_OPTION_BLOCK2); + coap_register_option(c, COAP_OPTION_BLOCK1); + +#ifdef WITH_POSIX + c->sockfd = socket(listen_addr->addr.sa.sa_family, SOCK_DGRAM, 0); + if ( c->sockfd < 0 ) + { +#ifndef NDEBUG + coap_log(LOG_EMERG, "coap_new_context: socket\n"); +#endif /* WITH_POSIX */ + goto onerror; + } + + if ( setsockopt( c->sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse) ) < 0 ) + { +#ifndef NDEBUG + coap_log(LOG_WARNING, "setsockopt SO_REUSEADDR\n"); +#endif + } + + if (bind(c->sockfd, &listen_addr->addr.sa, listen_addr->size) < 0) + { +#ifndef NDEBUG + coap_log(LOG_EMERG, "coap_new_context: bind\n"); +#endif + goto onerror; + } + + return c; + + onerror: + if ( c->sockfd >= 0 ) + close ( c->sockfd ); + coap_free( c ); + return NULL; + +#endif /* WITH_POSIX */ +#ifdef WITH_CONTIKI + c->conn = udp_new(NULL, 0, NULL); + udp_bind(c->conn, listen_addr->port); + + process_start(&coap_retransmit_process, (char *)c); + + PROCESS_CONTEXT_BEGIN(&coap_retransmit_process); +#ifndef WITHOUT_OBSERVE + etimer_set(&c->notify_timer, COAP_RESOURCE_CHECK_TIME * COAP_TICKS_PER_SECOND); +#endif /* WITHOUT_OBSERVE */ + /* the retransmit timer must be initialized to some large value */ + etimer_set(&the_coap_context.retransmit_timer, 0xFFFF); + PROCESS_CONTEXT_END(&coap_retransmit_process); + return c; +#endif /* WITH_CONTIKI */ +#ifdef WITH_LWIP + c->pcb = udp_new(); + /* hard assert: this is not expected to fail dynamically */ + LWIP_ASSERT("Failed to allocate PCB for CoAP", c->pcb != NULL); + + udp_recv(c->pcb, received_package, (void*)c); + udp_bind(c->pcb, &listen_addr->addr, listen_addr->port); + + c->timer_configured = 0; + + return c; +#endif +} + +void coap_free_context(coap_context_t *context) +{ +#if defined(WITH_POSIX) || defined(WITH_LWIP) + coap_resource_t *res; +#ifndef COAP_RESOURCES_NOHASH + coap_resource_t *rtmp; +#endif +#endif /* WITH_POSIX || WITH_LWIP */ + if (!context) + return; + + coap_delete_all(context->recvqueue); + coap_delete_all(context->sendqueue); + +#ifdef WITH_LWIP + context->sendqueue = NULL; + coap_retransmittimer_restart(context); +#endif + +#if defined(WITH_POSIX) || defined(WITH_LWIP) +#ifdef COAP_RESOURCES_NOHASH + LL_FOREACH(context->resources, res) + { +#else + HASH_ITER(hh, context->resources, res, rtmp) + { +#endif + coap_delete_resource(context, res->key); + } +#endif /* WITH_POSIX || WITH_LWIP */ + +#ifdef WITH_POSIX + /* coap_delete_list(context->subscriptions); */ + close( context->sockfd ); + coap_free( context ); +#endif +#ifdef WITH_LWIP + udp_remove(context->pcb); + memp_free(MEMP_COAP_CONTEXT, context); +#endif +#ifdef WITH_CONTIKI + memset(&the_coap_context, 0, sizeof(coap_context_t)); + initialized = 0; +#endif /* WITH_CONTIKI */ +} + +int coap_option_check_critical(coap_context_t *ctx, coap_pdu_t *pdu, coap_opt_filter_t unknown) +{ + + coap_opt_iterator_t opt_iter; + int ok = 1; + + coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL); + + while (coap_option_next(&opt_iter)) + { + + /* The following condition makes use of the fact that + * coap_option_getb() returns -1 if type exceeds the bit-vector + * filter. As the vector is supposed to be large enough to hold + * the largest known option, we know that everything beyond is + * bad. + */ + if (opt_iter.type & 0x01 && coap_option_getb(ctx->known_options, opt_iter.type) < 1) + { + debug("unknown critical option %d\n", opt_iter.type); + + ok = 0; + + /* When opt_iter.type is beyond our known option range, + * coap_option_setb() will return -1 and we are safe to leave + * this loop. */ + if (coap_option_setb(unknown, opt_iter.type) == -1) + break; + } + } + + return ok; +} + +void coap_transaction_id(const coap_address_t *peer, const coap_pdu_t *pdu, coap_tid_t *id) +{ + coap_key_t h; + + memset(h, 0, sizeof(coap_key_t)); + + /* Compare the complete address structure in case of IPv4. For IPv6, + * we need to look at the transport address only. */ + +#ifdef WITH_POSIX + switch (peer->addr.sa.sa_family) + { + case AF_INET: + coap_hash((const unsigned char *)&peer->addr.sa, peer->size, h); + break; + case AF_INET6: + coap_hash((const unsigned char *)&peer->addr.sin6.sin6_port, + sizeof(peer->addr.sin6.sin6_port), h); + coap_hash((const unsigned char *)&peer->addr.sin6.sin6_addr, + sizeof(peer->addr.sin6.sin6_addr), h); + break; + default: + return; + } +#endif +#if defined(WITH_LWIP) || defined(WITH_CONTIKI) + /* FIXME: with lwip, we can do better */ + coap_hash((const unsigned char *)&peer->port, sizeof(peer->port), h); + coap_hash((const unsigned char *)&peer->addr, sizeof(peer->addr), h); +#endif /* WITH_LWIP || WITH_CONTIKI */ + + coap_hash((const unsigned char *)&pdu->hdr->id, sizeof(unsigned short), h); + + *id = ((h[0] << 8) | h[1]) ^ ((h[2] << 8) | h[3]); +} + +coap_tid_t coap_send_ack(coap_context_t *context, const coap_address_t *dst, coap_pdu_t *request) +{ + coap_pdu_t *response; + coap_tid_t result = COAP_INVALID_TID; + + if (request && request->hdr->type == COAP_MESSAGE_CON) + { + response = coap_pdu_init(COAP_MESSAGE_ACK, 0, request->hdr->id, sizeof(coap_pdu_t)); + if (response) + { + result = coap_send(context, dst, response); + coap_delete_pdu(response); + } + } + return result; +} + +#ifdef WITH_POSIX +/* releases space allocated by PDU if free_pdu is set */ +coap_tid_t +coap_send_impl(coap_context_t *context, + const coap_address_t *dst, + coap_pdu_t *pdu) +{ + + char* z = inet_ntoa(*(struct in_addr *)&(dst->addr)); + + ssize_t bytes_written; + coap_tid_t id = COAP_INVALID_TID; + + if ( !context || !dst || !pdu ) + return id; + + bytes_written = sendto( context->sockfd, pdu->hdr, pdu->length, 0, + &dst->addr.sa, dst->size); + + if (bytes_written >= 0) + { + coap_transaction_id(dst, pdu, &id); + } + else + { + coap_log(LOG_CRIT, "coap_send: sendto\n"); + } + + return id; +} +#endif /* WITH_POSIX */ +#ifdef WITH_CONTIKI +/* releases space allocated by PDU if free_pdu is set */ +coap_tid_t +coap_send_impl(coap_context_t *context, + const coap_address_t *dst, + coap_pdu_t *pdu) +{ + coap_tid_t id = COAP_INVALID_TID; + + if ( !context || !dst || !pdu ) + return id; + + /* FIXME: is there a way to check if send was successful? */ + uip_udp_packet_sendto(context->conn, pdu->hdr, pdu->length, + &dst->addr, dst->port); + + coap_transaction_id(dst, pdu, &id); + + return id; +} +#endif /* WITH_CONTIKI */ +#ifdef WITH_LWIP +coap_tid_t +coap_send_impl(coap_context_t *context, + const coap_address_t *dst, + coap_pdu_t *pdu) +{ + coap_tid_t id = COAP_INVALID_TID; + struct pbuf *p; + uint8_t err; + char *data_backup; + + if ( !context || !dst || !pdu ) + { + return id; + } + + data_backup = pdu->data; + + /* FIXME: we can't check this here with the existing infrastructure, but we + * should actually check that the pdu is not held by anyone but us. the + * respective pbuf is already exclusively owned by the pdu. */ + + p = pdu->pbuf; + LWIP_ASSERT("The PDU header is not where it is expected", pdu->hdr == p->payload + sizeof(coap_pdu_t)); + + err = pbuf_header(p, -sizeof(coap_pdu_t)); + if (err) + { + debug("coap_send_impl: pbuf_header failed\n"); + pbuf_free(p); + return id; + } + + coap_transaction_id(dst, pdu, &id); + + pbuf_realloc(p, pdu->length); + + udp_sendto(context->pcb, p, + &dst->addr, dst->port); + + pbuf_header(p, -(ptrdiff_t)((uint8_t*)pdu - (uint8_t*)p->payload) - sizeof(coap_pdu_t)); /* FIXME hack around udp_sendto not restoring; see http://lists.gnu.org/archive/html/lwip-users/2013-06/msg00008.html. for udp over ip over ethernet, this was -42; as we're doing ppp too, this has to be calculated generically */ + + err = pbuf_header(p, sizeof(coap_pdu_t)); + LWIP_ASSERT("Cannot undo pbuf_header", err == 0); + + /* restore destroyed pdu data */ + LWIP_ASSERT("PDU not restored", p->payload == pdu); + pdu->max_size = p->tot_len - sizeof(coap_pdu_t); /* reduced after pbuf_realloc */ + pdu->hdr = p->payload + sizeof(coap_pdu_t); + pdu->max_delta = 0; /* won't be used any more */ + pdu->length = pdu->max_size; + pdu->data = data_backup; + pdu->pbuf = p; + + return id; +} +#endif /* WITH_LWIP */ + +coap_tid_t coap_send(coap_context_t *context, const coap_address_t *dst, coap_pdu_t *pdu) +{ + return coap_send_impl(context, dst, pdu); +} + +coap_tid_t coap_send_error(coap_context_t *context, coap_pdu_t *request, const coap_address_t *dst, + unsigned char code, coap_opt_filter_t opts) +{ + coap_pdu_t *response; + coap_tid_t result = COAP_INVALID_TID; + + assert(request); + assert(dst); + + response = coap_new_error_response(request, code, opts); + if (response) + { + result = coap_send(context, dst, response); + coap_delete_pdu(response); + } + + return result; +} + +coap_tid_t coap_send_message_type(coap_context_t *context, const coap_address_t *dst, + coap_pdu_t *request, unsigned char type) +{ + coap_pdu_t *response; + coap_tid_t result = COAP_INVALID_TID; + + if (request) + { + response = coap_pdu_init(type, 0, request->hdr->id, sizeof(coap_pdu_t)); + if (response) + { + result = coap_send(context, dst, response); + coap_delete_pdu(response); + } + } + return result; +} + +coap_tid_t coap_send_confirmed(coap_context_t *context, const coap_address_t *dst, coap_pdu_t *pdu) +{ + coap_queue_t *node; + coap_tick_t now; + int r; + + node = coap_new_node(); + if (!node) + { + debug("coap_send_confirmed: insufficient memory\n"); + return COAP_INVALID_TID; + } + + node->id = coap_send_impl(context, dst, pdu); + if (COAP_INVALID_TID == node->id) + { + debug("coap_send_confirmed: error sending pdu\n"); + coap_free_node(node); + return COAP_INVALID_TID; + } + + prng((unsigned char *)&r, sizeof(r)); + + /* add randomized RESPONSE_TIMEOUT to determine retransmission timeout */ + node->timeout = COAP_DEFAULT_RESPONSE_TIMEOUT * COAP_TICKS_PER_SECOND + + (COAP_DEFAULT_RESPONSE_TIMEOUT >> 1) * ((COAP_TICKS_PER_SECOND * (r & 0xFF)) >> 8); + + memcpy(&node->remote, dst, sizeof(coap_address_t)); + node->pdu = pdu; + + /* Set timer for pdu retransmission. If this is the first element in + * the retransmission queue, the base time is set to the current + * time and the retransmission time is node->timeout. If there is + * already an entry in the sendqueue, we must check if this node is + * to be retransmitted earlier. Therefore, node->timeout is first + * normalized to the base time and then inserted into the queue with + * an adjusted relative time. + */coap_ticks(&now); + if (context->sendqueue == NULL) + { + node->t = node->timeout; + context->sendqueue_basetime = now; + } + else + { + /* make node->t relative to context->sendqueue_basetime */ + node->t = (now - context->sendqueue_basetime) + node->timeout; + } + + coap_insert_node(&context->sendqueue, node); + +#ifdef WITH_LWIP + if (node == context->sendqueue) /* don't bother with timer stuff if there are earlier retransmits */ + coap_retransmittimer_restart(context); +#endif + +#ifdef WITH_CONTIKI + { /* (re-)initialize retransmission timer */ + coap_queue_t *nextpdu; + + nextpdu = coap_peek_next(context); + assert(nextpdu); /* we have just inserted a node */ + + /* must set timer within the context of the retransmit process */ + PROCESS_CONTEXT_BEGIN(&coap_retransmit_process); + etimer_set(&context->retransmit_timer, nextpdu->t); + PROCESS_CONTEXT_END(&coap_retransmit_process); + } +#endif /* WITH_CONTIKI */ + + return node->id; +} + +coap_tid_t coap_retransmit(coap_context_t *context, coap_queue_t *node) +{ + if (!context || !node) + return COAP_INVALID_TID; + + /* re-initialize timeout when maximum number of retransmissions are not reached yet */ + if (node->retransmit_cnt < COAP_DEFAULT_MAX_RETRANSMIT) + { + node->retransmit_cnt++; + node->t = node->timeout << node->retransmit_cnt; + coap_insert_node(&context->sendqueue, node); +#ifdef WITH_LWIP + if (node == context->sendqueue) /* don't bother with timer stuff if there are earlier retransmits */ + coap_retransmittimer_restart(context); +#endif + + debug( + "** retransmission #%d of transaction %d\n", node->retransmit_cnt, ntohs(node->pdu->hdr->id)); + + node->id = coap_send_impl(context, &node->remote, node->pdu); + return node->id; + } + + /* no more retransmissions, remove node from system */ + +#ifndef WITH_CONTIKI + debug("** removed transaction %d\n", ntohs(node->id)); +#endif + +#ifndef WITHOUT_OBSERVE + /* Check if subscriptions exist that should be canceled after + COAP_MAX_NOTIFY_FAILURES */ + if (node->pdu->hdr->code >= 64) + { + str token = + { 0, NULL }; + + token.length = node->pdu->hdr->token_length; + token.s = node->pdu->hdr->token; + + coap_handle_failed_notify(context, &node->remote, &token); + } +#endif /* WITHOUT_OBSERVE */ + + /* And finally delete the node */ + coap_delete_node(node); + return COAP_INVALID_TID; +} + +/** + * Checks if @p opt fits into the message that ends with @p maxpos. + * This function returns @c 1 on success, or @c 0 if the option @p opt + * would exceed @p maxpos. + */ +static inline int check_opt_size(coap_opt_t *opt, unsigned char *maxpos) +{ + if (opt && opt < maxpos) + { + if (((*opt & 0x0f) < 0x0f) || (opt + 1 < maxpos)) + return opt + COAP_OPT_SIZE(opt) < maxpos; + } + return 0; +} + +int coap_read(coap_context_t *ctx, char* data) +{ +#ifdef WITH_POSIX + static char buf[COAP_MAX_PDU_SIZE]; +#endif +#if defined(WITH_LWIP) || defined(WITH_CONTIKI) + char *buf; +#endif + coap_hdr_t *pdu; + ssize_t bytes_read = -1; + coap_address_t src, dst; + coap_queue_t *node; + +#ifdef WITH_CONTIKI + buf = uip_appdata; +#endif /* WITH_CONTIKI */ +#ifdef WITH_LWIP + LWIP_ASSERT("No package pending", ctx->pending_package != NULL); + LWIP_ASSERT("Can only deal with contiguous PBUFs to read the initial details", ctx->pending_package->tot_len == ctx->pending_package->len); + buf = ctx->pending_package->payload; +#endif /* WITH_LWIP */ + + pdu = (coap_hdr_t *) buf; + + coap_address_init(&src); + +#ifdef WITH_POSIX + bytes_read = recvfrom(ctx->sockfd, buf, sizeof(buf), 0, &src.addr.sa, &src.size); + +#endif /* WITH_POSIX */ +#ifdef WITH_CONTIKI + if(uip_newdata()) + { + uip_ipaddr_copy(&src.addr, &UIP_IP_BUF->srcipaddr); + src.port = UIP_UDP_BUF->srcport; + uip_ipaddr_copy(&dst.addr, &UIP_IP_BUF->destipaddr); + dst.port = UIP_UDP_BUF->destport; + + bytes_read = uip_datalen(); + ((char *)uip_appdata)[bytes_read] = 0; + PRINTF("Server received %d bytes from [", (int)bytes_read); + PRINT6ADDR(&src.addr); + PRINTF("]:%d\n", uip_ntohs(src.port)); + } +#endif /* WITH_CONTIKI */ +#ifdef WITH_LWIP + /* FIXME: use lwip address operation functions */ + src.addr.addr = ctx->pending_address.addr; + src.port = ctx->pending_port; + bytes_read = ctx->pending_package->tot_len; +#endif /* WITH_LWIP */ + + if (bytes_read < 0) + { + warn("coap_read: recvfrom"); + goto error_early; + } + + if ((size_t) bytes_read < sizeof(coap_hdr_t)) + { + debug("coap_read: discarded invalid frame\n"); + goto error_early; + } + + if (pdu->version != COAP_DEFAULT_VERSION) + { + debug("coap_read: unknown protocol version\n"); + goto error_early; + } + + node = coap_new_node(); + if (!node) + goto error_early; + +#ifdef WITH_LWIP + node->pdu = coap_pdu_from_pbuf(ctx->pending_package); + ctx->pending_package = NULL; +#else + node->pdu = coap_pdu_init(0, 0, 0, bytes_read); +#endif + if (!node->pdu) + goto error; + + coap_ticks(&node->t); + memcpy(&node->local, &dst, sizeof(coap_address_t)); + memcpy(&node->remote, &src, sizeof(coap_address_t)); + + if (!coap_pdu_parse((unsigned char *) buf, bytes_read, node->pdu)) + { + warn("discard malformed PDU"); + goto error; + } + + /* and add new node to receive queue */ + coap_transaction_id(&node->remote, node->pdu, &node->id); + coap_insert_node(&ctx->recvqueue, node); + +#ifndef NDEBUG + if (LOG_DEBUG <= coap_get_log_level()) + { +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 40 +#endif + unsigned char addr[INET6_ADDRSTRLEN + 8]; + + if (coap_print_addr(&src, addr, INET6_ADDRSTRLEN + 8)) + debug("** received %d bytes from %s:\n", (int)bytes_read, addr); + + coap_show_pdu(node->pdu); + } +#endif + + return 0; + + error: + /* FIXME: send back RST? */ + coap_delete_node(node); + return -1; + error_early: +#ifdef WITH_LWIP + /* even if there was an error, clean up */ + pbuf_free(ctx->pending_package); + ctx->pending_package = NULL; +#endif + return -1; +} + +int coap_remove_from_queue(coap_queue_t **queue, coap_tid_t id, coap_queue_t **node) +{ + coap_queue_t *p, *q; + + if (!queue || !*queue) + return 0; + + /* replace queue head if PDU's time is less than head's time */ + + if (id == (*queue)->id) + { /* found transaction */ + *node = *queue; + *queue = (*queue)->next; + if (*queue) + { /* adjust relative time of new queue head */ + (*queue)->t += (*node)->t; + } + (*node)->next = NULL; + /* coap_delete_node( q ); */ + debug("*** removed transaction %u\n", id); + return 1; + } + + /* search transaction to remove (only first occurence will be removed) */ + q = *queue; + do + { + p = q; + q = q->next; + } while (q && id != q->id); + + if (q) + { /* found transaction */ + p->next = q->next; + if (p->next) + { /* must update relative time of p->next */ + p->next->t += q->t; + } + q->next = NULL; + *node = q; + /* coap_delete_node( q ); */ + debug("*** removed transaction %u\n", id); + return 1; + } + + return 0; + +} + +static inline int token_match(const unsigned char *a, size_t alen, const unsigned char *b, + size_t blen) +{ + return alen == blen && (alen == 0 || memcmp(a, b, alen) == 0); +} + +void coap_cancel_all_messages(coap_context_t *context, const coap_address_t *dst, + const unsigned char *token, size_t token_length) +{ + /* cancel all messages in sendqueue that are for dst + * and use the specified token */ + coap_queue_t *p, *q; + + debug("cancel_all_messages\n"); + while (context->sendqueue && coap_address_equals(dst, &context->sendqueue->remote) + && token_match(token, token_length, context->sendqueue->pdu->hdr->token, + context->sendqueue->pdu->hdr->token_length)) + { + q = context->sendqueue; + context->sendqueue = q->next; + debug("**** removed transaction %d\n", ntohs(q->pdu->hdr->id)); + coap_delete_node(q); + } + + if (!context->sendqueue) + return; + + p = context->sendqueue; + q = p->next; + + /* when q is not NULL, it does not match (dst, token), so we can skip it */ + while (q) + { + if (coap_address_equals(dst, &q->remote) + && token_match(token, token_length, q->pdu->hdr->token, q->pdu->hdr->token_length)) + { + p->next = q->next; + debug("**** removed transaction %d\n", ntohs(q->pdu->hdr->id)); + coap_delete_node(q); + q = p->next; + } + else + { + p = q; + q = q->next; + } + } +} + +coap_queue_t * +coap_find_transaction(coap_queue_t *queue, coap_tid_t id) +{ + while (queue && queue->id != id) + queue = queue->next; + + return queue; +} + +coap_pdu_t * +coap_new_error_response(coap_pdu_t *request, unsigned char code, coap_opt_filter_t opts) +{ + coap_opt_iterator_t opt_iter; + coap_pdu_t *response; + size_t size = sizeof(coap_hdr_t) + request->hdr->token_length; + int type; + coap_opt_t *option; + unsigned short opt_type = 0; /* used for calculating delta-storage */ + +#if COAP_ERROR_PHRASE_LENGTH > 0 + char *phrase = coap_response_phrase(code); + + /* Need some more space for the error phrase and payload start marker */ + if (phrase) + size += strlen(phrase) + 1; +#endif + + assert(request); + + /* cannot send ACK if original request was not confirmable */ + type = request->hdr->type == COAP_MESSAGE_CON ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON; + + /* Estimate how much space we need for options to copy from + * request. We always need the Token, for 4.02 the unknown critical + * options must be included as well. */ + coap_option_clrb(opts, COAP_OPTION_CONTENT_TYPE); /* we do not want this */ + + coap_option_iterator_init(request, &opt_iter, opts); + + /* Add size of each unknown critical option. As known critical + options as well as elective options are not copied, the delta + value might grow. + */ + while ((option = coap_option_next(&opt_iter))) + { + unsigned short delta = opt_iter.type - opt_type; + /* calculate space required to encode (opt_iter.type - opt_type) */ + if (delta < 13) + { + size++; + } + else if (delta < 269) + { + size += 2; + } + else + { + size += 3; + } + + /* add coap_opt_length(option) and the number of additional bytes + * required to encode the option length */ + + size += coap_opt_length(option); + switch (*option & 0x0f) + { + case 0x0e: + size++; + /* fall through */ + case 0x0d: + size++; + break; + default: + ; + } + + opt_type = opt_iter.type; + } + + /* Now create the response and fill with options and payload data. */ + response = coap_pdu_init(type, code, request->hdr->id, size); + if (response) + { + /* copy token */ + if (!coap_add_token(response, request->hdr->token_length, request->hdr->token)) + { + debug("cannot add token to error response\n"); + coap_delete_pdu(response); + return NULL; + } + + /* copy all options */ + coap_option_iterator_init(request, &opt_iter, opts); + while ((option = coap_option_next(&opt_iter))) + coap_add_option(response, opt_iter.type, COAP_OPT_LENGTH(option), + COAP_OPT_VALUE(option)); + +#if COAP_ERROR_PHRASE_LENGTH > 0 + /* note that diagnostic messages do not need a Content-Format option. */ + if (phrase) + coap_add_data(response, strlen(phrase), (unsigned char *) phrase); +#endif + } + + return response; +} + +/** + * Quick hack to determine the size of the resource description for + * .well-known/core. + */ +static inline size_t get_wkc_len(coap_context_t *context, coap_opt_t *query_filter) +{ + unsigned char buf[1]; + size_t len = 0; + + if (print_wellknown(context, buf, &len, UINT_MAX, query_filter) & COAP_PRINT_STATUS_ERROR) + { + warn("cannot determine length of /.well-known/core\n"); + return 0; + } + + debug("get_wkc_len: print_wellknown() returned %zu\n", len); + + return len; +} + +#define SZX_TO_BYTES(SZX) ((size_t)(1 << ((SZX) + 4))) + +coap_pdu_t * +wellknown_response(coap_context_t *context, coap_pdu_t *request) +{ + coap_pdu_t *resp; + coap_opt_iterator_t opt_iter; + size_t len, wkc_len; + unsigned char buf[2]; + int result = 0; + int need_block2 = 0; /* set to 1 if Block2 option is required */ + coap_block_t block; + coap_opt_t *query_filter; + size_t offset = 0; + + resp = coap_pdu_init( + request->hdr->type == COAP_MESSAGE_CON ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON, + COAP_RESPONSE_CODE(205), + request->hdr->id, COAP_MAX_PDU_SIZE); + if (!resp) + { + debug("wellknown_response: cannot create PDU\n"); + return NULL; + } + + if (!coap_add_token(resp, request->hdr->token_length, request->hdr->token)) + { + debug("wellknown_response: cannot add token\n"); + goto error; + } + + query_filter = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter); + wkc_len = get_wkc_len(context, query_filter); + + /* check whether the request contains the Block2 option */ + if (coap_get_block(request, COAP_OPTION_BLOCK2, &block)) + { + offset = block.num << (block.szx + 4); + if (block.szx > 6) + { /* invalid, MUST lead to 4.00 Bad Request */ + resp->hdr->code = COAP_RESPONSE_CODE(400); + return resp; + } + else if (block.szx > COAP_MAX_BLOCK_SZX) + { + block.szx = COAP_MAX_BLOCK_SZX; + block.num = offset >> (block.szx + 4); + } + + need_block2 = 1; + } + + /* Check if there is sufficient space to add Content-Format option + * and data. We do this before adding the Content-Format option to + * avoid sending error responses with that option but no actual + * content. */ + if (resp->max_size <= (size_t) resp->length + 3) + { + debug("wellknown_response: insufficient storage space\n"); + goto error; + } + + /* Add Content-Format. As we have checked for available storage, + * nothing should go wrong here. */ + assert(coap_encode_var_bytes(buf, COAP_MEDIATYPE_APPLICATION_LINK_FORMAT) == 1); + coap_add_option(resp, COAP_OPTION_CONTENT_FORMAT, + coap_encode_var_bytes(buf, COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), buf); + + /* check if Block2 option is required even if not requested */ + if (!need_block2 && (resp->max_size - (size_t) resp->length < wkc_len)) + { + assert(resp->length <= resp->max_size); + const size_t payloadlen = resp->max_size - resp->length; + /* yes, need block-wise transfer */ + block.num = 0; + block.m = 0; /* the M bit is set by coap_write_block_opt() */ + block.szx = COAP_MAX_BLOCK_SZX; + while (payloadlen < SZX_TO_BYTES(block.szx)) + { + if (block.szx == 0) + { + debug("wellknown_response: message to small even for szx == 0\n"); + goto error; + } + else + { + block.szx--; + } + } + + need_block2 = 1; + } + + /* write Block2 option if necessary */ + if (need_block2) + { + if (coap_write_block_opt(&block, COAP_OPTION_BLOCK2, resp, wkc_len) < 0) + { + debug("wellknown_response: cannot add Block2 option\n"); + goto error; + } + } + + /* Manually set payload of response to let print_wellknown() write, + * into our buffer without copying data. */ + + resp->data = (unsigned char *) resp->hdr + resp->length; + *resp->data = COAP_PAYLOAD_START; + resp->data++; + resp->length++; + len = need_block2 ? SZX_TO_BYTES(block.szx) : resp->max_size - resp->length; + + result = print_wellknown(context, resp->data, &len, offset, query_filter); + if ((result & COAP_PRINT_STATUS_ERROR) != 0) + { + debug("print_wellknown failed\n"); + goto error; + } + + resp->length += COAP_PRINT_OUTPUT_LENGTH(result); + return resp; + + error: + /* set error code 5.03 and remove all options and data from response */ + resp->hdr->code = COAP_RESPONSE_CODE(503); + resp->length = sizeof(coap_hdr_t) + resp->hdr->token_length; + return resp; +} + +#define WANT_WKC(Pdu,Key) \ + (((Pdu)->hdr->code == COAP_REQUEST_GET) && is_wkc(Key)) + +void handle_request(coap_context_t *context, coap_queue_t *node, const char* responseData) +{ + + coap_method_handler_t h = NULL; + coap_pdu_t *response = NULL; + coap_opt_filter_t opt_filter; + coap_resource_t *resource; + coap_key_t key; + + coap_option_filter_clear(opt_filter); + + /* try to find the resource from the request URI */ + coap_hash_request_uri(node->pdu, key); + resource = coap_get_resource_from_key(context, key); + + if (!resource) + { + /* The resource was not found. Check if the request URI happens to + * be the well-known URI. In that case, we generate a default + * response, otherwise, we return 4.04 */ + + switch (node->pdu->hdr->code) + { + + case COAP_REQUEST_GET: + if (is_wkc(key)) + { /* GET request for .well-known/core */ + info("create default response for %s\n", COAP_DEFAULT_URI_WELLKNOWN); + + response = wellknown_response(context, node->pdu); + + } + else + { /* GET request for any another resource, return 4.04 */ + + debug( + "GET for unknown resource 0x%02x%02x%02x%02x, return 4.04\n", key[0], key[1], key[2], key[3]); + response = coap_new_error_response(node->pdu, COAP_RESPONSE_CODE(404), + opt_filter); + } + break; + + default: /* any other request type */ + + debug( + "unhandled request for unknown resource 0x%02x%02x%02x%02x\r\n", key[0], key[1], key[2], key[3]); + if (!coap_is_mcast(&node->local)) + response = coap_new_error_response(node->pdu, COAP_RESPONSE_CODE(405), + opt_filter); + } + + if (response && coap_send(context, &node->remote, response) == COAP_INVALID_TID) + { + warn("cannot send response for transaction %u\n", node->id); + } + coap_delete_pdu(response); + + return; + } + + /* the resource was found, check if there is a registered handler */ + if ((size_t) node->pdu->hdr->code - 1 + < sizeof(resource->handler) / sizeof(coap_method_handler_t)) + h = resource->handler[node->pdu->hdr->code - 1]; + + if (h) + { + debug( + "call custom handler for resource 0x%02x%02x%02x%02x\n", key[0], key[1], key[2], key[3]); + response = coap_pdu_init( + node->pdu->hdr->type == COAP_MESSAGE_CON ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON, + 0, node->pdu->hdr->id, COAP_MAX_PDU_SIZE); + + /* Implementation detail: coap_add_token() immediately returns 0 + if response == NULL */ + if (coap_add_token(response, node->pdu->hdr->token_length, node->pdu->hdr->token)) + { + str token = + { node->pdu->hdr->token_length, node->pdu->hdr->token }; + + //h(context, resource, &node->remote, + //node->pdu, &token, response); + + unsigned char buf[3]; + response->hdr->code = COAP_RESPONSE_CODE(205); + coap_add_option(response, COAP_OPTION_CONTENT_TYPE, + coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); + coap_add_option(response, COAP_OPTION_MAXAGE, coap_encode_var_bytes(buf, 0x2ffff), buf); + coap_add_data(response, strlen(responseData), (unsigned char *) responseData); + + if (response->hdr->type != COAP_MESSAGE_NON + || (response->hdr->code >= 64 && !coap_is_mcast(&node->local))) + { + + if (coap_send(context, &node->remote, response) == COAP_INVALID_TID) + { + debug("cannot send response for message %d\n", node->pdu->hdr->id); + } + } + + coap_delete_pdu(response); + } + else + { + warn("cannot generate response\r\n"); + } + } + else + { + if (WANT_WKC(node->pdu, key)) + { + debug("create default response for %s\n", COAP_DEFAULT_URI_WELLKNOWN); + response = wellknown_response(context, node->pdu); + } + else + response = coap_new_error_response(node->pdu, COAP_RESPONSE_CODE(405), opt_filter); + + if (!response || (coap_send(context, &node->remote, response) == COAP_INVALID_TID)) + { + debug("cannot send response for transaction %u\n", node->id); + } + coap_delete_pdu(response); + } +} + +static inline void handle_response(coap_context_t *context, coap_queue_t *sent, coap_queue_t *rcvd) +{ + + /* Call application-specific reponse handler when available. If + * not, we must acknowledge confirmable messages. */ + if (context->response_handler) + { + + context->response_handler(context, &rcvd->remote, sent ? sent->pdu : NULL, rcvd->pdu, + rcvd->id); + } + else + { + /* send ACK if rcvd is confirmable (i.e. a separate response) */ + coap_send_ack(context, &rcvd->remote, rcvd->pdu); + } +} + +static inline int +#ifdef __GNUC__ +handle_locally(coap_context_t *context __attribute__ ((unused)), + coap_queue_t *node __attribute__ ((unused))) +{ +#else /* not a GCC */ + handle_locally(coap_context_t *context, coap_queue_t *node) + { +#endif /* GCC */ + /* this function can be used to check if node->pdu is really for us */ + return 1; + } + + /** + * This function handles RST messages received for the message passed + * in @p sent. + */ + static void coap_handle_rst(coap_context_t *context, const coap_queue_t *sent) + { +#ifndef WITHOUT_OBSERVE + coap_resource_t *r; +#ifndef COAP_RESOURCES_NOHASH + coap_resource_t *tmp; +#endif + str token = + { 0, NULL }; + + /* remove observer for this resource, if any + * get token from sent and try to find a matching resource. Uh! + */ + + COAP_SET_STR(&token, sent->pdu->hdr->token_length, sent->pdu->hdr->token); + +#ifndef WITH_CONTIKI +#ifdef COAP_RESOURCES_NOHASH + LL_FOREACH(context->resources, r) + { +#else + HASH_ITER(hh, context->resources, r, tmp) + { +#endif + coap_delete_observer(r, &sent->remote, &token); + coap_cancel_all_messages(context, &sent->remote, token.s, token.length); + } +#else /* WITH_CONTIKI */ + r = (coap_resource_t *)resource_storage.mem; + for (i = 0; i < resource_storage.num; ++i, ++r) + { + if (resource_storage.count[i]) + { + coap_delete_observer(r, &sent->remote, &token); + coap_cancel_all_messages(context, &sent->remote, token.s, token.length); + } + } +#endif /* WITH_CONTIKI */ +#endif /* WITOUT_OBSERVE */ + } + + void coap_dispatch(coap_context_t *context, const char* responseData) + { + coap_queue_t *rcvd = NULL, *sent = NULL; + coap_pdu_t *response; + coap_opt_filter_t opt_filter; + + if (!context) + return; + + memset(opt_filter, 0, sizeof(coap_opt_filter_t)); + + while (context->recvqueue) + { + rcvd = context->recvqueue; + + /* remove node from recvqueue */ + context->recvqueue = context->recvqueue->next; + rcvd->next = NULL; + + if (rcvd->pdu->hdr->version != COAP_DEFAULT_VERSION) + { + debug("dropped packet with unknown version %u\n", rcvd->pdu->hdr->version); + goto cleanup; + } + + switch (rcvd->pdu->hdr->type) + { + case COAP_MESSAGE_ACK: + /* find transaction in sendqueue to stop retransmission */ + coap_remove_from_queue(&context->sendqueue, rcvd->id, &sent); + + if (rcvd->pdu->hdr->code == 0) + goto cleanup; + + /* FIXME: if sent code was >= 64 the message might have been a + * notification. Then, we must flag the observer to be alive + * by setting obs->fail_cnt = 0. */ + if (sent && COAP_RESPONSE_CLASS(sent->pdu->hdr->code) == 2) + { + const str token = + { sent->pdu->hdr->token_length, sent->pdu->hdr->token }; + coap_touch_observer(context, &sent->remote, &token); + } + break; + + case COAP_MESSAGE_RST: + /* We have sent something the receiver disliked, so we remove + * not only the transaction but also the subscriptions we might + * have. */ + + coap_log(LOG_ALERT, "got RST for message %u\n", ntohs(rcvd->pdu->hdr->id)); + + /* find transaction in sendqueue to stop retransmission */ + coap_remove_from_queue(&context->sendqueue, rcvd->id, &sent); + + if (sent) + coap_handle_rst(context, sent); + goto cleanup; + + case COAP_MESSAGE_NON: /* check for unknown critical options */ + if (coap_option_check_critical(context, rcvd->pdu, opt_filter) == 0) + goto cleanup; + break; + + case COAP_MESSAGE_CON: /* check for unknown critical options */ + if (coap_option_check_critical(context, rcvd->pdu, opt_filter) == 0) + { + + /* FIXME: send response only if we have received a request. Otherwise, + * send RST. */ + response = coap_new_error_response(rcvd->pdu, COAP_RESPONSE_CODE(402), + opt_filter); + + if (!response) + warn("coap_dispatch: cannot create error reponse\n"); + else + { + if (coap_send(context, &rcvd->remote, response) == COAP_INVALID_TID) + { + warn("coap_dispatch: error sending reponse\n"); + } + coap_delete_pdu(response); + } + + goto cleanup; + } + break; + } + + /* Pass message to upper layer if a specific handler was + * registered for a request that should be handled locally. */ + if (handle_locally(context, rcvd)) + { + if (COAP_MESSAGE_IS_REQUEST(rcvd->pdu->hdr)) + handle_request(context, rcvd, responseData); + else if (COAP_MESSAGE_IS_RESPONSE(rcvd->pdu->hdr)) + handle_response(context, sent, rcvd); + else + { + debug("dropped message with invalid code\n"); + coap_send_message_type(context, &rcvd->remote, rcvd->pdu, COAP_MESSAGE_RST); + } + } + + cleanup: coap_delete_node(sent); + coap_delete_node(rcvd); + } + } + + int coap_can_exit(coap_context_t *context) + { + return !context || (context->recvqueue == NULL && context->sendqueue == NULL); + } + +#ifdef WITH_CONTIKI + + /*---------------------------------------------------------------------------*/ + /* CoAP message retransmission */ + /*---------------------------------------------------------------------------*/ + PROCESS_THREAD(coap_retransmit_process, ev, data) + { + coap_tick_t now; + coap_queue_t *nextpdu; + + PROCESS_BEGIN(); + + debug("Started retransmit process\r\n"); + + while(1) + { + PROCESS_YIELD(); + if (ev == PROCESS_EVENT_TIMER) + { + if (etimer_expired(&the_coap_context.retransmit_timer)) + { + + nextpdu = coap_peek_next(&the_coap_context); + + coap_ticks(&now); + while (nextpdu && nextpdu->t <= now) + { + coap_retransmit(&the_coap_context, coap_pop_next(&the_coap_context)); + nextpdu = coap_peek_next(&the_coap_context); + } + + /* need to set timer to some value even if no nextpdu is available */ + etimer_set(&the_coap_context.retransmit_timer, + nextpdu ? nextpdu->t - now : 0xFFFF); + } +#ifndef WITHOUT_OBSERVE + if (etimer_expired(&the_coap_context.notify_timer)) + { + coap_check_notify(&the_coap_context); + etimer_reset(&the_coap_context.notify_timer); + } +#endif /* WITHOUT_OBSERVE */ + } + } + + PROCESS_END(); + } + /*---------------------------------------------------------------------------*/ + +#endif /* WITH_CONTIKI */ + +#ifdef WITH_LWIP + /* FIXME: retransmits that are not required any more due to incoming packages + * do *not* get cleared at the moment, the wakeup when the transmission is due + * is silently accepted. this is mainly due to the fact that the required + * checks are similar in two places in the code (when receiving ACK and RST) + * and that they cause more than one patch chunk, as it must be first checked + * whether the sendqueue item to be dropped is the next one pending, and later + * the restart function has to be called. nothing insurmountable, but it can + * also be implemented when things have stabilized, and the performance + * penality is minimal + * + * also, this completely ignores COAP_RESOURCE_CHECK_TIME. + * */ + + static void coap_retransmittimer_execute(void *arg) + { + coap_context_t *ctx = (coap_context_t*)arg; + coap_tick_t now; + coap_tick_t elapsed; + coap_queue_t *nextinqueue; + + ctx->timer_configured = 0; + + coap_ticks(&now); + + elapsed = now - ctx->sendqueue_basetime; /* that's positive for sure, and unless we haven't been called for a complete wrapping cycle, did not wrap */ + + nextinqueue = coap_peek_next(ctx); + while (nextinqueue != NULL) + { + if (nextinqueue->t > elapsed) + { + nextinqueue->t -= elapsed; + break; + } + else + { + elapsed -= nextinqueue->t; + coap_retransmit(ctx, coap_pop_next(ctx)); + nextinqueue = coap_peek_next(ctx); + } + } + + ctx->sendqueue_basetime = now; + + coap_retransmittimer_restart(ctx); + } + + static void coap_retransmittimer_restart(coap_context_t *ctx) + { + coap_tick_t now, elapsed, delay; + + if (ctx->timer_configured) + { + printf("clearing\n"); + sys_untimeout(coap_retransmittimer_execute, (void*)ctx); + ctx->timer_configured = 0; + } + if (ctx->sendqueue != NULL) + { + coap_ticks(&now); + elapsed = now - ctx->sendqueue_basetime; + if (ctx->sendqueue->t >= elapsed) + { + delay = ctx->sendqueue->t - elapsed; + } + else + { + /* a strange situation, but not completely impossible. + * + * this happens, for example, right after + * coap_retransmittimer_execute, when a retransmission + * was *just not yet* due, and the clock ticked before + * our coap_ticks was called. + * + * not trying to retransmit anything now, as it might + * cause uncontrollable recursion; let's just try again + * with the next main loop run. + * */ + delay = 0; + } + + printf("scheduling for %d ticks\n", delay); + sys_timeout(delay, coap_retransmittimer_execute, (void*)ctx); + ctx->timer_configured = 1; + } + } +#endif diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/net.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/net.h new file mode 100644 index 000000000..254b2b46e --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/net.h @@ -0,0 +1,448 @@ +/* net.h -- CoAP network interface + * + * Copyright (C) 2010--2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef _COAP_NET_H_ +#define _COAP_NET_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "config.h" + +#ifdef HAVE_ASSERT_H +#include +#else +#ifndef assert +#warning "assertions are disabled" +# define assert(x) +#endif +#endif + +#include +#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#ifdef WITH_LWIP +#include +#endif + +#include "option.h" +#include "address.h" +#include "prng.h" +#include "pdu.h" +#include "coap_time.h" + + struct coap_queue_t; + + typedef struct coap_queue_t + { + struct coap_queue_t *next; + + coap_tick_t t; /**< when to send PDU for the next time */ + unsigned char retransmit_cnt; /**< retransmission counter, will be removed when zero */ + unsigned int timeout; /**< the randomized timeout value */ + + coap_address_t local; /**< local address */ + coap_address_t remote; /**< remote address */ + coap_tid_t id; /**< unique transaction id */ + + coap_pdu_t *pdu; /**< the CoAP PDU to send */ + } coap_queue_t; + + /** Adds node to given queue, ordered by node->t. */ + int coap_insert_node(coap_queue_t **queue, coap_queue_t *node); + + /** Destroys specified node. */ + int coap_delete_node(coap_queue_t *node); + + /** Removes all items from given queue and frees the allocated storage. */ + void coap_delete_all(coap_queue_t *queue); + + /** Creates a new node suitable for adding to the CoAP sendqueue. */ + coap_queue_t *coap_new_node(); + + struct coap_resource_t; + struct coap_context_t; +#ifndef WITHOUT_ASYNC + struct coap_async_state_t; +#endif + + /** Message handler that is used as call-back in coap_context_t */ + typedef void (*coap_response_handler_t)(struct coap_context_t *, const coap_address_t *remote, + coap_pdu_t *sent, coap_pdu_t *received, const coap_tid_t id); + +#define COAP_MID_CACHE_SIZE 3 + typedef struct + { + unsigned char flags[COAP_MID_CACHE_SIZE]; + coap_key_t item[COAP_MID_CACHE_SIZE]; + } coap_mid_cache_t; + + /** The CoAP stack's global state is stored in a coap_context_t object */ + typedef struct coap_context_t + { + coap_opt_filter_t known_options; +#ifndef WITH_CONTIKI + struct coap_resource_t *resources; /**< hash table or list of known resources */ +#endif /* WITH_CONTIKI */ +#ifndef WITHOUT_ASYNC + /** list of asynchronous transactions */ + struct coap_async_state_t *async_state; +#endif /* WITHOUT_ASYNC */ + /** + * The time stamp in the first element of the sendqeue is relative + * to sendqueue_basetime. */ + coap_tick_t sendqueue_basetime; + coap_queue_t *sendqueue, *recvqueue; +#if WITH_POSIX + int sockfd; /**< send/receive socket */ +#endif /* WITH_POSIX */ +#ifdef WITH_CONTIKI + struct uip_udp_conn *conn; /**< uIP connection object */ + + struct etimer retransmit_timer; /**< fires when the next packet must be sent */ + struct etimer notify_timer; /**< used to check resources periodically */ +#endif /* WITH_CONTIKI */ +#ifdef WITH_LWIP + struct udp_pcb *pcb; /**< the underlying lwIP UDP PCB */ + struct pbuf *pending_package; /**< pbuf containing the last received package if not handled yet. This is only used to pass the package from the udp_recv callback into the coap_read function, which frees the pbuf and clears this field. */ + ip_addr_t pending_address; /**< the address associated with pending_package */ + u16_t pending_port; /**< the port associated with pending_package */ + + uint8_t timer_configured; /**< Set to 1 when a retransmission is scheduled using lwIP timers for this context, otherwise 0. */ +#endif /* WITH_LWIP */ + + /** + * The last message id that was used is stored in this field. The + * initial value is set by coap_new_context() and is usually a + * random value. A new message id can be created with + * coap_new_message_id(). + */ + unsigned short message_id; + + /** + * The next value to be used for Observe. This field is global for + * all resources and will be updated when notifications are created. + */ + unsigned int observe; + + coap_response_handler_t response_handler; + } coap_context_t; + + /** + * Registers a new message handler that is called whenever a response + * was received that matches an ongoing transaction. + * + * @param context The context to register the handler for. + * @param handler The response handler to register. + */ + static inline void coap_register_response_handler(coap_context_t *context, + coap_response_handler_t handler) + { + context->response_handler = handler; + } + + /** + * Registers the option type @p type with the given context object @p + * ctx. + * + * @param ctx The context to use. + * @param type The option type to register. + */ + inline static void coap_register_option(coap_context_t *ctx, unsigned char type) + { + coap_option_setb(ctx->known_options, type); + } + + /** + * Set sendqueue_basetime in the given context object @p ctx to @p + * now. This function returns the number of elements in the queue + * head that have timed out. + */ + unsigned int coap_adjust_basetime(coap_context_t *ctx, coap_tick_t now); + + /** Returns the next pdu to send without removing from sendqeue. */ + coap_queue_t *coap_peek_next(coap_context_t *context); + + /** Returns the next pdu to send and removes it from the sendqeue. */ + coap_queue_t *coap_pop_next(coap_context_t *context); + + /** Creates a new coap_context_t object that will hold the CoAP stack status. */ + coap_context_t *coap_new_context(const coap_address_t *listen_addr); + + /** + * Returns a new message id and updates @p context->message_id + * accordingly. The message id is returned in network byte order + * to make it easier to read in tracing tools. + * + * @param context the current coap_context_t object + * @return incremented message id in network byte order + */ + static inline unsigned short coap_new_message_id(coap_context_t *context) + { +#ifndef WITH_CONTIKI + return htons(++(context->message_id)); +#else /* WITH_CONTIKI */ + return uip_htons(++context->message_id); +#endif + } + + /* CoAP stack context must be released with coap_free_context() */ + void coap_free_context(coap_context_t *context); + + /** + * Sends a confirmed CoAP message to given destination. The memory + * that is allocated by pdu will not be released by + * coap_send_confirmed(). The caller must release the memory. + * + * @param context The CoAP context to use. + * @param dst The address to send to. + * @param pdu The CoAP PDU to send. + * @return The message id of the sent message or @c COAP_INVALID_TID on error. + */ + coap_tid_t coap_send_confirmed(coap_context_t *context, const coap_address_t *dst, + coap_pdu_t *pdu); + + /** + * Creates a new ACK PDU with specified error @p code. The options + * specified by the filter expression @p opts will be copied from the + * original request contained in @p request. Unless @c + * SHORT_ERROR_RESPONSE was defined at build time, the textual reason + * phrase for @p code will be added as payload, with Content-Type @c + * 0. This function returns a pointer to the new response message, or + * @c NULL on error. The storage allocated for the new message must be + * relased with coap_free(). + * + * @param request Specification of the received (confirmable) request. + * @param code The error code to set. + * @param opts An option filter that specifies which options to copy + * from the original request in @p node. + * + * @return A pointer to the new message or @c NULL on error. + */ + coap_pdu_t *coap_new_error_response(coap_pdu_t *request, unsigned char code, + coap_opt_filter_t opts); + /** + * Sends a non-confirmed CoAP message to given destination. The memory + * that is allocated by pdu will not be released by coap_send(). + * The caller must release the memory. + * + * @param context The CoAP context to use. + * @param dst The address to send to. + * @param pdu The CoAP PDU to send. + * @return The message id of the sent message or @c COAP_INVALID_TID on error. + */ + coap_tid_t coap_send(coap_context_t *context, const coap_address_t *dst, coap_pdu_t *pdu); + + /** + * Sends an error response with code @p code for request @p request to + * @p dst. @p opts will be passed to coap_new_error_response() to + * copy marked options from the request. This function returns the + * transaction id if the message was sent, or @c COAP_INVALID_TID + * otherwise. + * + * @param context The context to use. + * @param request The original request to respond to. + * @param dst The remote peer that sent the request. + * @param code The reponse code. + * @param opts A filter that specifies the options to copy from the + * @p request. + * + * @return The transaction id if the message was sent, or @c + * COAP_INVALID_TID otherwise. + */ + coap_tid_t coap_send_error(coap_context_t *context, coap_pdu_t *request, + const coap_address_t *dst, unsigned char code, coap_opt_filter_t opts); + + /** + * Helper funktion to create and send a message with @p type (usually + * ACK or RST). This function returns @c COAP_INVALID_TID when the + * message was not sent, a valid transaction id otherwise. + * + * @param context The CoAP context. + * @param dst Where to send the context. + * @param request The request that should be responded to. + * @param type Which type to set + * @return transaction id on success or @c COAP_INVALID_TID otherwise. + */ + coap_tid_t + coap_send_message_type(coap_context_t *context, const coap_address_t *dst, coap_pdu_t *request, + unsigned char type); + /** + * Sends an ACK message with code @c 0 for the specified @p request to + * @p dst. This function returns the corresponding transaction id if + * the message was sent or @c COAP_INVALID_TID on error. + * + * @param context The context to use. + * @param dst The destination address. + * @param request The request to be acknowledged. + * + * @return The transaction id if ACK was sent or @c COAP_INVALID_TID + * on error. + */ + coap_tid_t coap_send_ack(coap_context_t *context, const coap_address_t *dst, + coap_pdu_t *request); + + /** + * Sends an RST message with code @c 0 for the specified @p request to + * @p dst. This function returns the corresponding transaction id if + * the message was sent or @c COAP_INVALID_TID on error. + * + * @param context The context to use. + * @param dst The destination address. + * @param request The request to be reset. + * + * @return The transaction id if RST was sent or @c COAP_INVALID_TID + * on error. + */ + static inline coap_tid_t coap_send_rst(coap_context_t *context, const coap_address_t *dst, + coap_pdu_t *request) + { + return coap_send_message_type(context, dst, request, COAP_MESSAGE_RST); + } + + /** Handles retransmissions of confirmable messages */ + coap_tid_t coap_retransmit(coap_context_t *context, coap_queue_t *node); + + /** + * Reads data from the network and tries to parse as CoAP PDU. On success, 0 is returned + * and a new node with the parsed PDU is added to the receive queue in the specified context + * object. + */ + int coap_read(coap_context_t *context, char* data); + + /** + * Calculates a unique transaction id from given arguments @p peer and + * @p pdu. The id is returned in @p id. + * + * @param peer The remote party who sent @p pdu. + * @param pdu The message that initiated the transaction. + * @param id Set to the new id. + */ + void coap_transaction_id(const coap_address_t *peer, const coap_pdu_t *pdu, coap_tid_t *id); + + /** + * This function removes the element with given @p id from the list + * given list. If @p id was found, @p node is updated to point to the + * removed element. Note that the storage allocated by @p node is + * @b not released. The caller must do this manually using + * coap_delete_node(). This function returns @c 1 if the element with + * id @p id was found, @c 0 otherwise. For a return value of @c 0, + * the contents of @p node is undefined. + * + * @param queue The queue to search for @p id. + * @param id The node id to look for. + * @param node If found, @p node is updated to point to the + * removed node. You must release the storage pointed to by + * @p node manually. + * + * @return @c 1 if @p id was found, @c 0 otherwise. + */ + int coap_remove_from_queue(coap_queue_t **queue, coap_tid_t id, coap_queue_t **node); + + /** + * Removes the transaction identified by @p id from given @p queue. + * This is a convenience function for coap_remove_from_queue() with + * automatic deletion of the removed node. + * + * @param queue The queue to search for @p id. + * @param id The transaction id. + * + * @return @c 1 if node was found, removed and destroyed, @c 0 otherwise. + */ + inline static int coap_remove_transaction(coap_queue_t **queue, coap_tid_t id) + { + coap_queue_t *node; + if (!coap_remove_from_queue(queue, id, &node)) + return 0; + + coap_delete_node(node); + return 1; + } + + /** + * Retrieves transaction from queue. + * @queue The transaction queue to be searched + * @id Unique key of the transaction to find. + * @return A pointer to the transaction object or NULL if not found + */ + coap_queue_t *coap_find_transaction(coap_queue_t *queue, coap_tid_t id); + + /** + * Cancels all outstanding messages for peer @p dst that have the + * specified token. + * + * @param context The context in use + * @param dst Destination address of the messages to remove. + * @param token Message token + * @param token_length Actual length of @p token + */ + void coap_cancel_all_messages(coap_context_t *context, const coap_address_t *dst, + const unsigned char *token, size_t token_length); + + /** Dispatches the PDUs from the receive queue in given context. */ + void coap_dispatch(coap_context_t *context, const char* responseData); + + /** Returns 1 if there are no messages to send or to dispatch in the context's queues. */ + int coap_can_exit(coap_context_t *context); + + /** + * Returns the current value of an internal tick counter. The counter + * counts \c COAP_TICKS_PER_SECOND ticks every second. + */ + void coap_ticks(coap_tick_t *); + + /** + * Verifies that @p pdu contains no unknown critical options. Options + * must be registered at @p ctx, using the function + * coap_register_option(). A basic set of options is registered + * automatically by coap_new_context(). This function returns @c 1 if + * @p pdu is ok, @c 0 otherwise. The given filter object @p unknown + * will be updated with the unknown options. As only @c COAP_MAX_OPT + * options can be signalled this way, remaining options must be + * examined manually. + * + * @code + coap_opt_filter_t f = COAP_OPT_NONE; + coap_opt_iterator_t opt_iter; + + if (coap_option_check_critical(ctx, pdu, f) == 0) { + coap_option_iterator_init(pdu, &opt_iter, f); + + while (coap_option_next(&opt_iter)) { + if (opt_iter.type & 0x01) { + ... handle unknown critical option in opt_iter ... + } + } + } + * @endcode + * + * @param ctx The context where all known options are registered. + * @param pdu The PDU to check. + * @param unknown The output filter that will be updated to indicate the + * unknown critical options found in @p pdu. + * + * @return @c 1 if everything was ok, @c 0 otherwise. + */ + int coap_option_check_critical(coap_context_t *ctx, coap_pdu_t *pdu, coap_opt_filter_t unknown); + +#ifdef __cplusplus +} +#endif + +#endif /* _COAP_NET_H_ */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/option.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/option.c new file mode 100644 index 000000000..c8c8496eb --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/option.c @@ -0,0 +1,440 @@ +/* + * option.c -- helpers for handling options in CoAP PDUs + * + * Copyright (C) 2010-2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "config.h" + +#if defined(HAVE_ASSERT_H) && !defined(assert) +# include +#endif + +#include +#include + +#include "option.h" +#include "debug.h" + +coap_opt_t * +options_start(coap_pdu_t *pdu) +{ + + if (pdu && pdu->hdr + && (pdu->hdr->token + pdu->hdr->token_length < (unsigned char *) pdu->hdr + pdu->length)) + { + + coap_opt_t *opt = pdu->hdr->token + pdu->hdr->token_length; + return (*opt == COAP_PAYLOAD_START) ? NULL : opt; + + } + else + return NULL; +} + +size_t coap_opt_parse(const coap_opt_t *opt, size_t length, coap_option_t *result) +{ + + const coap_opt_t *opt_start = opt; /* store where parsing starts */ + assert(opt); + assert(result); + +#define ADVANCE_OPT(o,e,step) if ((e) < step) { \ + debug("cannot advance opt past end\n"); \ + return 0; \ + } else { \ + (e) -= step; \ + (o) = ((unsigned char *)(o)) + step; \ + } + + if (length < 1) + return 0; + + result->delta = (*opt & 0xf0) >> 4; + result->length = *opt & 0x0f; + + switch (result->delta) + { + case 15: + if (*opt != COAP_PAYLOAD_START) + debug("ignored reserved option delta 15\n"); + return 0; + case 14: + /* Handle two-byte value: First, the MSB + 269 is stored as delta value. + * After that, the option pointer is advanced to the LSB which is handled + * just like case delta == 13. */ + ADVANCE_OPT(opt, length, 1); + result->delta = ((*opt & 0xff) << 8) + 269; + if (result->delta < 269) + { + debug("delta too large\n"); + return 0; + } + /* fall through */ + case 13: + ADVANCE_OPT(opt, length, 1); + result->delta += *opt & 0xff; + break; + + default: + ; + } + + switch (result->length) + { + case 15: + debug("found reserved option length 15\n"); + return 0; + case 14: + /* Handle two-byte value: First, the MSB + 269 is stored as delta value. + * After that, the option pointer is advanced to the LSB which is handled + * just like case delta == 13. */ + ADVANCE_OPT(opt, length, 1); + result->length = ((*opt & 0xff) << 8) + 269; + /* fall through */ + case 13: + ADVANCE_OPT(opt, length, 1); + result->length += *opt & 0xff; + break; + + default: + ; + } + + ADVANCE_OPT(opt, length, 1); + /* opt now points to value, if present */ + + result->value = (unsigned char *) opt; + if (length < result->length) + { + debug("invalid option length\n"); + return 0; + } + //printf("[COAP] Option - coap_opt_parse result : %s, %d\n", result->value, result->length); + +#undef ADVANCE_OPT + + return (opt + result->length) - opt_start; +} + +coap_opt_iterator_t * +coap_option_iterator_init(coap_pdu_t *pdu, coap_opt_iterator_t *oi, const coap_opt_filter_t filter) +{ + assert(pdu); + assert(pdu->hdr); + assert(oi); + + memset(oi, 0, sizeof(coap_opt_iterator_t)); + + oi->next_option = (unsigned char *) pdu->hdr + sizeof(coap_hdr_t) + pdu->hdr->token_length; + if ((unsigned char *) pdu->hdr + pdu->length <= oi->next_option) + { + oi->bad = 1; + return NULL; + } + + assert((sizeof(coap_hdr_t) + pdu->hdr->token_length) <= pdu->length); + + oi->length = pdu->length - (sizeof(coap_hdr_t) + pdu->hdr->token_length); + + if (filter) + { + memcpy(oi->filter, filter, sizeof(coap_opt_filter_t)); + oi->filtered = 1; + } + return oi; +} + +static inline int opt_finished(coap_opt_iterator_t *oi) +{ + assert(oi); + + if (oi->bad || oi->length == 0 || !oi->next_option || *oi->next_option == COAP_PAYLOAD_START) + { + oi->bad = 1; + } + + return oi->bad; +} + +coap_opt_t * +coap_option_next(coap_opt_iterator_t *oi) +{ + coap_option_t option; + coap_opt_t *current_opt = NULL; + size_t optsize; + int b; /* to store result of coap_option_getb() */ + + assert(oi); + + if (opt_finished(oi)) + return NULL; + + while (1) + { + /* oi->option always points to the next option to deliver; as + * opt_finished() filters out any bad conditions, we can assume that + * oi->option is valid. */ + current_opt = oi->next_option; + + /* Advance internal pointer to next option, skipping any option that + * is not included in oi->filter. */ + optsize = coap_opt_parse(oi->next_option, oi->length, &option); + if (optsize) + { + assert(optsize <= oi->length); + + oi->next_option += optsize; + oi->length -= optsize; + + oi->type += option.delta; + } + else + { /* current option is malformed */ + oi->bad = 1; + return NULL; + } + + /* Exit the while loop when: + * - no filtering is done at all + * - the filter matches for the current option + * - the filter is too small for the current option number + */ + if (!oi->filtered || (b = coap_option_getb(oi->filter, oi->type)) > 0) + break; + else if (b < 0) + { /* filter too small, cannot proceed */ + oi->bad = 1; + return NULL; + } + } + + return current_opt; +} + +coap_opt_t * +coap_check_option(coap_pdu_t *pdu, unsigned char type, coap_opt_iterator_t *oi) +{ + coap_opt_filter_t f; + + coap_option_filter_clear(f); + coap_option_setb(f, type); + + coap_option_iterator_init(pdu, oi, f); + + return coap_option_next(oi); +} + +unsigned short coap_opt_delta(const coap_opt_t *opt) +{ + unsigned short n; + + n = (*opt++ & 0xf0) >> 4; + + switch (n) + { + case 15: /* error */ + warn("coap_opt_delta: illegal option delta\n"); + + /* This case usually should not happen, hence we do not have a + * proper way to indicate an error. */ + return 0; + case 14: + /* Handle two-byte value: First, the MSB + 269 is stored as delta value. + * After that, the option pointer is advanced to the LSB which is handled + * just like case delta == 13. */ + n = ((*opt++ & 0xff) << 8) + 269; + /* fall through */ + case 13: + n += *opt & 0xff; + break; + default: /* n already contains the actual delta value */ + ; + } + + return n; +} + +unsigned short coap_opt_length(const coap_opt_t *opt) +{ + unsigned short length; + + length = *opt & 0x0f; + switch (*opt & 0xf0) + { + case 0xf0: + debug("illegal option delta\n"); + return 0; + case 0xe0: + ++opt; + /* fall through to skip another byte */ + case 0xd0: + ++opt; + /* fall through to skip another byte */ + default: + ++opt; + } + + switch (length) + { + case 0x0f: + debug("illegal option length\n"); + return 0; + case 0x0e: + length = (*opt++ << 8) + 269; + /* fall through */ + case 0x0d: + length += *opt++; + break; + default: + ; + } + return length; +} + +unsigned char * +coap_opt_value(coap_opt_t *opt) +{ + size_t ofs = 1; + + switch (*opt & 0xf0) + { + case 0xf0: + debug("illegal option delta\n"); + return 0; + case 0xe0: + ++ofs; + /* fall through */ + case 0xd0: + ++ofs; + break; + default: + ; + } + + switch (*opt & 0x0f) + { + case 0x0f: + debug("illegal option length\n"); + return 0; + case 0x0e: + ++ofs; + /* fall through */ + case 0x0d: + ++ofs; + break; + default: + ; + } + + return (unsigned char *) opt + ofs; +} + +size_t coap_opt_size(const coap_opt_t *opt) +{ + coap_option_t option; + + /* we must assume that opt is encoded correctly */ + return coap_opt_parse(opt, (size_t) - 1, &option); +} + +size_t coap_opt_setheader(coap_opt_t *opt, size_t maxlen, unsigned short delta, size_t length) +{ + size_t skip = 0; + + assert(opt); + + if (maxlen == 0) /* need at least one byte */ + return 0; + + if (delta < 13) + { + opt[0] = delta << 4; + } + else if (delta < 270) + { + if (maxlen < 2) + { + debug("insufficient space to encode option delta %d", delta); + return 0; + } + + opt[0] = 0xd0; + opt[++skip] = delta - 13; + } + else + { + if (maxlen < 3) + { + debug("insufficient space to encode option delta %d", delta); + return 0; + } + + opt[0] = 0xe0; + opt[++skip] = ((delta - 269) >> 8) & 0xff; + opt[++skip] = (delta - 269) & 0xff; + } + + if (length < 13) + { + opt[0] |= length & 0x0f; + } + else if (length < 270) + { + if (maxlen < skip + 1) + { + debug("insufficient space to encode option length %d", length); + return 0; + } + + opt[0] |= 0x0d; + opt[++skip] = length - 13; + } + else + { + if (maxlen < skip + 2) + { + debug("insufficient space to encode option delta %d", delta); + return 0; + } + + opt[0] |= 0x0e; + opt[++skip] = ((length - 269) >> 8) & 0xff; + opt[++skip] = (length - 269) & 0xff; + } + + return skip + 1; +} + +size_t coap_opt_encode(coap_opt_t *opt, size_t maxlen, unsigned short delta, + const unsigned char *val, size_t length) +{ + size_t l = 1; + + l = coap_opt_setheader(opt, maxlen, delta, length); + assert(l <= maxlen); + + if (!l) + { + debug("coap_opt_encode: cannot set option header\n"); + return 0; + } + + maxlen -= l; + opt += l; + + if (maxlen < length) + { + debug("coap_opt_encode: option too large for buffer\n"); + return 0; + } + + if (val) /* better be safe here */ + memcpy(opt, val, length); + + return l + length; +} + diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/option.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/option.h new file mode 100644 index 000000000..78b2a0308 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/option.h @@ -0,0 +1,320 @@ +/* + * option.h -- helpers for handling options in CoAP PDUs + * + * Copyright (C) 2010-2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file option.h + * @brief helpers for handling options in CoAP PDUs + */ + +#ifndef _OPTION_H_ +#define _OPTION_H_ + +#include "bits.h" +#include "pdu.h" + +/** + * Use byte-oriented access methods here because sliding a complex + * struct coap_opt_t over the data buffer may cause bus error on + * certain platforms. + */ +typedef unsigned char coap_opt_t; +#define PCHAR(p) ((coap_opt_t *)(p)) + +/** Representation of CoAP options. */ +typedef struct +{ + unsigned short delta; + size_t length; + unsigned char *value; +} coap_option_t; + +/** + * Parses the option pointed to by @p opt into @p result. This + * function returns the number of bytes that have been parsed, or @c 0 + * on error. An error is signaled when illegal delta or length values + * are encountered or when option parsing would result in reading past + * the option (i.e. beyond opt + length). + * + * @param opt The beginning of the option to parse. + * @param length The maximum length of @p opt. + * @param result A pointer to the coap_option_t structure that is + * filled with actual values iff coap_opt_parse() > 0. + * @return The number of bytes parsed or @c 0 on error. + */ +size_t coap_opt_parse(const coap_opt_t *opt, size_t length, coap_option_t *result); + +/** + * Returns the size of the given option, taking into account a + * possible option jump. + * + * @param opt An option jump or the beginning of the option. + * @return The number of bytes between @p opt and the end of + * the option starting at @p opt. In case of an error, + * this function returns @c 0 as options need at least + * one byte storage space. + */ +size_t coap_opt_size(const coap_opt_t *opt); + +/** @deprecated { Use coap_opt_size() instead. } */ +#define COAP_OPT_SIZE(opt) coap_opt_size(opt) + +/** + * Calculates the beginning of the PDU's option section. + * + * @param pdu The PDU containing the options. + * @return A pointer to the first option if available, or @c NULL otherwise. + */ +coap_opt_t *options_start(coap_pdu_t *pdu); + +/** + * Interprets @p opt as pointer to a CoAP option and advances to + * the next byte past this option. + * @hideinitializer + */ +#define options_next(opt) \ + ((coap_opt_t *)((unsigned char *)(opt) + COAP_OPT_SIZE(opt))) + +/** + * @defgroup opt_filter Option Filters + * @{ + */ + +/** + * Fixed-size bit-vector we use for option filtering. It is large + * enough to hold the highest option number known at build time (20 in + * the core spec). + */ +typedef unsigned char coap_opt_filter_t[(COAP_MAX_OPT >> 3) + 1]; + +/** Pre-defined filter that includes all options. */ +#define COAP_OPT_ALL NULL + +/** + * Clears filter @p f. + * + * @param f The filter to clear. + */ +static inline void coap_option_filter_clear(coap_opt_filter_t f) +{ + memset(f, 0, sizeof(coap_opt_filter_t)); +} + +/** + * Sets the corresponding bit for @p type in @p filter. This function + * returns @c 1 if bit was set or @c -1 on error (i.e. when the given + * type does not fit in the filter). + * + * @param filter The filter object to change. + * @param type The type for which the bit should be set. + * + * @return @c 1 if bit was set, @c -1 otherwise. + */ +inline static int coap_option_setb(coap_opt_filter_t filter, unsigned short type) +{ + return bits_setb((uint8_t *) filter, sizeof(coap_opt_filter_t), type); +} + +/** + * Clears the corresponding bit for @p type in @p filter. This function + * returns @c 1 if bit was cleared or @c -1 on error (i.e. when the given + * type does not fit in the filter). + * + * @param filter The filter object to change. + * @param type The type for which the bit should be cleared. + * + * @return @c 1 if bit was set, @c -1 otherwise. + */ +inline static int coap_option_clrb(coap_opt_filter_t filter, unsigned short type) +{ + return bits_clrb((uint8_t *) filter, sizeof(coap_opt_filter_t), type); +} + +/** + * Gets the corresponding bit for @p type in @p filter. This function + * returns @c 1 if the bit is set @c 0 if not, or @c -1 on error (i.e. + * when the given type does not fit in the filter). + * + * @param filter The filter object to read bit from.. + * @param type The type for which the bit should be read. + * + * @return @c 1 if bit was set, @c 0 if not, @c -1 on error. + */ +inline static int coap_option_getb(const coap_opt_filter_t filter, unsigned short type) +{ + return bits_getb((uint8_t *) filter, sizeof(coap_opt_filter_t), type); +} + +/** + * Iterator to run through PDU options. This object must be + * initialized with coap_option_iterator_init(). Call + * coap_option_next() to walk through the list of options until + * coap_option_next() returns @c NULL. + * + * @code + * coap_opt_t *option; + * coap_opt_iterator_t opt_iter; + * coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL); + * + * while ((option = coap_option_next(&opt_iter))) { + * ... do something with option ... + * } + * @endcode + */ +typedef struct +{ + size_t length; /**< remaining length of PDU */ + unsigned short type; /**< decoded option type */ + unsigned int bad :1; /**< iterator object is ok if not set */ + unsigned int filtered :1; /**< denotes whether or not filter is used */ + coap_opt_t *next_option; /**< pointer to the unparsed next option */ + coap_opt_filter_t filter; /**< option filter */ +} coap_opt_iterator_t; + +/** + * Initializes the given option iterator @p oi to point to the + * beginning of the @p pdu's option list. This function returns @p oi + * on success, @c NULL otherwise (i.e. when no options exist). + * Note that a length check on the option list must be performed before + * coap_option_iterator_init() is called. + * + * @param pdu The PDU the options of which should be walked through. + * @param oi An iterator object that will be initilized. + * @param filter An optional option type filter. + * With @p type != @c COAP_OPT_ALL, coap_option_next() + * will return only options matching this bitmask. + * Fence-post options @c 14, @c 28, @c 42, ... are always + * skipped. + * + * @return The iterator object @p oi on success, @c NULL otherwise. + */ +coap_opt_iterator_t *coap_option_iterator_init(coap_pdu_t *pdu, coap_opt_iterator_t *oi, + const coap_opt_filter_t filter); + +/** + * Updates the iterator @p oi to point to the next option. This + * function returns a pointer to that option or @c NULL if no more + * options exist. The contents of @p oi will be updated. In + * particular, @c oi->n specifies the current option's ordinal number + * (counted from @c 1), @c oi->type is the option's type code, and @c + * oi->option points to the beginning of the current option + * itself. When advanced past the last option, @c oi->option will be + * @c NULL. + * + * Note that options are skipped whose corresponding bits in the + * filter specified with coap_option_iterator_init() are @c 0. Options + * with type codes that do not fit in this filter hence will always be + * returned. + * + * @param oi The option iterator to update. + * + * @return The next option or @c NULL if no more options exist. + */ +coap_opt_t *coap_option_next(coap_opt_iterator_t *oi); + +/** + * Retrieves the first option of type @p type from @p pdu. @p oi must + * point to a coap_opt_iterator_t object that will be initialized by + * this function to filter only options with code @p type. This + * function returns the first option with this type, or @c NULL if not + * found. + * + * @param pdu The PDU to parse for options. + * @param type The option type code to search for. + * @param oi An iterator object to use. + * + * @return A pointer to the first option of type @p type, or @c NULL + * if not found. + */ +coap_opt_t *coap_check_option(coap_pdu_t *pdu, unsigned char type, coap_opt_iterator_t *oi); + +/** + * Encodes the given delta and length values into @p opt. This + * function returns the number of bytes that were required to encode + * @p delta and @p length or @c 0 on error. Note that the result + * indicates by how many bytes @p opt must be advanced to encode the + * option value. + * + * @param opt The option buffer space where @p delta and @p length are + * written + * @param maxlen The maximum length of @p opt + * @param delta The actual delta value to encode. + * @param length The actual length value to encode. + * @return The number of bytes used or @c 0 on error. + */ +size_t coap_opt_setheader(coap_opt_t *opt, size_t maxlen, unsigned short delta, size_t length); + +/** + * Encodes option with given @p delta into @p opt. This function returns + * the number of bytes written to @p opt or @c 0 on error. This happens + * especially when @p opt does not provide sufficient space to store + * the option value, delta, and option jumps when required. + * + * @param opt The option buffer space where @p val is written + * @param n Maximum length of @p opt. + * @param delta The option delta. + * @param val The option value to copy into @p opt. + * @param len The actual length of @p val. + * @return The number of bytes that have been written to @p opt or + * @c 0 on error. The return value will always be less than @p n. + */ +size_t coap_opt_encode(coap_opt_t *opt, size_t n, unsigned short delta, const unsigned char *val, + size_t length); + +/** + * Decodes the delta value of the next option. This function returns + * the number of bytes read or @c 0 on error. The caller of this + * function must ensure that it does not read over the boundaries + * of @p opt (e.g. by calling coap_opt_check_delta(). + * + * @param opt The option to examine + * @return The number of bytes read or @c 0 on error. + */ +unsigned short coap_opt_delta(const coap_opt_t *opt); + +/** @deprecated { Use coap_opt_delta() instead. } */ +#define COAP_OPT_DELTA(opt) coap_opt_delta(opt) + +/** @deprecated { Use coap_opt_encode() instead. } */ +#define COAP_OPT_SETDELTA(opt,val) \ + coap_opt_encode((opt), COAP_MAX_PDU_SIZE, (val), NULL, 0) + +/** + * Returns the length of the given option. @p opt must point to an + * option jump or the beginning of the option. This function returns + * @c 0 when @p opt is not an option or the actual length of @p opt + * (which can be @c 0 as well). + * + * @note {The rationale for using @c 0 in case of an error is that in + * most contexts, the result of this function is used to skip the next + * coap_opt_length() bytes. } + * + * @param opt The option whose length should be returned. + * @return The option's length or @c 0 when undefined. + */ +unsigned short coap_opt_length(const coap_opt_t *opt); + +/** @deprecated { Use coap_opt_length() instead. } */ +#define COAP_OPT_LENGTH(opt) coap_opt_length(opt) + +/** + * Returns a pointer to the value of the given option. @p opt must + * point to an option jump or the beginning of the option. This + * function returns @c NULL if @p opt is not a valid option. + * + * @param opt The option whose value should be returned. + * @return A pointer to the option value or @c NULL on error. + */ +unsigned char *coap_opt_value(coap_opt_t *opt); + +/** @deprecated { Use coap_opt_value() instead. } */ +#define COAP_OPT_VALUE(opt) coap_opt_value((coap_opt_t *)opt) + +/** @} */ + +#endif /* _OPTION_H_ */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/pdu.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/pdu.c new file mode 100644 index 000000000..b8aaaad39 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/pdu.c @@ -0,0 +1,467 @@ +/* pdu.c -- CoAP message structure + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "config.h" + +#if defined(HAVE_ASSERT_H) && !defined(assert) +# include +#endif + +#include +#include +#include +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#include "debug.h" +#include "pdu.h" +#include "option.h" +#include "encode.h" + +#ifdef WITH_CONTIKI +#include "memb.h" + +typedef unsigned char _pdu[sizeof(coap_pdu_t) + COAP_MAX_PDU_SIZE]; + +MEMB(pdu_storage, _pdu, COAP_PDU_MAXCNT); + +void +coap_pdu_resources_init() +{ + memb_init(&pdu_storage); +} +#else /* WITH_CONTIKI */ +#include "mem.h" +#endif /* WITH_CONTIKI */ + +void coap_pdu_clear(coap_pdu_t *pdu, size_t size) +{ + assert(pdu); + + memset(pdu, 0, sizeof(coap_pdu_t) + size); + pdu->max_size = size; + pdu->hdr = (coap_hdr_t *) ((unsigned char *) pdu + sizeof(coap_pdu_t)); + pdu->hdr->version = COAP_DEFAULT_VERSION; + + /* data is NULL unless explicitly set by coap_add_data() */ + pdu->length = sizeof(coap_hdr_t); +} + +#ifdef WITH_LWIP +coap_pdu_t * +coap_pdu_from_pbuf(struct pbuf *pbuf) +{ + LWIP_ASSERT("Can only deal with contiguous PBUFs", pbuf->tot_len == pbuf->len); + LWIP_ASSERT("coap_read needs to receive an exclusive copy of the incoming pbuf", pbuf->ref == 1); + + void *data = pbuf->payload; + coap_pdu_t *result; + + u8_t header_error = pbuf_header(pbuf, sizeof(coap_pdu_t)); + LWIP_ASSERT("CoAP PDU header does not fit in existing header space", header_error == 0); + + result = (coap_pdu_t *)pbuf->payload; + + memset(result, 0, sizeof(coap_pdu_t)); + + result->max_size = pbuf->tot_len - sizeof(coap_pdu_t); + result->length = pbuf->tot_len - sizeof(coap_pdu_t); + result->hdr = data; + result->pbuf = pbuf; + + return result; +} +#endif + +coap_pdu_t * +coap_pdu_init(unsigned char type, unsigned char code, unsigned short id, size_t size) +{ + coap_pdu_t *pdu; +#ifdef WITH_LWIP + struct pbuf *p; +#endif + + assert(size <= COAP_MAX_PDU_SIZE); + /* Size must be large enough to fit the header. */ + if (size < sizeof(coap_hdr_t) || size > COAP_MAX_PDU_SIZE) + return NULL; + + /* size must be large enough for hdr */ +#ifdef WITH_POSIX + pdu = coap_malloc(sizeof(coap_pdu_t) + size); +#endif +#ifdef WITH_CONTIKI + pdu = (coap_pdu_t *)memb_alloc(&pdu_storage); +#endif +#ifdef WITH_LWIP + p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); + if (p != NULL) + { + u8_t header_error = pbuf_header(p, sizeof(coap_pdu_t)); + /* we could catch that case and allocate larger memory in advance, but then + * again, we'd run into greater trouble with incoming packages anyway */ + LWIP_ASSERT("CoAP PDU header does not fit in transport header", header_error == 0); + pdu = p->payload; + } + else + { + pdu = NULL; + } +#endif + if (pdu) + { + coap_pdu_clear(pdu, size); + pdu->hdr->id = id; + pdu->hdr->type = type; + pdu->hdr->code = code; +#ifdef WITH_LWIP + pdu->pbuf = p; +#endif + } + return pdu; +} + +coap_pdu_t * +coap_new_pdu() +{ + coap_pdu_t *pdu; + +#ifndef WITH_CONTIKI + pdu = coap_pdu_init(0, 0, ntohs(COAP_INVALID_TID), COAP_MAX_PDU_SIZE); +#else /* WITH_CONTIKI */ + pdu = coap_pdu_init(0, 0, uip_ntohs(COAP_INVALID_TID), COAP_MAX_PDU_SIZE); +#endif /* WITH_CONTIKI */ + +#ifndef NDEBUG + if (!pdu) + coap_log(LOG_CRIT, "coap_new_pdu: cannot allocate memory for new PDU\n"); +#endif + return pdu; +} + +void coap_delete_pdu(coap_pdu_t *pdu) +{ +#ifdef WITH_POSIX + coap_free( pdu ); +#endif +#ifdef WITH_LWIP + if (pdu != NULL) /* accepting double free as the other implementation accept that too */ + pbuf_free(pdu->pbuf); +#endif +#ifdef WITH_CONTIKI + memb_free(&pdu_storage, pdu); +#endif +} + +int coap_add_token(coap_pdu_t *pdu, size_t len, const unsigned char *data) +{ + const size_t HEADERLENGTH = len + 4; + /* must allow for pdu == NULL as callers may rely on this */ + if (!pdu || len > 8 || pdu->max_size < HEADERLENGTH) + return 0; + + pdu->hdr->token_length = len; + if (len) + memcpy(pdu->hdr->token, data, len); + pdu->max_delta = 0; + pdu->length = HEADERLENGTH; + pdu->data = NULL; + + return 1; +} + +/** @FIXME de-duplicate code with coap_add_option_later */ +size_t coap_add_option(coap_pdu_t *pdu, unsigned short type, unsigned int len, + const unsigned char *data) +{ + size_t optsize; + coap_opt_t *opt; + + assert(pdu); + pdu->data = NULL; + + if (type < pdu->max_delta) + { + warn("coap_add_option: options are not in correct order\n"); + return 0; + } + + opt = (unsigned char *) pdu->hdr + pdu->length; + + /* encode option and check length */ + optsize = coap_opt_encode(opt, pdu->max_size - pdu->length, type - pdu->max_delta, data, len); + + if (!optsize) + { + warn("coap_add_option: cannot add option\n"); + /* error */ + return 0; + } + else + { + pdu->max_delta = type; + pdu->length += optsize; + } + + return optsize; +} + +/** @FIXME de-duplicate code with coap_add_option */ +unsigned char* +coap_add_option_later(coap_pdu_t *pdu, unsigned short type, unsigned int len) +{ + size_t optsize; + coap_opt_t *opt; + + assert(pdu); + pdu->data = NULL; + + if (type < pdu->max_delta) + { + warn("coap_add_option: options are not in correct order\n"); + return NULL; + } + + opt = (unsigned char *) pdu->hdr + pdu->length; + + /* encode option and check length */ + optsize = coap_opt_encode(opt, pdu->max_size - pdu->length, type - pdu->max_delta, NULL, len); + + if (!optsize) + { + warn("coap_add_option: cannot add option\n"); + /* error */ + return NULL; + } + else + { + pdu->max_delta = type; + pdu->length += optsize; + } + + return ((unsigned char*) opt) + optsize - len; +} + +int coap_add_data(coap_pdu_t *pdu, unsigned int len, const unsigned char *data) +{ + assert(pdu); + assert(pdu->data == NULL); + + if (len == 0) + return 1; + + if (pdu->length + len + 1 > pdu->max_size) + { + warn("coap_add_data: cannot add: data too large for PDU\n"); + assert(pdu->data == NULL); + return 0; + } + + pdu->data = (unsigned char *) pdu->hdr + pdu->length; + *pdu->data = COAP_PAYLOAD_START; + pdu->data++; + + memcpy(pdu->data, data, len); + pdu->length += len + 1; + return 1; +} + +int coap_get_data(coap_pdu_t *pdu, size_t *len, unsigned char **data) +{ + assert(pdu); + assert(len); + assert(data); + + if (pdu->data) + { + *len = (unsigned char *) pdu->hdr + pdu->length - pdu->data; + *data = pdu->data; + } + else + { /* no data, clear everything */ + *len = 0; + *data = NULL; + } + + return *data != NULL; +} + +#ifndef SHORT_ERROR_RESPONSE +typedef struct +{ + unsigned char code; + char *phrase; +} error_desc_t; + +/* if you change anything here, make sure, that the longest string does not + * exceed COAP_ERROR_PHRASE_LENGTH. */ +error_desc_t coap_error[] = +{ +{ COAP_RESPONSE_CODE(65), "2.01 Created" }, +{ COAP_RESPONSE_CODE(66), "2.02 Deleted" }, +{ COAP_RESPONSE_CODE(67), "2.03 Valid" }, +{ COAP_RESPONSE_CODE(68), "2.04 Changed" }, +{ COAP_RESPONSE_CODE(69), "2.05 Content" }, +{ COAP_RESPONSE_CODE(400), "Bad Request" }, +{ COAP_RESPONSE_CODE(401), "Unauthorized" }, +{ COAP_RESPONSE_CODE(402), "Bad Option" }, +{ COAP_RESPONSE_CODE(403), "Forbidden" }, +{ COAP_RESPONSE_CODE(404), "Not Found" }, +{ COAP_RESPONSE_CODE(405), "Method Not Allowed" }, +{ COAP_RESPONSE_CODE(408), "Request Entity Incomplete" }, +{ COAP_RESPONSE_CODE(413), "Request Entity Too Large" }, +{ COAP_RESPONSE_CODE(415), "Unsupported Media Type" }, +{ COAP_RESPONSE_CODE(500), "Internal Server Error" }, +{ COAP_RESPONSE_CODE(501), "Not Implemented" }, +{ COAP_RESPONSE_CODE(502), "Bad Gateway" }, +{ COAP_RESPONSE_CODE(503), "Service Unavailable" }, +{ COAP_RESPONSE_CODE(504), "Gateway Timeout" }, +{ COAP_RESPONSE_CODE(505), "Proxying Not Supported" }, +{ 0, NULL } /* end marker */ +}; + +char * +coap_response_phrase(unsigned char code) +{ + int i; + for (i = 0; coap_error[i].code; ++i) + { + if (coap_error[i].code == code) + return coap_error[i].phrase; + } + return NULL; +} +#endif + +/** + * Advances *optp to next option if still in PDU. This function + * returns the number of bytes opt has been advanced or @c 0 + * on error. + */ +static size_t next_option_safe(coap_opt_t **optp, size_t *length, coap_option_t* option) +{ + //coap_option_t option; + size_t optsize; + + assert(optp); + assert(*optp); + assert(length); + optsize = coap_opt_parse(*optp, *length, option); + if (optsize) + { + assert(optsize <= *length); + + *optp += optsize; + *length -= optsize; + } + + return optsize; +} + +int coap_pdu_parse(unsigned char *data, size_t length, coap_pdu_t *pdu) +{ + coap_opt_t *opt; + + char optionResult[256] = + { 0, }; + + assert(data); + assert(pdu); + + if (pdu->max_size < length) + { + debug("insufficient space to store parsed PDU\n"); + printf("[COAP] insufficient space to store parsed PDU\n"); + return 0; + } + + if (length < sizeof(coap_hdr_t)) + { + debug("discarded invalid PDU\n"); + } + + pdu->hdr->version = data[0] >> 6; + pdu->hdr->type = (data[0] >> 4) & 0x03; + pdu->hdr->token_length = data[0] & 0x0f; + pdu->hdr->code = data[1]; + /* + printf("[COAP] pdu - version : %d\n", pdu->hdr->version); + printf("[COAP] pdu - type : %d\n", pdu->hdr->type); + printf("[COAP] pdu - token_length : %d\n", pdu->hdr->token_length); + printf("[COAP] pdu - code : %d\n", pdu->hdr->code); + */ + pdu->data = NULL; + + /* sanity checks */ + if (pdu->hdr->code == 0) + { + if (length != sizeof(coap_hdr_t) || pdu->hdr->token_length) + { + debug("coap_pdu_parse: empty message is not empty\n"); + goto discard; + } + } + + if (length < sizeof(coap_hdr_t) + pdu->hdr->token_length || pdu->hdr->token_length > 8) + { + debug("coap_pdu_parse: invalid Token\n"); + goto discard; + } + + /* Copy message id in network byte order, so we can easily write the + * response back to the network. */ + memcpy(&pdu->hdr->id, data + 2, 2); + + //printf("[COAP] pdu - id : %d\n", pdu->hdr->id); + + /* append data (including the Token) to pdu structure */ + memcpy(pdu->hdr + 1, data + sizeof(coap_hdr_t), length - sizeof(coap_hdr_t)); + pdu->length = length; + + /* Finally calculate beginning of data block and thereby check integrity + * of the PDU structure. */ + + /* skip header + token */ + length -= (pdu->hdr->token_length + sizeof(coap_hdr_t)); + opt = (unsigned char *) (pdu->hdr + 1) + pdu->hdr->token_length; + + while (length && *opt != COAP_PAYLOAD_START) + { + coap_option_t option; + memset(&option, 0, sizeof(coap_option_t)); + if (!next_option_safe(&opt, (size_t *) &length, &option)) + { + debug("coap_pdu_parse: drop\n"); + goto discard; + } + } + + /* end of packet or start marker */ + if (length) + { + assert(*opt == COAP_PAYLOAD_START); + opt++; + length--; + + if (!length) + { + debug("coap_pdu_parse: message ending in payload start marker\n"); + goto discard; + } + + debug( + "set data to %p (pdu ends at %p)\n", (unsigned char *)opt, (unsigned char *)pdu->hdr + pdu->length); + pdu->data = (unsigned char *) opt; + //printf("[COAP] pdu - data : %s\n", pdu->data); + } + + return 1; + + discard: return 0; +} diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/pdu.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/pdu.h new file mode 100644 index 000000000..e01d851e6 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/pdu.h @@ -0,0 +1,346 @@ +/* pdu.h -- CoAP message structure + * + * Copyright (C) 2010--2012 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef _PDU_H_ +#define _PDU_H_ + +#include "config.h" +#include "coap_list.h" +#include "uri.h" + +#ifdef WITH_LWIP +#include +#endif + +/* pre-defined constants that reflect defaults for CoAP */ + +#define COAP_DEFAULT_RESPONSE_TIMEOUT 2 /* response timeout in seconds */ +#define COAP_DEFAULT_MAX_RETRANSMIT 4 /* max number of retransmissions */ +#define COAP_DEFAULT_PORT 5683 /* CoAP default UDP port */ +#define COAP_DEFAULT_MAX_AGE 60 /* default maximum object lifetime in seconds */ +#ifndef COAP_MAX_PDU_SIZE +#define COAP_MAX_PDU_SIZE 1400 /* maximum size of a CoAP PDU */ +#endif /* COAP_MAX_PDU_SIZE */ + +#define COAP_DEFAULT_VERSION 1 /* version of CoAP supported */ +#define COAP_DEFAULT_SCHEME "coap" /* the default scheme for CoAP URIs */ + +/** well-known resources URI */ +#define COAP_DEFAULT_URI_WELLKNOWN ".well-known/core" + +#ifdef __COAP_DEFAULT_HASH +/* pre-calculated hash key for the default well-known URI */ +#define COAP_DEFAULT_WKC_HASHKEY "\345\130\144\245" +#endif + +/* CoAP message types */ + +#define COAP_MESSAGE_CON 0 /* confirmable message (requires ACK/RST) */ +#define COAP_MESSAGE_NON 1 /* non-confirmable message (one-shot message) */ +#define COAP_MESSAGE_ACK 2 /* used to acknowledge confirmable messages */ +#define COAP_MESSAGE_RST 3 /* indicates error in received messages */ + +/* CoAP request methods */ + +#define COAP_REQUEST_GET 1 +#define COAP_REQUEST_POST 2 +#define COAP_REQUEST_PUT 3 +#define COAP_REQUEST_DELETE 4 + +/* CoAP option types (be sure to update check_critical when adding options */ + +#define COAP_OPTION_IF_MATCH 1 /* C, opaque, 0-8 B, (none) */ +#define COAP_OPTION_URI_HOST 3 /* C, String, 1-255 B, destination address */ +#define COAP_OPTION_ETAG 4 /* E, opaque, 1-8 B, (none) */ +#define COAP_OPTION_IF_NONE_MATCH 5 /* empty, 0 B, (none) */ +#define COAP_OPTION_URI_PORT 7 /* C, uint, 0-2 B, destination port */ +#define COAP_OPTION_LOCATION_PATH 8 /* E, String, 0-255 B, - */ +#define COAP_OPTION_URI_PATH 11 /* C, String, 0-255 B, (none) */ +#define COAP_OPTION_CONTENT_FORMAT 12 /* E, uint, 0-2 B, (none) */ +#define COAP_OPTION_CONTENT_TYPE COAP_OPTION_CONTENT_FORMAT +#define COAP_OPTION_MAXAGE 14 /* E, uint, 0--4 B, 60 Seconds */ +#define COAP_OPTION_URI_QUERY 15 /* C, String, 1-255 B, (none) */ +#define COAP_OPTION_ACCEPT 17 /* C, uint, 0-2 B, (none) */ +#define COAP_OPTION_LOCATION_QUERY 20 /* E, String, 0-255 B, (none) */ +#define COAP_OPTION_PROXY_URI 35 /* C, String, 1-1034 B, (none) */ +#define COAP_OPTION_PROXY_SCHEME 39 /* C, String, 1-255 B, (none) */ +#define COAP_OPTION_SIZE1 60 /* E, uint, 0-4 B, (none) */ + +/* option types from draft-ietf-coap-observe-09 */ + +#define COAP_OPTION_OBSERVE 6 /* E, empty/uint, 0 B/0-3 B, (none) */ +#define COAP_OPTION_SUBSCRIPTION COAP_OPTION_OBSERVE + +/* selected option types from draft-core-block-04 */ + +#define COAP_OPTION_BLOCK2 23 /* C, uint, 0--3 B, (none) */ +#define COAP_OPTION_BLOCK1 27 /* C, uint, 0--3 B, (none) */ + +#define COAP_MAX_OPT 63 /**< the highest option number we know */ + +/* CoAP result codes (HTTP-Code / 100 * 40 + HTTP-Code % 100) */ + +/* As of draft-ietf-core-coap-04, response codes are encoded to base + * 32, i.e. the three upper bits determine the response class while + * the remaining five fine-grained information specific to that class. + */ +#define COAP_RESPONSE_CODE(N) (((N)/100 << 5) | (N)%100) + +/* Determines the class of response code C */ +#define COAP_RESPONSE_CLASS(C) (((C) >> 5) & 0xFF) + +#ifndef SHORT_ERROR_RESPONSE +/** + * Returns a human-readable response phrase for the specified CoAP + * response @p code. This function returns @c NULL if not found. + * + * @param code The response code for which the literal phrase should + * be retrieved. + * + * @return A zero-terminated string describing the error, or @c NULL + * if not found. + */ +char *coap_response_phrase(unsigned char code); + +#define COAP_ERROR_PHRASE_LENGTH 32 /**< maximum length of error phrase */ + +#else +#define coap_response_phrase(x) ((char *)NULL) + +#define COAP_ERROR_PHRASE_LENGTH 0 /**< maximum length of error phrase */ +#endif /* SHORT_ERROR_RESPONSE */ + +/* The following definitions exist for backwards compatibility */ +#if 0 /* this does not exist any more */ +#define COAP_RESPONSE_100 40 /* 100 Continue */ +#endif +#define COAP_RESPONSE_200 COAP_RESPONSE_CODE(200) /* 2.00 OK */ +#define COAP_RESPONSE_201 COAP_RESPONSE_CODE(201) /* 2.01 Created */ +#define COAP_RESPONSE_304 COAP_RESPONSE_CODE(203) /* 2.03 Valid */ +#define COAP_RESPONSE_400 COAP_RESPONSE_CODE(400) /* 4.00 Bad Request */ +#define COAP_RESPONSE_404 COAP_RESPONSE_CODE(404) /* 4.04 Not Found */ +#define COAP_RESPONSE_405 COAP_RESPONSE_CODE(405) /* 4.05 Method Not Allowed */ +#define COAP_RESPONSE_415 COAP_RESPONSE_CODE(415) /* 4.15 Unsupported Media Type */ +#define COAP_RESPONSE_500 COAP_RESPONSE_CODE(500) /* 5.00 Internal Server Error */ +#define COAP_RESPONSE_501 COAP_RESPONSE_CODE(501) /* 5.01 Not Implemented */ +#define COAP_RESPONSE_503 COAP_RESPONSE_CODE(503) /* 5.03 Service Unavailable */ +#define COAP_RESPONSE_504 COAP_RESPONSE_CODE(504) /* 5.04 Gateway Timeout */ +#if 0 /* these response codes do not have a valid code any more */ +# define COAP_RESPONSE_X_240 240 /* Token Option required by server */ +# define COAP_RESPONSE_X_241 241 /* Uri-Authority Option required by server */ +#endif +#define COAP_RESPONSE_X_242 COAP_RESPONSE_CODE(402) /* Critical Option not supported */ + +/* CoAP media type encoding */ + +#define COAP_MEDIATYPE_TEXT_PLAIN 0 /* text/plain (UTF-8) */ +#define COAP_MEDIATYPE_APPLICATION_LINK_FORMAT 40 /* application/link-format */ +#define COAP_MEDIATYPE_APPLICATION_XML 41 /* application/xml */ +#define COAP_MEDIATYPE_APPLICATION_OCTET_STREAM 42 /* application/octet-stream */ +#define COAP_MEDIATYPE_APPLICATION_RDF_XML 43 /* application/rdf+xml */ +#define COAP_MEDIATYPE_APPLICATION_EXI 47 /* application/exi */ +#define COAP_MEDIATYPE_APPLICATION_JSON 50 /* application/json */ + +/* Note that identifiers for registered media types are in the range 0-65535. We + * use an unallocated type here and hope for the best. */ +#define COAP_MEDIATYPE_ANY 0xff /* any media type */ + +/* CoAP transaction id */ +/*typedef unsigned short coap_tid_t; */ +typedef int coap_tid_t; +#define COAP_INVALID_TID -1 + +#ifdef WORDS_BIGENDIAN +typedef struct +{ + unsigned int version:2; /* protocol version */ + unsigned int type:2; /* type flag */ + unsigned int token_length:4; /* length of Token */ + unsigned int code:8; /* request method (value 1--10) or response code (value 40-255) */ + unsigned short id; /* message id */ + unsigned char token[]; /* the actual token, if any */ +}coap_hdr_t; +#else +typedef struct +{ + unsigned int token_length :4; /* length of Token */ + unsigned int type :2; /* type flag */ + unsigned int version :2; /* protocol version */ + unsigned int code :8; /* request method (value 1--10) or response code (value 40-255) */ + unsigned short id; /* transaction id (network byte order!) */ + unsigned char token[]; /* the actual token, if any */ +} coap_hdr_t; +#endif + +#define COAP_MESSAGE_IS_EMPTY(MSG) ((MSG)->code == 0) +#define COAP_MESSAGE_IS_REQUEST(MSG) (!COAP_MESSAGE_IS_EMPTY(MSG) \ + && ((MSG)->code < 32)) +#define COAP_MESSAGE_IS_RESPONSE(MSG) ((MSG)->code >= 64 && (MSG)->code <= 191) + +#define COAP_OPT_LONG 0x0F /* OC == 0b1111 indicates that the option list in a + * CoAP message is limited by 0b11110000 marker */ + +#define COAP_OPT_END 0xF0 /* end marker */ + +#define COAP_PAYLOAD_START 0xFF /* payload marker */ + +/** + * Structures for more convenient handling of options. (To be used with ordered + * coap_list_t.) The option's data will be added to the end of the coap_option + * structure (see macro COAP_OPTION_DATA). + */ +typedef struct +{ + unsigned short key; /* the option key (no delta coding) */ + unsigned int length; +} coap_option; + +#define COAP_OPTION_KEY(option) (option).key +#define COAP_OPTION_LENGTH(option) (option).length +#define COAP_OPTION_DATA(option) ((unsigned char *)&(option) + sizeof(coap_option)) + +/** Header structure for CoAP PDUs */ + +typedef struct +{ + size_t max_size; /**< allocated storage for options and data */ + + coap_hdr_t *hdr; + unsigned short max_delta; /**< highest option number */ + unsigned short length; /**< PDU length (including header, options, data) */ + unsigned char *data; /**< payload */ + +#ifdef WITH_LWIP + struct pbuf *pbuf; /**< lwIP PBUF. The allocated coap_pdu_t will always reside inside the pbuf's payload, but the pointer has to be kept because no exact offset can be given. This field must not be accessed from outside, because the pbuf's reference count is checked to be 1 when the pbuf is assigned to the pdu, and the pbuf stays exclusive to this pdu. */ +#endif + +} coap_pdu_t; + +/** Options in coap_pdu_t are accessed with the macro COAP_OPTION. */ +#define COAP_OPTION(node) ((coap_option *)(node)->options) + +#ifdef WITH_LWIP +/** + * Creates a CoAP PDU from an lwIP @p pbuf, whose reference is passed on to + * this function. + * + * The pbuf is checked for being contiguous, for having enough head space for + * the PDU struct (which is located directly in front of the data, overwriting + * the old other headers), and for having only one reference. The reference is + * stored in the PDU and will be freed when the PDU is freed. + * + * (For now, these are errors; in future, a new pbuf might be allocated, the + * data copied and the passed pbuf freed). + * + * This behaves like coap_pdu_init(0, 0, 0, pbuf->tot_len), and afterwards + * copying the contents of the pbuf to the pdu. + * + * @return A pointer to the new PDU object or @c NULL on error. + */ +coap_pdu_t * coap_pdu_from_pbuf(struct pbuf *pbuf); +#endif + +/** + * Creates a new CoAP PDU of given @p size (must be large enough to hold the + * basic CoAP message header (coap_hdr_t). The function returns a pointer to + * the node coap_pdu_t object on success, or @c NULL on error. The storage + * allocated for the result must be released with coap_delete_pdu(). + * + * @param type The type of the PDU (one of COAP_MESSAGE_CON, + * COAP_MESSAGE_NON, COAP_MESSAGE_ACK, COAP_MESSAGE_RST). + * @param code The message code. + * @param id The message id to set or COAP_INVALID_TID if unknown. + * @param size The number of bytes to allocate for the actual message. + * + * @return A pointer to the new PDU object or @c NULL on error. + */ +coap_pdu_t * +coap_pdu_init(unsigned char type, unsigned char code, unsigned short id, size_t size); + +/** + * Clears any contents from @p pdu and resets @c version field, @c + * length and @c data pointers. @c max_size is set to @p size, any + * other field is set to @c 0. Note that @p pdu must be a valid + * pointer to a coap_pdu_t object created e.g. by coap_pdu_init(). + */ +void coap_pdu_clear(coap_pdu_t *pdu, size_t size); + +/** + * Creates a new CoAP PDU. The object is created on the heap and must be released + * using coap_delete_pdu(); + * + * @deprecated This function allocates the maximum storage for each + * PDU. Use coap_pdu_init() instead. + */ +coap_pdu_t *coap_new_pdu(); + +void coap_delete_pdu(coap_pdu_t *); + +/** + * Parses @p data into the CoAP PDU structure given in @p result. This + * function returns @c 0 on error or a number greater than zero on + * success. + * + * @param data The raw data to parse as CoAP PDU + * @param length The actual size of @p data + * @param result The PDU structure to fill. Note that the structure must + * provide space for at least @p length bytes to hold the + * entire CoAP PDU. + * @return A value greater than zero on success or @c 0 on error. + */ +int coap_pdu_parse(unsigned char *data, size_t length, coap_pdu_t *result); + +/** + * Adds token of length @p len to @p pdu. Adding the token destroys + * any following contents of the pdu. Hence options and data must be + * added after coap_add_token() has been called. In @p pdu, length is + * set to @p len + @c 4, and max_delta is set to @c 0. This funtion + * returns @c 0 on error or a value greater than zero on success. + * + * @param pdu The PDU where the token is to be added. + * @param len The length of the new token. + * @param data The token to add. + * @return A value greater than zero on success, or @c 0 on error. + */ +int coap_add_token(coap_pdu_t *pdu, size_t len, const unsigned char *data); + +/** + * Adds option of given type to pdu that is passed as first + * parameter. coap_add_option() destroys the PDU's data, so + * coap_add_data() must be called after all options have been added. + * As coap_add_token() destroys the options following the token, + * the token must be added before coap_add_option() is called. + * This function returns the number of bytes written or @c 0 on error. + */ +size_t coap_add_option(coap_pdu_t *pdu, unsigned short type, unsigned int len, + const unsigned char *data); + +/** + * Adds option of given type to pdu that is passed as first + * parameter, but does not write a value. It works like coap_add_option with + * respect to calling sequence (i.e. after token and before data). + * This function returns a memory address to which the option data has to be + * written before the PDU can be sent, or @c NULL on error. + */ +unsigned char *coap_add_option_later(coap_pdu_t *pdu, unsigned short type, unsigned int len); + +/** + * Adds given data to the pdu that is passed as first parameter. Note + * that the PDU's data is destroyed by coap_add_option(). coap_add_data() + * must be called only once per PDU, otherwise the result is undefined. + */ +int coap_add_data(coap_pdu_t *pdu, unsigned int len, const unsigned char *data); + +/** + * Retrieves the length and data pointer of specified PDU. Returns 0 on error + * or 1 if *len and *data have correct values. Note that these values are + * destroyed with the pdu. + */ +int coap_get_data(coap_pdu_t *pdu, size_t *len, unsigned char **data); + +#endif /* _PDU_H_ */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/prng.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/prng.h new file mode 100644 index 000000000..ca86e72db --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/prng.h @@ -0,0 +1,87 @@ +/* prng.h -- Pseudo Random Numbers + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file prng.h + * @brief Pseudo Random Numbers + */ + +#ifndef _COAP_PRNG_H_ +#define _COAP_PRNG_H_ + +#include "config.h" + +/** + * @defgroup prng Pseudo Random Numbers + * @{ + */ + +#ifndef WITH_CONTIKI +#include + +/** + * Fills \p buf with \p len random bytes. This is the default + * implementation for prng(). You might want to change prng() to use + * a better PRNG on your specific platform. + */ +static inline int coap_prng_impl(unsigned char *buf, size_t len) +{ + while (len--) + *buf++ = rand() & 0xFF; + return 1; +} +#else /* WITH_CONTIKI */ +#include + +/** + * Fills \p buf with \p len random bytes. This is the default + * implementation for prng(). You might want to change prng() to use + * a better PRNG on your specific platform. + */ +static inline int +contiki_prng_impl(unsigned char *buf, size_t len) +{ + unsigned short v = random_rand(); + while (len > sizeof(v)) + { + memcpy(buf, &v, sizeof(v)); + len -= sizeof(v); + buf += sizeof(v); + v = random_rand(); + } + + memcpy(buf, &v, len); + return 1; +} + +#define prng(Buf,Length) contiki_prng_impl((Buf), (Length)) +#define prng_init(Value) random_init((unsigned short)(Value)) +#endif /* WITH_CONTIKI */ + +#ifndef prng +/** + * Fills \p Buf with \p Length bytes of random data. + * + * @hideinitializer + */ +#define prng(Buf,Length) coap_prng_impl((Buf), (Length)) +#endif + +#ifndef prng_init +/** + * Called to set the PRNG seed. You may want to re-define this to + * allow for a better PRNG. + * + * @hideinitializer + */ +#define prng_init(Value) srand((unsigned long)(Value)) +#endif + +/** @} */ + +#endif /* _COAP_PRNG_H_ */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/resource.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/resource.c new file mode 100644 index 000000000..d6ae50f46 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/resource.c @@ -0,0 +1,935 @@ +/* resource.c -- generic resource handling + * + * Copyright (C) 2010--2014 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "config.h" +#include "net.h" +#include "debug.h" +#include "resource.h" +#include "subscribe.h" + +#ifdef WITH_LWIP +#include "utlist.h" +/* mem.h is only needed for the string free calls for + * COAP_ATTR_FLAGS_RELEASE_NAME / COAP_ATTR_FLAGS_RELEASE_VALUE / + * COAP_RESOURCE_FLAGS_RELEASE_URI. not sure what those lines should actually + * do on lwip. */ +#include "mem.h" + +#include + +#define COAP_MALLOC_TYPE(Type) \ + ((coap_##Type##_t *)memp_malloc(MEMP_COAP_##Type)) +#define COAP_FREE_TYPE(Type, Object) memp_free(MEMP_COAP_##Type, Object) + +#endif +#ifdef WITH_POSIX +#include "utlist.h" +#include "mem.h" + +#define COAP_MALLOC_TYPE(Type) \ + ((coap_##Type##_t *)coap_malloc(sizeof(coap_##Type##_t))) +#define COAP_FREE_TYPE(Type, Object) coap_free(Object) + +#endif /* WITH_POSIX */ +#ifdef WITH_CONTIKI +#include "memb.h" + +MEMB(resource_storage, coap_resource_t, COAP_MAX_RESOURCES); +MEMB(attribute_storage, coap_attr_t, COAP_MAX_ATTRIBUTES); +MEMB(subscription_storage, coap_subscription_t, COAP_MAX_SUBSCRIBERS); + +void +coap_resources_init() +{ + memb_init(&resource_storage); + memb_init(&attribute_storage); + memb_init(&subscription_storage); +} + +static inline coap_subscription_t * +coap_malloc_subscription() +{ + return memb_alloc(&subscription_storage); +} + +static inline void +coap_free_subscription(coap_subscription_t *subscription) +{ + memb_free(&subscription_storage, subscription); +} +#endif /* WITH_CONTIKI */ + +#define min(a,b) ((a) < (b) ? (a) : (b)) + +/* Helper functions for conditional output of character sequences into + * a given buffer. The first Offset characters are skipped. + */ + +/** + * Adds Char to Buf if Offset is zero. Otherwise, Char is not written + * and Offset is decremented. + */ +#define PRINT_WITH_OFFSET(Buf,Offset,Char) \ + if ((Offset) == 0) { \ + (*(Buf)++) = (Char); \ + } else { \ + (Offset)--; \ + } \ + +/** + * Adds Char to Buf if Offset is zero and Buf is less than Bufend. + */ +#define PRINT_COND_WITH_OFFSET(Buf,Bufend,Offset,Char,Result) { \ + if ((Buf) < (Bufend)) { \ + PRINT_WITH_OFFSET(Buf,Offset,Char); \ + } \ + (Result)++; \ + } + +/** + * Copies at most Length characters of Str to Buf. The first Offset + * characters are skipped. Output may be truncated to Bufend - Buf + * characters. + */ +#define COPY_COND_WITH_OFFSET(Buf,Bufend,Offset,Str,Length,Result) { \ + size_t i; \ + for (i = 0; i < (Length); i++) { \ + PRINT_COND_WITH_OFFSET((Buf), (Bufend), (Offset), (Str)[i], (Result)); \ + } \ + } + +int match(const str *text, const str *pattern, int match_prefix, int match_substring) +{ + assert(text); + assert(pattern); + + if (text->length < pattern->length) + return 0; + + if (match_substring) + { + unsigned char *next_token = text->s; + size_t remaining_length = text->length; + while (remaining_length) + { + size_t token_length; + unsigned char *token = next_token; + next_token = memchr(token, ' ', remaining_length); + + if (next_token) + { + token_length = next_token - token; + remaining_length -= (token_length + 1); + next_token++; + } + else + { + token_length = remaining_length; + remaining_length = 0; + } + + if ((match_prefix || pattern->length == token_length) + && memcmp(token, pattern->s, pattern->length) == 0) + return 1; + } + return 0; + } + + return (match_prefix || pattern->length == text->length) + && memcmp(text->s, pattern->s, pattern->length) == 0; +} + +/** + * Prints the names of all known resources to @p buf. This function + * sets @p buflen to the number of bytes actually written and returns + * @c 1 on succes. On error, the value in @p buflen is undefined and + * the return value will be @c 0. + * + * @param context The context with the resource map. + * @param buf The buffer to write the result. + * @param buflen Must be initialized to the maximum length of @p buf and will be + * set to the length of the well-known response on return. + * @param offset The offset in bytes where the output shall start and is + * shifted accordingly with the characters that have been + * processed. This parameter is used to support the block + * option. + * @param query_filter A filter query according to Link Format + * + * @return COAP_PRINT_STATUS_ERROR on error. Otherwise, the lower 28 bits are + * set to the number of bytes that have actually been written to + * @p buf. COAP_PRINT_STATUS_TRUNC is set when the output has been + * truncated. + */ +#if defined(__GNUC__) && defined(WITHOUT_QUERY_FILTER) +coap_print_status_t +print_wellknown(coap_context_t *context, unsigned char *buf, size_t *buflen, + size_t offset, + coap_opt_t *query_filter __attribute__ ((unused))) +{ +#else /* not a GCC */ +coap_print_status_t print_wellknown(coap_context_t *context, unsigned char *buf, size_t *buflen, + size_t offset, coap_opt_t *query_filter) +{ +#endif /* GCC */ + coap_resource_t *r; + unsigned char *p = buf; + const unsigned char *bufend = buf + *buflen; + size_t left, written = 0; + coap_print_status_t result; + const size_t old_offset = offset; + int subsequent_resource = 0; +#ifndef COAP_RESOURCES_NOHASH + coap_resource_t *tmp; +#endif +#ifndef WITHOUT_QUERY_FILTER + str resource_param = + { 0, NULL }, query_pattern = + { 0, NULL }; + int flags = 0; /* MATCH_SUBSTRING, MATCH_PREFIX, MATCH_URI */ +#define MATCH_URI 0x01 +#define MATCH_PREFIX 0x02 +#define MATCH_SUBSTRING 0x04 + static const str _rt_attributes[] = + { + { 2, (unsigned char *) "rt" }, + { 2, (unsigned char *) "if" }, + { 3, (unsigned char *) "rel" }, + { 0, NULL } }; +#endif /* WITHOUT_QUERY_FILTER */ + +#ifdef WITH_CONTIKI + int i; +#endif /* WITH_CONTIKI */ + +#ifndef WITHOUT_QUERY_FILTER + /* split query filter, if any */ + if (query_filter) + { + resource_param.s = COAP_OPT_VALUE(query_filter); + while (resource_param.length < COAP_OPT_LENGTH(query_filter) + && resource_param.s[resource_param.length] != '=') + resource_param.length++; + + if (resource_param.length < COAP_OPT_LENGTH(query_filter)) + { + const str *rt_attributes; + if (resource_param.length == 4 && memcmp(resource_param.s, "href", 4) == 0) + flags |= MATCH_URI; + + for (rt_attributes = _rt_attributes; rt_attributes->s; rt_attributes++) + { + if (resource_param.length == rt_attributes->length + && memcmp(resource_param.s, rt_attributes->s, rt_attributes->length) == 0) + { + flags |= MATCH_SUBSTRING; + break; + } + } + + /* rest is query-pattern */ + query_pattern.s = COAP_OPT_VALUE(query_filter) + resource_param.length + 1; + + assert((resource_param.length + 1) <= COAP_OPT_LENGTH(query_filter)); + query_pattern.length = COAP_OPT_LENGTH(query_filter) - (resource_param.length + 1); + + if ((query_pattern.s[0] == '/') && ((flags & MATCH_URI) == MATCH_URI)) + { + query_pattern.s++; + query_pattern.length--; + } + + if (query_pattern.length && query_pattern.s[query_pattern.length - 1] == '*') + { + query_pattern.length--; + flags |= MATCH_PREFIX; + } + } + } +#endif /* WITHOUT_QUERY_FILTER */ + +#ifndef WITH_CONTIKI + +#ifdef COAP_RESOURCES_NOHASH + LL_FOREACH(context->resources, r) + { +#else + HASH_ITER(hh, context->resources, r, tmp) + { +#endif +#else /* WITH_CONTIKI */ + r = (coap_resource_t *)resource_storage.mem; + for (i = 0; i < resource_storage.num; ++i, ++r) + { + if (!resource_storage.count[i]) + continue; +#endif /* WITH_CONTIKI */ + +#ifndef WITHOUT_QUERY_FILTER + if (resource_param.length) + { /* there is a query filter */ + + if (flags & MATCH_URI) + { /* match resource URI */ + if (!match(&r->uri, &query_pattern, (flags & MATCH_PREFIX) != 0, + (flags & MATCH_SUBSTRING) != 0)) + continue; + } + else + { /* match attribute */ + coap_attr_t *attr; + str unquoted_val; + attr = coap_find_attr(r, resource_param.s, resource_param.length); + if (!attr) + continue; + if (attr->value.s[0] == '"') + { /* if attribute has a quoted value, remove double quotes */ + unquoted_val.length = attr->value.length - 2; + unquoted_val.s = attr->value.s + 1; + } + else + { + unquoted_val = attr->value; + } + if (!(match(&unquoted_val, &query_pattern, (flags & MATCH_PREFIX) != 0, + (flags & MATCH_SUBSTRING) != 0))) + continue; + } + } +#endif /* WITHOUT_QUERY_FILTER */ + + if (!subsequent_resource) + { /* this is the first resource */ + subsequent_resource = 1; + } + else + { + PRINT_COND_WITH_OFFSET(p, bufend, offset, ',', written); + } + + left = bufend - p; /* calculate available space */ + result = coap_print_link(r, p, &left, &offset); + + if (result & COAP_PRINT_STATUS_ERROR) + { + break; + } + + /* coap_print_link() returns the number of characters that + * where actually written to p. Now advance to its end. */ + p += COAP_PRINT_OUTPUT_LENGTH(result); + written += left; + } + + *buflen = written; + result = p - buf; + if (result + old_offset - offset < *buflen) + { + result |= COAP_PRINT_STATUS_TRUNC; + } + return result; +} + +coap_resource_t * +coap_resource_init(const unsigned char *uri, size_t len, int flags) +{ + coap_resource_t *r; + +#ifdef WITH_POSIX + r = (coap_resource_t *)coap_malloc(sizeof(coap_resource_t)); +#endif +#ifdef WITH_LWIP + r = (coap_resource_t *)memp_malloc(MEMP_COAP_RESOURCE); +#endif +#ifdef WITH_CONTIKI + r = (coap_resource_t *)memb_alloc(&resource_storage); +#endif + if (r) + { + memset(r, 0, sizeof(coap_resource_t)); + +#ifdef WITH_CONTIKI + LIST_STRUCT_INIT(r, link_attr); +#endif /* WITH_CONTIKI */ + LIST_STRUCT_INIT(r, subscribers); + + r->uri.s = (unsigned char *) uri; + r->uri.length = len; + + coap_hash_path(r->uri.s, r->uri.length, r->key); + + r->flags = flags; + } + else + { + debug("coap_resource_init: no memory left\n"); + } + + return r; +} + +coap_attr_t * +coap_add_attr(coap_resource_t *resource, const unsigned char *name, size_t nlen, + const unsigned char *val, size_t vlen, int flags) +{ + coap_attr_t *attr; + + if (!resource || !name) + return NULL; + +#ifdef WITH_POSIX + attr = (coap_attr_t *)coap_malloc(sizeof(coap_attr_t)); +#endif +#ifdef WITH_LWIP + attr = (coap_attr_t *)memp_malloc(MEMP_COAP_RESOURCEATTR); +#endif +#ifdef WITH_CONTIKI + attr = (coap_attr_t *)memb_alloc(&attribute_storage); +#endif + + if (attr) + { + attr->name.length = nlen; + attr->value.length = val ? vlen : 0; + + attr->name.s = (unsigned char *) name; + attr->value.s = (unsigned char *) val; + + attr->flags = flags; + + /* add attribute to resource list */ +#ifndef WITH_CONTIKI + LL_PREPEND(resource->link_attr, attr); +#else /* WITH_CONTIKI */ + list_add(resource->link_attr, attr); +#endif /* WITH_CONTIKI */ + } + else + { + debug("coap_add_attr: no memory left\n"); + } + + return attr; +} + +coap_attr_t * +coap_find_attr(coap_resource_t *resource, const unsigned char *name, size_t nlen) +{ + coap_attr_t *attr; + + if (!resource || !name) + return NULL; + +#ifndef WITH_CONTIKI + LL_FOREACH(resource->link_attr, attr) + { +#else /* WITH_CONTIKI */ + for (attr = list_head(resource->link_attr); attr; + attr = list_item_next(attr)) + { +#endif /* WITH_CONTIKI */ + if (attr->name.length == nlen && memcmp(attr->name.s, name, nlen) == 0) + return attr; + } + + return NULL; +} + +void coap_delete_attr(coap_attr_t *attr) +{ + if (!attr) + return; + if (attr->flags & COAP_ATTR_FLAGS_RELEASE_NAME) + coap_free(attr->name.s); + if (attr->flags & COAP_ATTR_FLAGS_RELEASE_VALUE) + coap_free(attr->value.s); +#ifdef POSIX + coap_free(attr); +#endif +#ifdef WITH_LWIP + memp_free(MEMP_COAP_RESOURCEATTR, attr); +#endif +#ifdef WITH_CONTIKI + /* FIXME it looks like this was never implemented */ +#endif +} + +void coap_hash_request_uri(const coap_pdu_t *request, coap_key_t key) +{ + coap_opt_iterator_t opt_iter; + coap_opt_filter_t filter; + coap_opt_t *option; + + memset(key, 0, sizeof(coap_key_t)); + + coap_option_filter_clear(filter); + coap_option_setb(filter, COAP_OPTION_URI_PATH); + + coap_option_iterator_init((coap_pdu_t *) request, &opt_iter, filter); + while ((option = coap_option_next(&opt_iter))) + coap_hash(COAP_OPT_VALUE(option), COAP_OPT_LENGTH(option), key); +} + +void coap_add_resource(coap_context_t *context, coap_resource_t *resource) +{ +#ifndef WITH_CONTIKI +#ifdef COAP_RESOURCES_NOHASH + LL_PREPEND(context->resources, resource); +#else + HASH_ADD(hh, context->resources, key, sizeof(coap_key_t), resource); +#endif +#endif /* WITH_CONTIKI */ +} + +int coap_delete_resource(coap_context_t *context, coap_key_t key) +{ + coap_resource_t *resource; + coap_attr_t *attr, *tmp; +#ifdef WITH_CONTIKI + coap_subscription_t *obs; +#endif + + if (!context) + return 0; + + resource = coap_get_resource_from_key(context, key); + + if (!resource) + return 0; + +#if defined(WITH_POSIX) || defined(WITH_LWIP) +#ifdef COAP_RESOURCES_NOHASH + LL_DELETE(context->resources, resource); +#else + HASH_DELETE(hh, context->resources, resource); +#endif + + /* delete registered attributes */ + LL_FOREACH_SAFE(resource->link_attr, attr, tmp) coap_delete_attr(attr); + + if (resource->flags & COAP_RESOURCE_FLAGS_RELEASE_URI) + coap_free(resource->uri.s); + +#ifdef WITH_POSIX + coap_free(resource); +#endif +#ifdef WITH_LWIP + memp_free(MEMP_COAP_RESOURCE, resource); +#endif +#else /* not (WITH_POSIX || WITH_LWIP) */ + /* delete registered attributes */ + while ((attr = list_pop(resource->link_attr))) + memb_free(&attribute_storage, attr); + + /* delete subscribers */ + while ((obs = list_pop(resource->subscribers))) + { + /* FIXME: notify observer that its subscription has been removed */ + memb_free(&subscription_storage, obs); + } + + memb_free(&resource_storage, resource); +#endif /* WITH_CONTIKI */ + + return 1; +} + +coap_resource_t * +coap_get_resource_from_key(coap_context_t *context, coap_key_t key) +{ +#ifndef WITH_CONTIKI + coap_resource_t *resource; +#ifdef COAP_RESOURCES_NOHASH + resource = NULL; + LL_FOREACH(context->resources, resource) + { + /* if you think you can outspart the compiler and speed things up by (eg by + * casting to uint32* and comparing alues), increment this counter: 1 */ + if (memcmp(key, resource->key, sizeof(coap_key_t)) == 0) + return resource; + } + return NULL; +#else + HASH_FIND(hh, context->resources, key, sizeof(coap_key_t), resource); + + return resource; +#endif +#else /* WITH_CONTIKI */ + int i; + coap_resource_t *ptr2; + + /* the search function is basically taken from memb.c */ + ptr2 = (coap_resource_t *)resource_storage.mem; + for (i = 0; i < resource_storage.num; ++i) + { + if (resource_storage.count[i] && + (memcmp(ptr2->key, key, sizeof(coap_key_t)) == 0)) + return (coap_resource_t *)ptr2; + ++ptr2; + } + + return NULL; +#endif /* WITH_CONTIKI */ +} + +coap_print_status_t coap_print_link(const coap_resource_t *resource, unsigned char *buf, + size_t *len, size_t *offset) +{ + unsigned char *p = buf; + const unsigned char *bufend = buf + *len; + coap_attr_t *attr; + coap_print_status_t result = 0; + const size_t old_offset = *offset; + + *len = 0; + PRINT_COND_WITH_OFFSET(p, bufend, *offset, '<', *len); + PRINT_COND_WITH_OFFSET(p, bufend, *offset, '/', *len); + + COPY_COND_WITH_OFFSET(p, bufend, *offset, resource->uri.s, resource->uri.length, *len); + + PRINT_COND_WITH_OFFSET(p, bufend, *offset, '>', *len); + +#ifndef WITH_CONTIKI + LL_FOREACH(resource->link_attr, attr) + { +#else /* WITH_CONTIKI */ + for (attr = list_head(resource->link_attr); attr; + attr = list_item_next(attr)) + { +#endif /* WITH_CONTIKI */ + + PRINT_COND_WITH_OFFSET(p, bufend, *offset, ';', *len); + + COPY_COND_WITH_OFFSET(p, bufend, *offset, attr->name.s, attr->name.length, *len); + + if (attr->value.s) + { + PRINT_COND_WITH_OFFSET(p, bufend, *offset, '=', *len); + + COPY_COND_WITH_OFFSET(p, bufend, *offset, attr->value.s, attr->value.length, *len); + } + + } + if (resource->observable) + { + COPY_COND_WITH_OFFSET(p, bufend, *offset, ";obs", 4, *len); + } + + result = p - buf; + if (result + old_offset - *offset < *len) + { + result |= COAP_PRINT_STATUS_TRUNC; + } + + return result; +} + +#ifndef WITHOUT_OBSERVE +coap_subscription_t * +coap_find_observer(coap_resource_t *resource, const coap_address_t *peer, const str *token) +{ + coap_subscription_t *s; + + assert(resource); + assert(peer); + + for (s = list_head(resource->subscribers); s; s = list_item_next(s)) + { + if (coap_address_equals(&s->subscriber, peer) + && (!token + || (token->length == s->token_length + && memcmp(token->s, s->token, token->length) == 0))) + return s; + } + + return NULL; +} + +coap_subscription_t * +coap_add_observer(coap_resource_t *resource, const coap_address_t *observer, const str *token) +{ + coap_subscription_t *s; + + assert(observer); + + /* Check if there is already a subscription for this peer. */ + s = coap_find_observer(resource, observer, token); + + /* We are done if subscription was found. */ + if (s) + return s; + + /* s points to a different subscription, so we have to create + * another one. */ + s = COAP_MALLOC_TYPE(subscription); + + if (!s) + return NULL; + + coap_subscription_init(s); + memcpy(&s->subscriber, observer, sizeof(coap_address_t)); + + if (token && token->length) + { + s->token_length = token->length; + memcpy(s->token, token->s, min(s->token_length, 8)); + } + + /* add subscriber to resource */ + list_add(resource->subscribers, s); + + return s; +} + +void coap_touch_observer(coap_context_t *context, const coap_address_t *observer, const str *token) +{ + coap_resource_t *r; + coap_subscription_t *s; + +#ifndef WITH_CONTIKI +#ifdef COAP_RESOURCES_NOHASH + LL_FOREACH(context->resources, r) + { +#else + coap_resource_t *tmp; + HASH_ITER(hh, context->resources, r, tmp) + { +#endif + s = coap_find_observer(r, observer, token); + if (s) + { + s->fail_cnt = 0; + } + } +#else /* WITH_CONTIKI */ + r = (coap_resource_t *)resource_storage.mem; + for (i = 0; i < resource_storage.num; ++i, ++r) + { + if (resource_storage.count[i]) + { + s = coap_find_observer(r, observer, token); + if (s) + { + s->fail_cnt = 0; + } + } + } +#endif /* WITH_CONTIKI */ +} + +void coap_delete_observer(coap_resource_t *resource, const coap_address_t *observer, + const str *token) +{ + coap_subscription_t *s; + + s = coap_find_observer(resource, observer, token); + + if (s) + { + list_remove(resource->subscribers, s); + + COAP_FREE_TYPE(subscription, s); + } +} + +static void coap_notify_observers(coap_context_t *context, coap_resource_t *r) +{ + coap_method_handler_t h; + coap_subscription_t *obs; + str token; + coap_pdu_t *response; + + if (r->observable && (r->dirty || r->partiallydirty)) + { + r->partiallydirty = 0; + + /* retrieve GET handler, prepare response */ + h = r->handler[COAP_REQUEST_GET - 1]; + assert(h); /* we do not allow subscriptions if no + * GET handler is defined */ + + for (obs = list_head(r->subscribers); obs; obs = list_item_next(obs)) + { + if (r->dirty == 0 && obs->dirty == 0) + /* running this resource due to partiallydirty, but this observation's notification was already enqueued */ + continue; + + coap_tid_t tid = COAP_INVALID_TID; + obs->dirty = 0; + /* initialize response */ + response = coap_pdu_init(COAP_MESSAGE_CON, 0, 0, COAP_MAX_PDU_SIZE); + if (!response) + { + obs->dirty = 1; + r->partiallydirty = 1; + debug("coap_check_notify: pdu init failed, resource stays partially dirty\n"); + continue; + } + + if (!coap_add_token(response, obs->token_length, obs->token)) + { + obs->dirty = 1; + r->partiallydirty = 1; + debug("coap_check_notify: cannot add token, resource stays partially dirty\n"); + coap_delete_pdu(response); + continue; + } + + token.length = obs->token_length; + token.s = obs->token; + + response->hdr->id = coap_new_message_id(context); + if (obs->non && obs->non_cnt < COAP_OBS_MAX_NON) + { + response->hdr->type = COAP_MESSAGE_NON; + } + else + { + response->hdr->type = COAP_MESSAGE_CON; + } + /* fill with observer-specific data */ + h(context, r, &obs->subscriber, NULL, &token, response); + + if (response->hdr->type == COAP_MESSAGE_CON) + { + tid = coap_send_confirmed(context, &obs->subscriber, response); + obs->non_cnt = 0; + } + else + { + tid = coap_send(context, &obs->subscriber, response); + obs->non_cnt++; + } + + if (COAP_INVALID_TID == tid || response->hdr->type != COAP_MESSAGE_CON) + coap_delete_pdu(response); + if (COAP_INVALID_TID == tid) + { + debug("coap_check_notify: sending failed, resource stays partially dirty\n"); + obs->dirty = 1; + r->partiallydirty = 1; + } + + } + + /* Increment value for next Observe use. */ + context->observe++; + } + r->dirty = 0; +} + +void coap_check_notify(coap_context_t *context) +{ + coap_resource_t *r; +#ifndef WITH_CONTIKI + +#ifdef COAP_RESOURCES_NOHASH + LL_FOREACH(context->resources, r) + { +#else + coap_resource_t *tmp; + HASH_ITER(hh, context->resources, r, tmp) + { +#endif + coap_notify_observers(context, r); + } +#else /* WITH_CONTIKI */ + int i; + + r = (coap_resource_t *)resource_storage.mem; + for (i = 0; i < resource_storage.num; ++i, ++r) + { + if (resource_storage.count[i]) + { + coap_notify_observers(context, r); + } + } +#endif /* WITH_CONTIKI */ +} + +/** + * Checks the failure counter for (peer, token) and removes peer from + * the list of observers for the given resource when COAP_OBS_MAX_FAIL + * is reached. + * + * @param context The CoAP context to use + * @param resource The resource to check for (peer, token) + * @param peer The observer's address + * @param token The token that has been used for subscription. + */ +static void coap_remove_failed_observers(coap_context_t *context, coap_resource_t *resource, + const coap_address_t *peer, const str *token) +{ + coap_subscription_t *obs; + + for (obs = list_head(resource->subscribers); obs; obs = list_item_next(obs)) + { + if (coap_address_equals(peer, &obs->subscriber) && token->length == obs->token_length + && memcmp(token->s, obs->token, token->length) == 0) + { + + /* count failed notifies and remove when + * COAP_MAX_FAILED_NOTIFY is reached */ + if (obs->fail_cnt < COAP_OBS_MAX_FAIL) + obs->fail_cnt++; + else + { + list_remove(resource->subscribers, obs); + obs->fail_cnt = 0; + +#ifndef NDEBUG + if (LOG_DEBUG <= coap_get_log_level()) + { +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 40 +#endif + unsigned char addr[INET6_ADDRSTRLEN + 8]; + + if (coap_print_addr(&obs->subscriber, addr, INET6_ADDRSTRLEN + 8)) + debug("** removed observer %s\n", addr); + } +#endif + coap_cancel_all_messages(context, &obs->subscriber, obs->token, obs->token_length); + + COAP_FREE_TYPE(subscription, obs); + } + } + break; /* break loop if observer was found */ + } +} + +void coap_handle_failed_notify(coap_context_t *context, const coap_address_t *peer, + const str *token) +{ + coap_resource_t *r; + +#ifndef WITH_CONTIKI + +#ifdef COAP_RESOURCES_NOHASH + LL_FOREACH(context->resources, r) + { +#else + coap_resource_t *tmp; + HASH_ITER(hh, context->resources, r, tmp) + { +#endif + coap_remove_failed_observers(context, r, peer, token); + } +#else /* WITH_CONTIKI */ + int i; + + r = (coap_resource_t *)resource_storage.mem; + for (i = 0; i < resource_storage.num; ++i, ++r) + { + if (resource_storage.count[i]) + { + coap_remove_failed_observers(context, r, peer, token); + } + } +#endif /* WITH_CONTIKI */ +} +#endif /* WITHOUT_NOTIFY */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/resource.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/resource.h new file mode 100644 index 000000000..5ed358355 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/resource.h @@ -0,0 +1,318 @@ +/* resource.h -- generic resource handling + * + * Copyright (C) 2010,2011,2014 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file resource.h + * @brief generic resource handling + */ + +#ifndef _COAP_RESOURCE_H_ +#define _COAP_RESOURCE_H_ + +#include "config.h" +#include "t_list.h" + +#if defined(HAVE_ASSERT_H) && !defined(assert) +# include +#endif + +#ifndef COAP_RESOURCE_CHECK_TIME +/** The interval in seconds to check if resources have changed. */ +#define COAP_RESOURCE_CHECK_TIME 2 +#endif /* COAP_RESOURCE_CHECK_TIME */ + +#ifndef WITH_CONTIKI +# ifdef COAP_RESOURCES_NOHASH +# include "utlist.h" +# else +# include "uthash.h" +# endif +#else /* WITH_CONTIKI */ +#endif /* WITH_CONTIKI */ +#include "hashkey.h" +#include "async.h" +#include "str.h" +#include "pdu.h" +#include "net.h" +#include "subscribe.h" + +/** Definition of message handler function (@sa coap_resource_t). */ +typedef void (*coap_method_handler_t)(coap_context_t *, struct coap_resource_t *, coap_address_t *, + coap_pdu_t *, str * /* token */, coap_pdu_t * /* response */); + +#define COAP_ATTR_FLAGS_RELEASE_NAME 0x1 +#define COAP_ATTR_FLAGS_RELEASE_VALUE 0x2 + +typedef struct coap_attr_t +{ + struct coap_attr_t *next; + str name; + str value; + int flags; +} coap_attr_t; + +#define COAP_RESOURCE_FLAGS_RELEASE_URI 0x1 + +typedef struct coap_resource_t +{ + unsigned int dirty :1; /**< set to 1 if resource has changed */ + unsigned int partiallydirty :1; /**< set to 1 if some subscribers have not yet been notified of the last change */ + unsigned int observable :1; /**< can be observed */ + unsigned int cacheable :1; /**< can be cached */ + + /** + * Used to store handlers for the four coap methods @c GET, @c POST, + * @c PUT, and @c DELETE. coap_dispatch() will pass incoming + * requests to the handler that corresponds to its request method or + * generate a 4.05 response if no handler is available. + */ + coap_method_handler_t handler[4]; + + coap_key_t key; /**< the actual key bytes for this resource */ + +#ifndef WITH_CONTIKI +#ifdef COAP_RESOURCES_NOHASH + struct coap_resource_t *next; +#else + UT_hash_handle hh; +#endif +#endif /* WITH_CONTIKI */ + +#ifndef WITH_CONTIKI + coap_attr_t *link_attr; /**< attributes to be included with the link format */ +#else /* WITH_CONTIKI */ + LIST_STRUCT(link_attr); /**< attributes to be included with the link format */ +#endif /* WITH_CONTIKI */ + LIST_STRUCT(subscribers); /**< list of observers for this resource */ + + /** + * Request URI for this resource. This field will point into the + * static memory. */ + str uri; + int flags; + +} coap_resource_t; + +/** + * Creates a new resource object and initializes the link field to the + * string of length @p len. This function returns the + * new coap_resource_t object. + * + * @param uri The URI path of the new resource. + * @param len The length of @p uri. + * @param flags Flags for memory management (in particular release of memory) + * + * @return A pointer to the new object or @c NULL on error. + */ +coap_resource_t *coap_resource_init(const unsigned char *uri, size_t len, int flags); + +/** + * Registers the given @p resource for @p context. The resource must + * have been created by coap_resource_init(), the storage allocated + * for the resource will be released by coap_delete_resource(). + * + * @param context The context to use. + * @param resource The resource to store. + */ +void coap_add_resource(coap_context_t *context, coap_resource_t *resource); + +/** + * Deletes a resource identified by @p key. The storage allocated for + * that resource is freed. + * + * @param context The context where the resources are stored. + * @param key The unique key for the resource to delete. + * + * @return @c 1 if the resource was found (and destroyed), @c 0 otherwise. + */ +int coap_delete_resource(coap_context_t *context, coap_key_t key); + +/** + * Registers a new attribute with the given @p resource. As the + * attributes str fields will point to @p name and @p val the + * caller must ensure that these pointers are valid during the + * attribute's lifetime. + * + * @param resource The resource to register the attribute with. + * @param name The attribute's name. + * @param nlen Length of @p name. + * @param val The attribute's value or @c NULL if none. + * @param vlen Length of @p val if specified. + * @param flags Flags for memory management (in particular release of memory) + * + * @return A pointer to the new attribute or @c NULL on error. + */ +coap_attr_t *coap_add_attr(coap_resource_t *resource, const unsigned char *name, size_t nlen, + const unsigned char *val, size_t vlen, int flags); + +/** + * Returns @p resource's coap_attr_t object with given @p name if + * found, @c NULL otherwise. + * + * @param resource The resource to search for attribute @p name. + * @param name Name of the requested attribute. + * @param nlen Actual length of @p name. + * @return The first attribute with specified @p name or @c NULL if + * none was found. + */ +coap_attr_t *coap_find_attr(coap_resource_t *resource, const unsigned char *name, size_t nlen); + +/** + * Deletes an attribute + * + * @param attr Pointer to a previously created attribute + * + */ +void coap_delete_attr(coap_attr_t *attr); + +/** + * Status word to encode the result of conditional print or copy + * operations such as coap_print_link(). The lower 28 bits of + * coap_print_status_t are used to encode the number of characters + * that has actually been printed, bits 28 to 31 encode the status. + * When COAP_PRINT_STATUS_ERROR is set, an error occurred during + * output. In this case, the other bits are undefined. + * COAP_PRINT_STATUS_TRUNC indicates that the output is truncated, + * i.e. the printing would have exceeded the current buffer. + */ +typedef unsigned int coap_print_status_t; + +#define COAP_PRINT_STATUS_MASK 0xF0000000u +#define COAP_PRINT_OUTPUT_LENGTH(v) ((v) & ~COAP_PRINT_STATUS_MASK) +#define COAP_PRINT_STATUS_ERROR 0x80000000u +#define COAP_PRINT_STATUS_TRUNC 0x40000000u + +/** + * Writes a description of this resource in link-format to given text + * buffer. @p len must be initialized to the maximum length of @p buf + * and will be set to the number of characters actually written if + * successful. This function returns @c 1 on success or @c 0 on + * error. + * + * @param resource The resource to describe. + * @param buf The output buffer to write the description to. + * @param len Must be initialized to the length of @p buf and + * will be set to the length of the printed link description. + * @param offset The offset within the resource description where to + * start writing into @p buf. This is useful for dealing + * with the Block2 option. @p offset is updated during + * output as it is consumed. + * + * @return If COAP_PRINT_STATUS_ERROR is set, an error occured. Otherwise, + * the lower 28 bits will indicate the number of characters that + * have actually been output into @p buffer. The flag + * COAP_PRINT_STATUS_TRUNC indicates that the output has been + * truncated. + */ +coap_print_status_t coap_print_link(const coap_resource_t *resource, unsigned char *buf, + size_t *len, size_t *offset); + +/** + * Registers the specified @p handler as message handler for the request type + * @p method + * + * @param resource The resource for which the handler shall be registered. + * @param method The CoAP request method to handle. + * @param handler The handler to register with @p resource. + */ +static inline void coap_register_handler(coap_resource_t *resource, unsigned char method, + coap_method_handler_t handler) +{ + assert(resource); + assert( + method > 0 + && (size_t)(method - 1) + < sizeof(resource->handler) / sizeof(coap_method_handler_t)); + resource->handler[method - 1] = handler; +} + +/** + * Returns the resource identified by the unique string @p key. If no + * resource was found, this function returns @c NULL. + * + * @param context The context to look for this resource. + * @param key The unique key of the resource. + * + * @return A pointer to the resource or @c NULL if not found. + */ +coap_resource_t *coap_get_resource_from_key(coap_context_t *context, coap_key_t key); + +/** + * Calculates the hash key for the resource requested by the + * Uri-Options of @p request. This function calls coap_hash() for + * every path segment. + * + * @param request The requesting pdu. + * @param key The resulting hash is stored in @p key + */ +void coap_hash_request_uri(const coap_pdu_t *request, coap_key_t key); + +/** + * @addtogroup observe + */ + +/** + * Adds the specified peer as observer for @p resource. The + * subscription is identified by the given @p token. This function + * returns the registered subscription information if the @p observer + * has been added, or @c NULL on error. + * + * @param resource The observed resource. + * @param observer The remote peer that wants to received status updates. + * @param token The token that identifies this subscription. + * @param token_length The actual length of @p token. Must be @c 0 when + * @p token is @c NULL. + * @return A pointer to the added/updated subscription information or + * @c NULL on error. + */ +coap_subscription_t *coap_add_observer(coap_resource_t *resource, const coap_address_t *observer, + const str *token); + +/** + * Returns a subscription object for given @p peer. + * + * @param resource The observed resource. + * @param peer The address to search for. + * @param token The token that identifies this subscription or @c NULL for any + * token. + * @return A valid subscription if exists or @c NULL otherwise. + */ +coap_subscription_t *coap_find_observer(coap_resource_t *resource, const coap_address_t *peer, + const str *token); + +/** + * Marks an observer as alive. + * + * @param context The CoAP context to use + * @param observer The transport address of the observer + * @param token The corresponding token that has been used for + * the subscription + */ +void coap_touch_observer(coap_context_t *context, const coap_address_t *observer, const str *token); + +/** + * Removes any subscription for @p observer from @p resource and releases + * the allocated storage. + * + * @param resource The observed resource. + * @param observer The observer's address. + * @param token The token that identifies this subscription or @c NULL for any + * token. + */ +void coap_delete_observer(coap_resource_t *resource, const coap_address_t *observer, + const str *token); + +/** + * Checks for all known resources, if they are dirty and notifies + * subscribed observers. + */ +void coap_check_notify(coap_context_t *context); + +/** @} */ + +#endif /* _COAP_RESOURCE_H_ */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/str.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/str.c new file mode 100644 index 000000000..8b275e3ed --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/str.c @@ -0,0 +1,37 @@ +/* str.c -- strings to be used in the CoAP library + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "config.h" + +#include + +#include "debug.h" +#include "mem.h" +#include "str.h" + +str *coap_new_string(size_t size) +{ + str *s = coap_malloc(sizeof(str) + size + 1); + if (!s) + { +#ifndef NDEBUG + coap_log(LOG_CRIT, "coap_new_string: malloc\n"); +#endif + return NULL; + } + + memset(s, 0, sizeof(str)); + s->s = ((unsigned char *) s) + sizeof(str); + return s; +} + +void coap_delete_string(str *s) +{ + coap_free(s); +} + diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/str.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/str.h new file mode 100644 index 000000000..6405298a1 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/str.h @@ -0,0 +1,31 @@ +/* str.h -- strings to be used in the CoAP library + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef _COAP_STR_H_ +#define _COAP_STR_H_ + +#include + +typedef struct +{ + size_t length; /* length of string */ + unsigned char *s; /* string data */ +} str; + +#define COAP_SET_STR(st,l,v) { (st)->length = (l), (st)->s = (v); } + +/** + * Returns a new string object with at least size bytes storage + * allocated. The string must be released using coap_delete_string(); + */ +str *coap_new_string(size_t size); + +/** Deletes the given string and releases any memory allocated. */ +void coap_delete_string(str *); + +#endif /* _COAP_STR_H_ */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/subscribe.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/subscribe.c new file mode 100644 index 000000000..295f5c577 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/subscribe.c @@ -0,0 +1,445 @@ +/* subscribe.c -- subscription handling for CoAP + * see draft-ietf-coap-observe-09 + * + * Copyright (C) 2010--2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "config.h" + +#if defined(HAVE_ASSERT_H) && !defined(assert) +# include +#endif + +#include +#include +#ifdef HAVE_ARPA_INET_H +# include +#endif + +/* #include "resource.h" */ + +#include "mem.h" +#include "encode.h" +#include "debug.h" +#include "subscribe.h" + +void coap_subscription_init(coap_subscription_t *s) +{ + assert(s); + memset(s, 0, sizeof(coap_subscription_t)); +} + +#if 0 +#define HMASK (ULONG_MAX >> 1) + +void +notify(coap_context_t *context, coap_resource_t *res, + coap_subscription_t *sub, unsigned int duration, int code) +{ +#if 0 + coap_pdu_t *pdu; + int ls, finished=0; + unsigned char ct, d; + unsigned int length; +#ifndef NDEBUG + char addr[INET6_ADDRSTRLEN]; +#endif + + if ( !context || !res || !sub || !(pdu = coap_new_pdu()) ) + return; + + pdu->hdr->type = COAP_MESSAGE_CON; + pdu->hdr->id = rand(); /* use a random transaction id */ + pdu->hdr->code = code; + + /* FIXME: content-type and data (how about block?) */ + if (res->uri->host.length) + coap_add_option (pdu, COAP_OPTION_URI_HOST, + res->uri->host.length, + res->uri->host.s ); + + if (res->uri->path.length) + coap_add_option (pdu, COAP_OPTION_URI_PATH, + res->uri->path.length, + res->uri->path.s); + + d = COAP_PSEUDOFP_ENCODE_8_4_DOWN(duration, ls); + + coap_add_option ( pdu, COAP_OPTION_SUBSCRIPTION, 1, &d ); + + if (sub->token.length) + { + coap_add_option (pdu, COAP_OPTION_TOKEN, + sub->token.length, + sub->token.s); + } + + if (res->uri->query.length) + coap_add_option (pdu, COAP_OPTION_URI_QUERY, + res->uri->query.length, + res->uri->query.s ); + + if (res->data) + { + length = (unsigned char *)pdu->hdr + COAP_MAX_PDU_SIZE - pdu->data; + ct = res->mediatype; + res->data(res->uri, &ct, 0, pdu->data, &length, &finished); + pdu->length += length; + + /* TODO: add block option if not finished */ + /* TODO: add mediatype */ + } + +#ifndef NDEBUG + if ( inet_ntop(sub->subscriber.addr.sa.sa_family, + &sub->subscriber.addr, addr, sizeof(addr)) ) + { + debug("*** notify for %s to [%s]\n", res->uri->path.s, addr); + } +#endif + if (pdu && coap_send_confirmed(context, + &sub->subscriber.addr.sa, + sub->subscriber.size, pdu) + == COAP_INVALID_TID) + { +#ifndef NDEBUG + debug("coap_check_resource_list: error sending notification\n"); +#endif + coap_delete_pdu(pdu); + } +#endif +} + +void +coap_check_resource_list(coap_context_t *context) +{ + coap_resource_t *res, *tmp; + coap_list_t *sub; + coap_key_t key; + time_t now; + + if ( !context || !context->resources /* || !context->subscribers */) + return; + + time(&now); /* FIXME: use coap_ticks() */ + + HASH_ITER(hh, context->resources, res, tmp) + { + if (res->dirty) + { + debug("FIXME: notify subscribers\n"); +#if 0 + key = coap_uri_hash( COAP_RESOURCE(res)->uri ); + + /* is subscribed? */ + for (sub = context->subscriptions; sub; sub = sub->next) + { + if ( COAP_SUBSCRIPTION(sub)->resource == key ) + { + /* notify subscriber */ + notify(context, COAP_RESOURCE(res), COAP_SUBSCRIPTION(sub), + COAP_SUBSCRIPTION(sub)->expires - now, COAP_RESPONSE_200); + } + + } + + COAP_RESOURCE(res)->dirty = 0; +#endif + } + } +} + +#if 0 +coap_resource_t * +coap_get_resource_from_key(coap_context_t *ctx, coap_key_t key) +{ + coap_list_t *node; + + if (ctx) + { + /* TODO: use hash table for resources with key to access */ + for (node = ctx->resources; node; node = node->next) + { + printf("check %ux\n", coap_uri_hash(COAP_RESOURCE(node)->uri)); + if ( key == coap_uri_hash(COAP_RESOURCE(node)->uri) ) + { + printf("found\n"); + return COAP_RESOURCE(node); + } + } + } + + printf("not found\n"); + return NULL; +} + +coap_resource_t * +coap_get_resource(coap_context_t *ctx, coap_uri_t *uri) +{ +#ifndef NDEBUG + int i; + printf("search resource %ux", coap_uri_hash(uri)); + for (i=0; i < uri->path.length; ++i) + { + printf(" %02x", uri->path.s[i]); + } + printf("\n"); +#endif + return uri ? coap_get_resource_from_key(ctx, coap_uri_hash(uri)) : NULL; +} +#endif + +void +coap_check_subscriptions(coap_context_t *context) +{ + time_t now; + coap_list_t *node; +#ifndef NDEBUG + char addr[INET6_ADDRSTRLEN]; +#endif + + if ( !context ) + return; + + time(&now); + + node = context->subscriptions; + while ( node && COAP_SUBSCRIPTION(node)->expires < now ) + { +#ifndef NDEBUG + if (inet_ntop(COAP_SUBSCRIPTION(node)->subscriber.addr.sa.sa_family, + &COAP_SUBSCRIPTION(node)->subscriber.addr, + addr, sizeof(addr))) + { + + debug("** removed expired subscription from [%s]\n", addr); + } +#endif +#if 0 + notify(context, + coap_get_resource_from_key(context, COAP_SUBSCRIPTION(node)->resource), + COAP_SUBSCRIPTION(node), + 0, COAP_RESPONSE_400); +#endif + context->subscriptions = node->next; + coap_delete(node); + node = context->subscriptions; + } +} + +void +coap_free_resource(void *res) +{ + if ( res ) + { +#if 0 + coap_free(((coap_resource_t *)res)->uri); + coap_delete_string(((coap_resource_t *)res)->name); +#endif + } +} + +#if 0 +/** + * Deletes the resource that is identified by key. Returns 1 if the resource was + * removed, 0 on error (e.g. if no such resource exists). + */ +int +coap_delete_resource(coap_context_t *context, coap_key_t key) +{ + coap_list_t *prev, *node; + + if (!context || key == COAP_INVALID_HASHKEY) + return 0; + + for (prev = NULL, node = context->resources; node; + prev = node, node = node->next) + { + if (coap_uri_hash(COAP_RESOURCE(node)->uri) == key) + { +#ifndef NDEBUG + debug("removed key %lu (%s)\n",key,COAP_RESOURCE(node)->uri->path.s); +#endif + if (!prev) + context->resources = node->next; + else + prev->next = node->next; + + coap_delete(node); + return 1; + } + } + return 0; +} +#endif + +coap_subscription_t * +coap_new_subscription(coap_context_t *context, const coap_uri_t *resource, + const struct sockaddr *addr, socklen_t addrlen, time_t expiry) +{ + coap_subscription_t *result; + + if ( !context || !resource || !addr + || !(result = coap_malloc(sizeof(coap_subscription_t)))) + return NULL; + + result->resource = coap_uri_hash(resource); + result->expires = expiry; + memcpy(&result->subscriber.addr.sa, addr, addrlen); + + memset(&result->token, 0, sizeof(str)); + + return result; + +} + +coap_list_t * +coap_list_push_first(coap_list_t **list, void *data, void (*delete_func)(void *) ) +{ + coap_list_t *node; + node = coap_new_listnode(data, delete_func); + if ( !node || !list ) + return NULL; + + if ( !*list ) + { + *list = node; + } + else + { + node->next = *list; + *list = node; + } + + return node; +} + +int +_order_subscription(void *a, void *b) +{ + if ( !a || !b ) + return a < b ? -1 : 1; + + return ((coap_subscription_t *)a)->expires < ((coap_subscription_t *)b)->expires ? -1 : 1; +} + +coap_key_t +coap_subscription_hash(coap_subscription_t *subscription) +{ + if ( !subscription ) + return COAP_INVALID_HASHKEY; + + return _hash2( subscription->resource, (unsigned char *)&subscription->subscriber, + sizeof(subscription->subscriber) ); +} + +coap_key_t +coap_add_subscription(coap_context_t *context, + coap_subscription_t *subscription) +{ + coap_list_t *node; + if ( !context || !subscription ) + return COAP_INVALID_HASHKEY; + + if ( !(node = coap_new_listnode(subscription, NULL)) ) + return COAP_INVALID_HASHKEY; + + if ( !coap_insert(&context->subscriptions, node, _order_subscription ) ) + { + coap_free( node ); /* do not call coap_delete(), so subscription object will survive */ + return COAP_INVALID_HASHKEY; + } + + return coap_subscription_hash(subscription); +} + +coap_subscription_t * +coap_find_subscription(coap_context_t *context, + coap_key_t hashkey, + struct sockaddr *addr, + str *token) +{ +#if 0 + coap_list_t *node; +#endif + + if (!context || !addr || hashkey == COAP_INVALID_HASHKEY) + return NULL; + + /* FIXME: I do not like the way subscriptions work right now. To be fixed. */ + +#if 0 + for (node = context->subscriptions; node; node = node->next) + { + if (COAP_SUBSCRIPTION(node)->resource == hashkey) + { + + if (token) + { /* do not proceed if tokens do not match */ + if (token->length != COAP_SUBSCRIPTION(node)->token.length || + memcmp(token->s, COAP_SUBSCRIPTION(node)->token.s, + token->length) != 0) + continue; + } + + if (subscriber->sin6_port == COAP_SUBSCRIPTION(node)->subscriber.sin6_port + && memcmp(&subscriber->sin6_addr, + &COAP_SUBSCRIPTION(node)->subscriber.sin6_addr, + sizeof(struct in6_addr)) == 0) + return COAP_SUBSCRIPTION(node); + } + } +#endif + return NULL; +} + +int +coap_delete_subscription(coap_context_t *context, + coap_key_t key, + struct sockaddr *addr) +{ +#if 0 + coap_list_t *prev, *node; +#endif + + if (!context || !addr || key == COAP_INVALID_HASHKEY) + return 0; + + /* FIXME: I do not like the way subscriptions work right now. To be fixed. */ + +#if 0 + for (prev = NULL, node = context->subscriptions; node; + prev = node, node = node->next) + { + if (COAP_SUBSCRIPTION(node)->resource == key) + { + if (subscriber->sin6_port == COAP_SUBSCRIPTION(node)->subscriber.sin6_port + && memcmp(&subscriber->sin6_addr, + &COAP_SUBSCRIPTION(node)->subscriber.sin6_addr, + sizeof(struct in6_addr)) == 0) + { + + if (!prev) + { + context->subscriptions = node->next; + coap_free(COAP_SUBSCRIPTION(node)->token.s); + coap_delete(node); + } + else + { + prev->next = node->next; + coap_free(COAP_SUBSCRIPTION(node)->token.s); + coap_delete(node); + } + return 1; + } + } + } +#endif + + return 0; +} +#endif diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/subscribe.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/subscribe.h new file mode 100644 index 000000000..7b7dc05ce --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/subscribe.h @@ -0,0 +1,201 @@ +/* subscribe.h -- subscription handling for CoAP + * see draft-hartke-coap-observe-03 + * + * Copyright (C) 2010--2012 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef _COAP_SUBSCRIBE_H_ +#define _COAP_SUBSCRIBE_H_ + +#include "config.h" +#include "address.h" + +/** + * @defgroup observe Resource observation + * @{ + */ + +#ifndef COAP_OBS_MAX_NON +/** + * Number of notifications that may be sent non-confirmable before a + * confirmable message is sent to detect if observers are alive. The + * maximum allowed value here is @c 15. + */ +#define COAP_OBS_MAX_NON 5 +#endif /* COAP_OBS_MAX_NON */ + +#ifndef COAP_OBS_MAX_FAIL +/** + * Number of confirmable notifications that may fail (i.e. time out + * without being ACKed) before an observer is removed. The maximum + * value for COAP_OBS_MAX_FAIL is @c 3. + */ +#define COAP_OBS_MAX_FAIL 3 +#endif /* COAP_OBS_MAX_FAIL */ + +/** Subscriber information */ +typedef struct coap_subscription_t +{ + struct coap_subscription_t *next; /**< next element in linked list */ + coap_address_t subscriber; /**< address and port of subscriber */ + + unsigned int non :1; /**< send non-confirmable notifies if @c 1 */ + unsigned int non_cnt :4; /**< up to 15 non-confirmable notifies allowed */ + unsigned int fail_cnt :2; /**< up to 3 confirmable notifies can fail */ + unsigned int dirty :1; /**< set if the notification temporarily could not be sent (in that case, the resource's partiallydirty flag is set too) */ + + size_t token_length; /**< actual length of token */ + unsigned char token[8]; /**< token used for subscription */ + /* @todo CON/NON flag, block size */ +} coap_subscription_t; + +void coap_subscription_init(coap_subscription_t *); + +#if 0 +#include "uthash.h" +#include "uri.h" +#include "list.h" +#include "pdu.h" +#include "net.h" + +#if 0 +typedef unsigned long coap_key_t; + +/** Used to indicate that a hashkey is invalid. */ +#define COAP_INVALID_HASHKEY ((coap_key_t)-1) + +typedef struct +{ + coap_uri_t *uri; /* unique identifier; memory is released by coap_delete_resource() */ + UT_hash_handle hh; /**< hash handle (for internal use only) */ + str *name; /* display name of the resource */ + unsigned char mediatype; /* media type for resource representation */ + unsigned int dirty:1; /* set to 1 if resource has changed */ + unsigned int writable:1; /* set to 1 if resource can be changed using PUT */ + + /* cache-control */ + unsigned char etag[4]; /* version identifier for this resource + * (zero terminated, first byte is zero if not set). */ + unsigned int maxage; /* maximum cache time (zero means no Max-age option) */ + + /** + * Callback function that copies the resource representation into the provided data + * buffer (PDU payload). finished is set to 1 to indicate that this was the last block + * of buflen data for this resource representation, 0 means that data is not finished + * and a subsequent call with offset updated by buflen would yield more data (i.e. + * the M-bit of CoAP's block option must be set if offset and buflen are selected + * accordingly. + * When called, buflen must be set to the maximum length of buf that is to be filled + * with the mediatype representation of the resource identified by uri. + * The mediatype must be set to the requested mediatype of COAP_MEDIATYPE_ANY if + * none was given. On return, the mediatype will be set to the type that is + * actually used. + * The return value indicates the result code that should be used in a response to + * this function. + */ + int (*data)(coap_uri_t *uri, unsigned char *mediatype, unsigned int offset, unsigned char *buf, unsigned int *buflen, int *finished); +}coap_resource_t; +#endif + +typedef struct +{ + coap_key_t resource; /* hash key for subscribed resource */ + time_t expires; /* expiry time of subscription */ + + coap_address_t subscriber; /**< subscriber's address */ + + str token; /**< subscription token */ +}coap_subscription_t; + +#define COAP_RESOURCE(node) ((coap_resource_t *)(node)->data) +#define COAP_SUBSCRIPTION(node) ((coap_subscription_t *)(node)->data) + +/** Checks subscribed resources for updates and notifies subscribers of changes. */ +void coap_check_resource_list(coap_context_t *context); + +/** Removes expired subscriptions. */ +void coap_check_subscriptions(coap_context_t *context); + +#if 0 +/** + * Adds specified resource to the resource observation list. Returns a + * unique key for the resource. The alloceted memory is released when + * the resource is destroyed with coap_delete_resource(). + */ +coap_key_t coap_add_resource(coap_context_t *context, coap_resource_t *); + +/** + * Deletes the resource that is identified by key. Returns 1 if the resource was + * removed, 0 on error (e.g. if no such resource exists). + */ +int coap_delete_resource(coap_context_t *context, coap_key_t key); +#endif +/** + * Creates a new subscription object filled with the given data. The storage + * allocated for this object must be released using coap_free(). */ +coap_subscription_t *coap_new_subscription(coap_context_t *context, + const coap_uri_t *resource, + const struct sockaddr *subscriber, + socklen_t addrlen, + time_t expiry); + +/** + * Adds the given subsription object to the observer list. + * @param context The CoAP context + * @param subscription A new subscription oobject created with coap_new_subscription() + * @return A unique hash key for this resource or COAP_INVALID_HASHKEY on error. + * The storage allocated for the subscription object is released when it is + * removed from the subscription list, unless the function has returned + * COAP_INVALID_HASHKEY. In this case, the storage must be released by the + * caller of this function. + */ +coap_key_t coap_add_subscription(coap_context_t *context, + coap_subscription_t *subscription); + +/** + * Returns the subscription from subscriber for the resource identified + * by hashkey. When token is not NULL the subscription must have the + * same token. + * @param context The CoAP context + * @param hashkey The unique key that identifies the subscription + * @param subscriber The subscriber's transport address + * @param token If not NULL, this specifies a token given by the + * subscriber to identify its subscription. + * @return The requested subscription object or NULL when not found. + */ +coap_subscription_t * coap_find_subscription(coap_context_t *context, + coap_key_t hashkey, + struct sockaddr *subscriber, + str *token); +/** + * Removes a subscription from the subscription list stored in context and + * releases the storage that was allocated for this subscription. + * @param context The CoAP context. + * @param haskey The unique key that identifies the subscription to remove. + * @return 1 if a subscription was removed, 0 otherwise. + */ +int coap_delete_subscription(coap_context_t *context, + coap_key_t hashkey, + struct sockaddr *subscriber); + +/** Returns a unique hash for the specified URI or COAP_INVALID_HASHKEY on error. */ +coap_key_t coap_uri_hash(const coap_uri_t *uri); + +/** Returns a unique hash for the specified subscription or COAP_INVALID_HASHKEY on error. */ +coap_key_t coap_subscription_hash(coap_subscription_t *subscription); +#if 0 +/** Returns the resource identified by key or NULL if not found. */ +coap_resource_t *coap_get_resource_from_key(coap_context_t *ctx, coap_key_t key); + +/** Returns the resource identified by uri or NULL if not found. */ +coap_resource_t *coap_get_resource(coap_context_t *ctx, coap_uri_t *uri); +#endif + +#endif + +/** @} */ + +#endif /* _COAP_SUBSCRIBE_H_ */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/t_list.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/t_list.h new file mode 100644 index 000000000..47653d1b4 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/t_list.h @@ -0,0 +1,152 @@ +/* t_list -- tinydtls lists + * + * Copyright (C) 2012 Olaf Bergmann + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file t_list.h + * @brief Wrappers for list structures and functions + */ + +#ifndef _DTLS_LIST_H_ +#define _DTLS_LIST_H_ + +#ifndef WITH_CONTIKI +#include "uthash.h" +#include "utlist.h" + +/* We define list structures and utility functions to be compatible + * with Contiki list structures. The Contiki list API is part of the + * Contiki operating system, and therefore the following licensing + * terms apply (taken from contiki/core/lib/list.h): + * + * Copyright (c) 2004, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * Author: Adam Dunkels + * + * $ Id: list.h,v 1.5 2010/09/13 13:31:00 adamdunkels Exp $ + */ + +typedef void **list_t; +struct list +{ + struct list *next; +}; + +#define LIST_CONCAT(s1, s2) s1##s2 + +#define LIST_STRUCT(name) \ + void *LIST_CONCAT(name, _list); \ + list_t name + +#define LIST_STRUCT_INIT(struct_ptr, name) { \ + (struct_ptr)->name = &((struct_ptr)->LIST_CONCAT(name,_list)); \ + (struct_ptr)->LIST_CONCAT(name,_list) = NULL; \ + } + +static inline void * +list_head(list_t the_list) +{ + return *the_list; +} + +static inline void list_remove(list_t the_list, void *item) +{ + if (list_head(the_list)) + LL_DELETE(*(struct list **)the_list, (struct list *)item); +} + +static inline void list_add(list_t the_list, void *item) +{ + list_remove(the_list, item); + LL_APPEND(*(struct list **)the_list, (struct list *)item); +} + +static inline void list_push(list_t the_list, void *item) +{ + LL_PREPEND(*(struct list **)the_list, (struct list *)item); +} + +static inline void * +list_pop(list_t the_list) +{ + struct list *l; + l = (struct list*) *the_list; + if (l) + list_remove(the_list, l); + + return l; +} + +static inline void list_insert(list_t the_list, void *previtem, void *newitem) +{ + if (previtem == NULL) + { + list_push(the_list, newitem); + } + else + { + ((struct list *) newitem)->next = ((struct list *) previtem)->next; + ((struct list *) previtem)->next = (struct list*) newitem; + } +} + +static inline void * +list_item_next(void *item) +{ + return item == NULL ? NULL : ((struct list *) item)->next; +} + +#else /* WITH_CONTIKI */ +#include "list.h" +#endif /* WITH_CONTIKI */ + +#endif /* _DTLS_LIST_H_ */ + diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/Makefile b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/Makefile new file mode 100644 index 000000000..639755292 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/Makefile @@ -0,0 +1,57 @@ +# Makefile for libcoap +# +# Copyright (C) 2012 Olaf Bergmann +# +# This file is part of the CoAP library libcoap. Please see +# README for terms of use. + +# the library's version +VERSION:=4.1.1 + +# tools + +SHELL = /bin/sh +MKDIR = mkdir + +abs_builddir = /connectivity/connectivity/src/bt_edr_adapter/libcoap-4.1.1/tests +top_builddir = .. +top_srcdir = .. +# files and flags +ifneq (,) + PROGRAMS:=testdriver +endif +SOURCES:= test_uri.c test_options.c test_pdu.c test_error_response.c \ + test_sendqueue.c test_wellknown.c +HEADERS:=$(SOURCES:.c=.h) +OBJECTS:= $(patsubst %.c, %.o, $(SOURCES)) +CFLAGS:=-g -Wall -g -O2 +CPPFLAGS:=-I$(top_srcdir) -DWITH_POSIX +DISTDIR?=$(top_builddir)/libcoap-4.1.1 +FILES:=Makefile.in testdriver.c $(HEADERS) $(SOURCES) +LDFLAGS:=-L$(top_builddir) +LDLIBS:=-lcunit +libcoap =$(top_builddir)/libcoap.a + +.PHONY: clean distclean + +.SUFFIXES: +.SUFFIXES: .c .o + +all: $(PROGRAMS) + +check: + echo DISTDIR: $(DISTDIR) + echo top_builddir: $(top_builddir) + +testdriver: $(OBJECTS) $(libcoap) + +clean: + @rm -f $(PROGRAMS) $(OBJECTS) + +distclean: clean + @rm -rf $(DISTDIR) + @rm -f *~ + +dist: $(FILES) + test -d $(DISTDIR)/tests || mkdir $(DISTDIR)/tests + cp $(FILES) $(DISTDIR)/tests diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/Makefile.in b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/Makefile.in new file mode 100644 index 000000000..95da5c004 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/Makefile.in @@ -0,0 +1,57 @@ +# Makefile for libcoap +# +# Copyright (C) 2012 Olaf Bergmann +# +# This file is part of the CoAP library libcoap. Please see +# README for terms of use. + +# the library's version +VERSION:=@PACKAGE_VERSION@ + +# tools +@SET_MAKE@ +SHELL = /bin/sh +MKDIR = mkdir + +abs_builddir = @abs_builddir@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +# files and flags +ifneq (,@TESTS@) + PROGRAMS:=testdriver +endif +SOURCES:= test_uri.c test_options.c test_pdu.c test_error_response.c \ + test_sendqueue.c test_wellknown.c +HEADERS:=$(SOURCES:.c=.h) +OBJECTS:= $(patsubst %.c, %.o, $(SOURCES)) +CFLAGS:=-g -Wall @CFLAGS@ +CPPFLAGS:=-I$(top_srcdir) @CPPFLAGS@ +DISTDIR?=$(top_builddir)/@PACKAGE_TARNAME@-@PACKAGE_VERSION@ +FILES:=Makefile.in testdriver.c $(HEADERS) $(SOURCES) +LDFLAGS:=-L$(top_builddir) @LDFLAGS@ +LDLIBS:=-lcunit @LIBS@ +libcoap =$(top_builddir)/libcoap.a + +.PHONY: clean distclean + +.SUFFIXES: +.SUFFIXES: .c .o + +all: $(PROGRAMS) + +check: + echo DISTDIR: $(DISTDIR) + echo top_builddir: $(top_builddir) + +testdriver: $(OBJECTS) $(libcoap) + +clean: + @rm -f $(PROGRAMS) $(OBJECTS) + +distclean: clean + @rm -rf $(DISTDIR) + @rm -f *~ + +dist: $(FILES) + test -d $(DISTDIR)/tests || mkdir $(DISTDIR)/tests + cp $(FILES) $(DISTDIR)/tests diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_error_response.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_error_response.c new file mode 100644 index 000000000..fad09415c --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_error_response.c @@ -0,0 +1,330 @@ +/* libcoap unit tests + * + * Copyright (C) 2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include +#include +#include +#include +#include +#include "test_error_response.h" + +coap_pdu_t *pdu; /* Holds the request PDU for most tests */ +coap_opt_filter_t opts; /* option filter used for generating responses */ + +/************************************************************************ + ** PDU decoder + ************************************************************************/ + +/* FIXME: handle COAP_ERROR_PHRASE_LENGTH == 0 */ + +void t_error_response1(void) +{ + char teststr[] = + { 0x60, 0x80, 0x12, 0x34, 0xff, 'B', 'a', 'd', ' ', 'R', 'e', 'q', 'u', 'e', 's', 't' }; + coap_pdu_t *response; + + coap_pdu_clear(pdu, pdu->max_size); + pdu->hdr->type = COAP_MESSAGE_CON; + pdu->hdr->id = htons(0x1234); + + /* result = coap_add_token(pdu, 5, (unsigned char *)"token"); */ + coap_option_filter_clear(opts); + response = coap_new_error_response(pdu, COAP_RESPONSE_CODE(400), opts); + + CU_ASSERT_PTR_NOT_NULL(response); + + CU_ASSERT(response->length == sizeof(teststr)); + CU_ASSERT(response->hdr->version == 1); + CU_ASSERT(response->hdr->type == COAP_MESSAGE_ACK); + CU_ASSERT(response->hdr->token_length == 0); + CU_ASSERT(response->hdr->code == 0x80); + CU_ASSERT(pdu->hdr->id == htons(0x1234)); + + CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0); +} + +void t_error_response2(void) +{ + char teststr[] = + { 0x55, 0x84, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0xff, 'N', 'o', 't', ' ', 'F', 'o', 'u', 'n', + 'd' }; + coap_pdu_t *response; + + coap_pdu_clear(pdu, pdu->max_size); + pdu->hdr->type = COAP_MESSAGE_NON; + pdu->hdr->id = htons(0x1234); + coap_add_token(pdu, 5, (unsigned char *) "token"); + coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (unsigned char *) "time"); + + coap_option_filter_clear(opts); + response = coap_new_error_response(pdu, COAP_RESPONSE_CODE(404), opts); + + CU_ASSERT_PTR_NOT_NULL(response); + + CU_ASSERT(response->length == sizeof(teststr)); + CU_ASSERT(response->hdr->version == 1); + CU_ASSERT(response->hdr->type == COAP_MESSAGE_NON); + CU_ASSERT(response->hdr->token_length == 5); + CU_ASSERT(response->hdr->code == 0x84); + + CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0); +} + +void t_error_response3(void) +{ + const unsigned char code = COAP_RESPONSE_CODE(402); + char teststr[] = + { 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', 'n', 0x90, 0xff, 'B', 'a', 'd', ' ', 'O', 'p', + 't', 'i', 'o', 'n' }; + coap_pdu_t *response; + + coap_pdu_clear(pdu, pdu->max_size); + pdu->hdr->type = COAP_MESSAGE_CON; + coap_add_token(pdu, 5, (unsigned char *) "token"); + /* coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (unsigned char *)"time"); */ + + /* unknown critical option 9 */ + coap_add_option(pdu, 9, 0, NULL); + + coap_option_filter_clear(opts); + coap_option_setb(opts, 9); + response = coap_new_error_response(pdu, code, opts); + + CU_ASSERT_PTR_NOT_NULL(response); + + CU_ASSERT(response->length == sizeof(teststr)); + CU_ASSERT(response->hdr->version == 1); + CU_ASSERT(response->hdr->type == COAP_MESSAGE_ACK); + CU_ASSERT(response->hdr->token_length == 5); + CU_ASSERT(response->hdr->code == code); + + CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0); +} + +void t_error_response4(void) +{ + const unsigned char code = COAP_RESPONSE_CODE(402); + unsigned char optval[] = + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b }; + char teststr[] = + { 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', 'n', 0x9c, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0xff, 'B', 'a', 'd', ' ', 'O', 'p', 't', 'i', 'o', + 'n' }; + coap_pdu_t *response; + + coap_pdu_clear(pdu, pdu->max_size); + pdu->hdr->type = COAP_MESSAGE_CON; + coap_add_token(pdu, 5, (unsigned char *) "token"); + /* coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (unsigned char *)"time"); */ + + /* unknown critical option 9 */ + coap_add_option(pdu, 9, sizeof(optval), optval); + + coap_option_filter_clear(opts); + coap_option_setb(opts, 9); + response = coap_new_error_response(pdu, code, opts); + + CU_ASSERT_PTR_NOT_NULL(response); + + CU_ASSERT(response->length == sizeof(teststr)); + CU_ASSERT(response->hdr->version == 1); + CU_ASSERT(response->hdr->type == COAP_MESSAGE_ACK); + CU_ASSERT(response->hdr->token_length == 5); + CU_ASSERT(response->hdr->code == code); + + CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0); +} + +void t_error_response5(void) +{ + const unsigned char code = COAP_RESPONSE_CODE(402); + unsigned char optval[] = + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12 }; + char teststr[] = + { 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', 'n', 0x9d, 0x06, 0x00, 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, + 0xff, 'B', 'a', 'd', ' ', 'O', 'p', 't', 'i', 'o', 'n' }; + coap_pdu_t *response; + + coap_pdu_clear(pdu, pdu->max_size); + pdu->hdr->type = COAP_MESSAGE_CON; + coap_add_token(pdu, 5, (unsigned char *) "token"); + /* coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (unsigned char *)"time"); */ + + /* unknown critical option 9 */ + coap_add_option(pdu, 9, sizeof(optval), optval); + + coap_option_filter_clear(opts); + coap_option_setb(opts, 9); + response = coap_new_error_response(pdu, code, opts); + + CU_ASSERT_PTR_NOT_NULL(response); + + CU_ASSERT(response->length == sizeof(teststr)); + CU_ASSERT(response->hdr->version == 1); + CU_ASSERT(response->hdr->type == COAP_MESSAGE_ACK); + CU_ASSERT(response->hdr->token_length == 5); + CU_ASSERT(response->hdr->code == code); + + CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0); +} + +void t_error_response6(void) +{ + const unsigned char code = COAP_RESPONSE_CODE(402); + unsigned char optval[] = + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12 }; + char teststr[] = + { 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', 'n', 0xdd, 0x0a, 0x06, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, + 0x12, 0xff, 'B', 'a', 'd', ' ', 'O', 'p', 't', 'i', 'o', 'n' }; + coap_pdu_t *response; + + coap_pdu_clear(pdu, pdu->max_size); + pdu->hdr->type = COAP_MESSAGE_CON; + coap_add_token(pdu, 5, (unsigned char *) "token"); + /* coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (unsigned char *)"time"); */ + + /* unknown critical option 23 */ + coap_add_option(pdu, 23, sizeof(optval), optval); + + coap_option_filter_clear(opts); + coap_option_setb(opts, 23); + response = coap_new_error_response(pdu, code, opts); + + CU_ASSERT_PTR_NOT_NULL(response); + + CU_ASSERT(response->length == sizeof(teststr)); + CU_ASSERT(response->hdr->version == 1); + CU_ASSERT(response->hdr->type == COAP_MESSAGE_ACK); + CU_ASSERT(response->hdr->token_length == 5); + CU_ASSERT(response->hdr->code == code); + + CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0); +} + +void t_error_response7(void) +{ + const unsigned char code = COAP_RESPONSE_CODE(402); + unsigned char optval[] = + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12 }; + char teststr[] = + { 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', 'n', 0xdd, 0x0a, 0x06, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, + 0x12, 0xff, 'B', 'a', 'd', ' ', 'O', 'p', 't', 'i', 'o', 'n' }; + coap_pdu_t *response; + + coap_pdu_clear(pdu, pdu->max_size); + pdu->hdr->type = COAP_MESSAGE_CON; + coap_add_token(pdu, 5, (unsigned char *) "token"); + /* known option 11 */ + coap_add_option(pdu, 11, 4, (unsigned char *) "time"); + + /* unknown critical option 23 */ + coap_add_option(pdu, 23, sizeof(optval), optval); + + coap_option_filter_clear(opts); + coap_option_setb(opts, 23); + response = coap_new_error_response(pdu, code, opts); + + CU_ASSERT_PTR_NOT_NULL(response); + + CU_ASSERT(response->length == sizeof(teststr)); + CU_ASSERT(response->hdr->version == 1); + CU_ASSERT(response->hdr->type == COAP_MESSAGE_ACK); + CU_ASSERT(response->hdr->token_length == 5); + CU_ASSERT(response->hdr->code == code); + + CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0); +} + +void t_error_response8(void) +{ + const unsigned char code = COAP_RESPONSE_CODE(503); + char teststr[] = + { 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', 'n', 0xe0, 0x02, 0xdc, 0xd0, 0x00, 0xff, 'S', 'e', + 'r', 'v', 'i', 'c', 'e', ' ', 'U', 'n', 'a', 'v', 'a', 'i', 'l', 'a', 'b', 'l', 'e' }; + coap_pdu_t *response; + + coap_pdu_clear(pdu, pdu->max_size); + pdu->hdr->type = COAP_MESSAGE_CON; + coap_add_token(pdu, 5, (unsigned char *) "token"); + /* known option 1000 */ + coap_add_option(pdu, 1000, 0, NULL); + + /* unknown options 1001 and 1014 */ + coap_add_option(pdu, 1001, 0, NULL); + coap_add_option(pdu, 1014, 0, NULL); + + /* known option 2000 */ + coap_add_option(pdu, 2000, 0, NULL); + + coap_option_filter_clear(opts); + coap_option_setb(opts, 1001); + coap_option_setb(opts, 1014); + response = coap_new_error_response(pdu, code, opts); + + CU_ASSERT_PTR_NOT_NULL(response); + + CU_ASSERT(response->length == sizeof(teststr)); + CU_ASSERT(response->hdr->version == 1); + CU_ASSERT(response->hdr->type == COAP_MESSAGE_ACK); + CU_ASSERT(response->hdr->token_length == 5); + CU_ASSERT(response->hdr->code == code); + + CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0); +} + +int t_error_response_tests_create(void) +{ + pdu = coap_pdu_init(0, 0, 0, COAP_MAX_PDU_SIZE); + + return pdu == NULL; +} + +int t_error_response_tests_remove(void) +{ + coap_delete_pdu(pdu); + return 0; +} + +CU_pSuite t_init_error_response_tests(void) +{ + CU_pSuite suite[1]; + + suite[0] = CU_add_suite("error response generator", t_error_response_tests_create, + t_error_response_tests_remove); + if (!suite[0]) + { /* signal error */ + fprintf(stderr, "W: cannot add error response generator test suite (%s)\n", + CU_get_error_msg()); + + return NULL; + } + +#define ERROR_RESPONSE_TEST(s,t) \ + if (!CU_ADD_TEST(s,t)) { \ + fprintf(stderr, "W: cannot add error response generator test (%s)\n", \ + CU_get_error_msg()); \ + } + + ERROR_RESPONSE_TEST(suite[0], t_error_response1); + ERROR_RESPONSE_TEST(suite[0], t_error_response2); + ERROR_RESPONSE_TEST(suite[0], t_error_response3); + ERROR_RESPONSE_TEST(suite[0], t_error_response4); + ERROR_RESPONSE_TEST(suite[0], t_error_response5); + ERROR_RESPONSE_TEST(suite[0], t_error_response6); + ERROR_RESPONSE_TEST(suite[0], t_error_response7); + ERROR_RESPONSE_TEST(suite[0], t_error_response8); + + return suite[0]; +} + diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_error_response.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_error_response.h new file mode 100644 index 000000000..2bab63c90 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_error_response.h @@ -0,0 +1,11 @@ +/* libcoap unit tests + * + * Copyright (C) 2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include + +CU_pSuite t_init_error_response_tests(void); diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_options.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_options.c new file mode 100644 index 000000000..de5b3a69a --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_options.c @@ -0,0 +1,853 @@ +/* libcoap unit tests + * + * Copyright (C) 2012 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include +#include +#include +#include +#include "test_options.h" + +/************************************************************************ + ** decoder tests + ************************************************************************/ + +void t_parse_option1(void) +{ + /* delta == 0, length == 0, value == 0 */ + str teststr = + { 1, (unsigned char *) "" }; + + size_t result; + coap_option_t option; + + /* result = coap_opt_parse(teststr.s, teststr.s + teststr.length, &option); */ + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 1); + CU_ASSERT(option.delta == 0); + CU_ASSERT(option.length == 0); + /* FIXME: value? */ +} + +void t_parse_option2(void) +{ + /* delta == 12, length == 1, value == 0 */ + str teststr = + { 2, (unsigned char *) "\xc1" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 2); + CU_ASSERT(option.delta == 12); + CU_ASSERT(option.length == 1); + CU_ASSERT(option.value == teststr.s + 1); +} + +void t_parse_option3(void) +{ + /* delta == 3, length == 12, value == 0 */ + str teststr = + { 13, (unsigned char *) "\x3c\x00\x01\x02\x03\x04" + "\x05\x06\x07\x08\x09\x0a\x0b" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 13); + CU_ASSERT(option.delta == 3); + CU_ASSERT(option.length == 12); + CU_ASSERT(option.value == teststr.s + 1); + /* CU_ASSERT(memcmp(option.value, teststr.s + 1, 12) == 0); */ +} + +void t_parse_option4(void) +{ + /* delta == 15, length == 3, value == 0 */ + str teststr = + { 2, (unsigned char *) "\xf3" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 0); +} + +void t_parse_option5(void) +{ + /* delta == 3, length == 15, value == 0 */ + str teststr = + { 2, (unsigned char *) "\x3f" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 0); +} + +void t_parse_option6(void) +{ + /* delta == 15, length == 15 */ + str teststr = + { 1, (unsigned char *) "\xff" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 0); +} + +void t_parse_option7(void) +{ + /* delta == 20, length == 0 */ + str teststr = + { 2, (unsigned char *) "\xd0\x07" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 2); + CU_ASSERT(option.delta == 20); + CU_ASSERT(option.length == 0); +} + +void t_parse_option8(void) +{ + /* delta == 780, length == 0 */ + str teststr = + { 3, (unsigned char *) "\xe0\x01\xff" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 3); + CU_ASSERT(option.delta == 780); + CU_ASSERT(option.length == 0); +} + +void t_parse_option9(void) +{ + /* delta == 65535, length == 0 */ + str teststr = + { 3, (unsigned char *) "\xe0\xfe\xf2" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 3); + CU_ASSERT(option.delta == 65535); +} + +void t_parse_option10(void) +{ + /* delta > 65535 (illegal), length == 0 */ + str teststr = + { 3, (unsigned char *) "\xe0\xff\xff" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 0); +} + +void t_parse_option11(void) +{ + /* illegal delta value (option too short) */ + str teststr = + { 1, (unsigned char *) "\xd0" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 0); +} + +void t_parse_option12(void) +{ + /* delta == 280, length == 500 */ + str teststr = + { 3, (unsigned char *) "\xee\xff\x0b" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 0); +} + +void t_parse_option13(void) +{ + /* delta == 280, length == 500 */ + unsigned char _data[505]; + str teststr = + { sizeof(_data), _data }; + teststr.s[0] = 0xee; + teststr.s[1] = 0x00; + teststr.s[2] = 0x0b; + teststr.s[3] = 0x00; + teststr.s[4] = 0xe7; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == sizeof(_data)); + CU_ASSERT(option.delta == 280); + CU_ASSERT(option.length == 500); + CU_ASSERT(option.value == &_data[5]); +} + +void t_parse_option14(void) +{ + /* delta == 268, length == 65535 */ + unsigned char *data; + unsigned int length = 4 + 65535; + + data = (unsigned char *) malloc(length); + if (!data) + { + CU_FAIL("internal error in test framework -- insufficient memory\n"); + return; + } + + data[0] = 0xde; + data[1] = 0xff; + data[2] = 0xfe; + data[3] = 0xf2; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(data, length, &option); + CU_ASSERT(result == length); + CU_ASSERT(option.delta == 268); + CU_ASSERT(option.length == 65535); + CU_ASSERT(option.value == &data[4]); +} + +/************************************************************************ + ** encoder tests + ************************************************************************/ + +void t_encode_option1(void) +{ + char teststr[] = + { 0x00 }; + unsigned char buf[40]; + size_t result; + + result = coap_opt_setheader((coap_opt_t *) buf, sizeof(buf), 0, 0); + CU_ASSERT(result == sizeof(teststr)); + + CU_ASSERT(memcmp(buf, teststr, result) == 0); +} + +void t_encode_option2(void) +{ + char teststr[] = + { 0x5d, 0xff }; + unsigned char buf[40]; + size_t result; + + result = coap_opt_setheader((coap_opt_t *) buf, sizeof(buf), 5, 268); + CU_ASSERT(result == sizeof(teststr)); + + CU_ASSERT(memcmp(buf, teststr, result) == 0); +} + +void t_encode_option3(void) +{ + char teststr[] = + { 0xd1, 0x01 }; + unsigned char buf[40]; + size_t result; + + result = coap_opt_setheader((coap_opt_t *) buf, sizeof(buf), 14, 1); + CU_ASSERT(result == sizeof(teststr)); + + CU_ASSERT(memcmp(buf, teststr, result) == 0); +} + +void t_encode_option4(void) +{ + char teststr[] = + { 0xdd, 0xff, 0xab }; + unsigned char buf[40]; + size_t result; + + result = coap_opt_setheader((coap_opt_t *) buf, sizeof(buf), 268, 184); + CU_ASSERT(result == sizeof(teststr)); + + CU_ASSERT(memcmp(buf, teststr, result) == 0); +} + +void t_encode_option5(void) +{ + char teststr[] = + { 0xed, 0x13, 0x00, 0xff }; + unsigned char buf[40]; + size_t result; + + result = coap_opt_setheader((coap_opt_t *) buf, sizeof(buf), 5133, 268); + CU_ASSERT(result == sizeof(teststr)); + + CU_ASSERT(memcmp(buf, teststr, result) == 0); +} + +void t_encode_option6(void) +{ + char teststr[] = + { 0xee, 0xfe, 0xf2, 0xfe, 0xf2 }; + unsigned char buf[40]; + size_t result; + + result = coap_opt_setheader((coap_opt_t *) buf, sizeof(buf), 65535, 65535); + CU_ASSERT(result == sizeof(teststr)); + + CU_ASSERT(memcmp(buf, teststr, result) == 0); +} + +void t_encode_option7(void) +{ + char teststr[] = + { 0x35, 'v', 'a', 'l', 'u', 'e' }; + const size_t valoff = 1; + unsigned char buf[40]; + size_t result; + + result = coap_opt_encode((coap_opt_t *) buf, sizeof(buf), 3, (unsigned char *) teststr + valoff, + sizeof(teststr) - valoff); + + CU_ASSERT(result == sizeof(teststr)); + + CU_ASSERT(memcmp(buf, teststr, result) == 0); +} + +void t_encode_option8(void) +{ + /* value does not fit in message buffer */ + unsigned char buf[40]; + size_t result; + + result = coap_opt_encode((coap_opt_t *) buf, 8, 15, (unsigned char *) "something", 9); + + CU_ASSERT(result == 0); + + result = coap_opt_encode((coap_opt_t *) buf, 1, 15, (unsigned char *) "something", 9); + + CU_ASSERT(result == 0); +} + +/************************************************************************ + ** accessor tests + ************************************************************************/ + +void t_access_option1(void) +{ + const char teststr[] = + { 0x12, 'a', 'b' }; + + CU_ASSERT(coap_opt_delta((coap_opt_t *) teststr) == 1); + CU_ASSERT(coap_opt_length((coap_opt_t *) teststr) == 2); + CU_ASSERT_PTR_EQUAL(coap_opt_value((coap_opt_t *) teststr), teststr + 1); + CU_ASSERT(coap_opt_size((coap_opt_t *) teststr) == sizeof(teststr)); +} + +void t_access_option2(void) +{ + const char teststr[] = + { 0xe2, 0x18, 0xfd, 'a', 'b' }; + + CU_ASSERT(coap_opt_delta((coap_opt_t *) teststr) == 6666); + CU_ASSERT(coap_opt_length((coap_opt_t *) teststr) == 2); + CU_ASSERT_PTR_EQUAL(coap_opt_value((coap_opt_t *) teststr), teststr + 3); + CU_ASSERT(coap_opt_size((coap_opt_t *) teststr) == sizeof(teststr)); +} + +void t_access_option3(void) +{ + const char teststr[] = + { 0xed, 0x18, 0x0a, 0x00, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm' }; + + CU_ASSERT(coap_opt_delta((coap_opt_t *) teststr) == 6423); + CU_ASSERT(coap_opt_length((coap_opt_t *) teststr) == 13); + CU_ASSERT_PTR_EQUAL(coap_opt_value((coap_opt_t *) teststr), teststr + 4); + CU_ASSERT(coap_opt_size((coap_opt_t *) teststr) == sizeof(teststr)); +} + +void t_access_option4(void) +{ + const char teststr[] = + { 0xde, 0xff, 0xfe, 0xf2, 'a', 'b', 'c' }; + + CU_ASSERT(coap_opt_delta((coap_opt_t *) teststr) == 268); + CU_ASSERT(coap_opt_length((coap_opt_t *) teststr) == 65535); + CU_ASSERT_PTR_EQUAL(coap_opt_value((coap_opt_t *) teststr), teststr + 4); + CU_ASSERT(coap_opt_size((coap_opt_t *) teststr) == 65535 + 4); +} + +void t_access_option5(void) +{ + const char teststr[] = + { 0xee, 0xfe, 0xf2, 0x00, 0xdd, 'a', 'b', 'c' }; + + CU_ASSERT(coap_opt_delta((coap_opt_t *) teststr) == 65535); + CU_ASSERT(coap_opt_length((coap_opt_t *) teststr) == 490); + CU_ASSERT_PTR_EQUAL(coap_opt_value((coap_opt_t *) teststr), teststr + 5); + CU_ASSERT(coap_opt_size((coap_opt_t *) teststr) == 495); +} + +void t_access_option6(void) +{ + const char teststr[] = + { 0xf2, 'a', 'b' }; + + CU_ASSERT(coap_opt_delta((coap_opt_t *) teststr) == 0); + CU_ASSERT(coap_opt_length((coap_opt_t *) teststr) == 0); + CU_ASSERT_PTR_EQUAL(coap_opt_value((coap_opt_t *) teststr), NULL); + CU_ASSERT(coap_opt_size((coap_opt_t *) teststr) == 0); +} + +void t_access_option7(void) +{ + const char teststr[] = + { 0x2f, 'a', 'b' }; + + CU_ASSERT(coap_opt_delta((coap_opt_t *) teststr) == 2); + CU_ASSERT(coap_opt_length((coap_opt_t *) teststr) == 0); + CU_ASSERT_PTR_EQUAL(coap_opt_value((coap_opt_t *) teststr), NULL); + CU_ASSERT(coap_opt_size((coap_opt_t *) teststr) == 0); +} + +/************************************************************************ + ** accessor tests + ************************************************************************/ + +#define TEST_MAX_SIZE 1000 + +void t_iterate_option1(void) +{ + /* CoAP PDU without token, options, or data */ + char teststr[] __attribute__ ((aligned (8))) = + { 0x00, 0x00, 0x00, 0x00 }; + + coap_pdu_t pdu = + { .max_size = TEST_MAX_SIZE, .hdr = (coap_hdr_t *) teststr, .length = sizeof(teststr) }; + coap_opt_iterator_t oi, *result; + coap_opt_t *option; + + result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL); + + CU_ASSERT(result == NULL); + CU_ASSERT(oi.bad == 1); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT(option == NULL); +} + +void t_iterate_option2(void) +{ + /* CoAP PDU with token but without options and data */ + char teststr[] __attribute__ ((aligned (8))) = + { 0x03, 0x00, 0x00, 0x00, 't', 'o', 'k' }; + + coap_pdu_t pdu = + { .max_size = TEST_MAX_SIZE, .hdr = (coap_hdr_t *) teststr, .length = sizeof(teststr) }; + coap_opt_iterator_t oi, *result; + coap_opt_t *option; + + result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL); + + CU_ASSERT(result == NULL); + CU_ASSERT(oi.bad == 1); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT(option == NULL); +} + +void t_iterate_option3(void) +{ + /* CoAP PDU with token and options */ + char teststr[] __attribute__ ((aligned (8))) = + { 0x03, 0x00, 0x00, 0x00, 't', 'o', 'k', 0x13, 'o', 'p', 't', 0x00, 0xd1, 0x10, 'x' }; + + coap_pdu_t pdu = + { .max_size = TEST_MAX_SIZE, .hdr = (coap_hdr_t *) teststr, .length = sizeof(teststr) }; + coap_opt_iterator_t oi, *result; + coap_opt_t *option; + + result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL); + + CU_ASSERT_PTR_EQUAL(result, &oi); + CU_ASSERT(oi.bad == 0); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.type == 1); + CU_ASSERT_PTR_EQUAL(option, teststr + 7); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.type == 1); + CU_ASSERT_PTR_EQUAL(option, teststr + 11); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.type == 30); + CU_ASSERT_PTR_EQUAL(option, teststr + 12); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT_PTR_EQUAL(option, NULL); +} + +void t_iterate_option4(void) +{ + /* CoAP PDU with token, options, and data */ + char teststr[] __attribute__ ((aligned (8))) = + { 0x03, 0x00, 0x00, 0x00, 't', 'o', 'k', 0x13, 'o', 'p', 't', 0x00, 0xd1, 0x10, 'x', 0xff, 'd', + 'a', 't', 'a' }; + + coap_pdu_t pdu = + { .max_size = TEST_MAX_SIZE, .hdr = (coap_hdr_t *) teststr, .length = sizeof(teststr) }; + coap_opt_iterator_t oi, *result; + coap_opt_t *option; + + result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL); + + CU_ASSERT_PTR_EQUAL(result, &oi); + CU_ASSERT(oi.bad == 0); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.type == 1); + CU_ASSERT_PTR_EQUAL(option, teststr + 7); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.type == 1); + CU_ASSERT_PTR_EQUAL(option, teststr + 11); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.type == 30); + CU_ASSERT_PTR_EQUAL(option, teststr + 12); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT_PTR_EQUAL(option, NULL); +} + +void t_iterate_option5(void) +{ + /* CoAP PDU with malformed option */ + char teststr[] __attribute__ ((aligned (8))) = + { 0x00, 0x00, 0x00, 0x00, 0x52, 'o', 'p', 0xee, 0x12, 0x03, 0x00 }; + + coap_pdu_t pdu = + { .max_size = TEST_MAX_SIZE, .hdr = (coap_hdr_t *) teststr, .length = sizeof(teststr) }; + coap_opt_iterator_t oi, *result; + coap_opt_t *option; + + result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL); + + CU_ASSERT_PTR_EQUAL(result, &oi); + CU_ASSERT(oi.bad == 0); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.type == 5); + CU_ASSERT_PTR_EQUAL(option, teststr + 4); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT_PTR_EQUAL(option, NULL); +} + +void t_iterate_option6(void) +{ + /* option filter */ + /* CoAP PDU with token, options, and data */ + char teststr[] __attribute__ ((aligned (8))) = + { 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0xc0, 0x00 }; + + coap_pdu_t pdu = + { .max_size = TEST_MAX_SIZE, .hdr = (coap_hdr_t *) teststr, .length = sizeof(teststr) }; + coap_opt_iterator_t oi, *result; + coap_opt_t *option; + coap_opt_filter_t filter; + + coap_option_filter_clear(filter); + coap_option_setb(filter, 10); /* option nr 10 only */ + result = coap_option_iterator_init(&pdu, &oi, filter); + + CU_ASSERT_PTR_EQUAL(result, &oi); + CU_ASSERT(oi.bad == 0); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.type == 10); + CU_ASSERT_PTR_EQUAL(option, teststr + 5); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.type == 10); + CU_ASSERT_PTR_EQUAL(option, teststr + 6); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.type == 10); + CU_ASSERT_PTR_EQUAL(option, teststr + 7); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT_PTR_EQUAL(option, NULL); +} + +void t_iterate_option7(void) +{ + /* option filter */ + char teststr[] __attribute__ ((aligned (8))) = + { 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0xc0, 0x00, 0x10, 0x10, 0x00 }; + + coap_pdu_t pdu = + { .max_size = TEST_MAX_SIZE, .hdr = (coap_hdr_t *) teststr, .length = sizeof(teststr) }; + coap_opt_iterator_t oi, *result; + coap_opt_t *option; + coap_opt_filter_t filter; + + /* search options nr 8 and 22 */ + coap_option_filter_clear(filter); + coap_option_setb(filter, 8); + coap_option_setb(filter, 22); + result = coap_option_iterator_init(&pdu, &oi, filter); + + CU_ASSERT_PTR_EQUAL(result, &oi); + CU_ASSERT(oi.bad == 0); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.type == 8); + CU_ASSERT_PTR_EQUAL(option, teststr + 4); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.type == 22); + CU_ASSERT_PTR_EQUAL(option, teststr + 8); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.type == 22); + CU_ASSERT_PTR_EQUAL(option, teststr + 9); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT_PTR_EQUAL(option, NULL); +} + +void t_iterate_option8(void) +{ + /* option filter */ + char teststr[] __attribute__ ((aligned (8))) = + { 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0xc0, 0x00, 0x10, 0x10, 0x00 }; + + coap_pdu_t pdu = + { .max_size = TEST_MAX_SIZE, .hdr = (coap_hdr_t *) teststr, .length = sizeof(teststr) }; + coap_opt_iterator_t oi, *result; + coap_opt_t *option; + coap_opt_filter_t filter; + + /* search option nr 36 */ + coap_option_filter_clear(filter); + coap_option_setb(filter, 36); + result = coap_option_iterator_init(&pdu, &oi, filter); + + CU_ASSERT_PTR_EQUAL(result, &oi); + CU_ASSERT(oi.bad == 0); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT_PTR_EQUAL(option, NULL); +} + +void t_iterate_option9(void) +{ + /* options filter: option number too large for filter */ + char teststr[] __attribute__ ((aligned (8))) = + { 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0xc0, 0x00, 0x10, 0x10, 0x00 }; + + coap_pdu_t pdu = + { .max_size = TEST_MAX_SIZE, .hdr = (coap_hdr_t *) teststr, .length = sizeof(teststr) }; + coap_opt_iterator_t oi, *result; + coap_opt_t *option; + coap_opt_filter_t filter; + + /* search option nr 100 */ + coap_option_filter_clear(filter); + coap_option_setb(filter, 100); + result = coap_option_iterator_init(&pdu, &oi, filter); + + CU_ASSERT_PTR_EQUAL(result, &oi); + CU_ASSERT(oi.bad == 0); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT_PTR_EQUAL(option, NULL); +} + +void t_iterate_option10(void) +{ + /* options filter: option numbers in PDU exceed filter size */ + char teststr[] __attribute__ ((aligned (8))) = + { 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0xd0, 0x26, 0xe0, 0x10, 0x00 }; + + coap_pdu_t pdu = + { .max_size = TEST_MAX_SIZE, .hdr = (coap_hdr_t *) teststr, .length = sizeof(teststr) }; + coap_opt_iterator_t oi, *result; + coap_opt_t *option; + coap_opt_filter_t filter; + + /* search option nr 61 */ + coap_option_filter_clear(filter); + coap_option_setb(filter, 61); + result = coap_option_iterator_init(&pdu, &oi, filter); + + CU_ASSERT_PTR_EQUAL(result, &oi); + CU_ASSERT(oi.bad == 0); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT_PTR_EQUAL(option, teststr + 8); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT_PTR_EQUAL(option, NULL); +} + +/************************************************************************ + ** initialization + ************************************************************************/ + +CU_pSuite t_init_option_tests(void) +{ + CU_pSuite suite[4]; + + suite[0] = CU_add_suite("option parser", NULL, NULL); + if (!suite[0]) + { /* signal error */ + fprintf(stderr, "W: cannot add option parser test suite (%s)\n", CU_get_error_msg()); + + return NULL; + } + +#define OPTION_TEST(n,s) \ + if (!CU_add_test(suite[0], s, t_parse_option##n)) { \ + fprintf(stderr, "W: cannot add option parser test (%s)\n", \ + CU_get_error_msg()); \ + } + + OPTION_TEST(1, "parse option #1"); + OPTION_TEST(2, "parse option #2"); + OPTION_TEST(3, "parse option #3"); + OPTION_TEST(4, "parse option #4"); + OPTION_TEST(5, "parse option #5"); + OPTION_TEST(6, "parse option #6"); + OPTION_TEST(7, "parse option #7"); + OPTION_TEST(8, "parse option #8"); + OPTION_TEST(9, "parse option #9"); + OPTION_TEST(10, "parse option #10"); + OPTION_TEST(11, "parse option #11"); + OPTION_TEST(12, "parse option #12"); + OPTION_TEST(13, "parse option #13"); + OPTION_TEST(14, "parse option #14"); + + if ((suite[1] = CU_add_suite("option encoder", NULL, NULL))) + { +#define OPTION_ENCODER_TEST(n,s) \ + if (!CU_add_test(suite[1], s, t_encode_option##n)) { \ + fprintf(stderr, "W: cannot add option encoder test (%s)\n", \ + CU_get_error_msg()); \ + } + + OPTION_ENCODER_TEST(1, "encode option #1"); + OPTION_ENCODER_TEST(2, "encode option #2"); + OPTION_ENCODER_TEST(3, "encode option #3"); + OPTION_ENCODER_TEST(4, "encode option #4"); + OPTION_ENCODER_TEST(5, "encode option #5"); + OPTION_ENCODER_TEST(6, "encode option #6"); + OPTION_ENCODER_TEST(7, "encode option #7"); + OPTION_ENCODER_TEST(8, "encode option #8"); + + } + else + { + fprintf(stderr, "W: cannot add option encoder test suite (%s)\n", CU_get_error_msg()); + } + + if ((suite[2] = CU_add_suite("option accessors", NULL, NULL))) + { +#define OPTION_ACCESSOR_TEST(n,s) \ + if (!CU_add_test(suite[2], s, t_access_option##n)) { \ + fprintf(stderr, "W: cannot add option accessor function test (%s)\n", \ + CU_get_error_msg()); \ + } + + OPTION_ACCESSOR_TEST(1, "access option #1"); + OPTION_ACCESSOR_TEST(2, "access option #2"); + OPTION_ACCESSOR_TEST(3, "access option #3"); + OPTION_ACCESSOR_TEST(4, "access option #4"); + OPTION_ACCESSOR_TEST(5, "access option #5"); + OPTION_ACCESSOR_TEST(6, "access option #6"); + OPTION_ACCESSOR_TEST(7, "access option #7"); + + } + else + { + fprintf(stderr, "W: cannot add option acessor function test suite (%s)\n", + CU_get_error_msg()); + } + + if ((suite[3] = CU_add_suite("option iterator", NULL, NULL))) + { +#define OPTION_ITERATOR_TEST(n,s) \ + if (!CU_add_test(suite[3], s, t_iterate_option##n)) { \ + fprintf(stderr, "W: cannot add option iterator test (%s)\n", \ + CU_get_error_msg()); \ + } + + OPTION_ITERATOR_TEST(1, "option iterator #1"); + OPTION_ITERATOR_TEST(2, "option iterator #2"); + OPTION_ITERATOR_TEST(3, "option iterator #3"); + OPTION_ITERATOR_TEST(4, "option iterator #4"); + OPTION_ITERATOR_TEST(5, "option iterator #5"); + OPTION_ITERATOR_TEST(6, "option iterator #6"); + OPTION_ITERATOR_TEST(7, "option iterator #7"); + OPTION_ITERATOR_TEST(8, "option iterator #8"); + OPTION_ITERATOR_TEST(9, "option iterator #9"); + OPTION_ITERATOR_TEST(10, "option iterator #10"); + + } + else + { + fprintf(stderr, "W: cannot add option iterator test suite (%s)\n", CU_get_error_msg()); + } + + return suite[0]; +} + diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_options.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_options.h new file mode 100644 index 000000000..3ffcefe3e --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_options.h @@ -0,0 +1,11 @@ +/* libcoap unit tests + * + * Copyright (C) 2012 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include + +CU_pSuite t_init_option_tests(void); diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_pdu.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_pdu.c new file mode 100644 index 000000000..2592a324d --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_pdu.c @@ -0,0 +1,660 @@ +/* libcoap unit tests + * + * Copyright (C) 2012 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include +#include +#include +#include +#include +#include "test_pdu.h" + +coap_pdu_t *pdu; /* Holds the parsed PDU for most tests */ + +/************************************************************************ + ** PDU decoder + ************************************************************************/ + +void t_parse_pdu1(void) +{ + char teststr[] = + { 0x40, 0x01, 0x93, 0x34 }; + int result; + + result = coap_pdu_parse((unsigned char *) teststr, sizeof(teststr), pdu); + CU_ASSERT(result > 0); + + CU_ASSERT(pdu->length == sizeof(teststr)); + CU_ASSERT(pdu->hdr->version == 1); + CU_ASSERT(pdu->hdr->type == COAP_MESSAGE_CON); + CU_ASSERT(pdu->hdr->token_length == 0); + CU_ASSERT(pdu->hdr->code == COAP_REQUEST_GET); + CU_ASSERT(memcmp(&pdu->hdr->id, teststr + 2, 2) == 0); + CU_ASSERT_PTR_NULL(pdu->data); +} + +void t_parse_pdu2(void) +{ + char teststr[] = + { 0x55, 0x69, 0x12, 0x34, 't', 'o', 'k', 'e', 'n' }; + int result; + + result = coap_pdu_parse((unsigned char *) teststr, sizeof(teststr), pdu); + CU_ASSERT(result > 0); + + CU_ASSERT(pdu->length == sizeof(teststr)); + CU_ASSERT(pdu->hdr->version == 1); + CU_ASSERT(pdu->hdr->type == COAP_MESSAGE_NON); + CU_ASSERT(pdu->hdr->token_length == 5); + CU_ASSERT(pdu->hdr->code == 0x69); + CU_ASSERT(memcmp(&pdu->hdr->id, teststr + 2, 2) == 0); + CU_ASSERT(memcmp(pdu->hdr->token, teststr + 4, 5) == 0); + CU_ASSERT_PTR_NULL(pdu->data); +} + +void t_parse_pdu3(void) +{ + char teststr[] = + { 0x53, 0x69, 0x12, 0x34, 't', 'o', 'k', 'e', 'n' }; + int result; + + result = coap_pdu_parse((unsigned char *) teststr, sizeof(teststr), pdu); + CU_ASSERT(result == 0); +} + +void t_parse_pdu4(void) +{ + /* illegal token length */ + char teststr[] = + { 0x59, 0x69, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', '1', '2', '3', '4' }; + int result; + + result = coap_pdu_parse((unsigned char *) teststr, sizeof(teststr), pdu); + CU_ASSERT(result == 0); + + teststr[0] = 0x5f; + + result = coap_pdu_parse((unsigned char *) teststr, sizeof(teststr), pdu); + CU_ASSERT(result == 0); +} + +void t_parse_pdu5(void) +{ + /* PDU with options */ + char teststr[] = + { 0x55, 0x73, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0x00, 0xc1, 0x00 }; + int result; + + result = coap_pdu_parse((unsigned char *) teststr, sizeof(teststr), pdu); + CU_ASSERT(result > 0); + + CU_ASSERT(pdu->length == sizeof(teststr)); + CU_ASSERT(pdu->hdr->version == 1); + CU_ASSERT(pdu->hdr->type == COAP_MESSAGE_NON); + CU_ASSERT(pdu->hdr->token_length == 5); + CU_ASSERT(pdu->hdr->code == 0x73); + CU_ASSERT(memcmp(&pdu->hdr->id, teststr + 2, 2) == 0); + CU_ASSERT(memcmp(pdu->hdr->token, teststr + 4, 5) == 0); + CU_ASSERT_PTR_NULL(pdu->data); + + /* FIXME: check options */ +} + +void t_parse_pdu6(void) +{ + /* PDU with options that exceed the PDU */ + char teststr[] = + { 0x55, 0x73, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0x00, 0xc1, 0x00, 0xae, 0xf0, 0x03 }; + int result; + + result = coap_pdu_parse((unsigned char *) teststr, sizeof(teststr), pdu); + CU_ASSERT(result == 0); +} + +void t_parse_pdu7(void) +{ + /* PDU with options and payload */ + char teststr[] = + { 0x55, 0x73, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0x00, 0xc1, 0x00, 0xff, 'p', 'a', 'y', 'l', + 'o', 'a', 'd' }; + int result; + + result = coap_pdu_parse((unsigned char *) teststr, sizeof(teststr), pdu); + CU_ASSERT(result > 0); + + CU_ASSERT(pdu->length == sizeof(teststr)); + CU_ASSERT(pdu->hdr->version == 1); + CU_ASSERT(pdu->hdr->type == COAP_MESSAGE_NON); + CU_ASSERT(pdu->hdr->token_length == 5); + CU_ASSERT(pdu->hdr->code == 0x73); + CU_ASSERT(memcmp(&pdu->hdr->id, teststr + 2, 2) == 0); + CU_ASSERT(memcmp(pdu->hdr->token, teststr + 4, 5) == 0); + + /* FIXME: check options */ + + CU_ASSERT(pdu->data == (unsigned char *) pdu->hdr + 13); + CU_ASSERT(memcmp(pdu->data, teststr + 13, 7) == 0); +} + +void t_parse_pdu8(void) +{ + /* PDU without options but with payload */ + char teststr[] = + { 0x50, 0x73, 0x12, 0x34, 0xff, 'p', 'a', 'y', 'l', 'o', 'a', 'd' }; + int result; + + result = coap_pdu_parse((unsigned char *) teststr, sizeof(teststr), pdu); + CU_ASSERT(result > 0); + + CU_ASSERT(pdu->length == sizeof(teststr)); + CU_ASSERT(pdu->hdr->version == 1); + CU_ASSERT(pdu->hdr->type == COAP_MESSAGE_NON); + CU_ASSERT(pdu->hdr->token_length == 0); + CU_ASSERT(pdu->hdr->code == 0x73); + CU_ASSERT(memcmp(&pdu->hdr->id, teststr + 2, 2) == 0); + + /* FIXME: check options */ + + CU_ASSERT(pdu->data == (unsigned char *) pdu->hdr + 5); + CU_ASSERT(memcmp(pdu->data, teststr + 5, 7) == 0); +} + +void t_parse_pdu9(void) +{ + /* PDU without options and payload but with payload start marker */ + char teststr[] = + { 0x70, 0x00, 0x12, 0x34, 0xff }; + int result; + + result = coap_pdu_parse((unsigned char *) teststr, sizeof(teststr), pdu); + CU_ASSERT(result == 0); +} + +void t_parse_pdu10(void) +{ + /* PDU without payload but with options and payload start marker */ + char teststr[] = + { 0x53, 0x73, 0x12, 0x34, 't', 'o', 'k', 0x30, 0xc1, 0x00, 0xff }; + int result; + + result = coap_pdu_parse((unsigned char *) teststr, sizeof(teststr), pdu); + CU_ASSERT(result == 0); +} + +void t_parse_pdu11(void) +{ + char teststr[] = + { 0x60, 0x00, 0x12, 0x34 }; + int result; + + result = coap_pdu_parse((unsigned char *) teststr, sizeof(teststr), pdu); + CU_ASSERT(result > 0); + + CU_ASSERT(pdu->length == sizeof(teststr)); + CU_ASSERT(pdu->hdr->version == 1); + CU_ASSERT(pdu->hdr->type == COAP_MESSAGE_ACK); + CU_ASSERT(pdu->hdr->token_length == 0); + CU_ASSERT(pdu->hdr->code == 0); + CU_ASSERT(memcmp(&pdu->hdr->id, teststr + 2, 2) == 0); +} + +void t_parse_pdu12(void) +{ + /* RST */ + char teststr[] = + { 0x70, 0x00, 0x12, 0x34 }; + int result; + + result = coap_pdu_parse((unsigned char *) teststr, sizeof(teststr), pdu); + CU_ASSERT(result > 0); + + CU_ASSERT(pdu->length == sizeof(teststr)); + CU_ASSERT(pdu->hdr->version == 1); + CU_ASSERT(pdu->hdr->type == COAP_MESSAGE_RST); + CU_ASSERT(pdu->hdr->token_length == 0); + CU_ASSERT(pdu->hdr->code == 0); + CU_ASSERT(memcmp(&pdu->hdr->id, teststr + 2, 2) == 0); +} + +void t_parse_pdu13(void) +{ + /* RST with content */ + char teststr[] = + { 0x70, 0x00, 0x12, 0x34, 0xff, 'c', 'o', 'n', 't', 'e', 'n', 't' }; + int result; + + result = coap_pdu_parse((unsigned char *) teststr, sizeof(teststr), pdu); + CU_ASSERT(result == 0); +} + +void t_parse_pdu14(void) +{ + /* ACK with content */ + char teststr[] = + { 0x60, 0x00, 0x12, 0x34, 0xff, 'c', 'o', 'n', 't', 'e', 'n', 't' }; + int result; + + result = coap_pdu_parse((unsigned char *) teststr, sizeof(teststr), pdu); + CU_ASSERT(result == 0); +} + +/************************************************************************ + ** PDU encoder + ************************************************************************/ + +void t_encode_pdu1(void) +{ + char teststr[] = + { 0x45, 0x01, 0x12, 0x34, 't', 'o', 'k', 'e', 'n' }; + int result; + + coap_pdu_clear(pdu, pdu->max_size); + pdu->hdr->type = COAP_MESSAGE_CON; + pdu->hdr->code = COAP_REQUEST_GET; + pdu->hdr->id = htons(0x1234); + + result = coap_add_token(pdu, 5, (unsigned char *) "token"); + + CU_ASSERT(result == 1); + CU_ASSERT(pdu->length = sizeof(teststr)); + CU_ASSERT_PTR_NULL(pdu->data); + CU_ASSERT(memcmp(pdu->hdr, teststr, sizeof(teststr)) == 0); +} + +void t_encode_pdu2(void) +{ + size_t old_max = pdu->max_size; + int result; + + coap_pdu_clear(pdu, 7); /* set very small PDU size */ + + pdu->hdr->type = COAP_MESSAGE_CON; + pdu->hdr->code = COAP_REQUEST_GET; + pdu->hdr->id = htons(0x1234); + + result = coap_add_token(pdu, 5, (unsigned char *) "token"); + + CU_ASSERT(result == 0); + + coap_pdu_clear(pdu, old_max); /* restore PDU size */ +} + +void t_encode_pdu3(void) +{ + int result; + + result = coap_add_token(pdu, 9, (unsigned char *) "123456789"); + + CU_ASSERT(result == 0); +} + +void t_encode_pdu4(void) +{ + /* PDU with options */ + char teststr[] = + { 0x60, 0x99, 0x12, 0x34, 0x3d, 0x05, 0x66, 0x61, 0x6e, 0x63, 0x79, 0x70, 0x72, 0x6f, 0x78, + 0x79, 0x2e, 0x63, 0x6f, 0x61, 0x70, 0x2e, 0x6d, 0x65, 0x84, 0x70, 0x61, 0x74, 0x68, + 0x00, 0xe8, 0x1e, 0x28, 0x66, 0x61, 0x6e, 0x63, 0x79, 0x6f, 0x70, 0x74 }; + int result; + + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + pdu->hdr->type = COAP_MESSAGE_ACK; + pdu->hdr->code = 0x99; + pdu->hdr->id = htons(0x1234); + + CU_ASSERT(pdu->length == 4); + + result = coap_add_option(pdu, COAP_OPTION_URI_HOST, 18, (unsigned char *) "fancyproxy.coap.me"); + + CU_ASSERT(result == 20); + CU_ASSERT(pdu->max_delta == 3); + CU_ASSERT(pdu->length == 24); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_option(pdu, COAP_OPTION_URI_PATH, 4, (unsigned char *) "path"); + + CU_ASSERT(result == 5); + CU_ASSERT(pdu->max_delta == 11); + CU_ASSERT(pdu->length == 29); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_option(pdu, COAP_OPTION_URI_PATH, 0, NULL); + + CU_ASSERT(result == 1); + CU_ASSERT(pdu->max_delta == 11); + CU_ASSERT(pdu->length == 30); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_option(pdu, 8000, 8, (unsigned char *) "fancyopt"); + + CU_ASSERT(result == 11); + CU_ASSERT(pdu->max_delta == 8000); + CU_ASSERT(pdu->length == 41); + CU_ASSERT_PTR_NULL(pdu->data); + + CU_ASSERT(pdu->length == sizeof(teststr)); + CU_ASSERT(memcmp(pdu->hdr, teststr, sizeof(teststr)) == 0); +} + +void t_encode_pdu5(void) +{ + /* PDU with token and options */ + char teststr[] = + { 0x68, 0x84, 0x12, 0x34, '1', '2', '3', '4', '5', '6', '7', '8', 0x18, 0x41, 0x42, 0x43, 0x44, + 0x45, 0x46, 0x47, 0x48, 0xd1, 0x03, 0x12 }; + int result; + + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + pdu->hdr->type = COAP_MESSAGE_ACK; + pdu->hdr->code = COAP_RESPONSE_CODE(404); + pdu->hdr->id = htons(0x1234); + + CU_ASSERT(pdu->length == 4); + + result = coap_add_token(pdu, 8, (unsigned char *) "12345678"); + + CU_ASSERT(pdu->length == 12); + + result = coap_add_option(pdu, COAP_OPTION_IF_MATCH, 8, (unsigned char *) "ABCDEFGH"); + + CU_ASSERT(result == 9); + CU_ASSERT(pdu->max_delta == 1); + CU_ASSERT(pdu->length == 21); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_option(pdu, COAP_OPTION_ACCEPT, 1, (unsigned char *) "\x12"); + + CU_ASSERT(result == 3); + CU_ASSERT(pdu->max_delta == 17); + CU_ASSERT(pdu->length == 24); + CU_ASSERT_PTR_NULL(pdu->data); + + CU_ASSERT(pdu->length == sizeof(teststr)); + CU_ASSERT(memcmp(pdu->hdr, teststr, sizeof(teststr)) == 0); +} + +void t_encode_pdu6(void) +{ + /* PDU with data */ + char teststr[] = + { 0x50, 0x02, 0x12, 0x34, 0xff, '1', '2', '3', '4', '5', '6', '7', '8' }; + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + pdu->hdr->type = COAP_MESSAGE_NON; + pdu->hdr->code = COAP_REQUEST_POST; + pdu->hdr->id = htons(0x1234); + + CU_ASSERT(pdu->length == 4); + CU_ASSERT_PTR_NULL(pdu->data); + + coap_add_data(pdu, 8, (unsigned char *) "12345678"); + + CU_ASSERT(pdu->length == sizeof(teststr)); + CU_ASSERT(memcmp(pdu->hdr, teststr, sizeof(teststr)) == 0); +} + +void t_encode_pdu7(void) +{ + /* PDU with empty data */ + char teststr[] = + { 0x40, 0x43, 0x12, 0x34 }; + int result; + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + pdu->hdr->type = COAP_MESSAGE_CON; + pdu->hdr->code = COAP_RESPONSE_CODE(203); + pdu->hdr->id = htons(0x1234); + + CU_ASSERT(pdu->length == 4); + + result = coap_add_data(pdu, 0, NULL); + + CU_ASSERT(result > 0); + CU_ASSERT(pdu->length == 4); + CU_ASSERT_PTR_NULL(pdu->data); + + CU_ASSERT(pdu->length == sizeof(teststr)); + CU_ASSERT(memcmp(pdu->hdr, teststr, sizeof(teststr)) == 0); +} + +void t_encode_pdu8(void) +{ + /* PDU with token and data */ + char teststr[] = + { 0x42, 0x43, 0x12, 0x34, 0x00, 0x01, 0xff, 0x00 }; + int result; + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + pdu->hdr->type = COAP_MESSAGE_CON; + pdu->hdr->code = COAP_RESPONSE_CODE(203); + pdu->hdr->id = htons(0x1234); + + CU_ASSERT(pdu->length == 4); + + result = coap_add_token(pdu, 2, (unsigned char *) "\x00\x01"); + + CU_ASSERT(result > 0); + + result = coap_add_data(pdu, 1, (unsigned char *) "\0"); + + CU_ASSERT(result > 0); + CU_ASSERT(pdu->length == 8); + CU_ASSERT(pdu->data == (unsigned char *) pdu->hdr + 7); + + CU_ASSERT(pdu->length == sizeof(teststr)); + CU_ASSERT(memcmp(pdu->hdr, teststr, sizeof(teststr)) == 0); +} + +void t_encode_pdu9(void) +{ + /* PDU with options and data */ + char teststr[] = + { 0x60, 0x44, 0x12, 0x34, 0x48, 's', 'o', 'm', 'e', 'e', 't', 'a', 'g', 0x10, 0xdd, 0x11, 0x04, + 's', 'o', 'm', 'e', 'r', 'a', 't', 'h', 'e', 'r', 'l', 'o', 'n', 'g', 'u', 'r', 'i', + 0xff, 'd', 'a', 't', 'a' }; + int result; + + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + pdu->hdr->type = COAP_MESSAGE_ACK; + pdu->hdr->code = COAP_RESPONSE_CODE(204); + pdu->hdr->id = htons(0x1234); + + CU_ASSERT(pdu->length == 4); + + result = coap_add_option(pdu, COAP_OPTION_ETAG, 8, (unsigned char *) "someetag"); + + CU_ASSERT(result == 9); + CU_ASSERT(pdu->max_delta == 4); + CU_ASSERT(pdu->length == 13); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_option(pdu, COAP_OPTION_IF_NONE_MATCH, 0, NULL); + + CU_ASSERT(result == 1); + CU_ASSERT(pdu->max_delta == 5); + CU_ASSERT(pdu->length == 14); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_option(pdu, COAP_OPTION_PROXY_URI, 17, (unsigned char *) "someratherlonguri"); + + CU_ASSERT(result == 20); + CU_ASSERT(pdu->max_delta == 35); + CU_ASSERT(pdu->length == 34); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_data(pdu, 4, (unsigned char *) "data"); + + CU_ASSERT(result > 0); + CU_ASSERT(pdu->length == 39); + CU_ASSERT(pdu->data == (unsigned char *) pdu->hdr + 35); + + CU_ASSERT(pdu->length == sizeof(teststr)); + CU_ASSERT(memcmp(pdu->hdr, teststr, sizeof(teststr)) == 0); +} + +void t_encode_pdu10(void) +{ + /* PDU with token, options and data */ + char teststr[] = + { 0x62, 0x44, 0x12, 0x34, 0x00, 0x00, 0x8d, 0xf2, 'c', 'o', 'a', 'p', ':', '/', '/', 'e', 'x', + 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm', '/', '1', '2', '3', '4', '5', '/', '%', + '3', 'F', 'x', 'y', 'z', '/', '3', '0', '4', '8', '2', '3', '4', '2', '3', '4', '/', + '2', '3', '4', '0', '2', '3', '4', '8', '2', '3', '4', '/', '2', '3', '9', '0', '8', + '4', '2', '3', '4', '-', '2', '3', '/', '%', 'A', 'B', '%', '3', '0', '%', 'a', 'f', + '/', '+', '1', '2', '3', '/', 'h', 'f', 'k', 's', 'd', 'h', '/', '2', '3', '4', '8', + '0', '-', '2', '3', '4', '-', '9', '8', '2', '3', '5', '/', '1', '2', '0', '4', '/', + '2', '4', '3', '5', '4', '6', '3', '4', '5', '3', '4', '5', '2', '4', '3', '/', '0', + '1', '9', '8', 's', 'd', 'n', '3', '-', 'a', '-', '3', '/', '/', '/', 'a', 'f', 'f', + '0', '9', '3', '4', '/', '9', '7', 'u', '2', '1', '4', '1', '/', '0', '0', '0', '2', + '/', '3', '9', '3', '2', '4', '2', '3', '5', '3', '2', '/', '5', '6', '2', '3', '4', + '0', '2', '3', '/', '-', '-', '-', '-', '/', '=', '1', '2', '3', '4', '=', '/', '0', + '9', '8', '1', '4', '1', '-', '9', '5', '6', '4', '6', '4', '3', '/', '2', '1', '9', + '7', '0', '-', '-', '-', '-', '-', '/', '8', '2', '3', '6', '4', '9', '2', '3', '4', + '7', '2', 'w', 'e', 'r', 'e', 'r', 'e', 'w', 'r', '0', '-', '9', '2', '1', '-', '3', + '9', '1', '2', '3', '-', '3', '4', '/', 0x0d, 0x01, '/', '/', '4', '9', '2', '4', '0', + '3', '-', '-', '0', '9', '8', '/', 0xc1, '*', 0xff, 'd', 'a', 't', 'a' }; + int result; + + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + pdu->hdr->type = COAP_MESSAGE_ACK; + pdu->hdr->code = COAP_RESPONSE_CODE(204); + pdu->hdr->id = htons(0x1234); + + CU_ASSERT(pdu->length == 4); + + result = coap_add_token(pdu, 2, (unsigned char *) "\0\0"); + + CU_ASSERT(result > 0); + result = + coap_add_option(pdu, COAP_OPTION_LOCATION_PATH, 255, + (unsigned char *) "coap://example.com/12345/%3Fxyz/3048234234/23402348234/239084234-23/%AB%30%af/+123/hfksdh/23480-234-98235/1204/243546345345243/0198sdn3-a-3///aff0934/97u2141/0002/3932423532/56234023/----/=1234=/098141-9564643/21970-----/82364923472wererewr0-921-39123-34/"); + + CU_ASSERT(result == 257); + CU_ASSERT(pdu->max_delta == 8); + CU_ASSERT(pdu->length == 263); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_option(pdu, COAP_OPTION_LOCATION_PATH, 14, + (unsigned char *) "//492403--098/"); + + CU_ASSERT(result == 16); + CU_ASSERT(pdu->max_delta == 8); + CU_ASSERT(pdu->length == 279); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_option(pdu, COAP_OPTION_LOCATION_QUERY, 1, (unsigned char *) "*"); + + CU_ASSERT(result == 2); + CU_ASSERT(pdu->max_delta == 20); + CU_ASSERT(pdu->length == 281); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_data(pdu, 4, (unsigned char *) "data"); + + CU_ASSERT(result > 0); + CU_ASSERT(pdu->length == 286); + CU_ASSERT(pdu->data == (unsigned char *) pdu->hdr + 282); + + CU_ASSERT(pdu->length == sizeof(teststr)); + CU_ASSERT(memcmp(pdu->hdr, teststr, sizeof(teststr)) == 0); +} + +void t_encode_pdu11(void) +{ + /* data too long for PDU */ + size_t old_max = pdu->max_size; + int result; + + coap_pdu_clear(pdu, 8); /* clear PDU, with small maximum */ + + CU_ASSERT(pdu->data == NULL); + result = coap_add_data(pdu, 10, (unsigned char *) "0123456789"); + + CU_ASSERT(result == 0); + CU_ASSERT(pdu->data == NULL); + + pdu->max_size = old_max; +} + +int t_pdu_tests_create(void) +{ + pdu = coap_pdu_init(0, 0, 0, COAP_MAX_PDU_SIZE); + + return pdu == NULL; +} + +int t_pdu_tests_remove(void) +{ + coap_delete_pdu(pdu); + return 0; +} + +CU_pSuite t_init_pdu_tests(void) +{ + CU_pSuite suite[2]; + + suite[0] = CU_add_suite("pdu parser", t_pdu_tests_create, t_pdu_tests_remove); + if (!suite[0]) + { /* signal error */ + fprintf(stderr, "W: cannot add pdu parser test suite (%s)\n", CU_get_error_msg()); + + return NULL; + } + +#define PDU_TEST(s,t) \ + if (!CU_ADD_TEST(s,t)) { \ + fprintf(stderr, "W: cannot add pdu parser test (%s)\n", \ + CU_get_error_msg()); \ + } + + PDU_TEST(suite[0], t_parse_pdu1); + PDU_TEST(suite[0], t_parse_pdu2); + PDU_TEST(suite[0], t_parse_pdu3); + PDU_TEST(suite[0], t_parse_pdu4); + PDU_TEST(suite[0], t_parse_pdu5); + PDU_TEST(suite[0], t_parse_pdu6); + PDU_TEST(suite[0], t_parse_pdu7); + PDU_TEST(suite[0], t_parse_pdu8); + PDU_TEST(suite[0], t_parse_pdu9); + PDU_TEST(suite[0], t_parse_pdu10); + PDU_TEST(suite[0], t_parse_pdu11); + PDU_TEST(suite[0], t_parse_pdu12); + PDU_TEST(suite[0], t_parse_pdu13); + PDU_TEST(suite[0], t_parse_pdu14); + + suite[1] = CU_add_suite("pdu encoder", t_pdu_tests_create, t_pdu_tests_remove); + if (suite[1]) + { +#define PDU_ENCODER_TEST(s,t) \ + if (!CU_ADD_TEST(s,t)) { \ + fprintf(stderr, "W: cannot add pdu encoder test (%s)\n", \ + CU_get_error_msg()); \ + } + PDU_ENCODER_TEST(suite[1], t_encode_pdu1); + PDU_ENCODER_TEST(suite[1], t_encode_pdu2); + PDU_ENCODER_TEST(suite[1], t_encode_pdu3); + PDU_ENCODER_TEST(suite[1], t_encode_pdu4); + PDU_ENCODER_TEST(suite[1], t_encode_pdu5); + PDU_ENCODER_TEST(suite[1], t_encode_pdu6); + PDU_ENCODER_TEST(suite[1], t_encode_pdu7); + PDU_ENCODER_TEST(suite[1], t_encode_pdu8); + PDU_ENCODER_TEST(suite[1], t_encode_pdu9); + PDU_ENCODER_TEST(suite[1], t_encode_pdu10); + PDU_ENCODER_TEST(suite[1], t_encode_pdu11); + + } + else + /* signal error */ + fprintf(stderr, "W: cannot add pdu parser test suite (%s)\n", CU_get_error_msg()); + + return suite[0]; +} + diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_pdu.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_pdu.h new file mode 100644 index 000000000..992b37720 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_pdu.h @@ -0,0 +1,11 @@ +/* libcoap unit tests + * + * Copyright (C) 2012 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include + +CU_pSuite t_init_pdu_tests(void); diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_sendqueue.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_sendqueue.c new file mode 100644 index 000000000..1b6c0764d --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_sendqueue.c @@ -0,0 +1,379 @@ +/* libcoap unit tests + * + * Copyright (C) 2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include +#include +#include "test_sendqueue.h" + +static coap_queue_t *sendqueue; + +/* timestamps for tests. The first element in this array denotes the + * base time in ticks, the following elements are timestamps relative + * to this basetime. + */ +static coap_tick_t timestamp[] = +{ 0, 100, 200, 30, 160 }; + +/* nodes for testing. node[0] is left empty */ +coap_queue_t *node[5]; + +coap_tick_t add_timestamps(coap_queue_t *queue, size_t num) +{ + coap_tick_t t = 0; + while (queue && num--) + { + t += queue->t; + queue = queue->next; + } + + return t; +} + +void t_sendqueue1(void) +{ + int result = coap_insert_node(&sendqueue, node[1]); + + CU_ASSERT(result > 0); + CU_ASSERT_PTR_NOT_NULL(sendqueue); + CU_ASSERT_PTR_EQUAL(sendqueue, node[1]); + CU_ASSERT(node[1]->t == timestamp[1]); +} + +void t_sendqueue2(void) +{ + int result; + + result = coap_insert_node(&sendqueue, node[2]); + + CU_ASSERT(result > 0); + CU_ASSERT_PTR_EQUAL(sendqueue, node[1]); + CU_ASSERT_PTR_EQUAL(sendqueue->next, node[2]); + + CU_ASSERT(sendqueue->t == timestamp[1]); + CU_ASSERT(node[2]->t == timestamp[2] - timestamp[1]); +} + +/* insert new node as first element in queue */ +void t_sendqueue3(void) +{ + int result; + result = coap_insert_node(&sendqueue, node[3]); + + CU_ASSERT(result > 0); + + CU_ASSERT_PTR_EQUAL(sendqueue, node[3]); + CU_ASSERT(node[3]->t == timestamp[3]); + + CU_ASSERT_PTR_NOT_NULL(sendqueue->next); + CU_ASSERT_PTR_NOT_NULL(sendqueue->next->next); + + CU_ASSERT(sendqueue->next->t == timestamp[1] - timestamp[3]); + CU_ASSERT(sendqueue->next->next->t == timestamp[2] - timestamp[1]); +} + +/* insert new node as fourth element in queue */ +void t_sendqueue4(void) +{ + int result; + + result = coap_insert_node(&sendqueue, node[4]); + + CU_ASSERT(result > 0); + + CU_ASSERT_PTR_EQUAL(sendqueue, node[3]); + + CU_ASSERT_PTR_NOT_NULL(sendqueue->next); + CU_ASSERT_PTR_EQUAL(sendqueue->next, node[1]); + + CU_ASSERT_PTR_NOT_NULL(sendqueue->next->next); + CU_ASSERT_PTR_EQUAL(sendqueue->next->next, node[4]); + + CU_ASSERT_PTR_NOT_NULL(sendqueue->next->next->next); + CU_ASSERT_PTR_EQUAL(sendqueue->next->next->next, node[2]); + + CU_ASSERT(sendqueue->next->t == timestamp[1] - timestamp[3]); + CU_ASSERT(add_timestamps(sendqueue, 1) == timestamp[3]); + CU_ASSERT(add_timestamps(sendqueue, 2) == timestamp[1]); + CU_ASSERT(add_timestamps(sendqueue, 3) == timestamp[4]); + CU_ASSERT(add_timestamps(sendqueue, 4) == timestamp[2]); +} + +void t_sendqueue5(void) +{ + const coap_tick_diff_t delta1 = 20, delta2 = 130; + unsigned int result; + coap_tick_t now; + struct coap_context_t ctx; + + /* space for saving the current node timestamps */ + static coap_tick_t times[sizeof(timestamp) / sizeof(coap_tick_t)]; + coap_queue_t *p; + int i; + + /* save timestamps of nodes in the sendqueue in their actual order */ + memset(times, 0, sizeof(times)); + for (p = sendqueue, i = 0; p; p = p->next, i++) + { + times[i] = p->t; + } + + coap_ticks(&now); + ctx.sendqueue = sendqueue; + ctx.sendqueue_basetime = now; + + now -= delta1; + result = coap_adjust_basetime(&ctx, now); + + CU_ASSERT(result == 0); + CU_ASSERT_PTR_NOT_NULL(ctx.sendqueue); + CU_ASSERT(ctx.sendqueue_basetime == now); + CU_ASSERT(ctx.sendqueue->t == timestamp[3] + delta1); + + now += delta2; + result = coap_adjust_basetime(&ctx, now); + CU_ASSERT(result == 2); + CU_ASSERT(ctx.sendqueue_basetime == now); + CU_ASSERT_PTR_NOT_NULL(ctx.sendqueue); + CU_ASSERT(ctx.sendqueue->t == 0); + + CU_ASSERT_PTR_NOT_NULL(ctx.sendqueue->next); + CU_ASSERT(ctx.sendqueue->next->t == 0); + + CU_ASSERT_PTR_NOT_NULL(ctx.sendqueue->next->next); + CU_ASSERT(ctx.sendqueue->next->next->t == delta2 - delta1 - timestamp[1]); + + /* restore timestamps of nodes in the sendqueue */ + for (p = sendqueue, i = 0; p; p = p->next, i++) + { + p->t = times[i]; + } +} + +void t_sendqueue6(void) +{ + unsigned int result; + coap_tick_t now; + const coap_tick_diff_t delta = 20; + struct coap_context_t ctx; + + /* space for saving the current node timestamps */ + static coap_tick_t times[sizeof(timestamp) / sizeof(coap_tick_t)]; + coap_queue_t *p; + int i; + + /* save timestamps of nodes in the sendqueue in their actual order */ + memset(times, 0, sizeof(times)); + for (p = sendqueue, i = 0; p; p = p->next, i++) + { + times[i] = p->t; + } + + coap_ticks(&now); + ctx.sendqueue = NULL; + ctx.sendqueue_basetime = now; + + result = coap_adjust_basetime(&ctx, now + delta); + + CU_ASSERT(result == 0); + CU_ASSERT(ctx.sendqueue_basetime == now + delta); + + /* restore timestamps of nodes in the sendqueue */ + for (p = sendqueue, i = 0; p; p = p->next, i++) + { + p->t = times[i]; + } +} +; + +void t_sendqueue7(void) +{ + int result; + coap_queue_t *tmp_node; + + CU_ASSERT_PTR_NOT_NULL(sendqueue); + CU_ASSERT_PTR_EQUAL(sendqueue, node[3]); + + CU_ASSERT_PTR_NOT_NULL(sendqueue->next); + CU_ASSERT_PTR_EQUAL(sendqueue->next, node[1]); + + result = coap_remove_from_queue(&sendqueue, 3, &tmp_node); + + CU_ASSERT(result == 1); + CU_ASSERT_PTR_NOT_NULL(tmp_node); + CU_ASSERT_PTR_EQUAL(tmp_node, node[3]); + + CU_ASSERT_PTR_NOT_NULL(sendqueue); + CU_ASSERT_PTR_EQUAL(sendqueue, node[1]); + + CU_ASSERT(sendqueue->t == timestamp[1]); +} +; + +void t_sendqueue8(void) +{ + int result; + coap_queue_t *tmp_node; + + result = coap_remove_from_queue(&sendqueue, 4, &tmp_node); + + CU_ASSERT(result == 1); + CU_ASSERT_PTR_NOT_NULL(tmp_node); + CU_ASSERT_PTR_EQUAL(tmp_node, node[4]); + + CU_ASSERT_PTR_NOT_NULL(sendqueue); + CU_ASSERT_PTR_EQUAL(sendqueue, node[1]); + CU_ASSERT(sendqueue->t == timestamp[1]); + + CU_ASSERT_PTR_NOT_NULL(sendqueue->next); + CU_ASSERT_PTR_EQUAL(sendqueue->next, node[2]); + CU_ASSERT(sendqueue->next->t == timestamp[2] - timestamp[1]); + + CU_ASSERT_PTR_NULL(sendqueue->next->next); +} +; + +void t_sendqueue9(void) +{ + coap_queue_t *tmp_node; + struct coap_context_t ctx; + + /* Initialize a fake context that points to our global sendqueue + * Note that all changes happen on ctx.sendqueue. */ + ctx.sendqueue = sendqueue; + tmp_node = coap_peek_next(&ctx); + sendqueue = ctx.sendqueue; /* must update global sendqueue for correct result */ + + CU_ASSERT_PTR_NOT_NULL(tmp_node); + CU_ASSERT_PTR_EQUAL(tmp_node, node[1]); + CU_ASSERT_PTR_EQUAL(tmp_node, ctx.sendqueue); + + tmp_node = coap_pop_next(&ctx); + sendqueue = ctx.sendqueue; /* must update global sendqueue for correct result */ + + CU_ASSERT_PTR_NOT_NULL(tmp_node); + CU_ASSERT_PTR_EQUAL(tmp_node, node[1]); + + CU_ASSERT_PTR_NOT_NULL(sendqueue); + CU_ASSERT_PTR_EQUAL(sendqueue, node[2]); + + CU_ASSERT(tmp_node->t == timestamp[1]); + CU_ASSERT(sendqueue->t == timestamp[2]); + + CU_ASSERT_PTR_NULL(sendqueue->next); +} +; + +void t_sendqueue10(void) +{ + coap_queue_t *tmp_node; + struct coap_context_t ctx; + + /* Initialize a fake context that points to our global sendqueue + * Note that all changes happen on ctx.sendqueue. */ + ctx.sendqueue = sendqueue; + + tmp_node = coap_pop_next(&ctx); + sendqueue = ctx.sendqueue; /* must update global sendqueue for correct result */ + + CU_ASSERT_PTR_NOT_NULL(tmp_node); + CU_ASSERT_PTR_EQUAL(tmp_node, node[2]); + + CU_ASSERT_PTR_NULL(sendqueue); + + CU_ASSERT(tmp_node->t == timestamp[2]); +} +; + +/* This function creates a set of nodes for testing. These nodes + * will exist for all tests and are modified by coap_insert_node() + * and + */ +int t_sendqueue_tests_create(void) +{ + int n, error = 0; + sendqueue = NULL; + coap_ticks(×tamp[0]); + + memset(node, 0, sizeof(node)); + for (n = 1; n < sizeof(node) / sizeof(coap_queue_t *); n++) + { + node[n] = coap_new_node(); + if (!node[n]) + { + error = 1; + break; + } + + node[n]->id = n; + node[n]->t = timestamp[n]; + } + + if (error) + { + /* destroy all test nodes and set entry to zero */ + for (n = 0; n < sizeof(node) / sizeof(coap_queue_t *); n++) + { + if (node[n]) + { + coap_delete_node(node[n]); + node[n] = NULL; + } + } + } + + return error; +} + +int t_sendqueue_tests_remove(void) +{ + int n; + + /* destroy all test nodes */ + for (n = 0; n < sizeof(node) / sizeof(coap_queue_t *); n++) + { + if (node[n]) + { + coap_delete_node(node[n]); + } + } + + return 0; +} + +CU_pSuite t_init_sendqueue_tests(void) +{ + CU_pSuite suite; + + suite = CU_add_suite("sendqueue", t_sendqueue_tests_create, t_sendqueue_tests_remove); + if (!suite) + { /* signal error */ + fprintf(stderr, "W: cannot add sendqueue test suite (%s)\n", CU_get_error_msg()); + + return NULL; + } + +#define SENDQUEUE_TEST(s,t) \ + if (!CU_ADD_TEST(s,t)) { \ + fprintf(stderr, "W: cannot add sendqueue test (%s)\n", \ + CU_get_error_msg()); \ + } + + SENDQUEUE_TEST(suite, t_sendqueue1); + SENDQUEUE_TEST(suite, t_sendqueue2); + SENDQUEUE_TEST(suite, t_sendqueue3); + SENDQUEUE_TEST(suite, t_sendqueue4); + SENDQUEUE_TEST(suite, t_sendqueue5); + SENDQUEUE_TEST(suite, t_sendqueue6); + SENDQUEUE_TEST(suite, t_sendqueue7); + SENDQUEUE_TEST(suite, t_sendqueue8); + SENDQUEUE_TEST(suite, t_sendqueue9); + SENDQUEUE_TEST(suite, t_sendqueue10); + + return suite; +} + diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_sendqueue.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_sendqueue.h new file mode 100644 index 000000000..56f3c1edb --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_sendqueue.h @@ -0,0 +1,11 @@ +/* libcoap unit tests + * + * Copyright (C) 2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include + +CU_pSuite t_init_sendqueue_tests(void); diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_uri.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_uri.c new file mode 100644 index 000000000..d5dafc59e --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_uri.c @@ -0,0 +1,396 @@ +/* libcoap unit tests + * + * Copyright (C) 2012 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include +#include +#include "test_uri.h" + +void t_parse_uri1(void) +{ + char teststr[] = "coap://[::1]/.well-known/core"; + + int result; + coap_uri_t uri; + + result = coap_split_uri((unsigned char *) teststr, strlen(teststr), &uri); + if (result == 0) + { + CU_ASSERT(uri.host.length == 3); + CU_ASSERT_NSTRING_EQUAL(uri.host.s, "::1", 3); + + CU_ASSERT(uri.port == COAP_DEFAULT_PORT); + + CU_ASSERT(uri.path.length == 16); + CU_ASSERT_NSTRING_EQUAL(uri.path.s, ".well-known/core", 16); + + CU_ASSERT(uri.query.length == 0); + CU_ASSERT(uri.query.s == NULL); + } + else + { + CU_FAIL("uri parser error"); + } +} + +void t_parse_uri2(void) +{ + char teststr[] = "coap://[::1]:8000/.well-known/core"; + int result; + coap_uri_t uri; + + result = coap_split_uri((unsigned char *) teststr, strlen(teststr), &uri); + if (result == 0) + { + CU_ASSERT(uri.host.length == 3); + CU_ASSERT_NSTRING_EQUAL(uri.host.s, "::1", 3); + + CU_ASSERT(uri.port == 8000); + + CU_ASSERT(uri.path.length == 16); + CU_ASSERT_NSTRING_EQUAL(uri.path.s, ".well-known/core", 16); + + CU_ASSERT(uri.query.length == 0); + CU_ASSERT(uri.query.s == NULL); + } + else + { + CU_FAIL("uri parser error"); + } +} + +void t_parse_uri3(void) +{ + char teststr[] = "coap://localhost/?foo&bla=fasel"; + int result; + coap_uri_t uri; + + result = coap_split_uri((unsigned char *) teststr, strlen(teststr), &uri); + if (result == 0) + { + CU_ASSERT(uri.host.length == 9); + CU_ASSERT_NSTRING_EQUAL(uri.host.s, "localhost", 9); + + CU_ASSERT(uri.port == COAP_DEFAULT_PORT); + + CU_ASSERT(uri.path.length == 0); + + CU_ASSERT(uri.query.length == 13); + CU_ASSERT_NSTRING_EQUAL(uri.query.s, "foo&bla=fasel", 13); + } + else + { + CU_FAIL("uri parser error"); + } +} + +void t_parse_uri4(void) +{ + char teststr[] = "coap://:100000"; + int result; + coap_uri_t uri; + + result = coap_split_uri((unsigned char *) teststr, strlen(teststr), &uri); + CU_ASSERT(result < 0); +} + +void t_parse_uri5(void) +{ + char teststr[] = "coap://foo:100000"; + int result; + coap_uri_t uri; + + result = coap_split_uri((unsigned char *) teststr, strlen(teststr), &uri); + if (result == 0) + { + CU_ASSERT(uri.host.length == 3); + CU_ASSERT_NSTRING_EQUAL(uri.host.s, "foo", 3); + + CU_ASSERT(uri.path.length == 0); + CU_ASSERT(uri.path.s == NULL); + + CU_ASSERT(uri.query.length == 0); + CU_ASSERT(uri.query.s == NULL); + + CU_FAIL("invalid port not detected"); + } + else + { + CU_PASS("detected invalid port"); + } +} + +void t_parse_uri6(void) +{ + char teststr[] = "coap://134.102.218.2/.well-known/core"; + int result; + coap_uri_t uri; + + result = coap_split_uri((unsigned char *) teststr, strlen(teststr), &uri); + if (result == 0) + { + CU_ASSERT(uri.host.length == 13); + CU_ASSERT_NSTRING_EQUAL(uri.host.s, "134.102.218.2", 13); + + CU_ASSERT(uri.port == COAP_DEFAULT_PORT); + + CU_ASSERT(uri.path.length == 16); + CU_ASSERT_NSTRING_EQUAL(uri.path.s, ".well-known/core", 16); + + CU_ASSERT(uri.query.length == 0); + CU_ASSERT(uri.query.s == NULL); + } + else + { + CU_FAIL("uri parser error"); + } +} + +void t_parse_uri7(void) +{ + char teststr[] = "coap://foo.bar:5683/some_resource/with/multiple/segments"; + int result; + coap_uri_t uri; + unsigned char buf[40]; + size_t buflen = sizeof(buf); + + /* The list of path segments to check against. Each segment is + preceded by a dummy option indicating that holds the (dummy) + delta value 0 and the actual segment length. */ + const unsigned char checkbuf[] = + { 0x0d, 0x00, 's', 'o', 'm', 'e', '_', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', 0x04, 'w', 'i', + 't', 'h', 0x08, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 0x08, 's', 'e', 'g', 'm', 'e', + 'n', 't', 's' }; + + result = coap_split_uri((unsigned char *) teststr, strlen(teststr), &uri); + if (result == 0) + { + CU_ASSERT(uri.host.length == 7); + CU_ASSERT_NSTRING_EQUAL(uri.host.s, "foo.bar", 7); + + CU_ASSERT(uri.port == 5683); + + CU_ASSERT(uri.path.length == 36); + CU_ASSERT_NSTRING_EQUAL(uri.path.s, "some_resource/with/multiple/segments", 36); + + CU_ASSERT(uri.query.length == 0); + CU_ASSERT(uri.query.s == NULL); + + /* check path segments */ + result = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); + CU_ASSERT(result == 4); + CU_ASSERT(buflen == sizeof(checkbuf)); + CU_ASSERT_NSTRING_EQUAL(buf, checkbuf, buflen); + } + else + { + CU_FAIL("uri parser error"); + } +} + +void t_parse_uri8(void) +{ + char teststr[] = "http://example.com/%7E%AB%13"; + int result; + coap_uri_t uri; + + result = coap_split_uri((unsigned char *) teststr, strlen(teststr), &uri); + if (result < 0) + { + CU_PASS("detected non-coap URI"); + } + else + { + CU_FAIL("non-coap URI not recognized"); + } +} + +void t_parse_uri9(void) +{ + char teststr[] = "http://example.com/%x"; + int result; + coap_uri_t uri; + + result = coap_split_uri((unsigned char *) teststr, strlen(teststr), &uri); + if (result < 0) + { + CU_PASS("detected non-coap URI"); + } + else + { + CU_FAIL("non-coap URI not recognized"); + } +} + +void t_parse_uri10(void) +{ + char teststr[] = "/absolute/path"; + int result; + coap_uri_t uri; + + result = coap_split_uri((unsigned char *) teststr, strlen(teststr), &uri); + if (result == 0) + { + CU_ASSERT(uri.host.length == 0); + CU_ASSERT(uri.host.s == NULL); + + CU_ASSERT(uri.port == COAP_DEFAULT_PORT); + + CU_ASSERT(uri.path.length == 13); + CU_ASSERT_NSTRING_EQUAL(uri.path.s, "absolute/path", 13); + + CU_ASSERT(uri.query.length == 0); + CU_ASSERT(uri.query.s == NULL); + } + else + { + CU_FAIL("uri parser error"); + } +} + +void t_parse_uri11(void) +{ + char teststr[] = "coap://xn--18j4d.example/%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF"; + int result; + coap_uri_t uri; + unsigned char buf[40]; + size_t buflen = sizeof(buf); + + /* The list of path segments to check against. Each segment is + preceded by a dummy option indicating that holds the (dummy) + delta value 0 and the actual segment length. */ + const unsigned char checkbuf[] = + { 0x0d, 0x02, 0xE3, 0x81, 0x93, 0xE3, 0x82, 0x93, 0xE3, 0x81, 0xAB, 0xE3, 0x81, 0xA1, 0xE3, + 0x81, 0xAF }; + + result = coap_split_uri((unsigned char *) teststr, strlen(teststr), &uri); + if (result == 0) + { + CU_ASSERT(uri.host.length == 17); + CU_ASSERT_NSTRING_EQUAL(uri.host.s, "xn--18j4d.example", 17); + + CU_ASSERT(uri.port == COAP_DEFAULT_PORT); + + CU_ASSERT(uri.path.length == 45); + CU_ASSERT_NSTRING_EQUAL(uri.path.s, "%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF", 45); + + CU_ASSERT(uri.query.length == 0); + CU_ASSERT(uri.query.s == NULL); + + /* check path segments */ + result = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); + CU_ASSERT(result == 1); + CU_ASSERT(buflen == sizeof(checkbuf)); + CU_ASSERT_NSTRING_EQUAL(buf, checkbuf, buflen); + } + else + { + CU_FAIL("uri parser error"); + } +} + +void t_parse_uri12(void) +{ + char teststr[] = "coap://198.51.100.1:61616//%2F//?%2F%2F&?%26"; + int result; + coap_uri_t uri; + unsigned char buf[40]; + size_t buflen = sizeof(buf); + + /* The list of path segments to check against. Each segment is + preceded by a dummy option indicating that holds the (dummy) + delta value 0 and the actual segment length. */ + const unsigned char uricheckbuf[] = + { 0x00, 0x01, 0x2f, 0x00, 0x00 }; + const unsigned char querycheckbuf[] = + { 0x02, 0x2f, 0x2f, 0x02, 0x3f, 0x26 }; + + result = coap_split_uri((unsigned char *) teststr, strlen(teststr), &uri); + if (result == 0) + { + CU_ASSERT(uri.host.length == 12); + CU_ASSERT_NSTRING_EQUAL(uri.host.s, "198.51.100.1", 12); + + CU_ASSERT(uri.port == 61616); + + CU_ASSERT(uri.path.length == 6); + CU_ASSERT_NSTRING_EQUAL(uri.path.s, "/%2F//", 6); + + CU_ASSERT(uri.query.length == 11); + CU_ASSERT_NSTRING_EQUAL(uri.query.s, "%2F%2F&?%26", 11); + + /* check path segments */ + result = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); + CU_ASSERT(result == 4); + CU_ASSERT(buflen == sizeof(uricheckbuf)); + CU_ASSERT_NSTRING_EQUAL(buf, uricheckbuf, buflen); + + /* check query segments */ + buflen = sizeof(buf); + result = coap_split_query(uri.query.s, uri.query.length, buf, &buflen); + CU_ASSERT(result == 2); + CU_ASSERT(buflen == sizeof(querycheckbuf)); + CU_ASSERT_NSTRING_EQUAL(buf, querycheckbuf, buflen); + } + else + { + CU_FAIL("uri parser error"); + } +} + +void t_parse_uri13(void) +{ + char teststr[] __attribute__ ((aligned (8))) = + { 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 'f', 'o', 'o', 0x3b, '.', 'w', 'e', 'l', 'l', '-', 'k', + 'n', 'o', 'w', 'n', 0x04, 'c', 'o', 'r', 'e' }; + + coap_pdu_t pdu = + { .max_size = sizeof(teststr), .hdr = (coap_hdr_t *) teststr, .length = sizeof(teststr) }; + + coap_key_t key; + + coap_hash_request_uri(&pdu, key); + + CU_ASSERT(sizeof(key) == sizeof(COAP_DEFAULT_WKC_HASHKEY) - 1); + CU_ASSERT_NSTRING_EQUAL(key, COAP_DEFAULT_WKC_HASHKEY, sizeof(key)); +} + +CU_pSuite t_init_uri_tests(void) +{ + CU_pSuite suite; + + suite = CU_add_suite("uri parser", NULL, NULL); + if (!suite) + { /* signal error */ + fprintf(stderr, "W: cannot add uri parser test suite (%s)\n", CU_get_error_msg()); + + return NULL; + } + +#define URI_TEST(s,t) \ + if (!CU_ADD_TEST(s,t)) { \ + fprintf(stderr, "W: cannot add uri parser test (%s)\n", \ + CU_get_error_msg()); \ + } + + URI_TEST(suite, t_parse_uri1); + URI_TEST(suite, t_parse_uri2); + URI_TEST(suite, t_parse_uri3); + URI_TEST(suite, t_parse_uri4); + URI_TEST(suite, t_parse_uri5); + URI_TEST(suite, t_parse_uri6); + URI_TEST(suite, t_parse_uri7); + URI_TEST(suite, t_parse_uri8); + URI_TEST(suite, t_parse_uri9); + URI_TEST(suite, t_parse_uri10); + URI_TEST(suite, t_parse_uri11); + URI_TEST(suite, t_parse_uri12); + URI_TEST(suite, t_parse_uri13); + + return suite; +} + diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_uri.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_uri.h new file mode 100644 index 000000000..165fad3ff --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_uri.h @@ -0,0 +1,11 @@ +/* libcoap unit tests + * + * Copyright (C) 2012 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include + +CU_pSuite t_init_uri_tests(void); diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_wellknown.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_wellknown.c new file mode 100644 index 000000000..97584d854 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_wellknown.c @@ -0,0 +1,337 @@ +/* libcoap unit tests + * + * Copyright (C) 2013--2014 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include +#include +#include +#include +#include +#include +#include "test_wellknown.h" + +#define TEST_PDU_SIZE 120 +#define TEST_URI_LEN 4 + +coap_context_t *ctx; /* Holds the coap context for most tests */ +coap_pdu_t *pdu; /* Holds the parsed PDU for most tests */ + +extern coap_pdu_t *wellknown_response(coap_context_t *, coap_pdu_t *); +extern int print_wellknown(coap_context_t *context, unsigned char *buf, size_t *buflen, + size_t offset, coap_opt_t *query_filter); + +void t_wellknown1(void) +{ + coap_print_status_t result; + coap_resource_t *r; + unsigned char buf[40]; + size_t buflen, offset, ofs; + + char teststr[] = + { /* ;title="some attribute";ct=0 (31 chars) */ + '<', '/', '>', ';', 't', 'i', 't', 'l', 'e', '=', '"', 's', 'o', 'm', 'e', ' ', 'a', 't', 't', + 'r', 'i', 'b', 'u', 't', 'e', '"', ';', 'c', 't', '=', '0' }; + + r = coap_resource_init(NULL, 0, 0); + + coap_add_attr(r, (unsigned char *) "ct", 2, (unsigned char *) "0", 1, 0); + coap_add_attr(r, (unsigned char *) "title", 5, (unsigned char *) "\"some attribute\"", 16, 0); + + coap_add_resource(ctx, r); + + for (offset = 0; offset < sizeof(teststr); offset++) + { + ofs = offset; + buflen = sizeof(buf); + + result = coap_print_link(r, buf, &buflen, &ofs); + + CU_ASSERT(result == sizeof(teststr) - offset); + CU_ASSERT(buflen == sizeof(teststr)); + CU_ASSERT(memcmp(buf, teststr + offset, sizeof(teststr) - offset) == 0); + } + + /* offset points behind teststr */ + ofs = offset; + buflen = sizeof(buf); + result = coap_print_link(r, buf, &buflen, &ofs); + + CU_ASSERT(result == 0); + CU_ASSERT(buflen == sizeof(teststr)); + + /* offset exceeds buffer */ + buflen = sizeof(buf); + ofs = buflen; + result = coap_print_link(r, buf, &buflen, &ofs); + + CU_ASSERT(result == 0); + CU_ASSERT(buflen == sizeof(teststr)); +} + +void t_wellknown2(void) +{ + coap_print_status_t result; + coap_resource_t *r; + unsigned char buf[10]; /* smaller than teststr */ + size_t buflen, offset, ofs; + + char teststr[] = + { /* ,;if="one";obs (21 chars) */ + '<', '/', 'a', 'b', 'c', 'd', '>', ';', 'i', 'f', '=', '"', 'o', 'n', 'e', '"', ';', 'o', 'b', + 's' }; + + r = coap_resource_init((unsigned char *) "abcd", 4, 0); + r->observable = 1; + coap_add_attr(r, (unsigned char *) "if", 2, (unsigned char *) "\"one\"", 5, 0); + + coap_add_resource(ctx, r); + + for (offset = 0; offset < sizeof(teststr) - sizeof(buf); offset++) + { + ofs = offset; + buflen = sizeof(buf); + + result = coap_print_link(r, buf, &buflen, &ofs); + + CU_ASSERT(result == (COAP_PRINT_STATUS_TRUNC | sizeof(buf))); + CU_ASSERT(buflen == sizeof(teststr)); + CU_ASSERT(ofs == 0); + CU_ASSERT(memcmp(buf, teststr + offset, sizeof(buf)) == 0); + } + + /* from here on, the resource description fits into buf */ + for (; offset < sizeof(teststr); offset++) + { + ofs = offset; + buflen = sizeof(buf); + result = coap_print_link(r, buf, &buflen, &ofs); + + CU_ASSERT(result == sizeof(teststr) - offset); + CU_ASSERT(buflen == sizeof(teststr)); + CU_ASSERT(ofs == 0); + CU_ASSERT(memcmp(buf, teststr + offset, COAP_PRINT_OUTPUT_LENGTH(result)) == 0); + } + + /* offset exceeds buffer */ + buflen = sizeof(buf); + ofs = offset; + result = coap_print_link(r, buf, &buflen, &ofs); + CU_ASSERT(result == 0); + CU_ASSERT(buflen == sizeof(teststr)); + CU_ASSERT(ofs == offset - sizeof(teststr)); +} + +void t_wellknown3(void) +{ + coap_print_status_t result; + int j; + coap_resource_t *r; + static char uris[2 * COAP_MAX_PDU_SIZE]; + unsigned char *uribuf = (unsigned char *) uris; + unsigned char buf[40]; + size_t buflen = sizeof(buf); + size_t offset; + const unsigned short num_resources = (sizeof(uris) / TEST_URI_LEN) - 1; + + /* , (TEST_URI_LEN + 4 chars) */ + for (j = 0; j < num_resources; j++) + { + int len = snprintf((char *) uribuf, TEST_URI_LEN + 1, "%0*d", TEST_URI_LEN, j); + r = coap_resource_init(uribuf, len, 0); + coap_add_resource(ctx, r); + uribuf += TEST_URI_LEN; + } + + /* the following test assumes that the first two resources from + * t_wellknown1() and t_wellknown2() need more than buflen + * characters. Otherwise, CU_ASSERT(result > 0) will fail. + */ + offset = num_resources * (TEST_URI_LEN + 4); + result = print_wellknown(ctx, buf, &buflen, offset, NULL); + CU_ASSERT((result & COAP_PRINT_STATUS_ERROR) == 0); + CU_ASSERT(COAP_PRINT_OUTPUT_LENGTH(result) > 0); +} + +/* Create wellknown response for request without Block-option. */ +void t_wellknown4(void) +{ + coap_pdu_t *response; + coap_block_t block; + + response = wellknown_response(ctx, pdu); + + CU_ASSERT_PTR_NOT_NULL(response); + + CU_ASSERT(coap_get_block(response, COAP_OPTION_BLOCK2, &block) != 0); + + CU_ASSERT(block.num == 0); + CU_ASSERT(block.m == 1); + CU_ASSERT( + 1 << (block.szx + 4) + == (unsigned char *) response->hdr + response->length - response->data); + + coap_delete_pdu(response); +} + +/* Create wellknown response for request with Block2-option and an szx + * value smaller than COAP_MAX_BLOCK_SZX. + */ +void t_wellknown5(void) +{ + coap_pdu_t *response; + coap_block_t inblock = + { .num = 1, .m = 0, .szx = 1 }; + coap_block_t block; + unsigned char buf[3]; + + if (!coap_add_option(pdu, COAP_OPTION_BLOCK2, + coap_encode_var_bytes(buf, ((inblock.num << 4) | (inblock.m << 3) | inblock.szx)), buf)) + { + CU_FAIL("cannot add Block2 option"); + return; + } + + response = wellknown_response(ctx, pdu); + + CU_ASSERT_PTR_NOT_NULL(response); + + CU_ASSERT(coap_get_block(response, COAP_OPTION_BLOCK2, &block) != 0); + + CU_ASSERT(block.num == inblock.num); + CU_ASSERT(block.m == 1); + CU_ASSERT( + 1 << (block.szx + 4) + == (unsigned char *) response->hdr + response->length - response->data); + + coap_delete_pdu(response); +} + +void t_wellknown6(void) +{ + coap_pdu_t *response; + coap_block_t block = + { .num = 0, .szx = 6 }; + unsigned char buf[TEST_PDU_SIZE]; + + do + { + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + pdu->hdr->type = COAP_MESSAGE_NON; + pdu->hdr->code = COAP_REQUEST_GET; + pdu->hdr->id = htons(0x1234); + + CU_ASSERT_PTR_NOT_NULL(pdu); + + if (!pdu + || !coap_add_option(pdu, COAP_OPTION_BLOCK2, + coap_encode_var_bytes(buf, ((block.num << 4) | block.szx)), buf)) + { + CU_FAIL("cannot create request"); + return; + } + + response = wellknown_response(ctx, pdu); + + CU_ASSERT_PTR_NOT_NULL(response); + + /* coap_show_pdu(response); */ + + CU_ASSERT(coap_get_block(response, COAP_OPTION_BLOCK2, &block) != 0); + + block.num++; + coap_delete_pdu(response); + } while (block.m == 1); +} + +int t_wkc_tests_create(void) +{ + coap_address_t addr; + + coap_address_init(&addr); + + addr.size = sizeof(struct sockaddr_in6); + addr.addr.sin6.sin6_family = AF_INET6; + addr.addr.sin6.sin6_addr = in6addr_any; + addr.addr.sin6.sin6_port = htons(COAP_DEFAULT_PORT); + + ctx = coap_new_context(&addr); + + pdu = coap_pdu_init(0, 0, 0, TEST_PDU_SIZE); +#if 0 + /* add resources to coap context */ + if (ctx && pdu) + { + coap_resource_t *r; + static char _buf[2 * COAP_MAX_PDU_SIZE]; + unsigned char *buf = (unsigned char *)_buf; + int i; + + /* ;title="some attribute";ct=0 (31 chars) */ + r = coap_resource_init(NULL, 0, 0); + + coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0); + coap_add_attr(r, (unsigned char *)"title", 5, (unsigned char *)"\"some attribute\"", 16, 0); + coap_add_resource(ctx, r); + + /* ,;if="one";obs (21 chars) */ + r = coap_resource_init((unsigned char *)"abcd", 4, 0); + r->observable = 1; + coap_add_attr(r, (unsigned char *)"if", 2, (unsigned char *)"\"one\"", 5, 0); + + coap_add_resource(ctx, r); + + /* , (TEST_URI_LEN + 4 chars) */ + for (i = 0; i < sizeof(_buf) / (TEST_URI_LEN + 4); i++) + { + int len = snprintf((char *)buf, TEST_URI_LEN + 1, + "%0*d", TEST_URI_LEN, i); + r = coap_resource_init(buf, len, 0); + coap_add_resource(ctx, r); + buf += TEST_URI_LEN + 1; + } + + } +#endif + return ctx == NULL || pdu == NULL; +} + +int t_wkc_tests_remove(void) +{ + coap_delete_pdu(pdu); + coap_free_context(ctx); + return 0; +} + +CU_pSuite t_init_wellknown_tests(void) +{ + CU_pSuite suite; + + suite = CU_add_suite(".well-known/core", t_wkc_tests_create, t_wkc_tests_remove); + if (!suite) + { /* signal error */ + fprintf(stderr, "W: cannot add .well-known/core test suite (%s)\n", CU_get_error_msg()); + + return NULL; + } + +#define WKC_TEST(s,t) \ + if (!CU_ADD_TEST(s,t)) { \ + fprintf(stderr, "W: cannot add .well-known/core test (%s)\n", \ + CU_get_error_msg()); \ + } + + WKC_TEST(suite, t_wellknown1); + WKC_TEST(suite, t_wellknown2); + WKC_TEST(suite, t_wellknown3); + WKC_TEST(suite, t_wellknown4); + WKC_TEST(suite, t_wellknown5); + WKC_TEST(suite, t_wellknown6); + + return suite; +} + diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_wellknown.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_wellknown.h new file mode 100644 index 000000000..47f20b344 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/test_wellknown.h @@ -0,0 +1,11 @@ +/* libcoap unit tests + * + * Copyright (C) 2013 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include + +CU_pSuite t_init_wellknown_tests(void); diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/testdriver.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/testdriver.c new file mode 100644 index 000000000..87f140473 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/tests/testdriver.c @@ -0,0 +1,53 @@ +#include + +#include +#include + +/* #include */ + +#include "test_uri.h" +#include "test_options.h" +#include "test_pdu.h" +#include "test_error_response.h" +#include "test_sendqueue.h" +#include "test_wellknown.h" + +int main(int argc, char **argv) +{ + CU_ErrorCode result; + CU_BasicRunMode run_mode = CU_BRM_VERBOSE; + + if (CU_initialize_registry() != CUE_SUCCESS) + { + fprintf(stderr, "E: test framework initialization failed\n"); + return -2; + } + + t_init_uri_tests(); + t_init_option_tests(); + t_init_pdu_tests(); + t_init_error_response_tests(); + t_init_sendqueue_tests(); + t_init_wellknown_tests(); + + CU_basic_set_mode(run_mode); + result = CU_basic_run_tests(); + + CU_cleanup_registry(); + + printf("\n\nknown bugs:\n"); + printf("\t- Test: t_parse_uri5 ... FAILED\n" + "\t 1. test_uri.c:109 - CU_FAIL(\"invalid port not detected\")\n"); + printf("\t- Test: t_parse_uri12 ... FAILED\n" + "\t 1. test_uri.c:301 - result == 4\n" + "\t 2. test_uri.c:302 - buflen == sizeof(uricheckbuf)\n" + "\t 3. test_uri.c:303 - CU_ASSERT_NSTRING_EQUAL(buf,uricheckbuf,buflen)\n" + "\t 4. test_uri.c:309 - buflen == sizeof(querycheckbuf)\n" + "\t 5. test_uri.c:310 - CU_ASSERT_NSTRING_EQUAL(buf,querycheckbuf,buflen)\n"); + printf( + "\t- Test: t_error_response8 ... FAILED\n" + "\t 1. test_error_response.c:310 - response->length == sizeof(teststr)\n" + "\t 2. test_error_response.c:316 - memcmp(response->hdr, teststr, sizeof(teststr)) == 0\n"); + + return result; +} diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/uri.c b/resource/csdk/connectivity/lib/libcoap-4.1.1/uri.c new file mode 100644 index 000000000..1b786862e --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/uri.c @@ -0,0 +1,577 @@ +/* uri.c -- helper functions for URI treatment + * + * Copyright (C) 2010--2012 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "config.h" + +#if defined(HAVE_ASSERT_H) && !defined(assert) +# include +#endif + +#include +#include +#include + +#include "mem.h" +#include "debug.h" +#include "pdu.h" +#include "option.h" +#include "uri.h" + +/** + * A length-safe version of strchr(). This function returns a pointer + * to the first occurrence of @p c in @p s, or @c NULL if not found. + * + * @param s The string to search for @p c. + * @param len The length of @p s. + * @param c The character to search. + * + * @return A pointer to the first occurence of @p c, or @c NULL + * if not found. + */ +static inline unsigned char * +strnchr(unsigned char *s, size_t len, unsigned char c) +{ + while (len && *s++ != c) + --len; + + return len ? s : NULL; +} + +int coap_split_uri(unsigned char *str_var, size_t len, coap_uri_t *uri) +{ + + unsigned char *p, *q; + int secure = 0, res = 0; + + if (!str_var || !uri) + return -1; + + memset(uri, 0, sizeof(coap_uri_t)); + uri->port = COAP_DEFAULT_PORT; + + /* search for scheme */ + p = str_var; + if (*p == '/') + { + q = p; + goto path; + } + + q = (unsigned char *) COAP_DEFAULT_SCHEME; + while (len && *q && tolower(*p) == *q) + { + ++p; + ++q; + --len; + } + + /* If q does not point to the string end marker '\0', the schema + * identifier is wrong. */ + if (*q) + { + res = -1; + goto error; + } + + /* There might be an additional 's', indicating the secure version: */ + if (len && (secure = tolower(*p) == 's')) + { + ++p; + --len; + } + + q = (unsigned char *) "://"; + while (len && *q && tolower(*p) == *q) + { + ++p; + ++q; + --len; + } + + if (*q) + { + res = -2; + goto error; + } + + /* p points to beginning of Uri-Host */ + q = p; + if (len && *p == '[') + { /* IPv6 address reference */ + ++p; + + while (len && *q != ']') + { + ++q; + --len; + } + + if (!len || *q != ']' || p == q) + { + res = -3; + goto error; + } + + COAP_SET_STR(&uri->host, q - p, p); + ++q; + --len; + } + else + { /* IPv4 address or FQDN */ + while (len && *q != ':' && *q != '/' && *q != '?') + { + // *q = tolower(*q); + + ++q; + --len; + } + + if (p == q) + { + res = -3; + goto error; + } + + COAP_SET_STR(&uri->host, q - p, p); + + } + + /* check for Uri-Port */ + if (len && *q == ':') + { + p = ++q; + --len; + + while (len && isdigit(*q)) + { + ++q; + --len; + } + + if (p < q) + { /* explicit port number given */ + int uri_port = 0; + + while (p < q) + uri_port = uri_port * 10 + (*p++ - '0'); + + uri->port = uri_port; + } + } + + path: /* at this point, p must point to an absolute path */ + + if (!len) + goto end; + + if (*q == '/') + { + p = ++q; + --len; + + while (len && *q != '?') + { + ++q; + --len; + } + + if (p < q) + { + COAP_SET_STR(&uri->path, q - p, p); + p = q; + } + } + + /* Uri_Query */ + if (len && *p == '?') + { + ++p; + --len; + COAP_SET_STR(&uri->query, len, p); + len = 0; + } + + end: return len ? -1 : 0; + + error: return res; +} + +/** + * Calculates decimal value from hexadecimal ASCII character given in + * @p c. The caller must ensure that @p c actually represents a valid + * heaxdecimal character, e.g. with isxdigit(3). + * + * @hideinitializer + */ +#define hexchar_to_dec(c) ((c) & 0x40 ? ((c) & 0x0F) + 9 : ((c) & 0x0F)) + +/** + * Decodes percent-encoded characters while copying the string @p seg + * of size @p length to @p buf. The caller of this function must + * ensure that the percent-encodings are correct (i.e. the character + * '%' is always followed by two hex digits. and that @p buf provides + * sufficient space to hold the result. This function is supposed to + * be called by make_decoded_option() only. + * + * @param seg The segment to decode and copy. + * @param length Length of @p seg. + * @param buf The result buffer. + */ +void decode_segment(const unsigned char *seg, size_t length, unsigned char *buf) +{ + + while (length--) + { + + if (*seg == '%') + { + *buf = (hexchar_to_dec(seg[1]) << 4) + hexchar_to_dec(seg[2]); + + seg += 2; + length -= 2; + } + else + { + *buf = *seg; + } + + ++buf; + ++seg; + } +} + +/** + * Runs through the given path (or query) segment and checks if + * percent-encodings are correct. This function returns @c -1 on error + * or the length of @p s when decoded. + */ +int check_segment(const unsigned char *s, size_t length) +{ + + size_t n = 0; + + while (length) + { + if (*s == '%') + { + if (length < 2 || !(isxdigit(s[1]) && isxdigit(s[2]))) + return -1; + + s += 2; + length -= 2; + } + + ++s; + ++n; + --length; + } + + return n; +} + +/** + * Writes a coap option from given string @p s to @p buf. @p s should + * point to a (percent-encoded) path or query segment of a coap_uri_t + * object. The created option will have type @c 0, and the length + * parameter will be set according to the size of the decoded string. + * On success, this function returns the option's size, or a value + * less than zero on error. This function must be called from + * coap_split_path_impl() only. + * + * @param s The string to decode. + * @param length The size of the percent-encoded string @p s. + * @param buf The buffer to store the new coap option. + * @param buflen The maximum size of @p buf. + * + * @return The option's size, or @c -1 on error. + * + * @bug This function does not split segments that are bigger than 270 + * bytes. + */ +int make_decoded_option(const unsigned char *s, size_t length, unsigned char *buf, size_t buflen) +{ + int res; + size_t written; + + if (!buflen) + { + debug("make_decoded_option(): buflen is 0!\n"); + return -1; + } + + res = check_segment(s, length); + if (res < 0) + return -1; + + /* write option header using delta 0 and length res */ + written = coap_opt_setheader(buf, buflen, 0, res); + + assert(written <= buflen); + + if (!written) /* encoding error */ + return -1; + + buf += written; /* advance past option type/length */ + buflen -= written; + + if (buflen < (size_t) res) + { + debug("buffer too small for option\n"); + return -1; + } + + decode_segment(s, length, buf); + + return written + res; +} + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +typedef void (*segment_handler_t)(unsigned char *, size_t, void *); + +/** + * Splits the given string into segments. You should call one of the + * macros coap_split_path() or coap_split_query() instead. + * + * @param parse_iter The iterator used for tokenizing. + * @param h A handler that is called with every token. + * @param data Opaque data that is passed to @p h when called. + * + * @return The number of characters that have been parsed from @p s. + */ +size_t coap_split_path_impl(coap_parse_iterator_t *parse_iter, segment_handler_t h, void *data) +{ + unsigned char *seg; + size_t length; + + assert(parse_iter); + assert(h); + + length = parse_iter->n; + + while ((seg = coap_parse_next(parse_iter))) + { + + /* any valid path segment is handled here: */ + h(seg, parse_iter->segment_length, data); + } + + return length - (parse_iter->n - parse_iter->segment_length); +} + +struct cnt_str +{ + str buf; + int n; +}; + +void write_option(unsigned char *s, size_t len, void *data) +{ + struct cnt_str *state = (struct cnt_str *) data; + int res; + assert(state); + + /* skip empty segments and those that consist of only one or two dots */ + if (memcmp(s, "..", min(len,2)) == 0) + return; + + res = make_decoded_option(s, len, state->buf.s, state->buf.length); + if (res > 0) + { + state->buf.s += res; + state->buf.length -= res; + state->n++; + } +} + +int coap_split_path(const unsigned char *s, size_t length, unsigned char *buf, size_t *buflen) +{ + struct cnt_str tmp = + { + { *buflen, buf }, 0 }; + coap_parse_iterator_t pi; + + coap_parse_iterator_init((unsigned char *) s, length, '/', (unsigned char *) "?#", 2, &pi); + coap_split_path_impl(&pi, write_option, &tmp); + + *buflen = *buflen - tmp.buf.length; + return tmp.n; +} + +int coap_split_query(const unsigned char *s, size_t length, unsigned char *buf, size_t *buflen) +{ + struct cnt_str tmp = + { + { *buflen, buf }, 0 }; + coap_parse_iterator_t pi; + + coap_parse_iterator_init((unsigned char *) s, length, '&', (unsigned char *) "#", 1, &pi); + + coap_split_path_impl(&pi, write_option, &tmp); + + *buflen = tmp.buf.length; + return tmp.n; +} + +#define URI_DATA(uriobj) ((unsigned char *)(uriobj) + sizeof(coap_uri_t)) + +coap_uri_t * +coap_new_uri(const unsigned char *uri, unsigned int length) +{ + unsigned char *result; + + result = coap_malloc(length + 1 + sizeof(coap_uri_t)); + + if (!result) + return NULL; + + memcpy(URI_DATA(result), uri, length); + URI_DATA(result)[length] = '\0'; /* make it zero-terminated */ + + if (coap_split_uri(URI_DATA(result), length, (coap_uri_t *) result) < 0) + { + free(result); + return NULL; + } + return (coap_uri_t *) result; +} + +coap_uri_t * +coap_clone_uri(const coap_uri_t *uri) +{ + coap_uri_t *result; + + if (!uri) + return NULL; + + result = (coap_uri_t *) coap_malloc( uri->query.length + uri->host.length + + uri->path.length + sizeof(coap_uri_t) + 1); + + if (!result) + return NULL; + + memset(result, 0, sizeof(coap_uri_t)); + + result->port = uri->port; + + if (uri->host.length) + { + result->host.s = URI_DATA(result); + result->host.length = uri->host.length; + + memcpy(result->host.s, uri->host.s, uri->host.length); + } + + if (uri->path.length) + { + result->path.s = URI_DATA(result) + uri->host.length; + result->path.length = uri->path.length; + + memcpy(result->path.s, uri->path.s, uri->path.length); + } + + if (uri->query.length) + { + result->query.s = URI_DATA(result) + uri->host.length + uri->path.length; + result->query.length = uri->query.length; + + memcpy(result->query.s, uri->query.s, uri->query.length); + } + + return result; +} + +/* hash URI path segments */ + +/* The function signature of coap_hash() is different from + * segment_handler_t hence we use this wrapper as safe typecast. */ +static inline void hash_segment(unsigned char *s, size_t len, void *data) +{ + coap_hash(s, len, data); +} + +int coap_hash_path(const unsigned char *path, size_t len, coap_key_t key) +{ + coap_parse_iterator_t pi; + + if (!path) + return 0; + + memset(key, 0, sizeof(coap_key_t)); + + coap_parse_iterator_init((unsigned char *) path, len, '/', (unsigned char *) "?#", 2, &pi); + coap_split_path_impl(&pi, hash_segment, key); + + return 1; +} + +/* iterator functions */ + +coap_parse_iterator_t * +coap_parse_iterator_init(unsigned char *s, size_t n, unsigned char separator, unsigned char *delim, + size_t dlen, coap_parse_iterator_t *pi) +{ + assert(pi); + assert(separator); + + pi->separator = separator; + pi->delim = delim; + pi->dlen = dlen; + pi->pos = s; + pi->n = n; + pi->segment_length = 0; + + return pi; +} + +unsigned char * +coap_parse_next(coap_parse_iterator_t *pi) +{ + unsigned char *p; + + if (!pi) + return NULL; + + /* proceed to the next segment */ + pi->n -= pi->segment_length; + pi->pos += pi->segment_length; + pi->segment_length = 0; + + /* last segment? */ + if (!pi->n || strnchr(pi->delim, pi->dlen, *pi->pos)) + { + pi->pos = NULL; + return NULL; + } + + /* skip following separator (the first segment might not have one) */ + if (*pi->pos == pi->separator) + { + ++pi->pos; + --pi->n; + } + + p = pi->pos; + + while (pi->segment_length < pi->n && *p != pi->separator && !strnchr(pi->delim, pi->dlen, *p)) + { + ++p; + ++pi->segment_length; + } + + if (!pi->n) + { + pi->pos = NULL; + pi->segment_length = 0; + } + + return pi->pos; +} + diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/uri.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/uri.h new file mode 100644 index 000000000..20dd28e53 --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/uri.h @@ -0,0 +1,171 @@ +/* uri.h -- helper functions for URI treatment + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#ifndef _COAP_URI_H_ +#define _COAP_URI_H_ + +#include "hashkey.h" +#include "str.h" + +/** Representation of parsed URI. Components may be filled from a + * string with coap_split_uri() and can be used as input for + * option-creation functions. */ +typedef struct +{ + str host; /**< host part of the URI */ + unsigned short port; /**< The port in host byte order */ + str path; /**< Beginning of the first path segment. + Use coap_split_path() to create Uri-Path options */ + str query; /**< The query part if present */ +} coap_uri_t; + +/** + * Creates a new coap_uri_t object from the specified URI. Returns the new + * object or NULL on error. The memory allocated by the new coap_uri_t + * must be released using coap_free(). + * @param uri The URI path to copy. + * @para length The length of uri. + * + * @return New URI object or NULL on error. + */ +coap_uri_t *coap_new_uri(const unsigned char *uri, unsigned int length); + +/** + * Clones the specified coap_uri_t object. Thie function allocates sufficient + * memory to hold the coap_uri_t structure and its contents. The object must + * be released with coap_free(). */ +coap_uri_t *coap_clone_uri(const coap_uri_t *uri); + +/** + * Calculates a hash over the given path and stores the result in + * @p key. This function returns @c 0 on error or @c 1 on success. + * + * @param path The URI path to generate hash for. + * @param len The length of @p path. + * @param key The output buffer. + * + * @return @c 1 if @p key was set, @c 0 otherwise. + */ +int coap_hash_path(const unsigned char *path, size_t len, coap_key_t key); + +/** + * @defgroup uri_parse URI Parsing Functions + * + * CoAP PDUs contain normalized URIs with their path and query split into + * multiple segments. The functions in this module help splitting strings. + * @{ + */ + +/** + * Iterator to for tokenizing a URI path or query. This structure must + * be initialized with coap_parse_iterator_init(). Call + * coap_parse_next() to walk through the tokens. + * + * @code + * unsigned char *token; + * coap_parse_iterator_t pi; + * coap_parse_iterator_init(uri.path.s, uri.path.length, '/', "?#", 2, &pi); + * + * while ((token = coap_parse_next(&pi))) { + * ... do something with token ... + * } + * @endcode + */ +typedef struct +{ + size_t n; /**< number of remaining characters in buffer */ + unsigned char separator; /**< segment separators */ + unsigned char *delim; /**< delimiters where to split the string */ + size_t dlen; /**< length of separator */ + unsigned char *pos; /**< current position in buffer */ + size_t segment_length; /**< length of current segment */ +} coap_parse_iterator_t; + +/** + * Initializes the given iterator @p pi. + * + * @param s The string to tokenize. + * @param n The length of @p s. + * @param separator The separator character that delimits tokens. + * @param delim A set of characters that delimit @s. + * @param dlen The length of @p delim. + * @param pi The iterator object to initialize. + * + * @return The initialized iterator object @p pi. + */ +coap_parse_iterator_t * +coap_parse_iterator_init(unsigned char *s, size_t n, unsigned char separator, unsigned char *delim, + size_t dlen, coap_parse_iterator_t *pi); + +/** + * Updates the iterator @p pi to point to the next token. This + * function returns a pointer to that token or @c NULL if no more + * tokens exist. The contents of @p pi will be updated. In particular, + * @c pi->segment_length specifies the length of the current token, @c + * pi->pos points to its beginning. + * + * @param pi The iterator to update. + * + * @return The next token or @c NULL if no more tokens exist. + */ +unsigned char *coap_parse_next(coap_parse_iterator_t *pi); + +/** + * Parses a given string into URI components. The identified syntactic + * components are stored in the result parameter @p uri. Optional URI + * components that are not specified will be set to { 0, 0 }, except + * for the port which is set to @c COAP_DEFAULT_PORT. This function + * returns @p 0 if parsing succeeded, a value less than zero + * otherwise. + * + * @param str_var The string to split up. + * @param len The actual length of @p str_var + * @param uri The coap_uri_t object to store the result. + * @return @c 0 on success, or < 0 on error. + * + * @note The host name part will be converted to lower case by this + * function. + */ +int +coap_split_uri(unsigned char *str_var, size_t len, coap_uri_t *uri); + +/** + * Splits the given URI path into segments. Each segment is preceded + * by an option pseudo-header with delta-value 0 and the actual length + * of the respective segment after percent-decoding. + * + * @param s The path string to split. + * @param length The actual length of @p s. + * @param buf Result buffer for parsed segments. + * @param buflen Maximum length of @p buf. Will be set to the actual number + * of bytes written into buf on success. + * + * @return The number of segments created or @c -1 on error. + */ +int coap_split_path(const unsigned char *s, size_t length, unsigned char *buf, size_t *buflen); + +/** + * Splits the given URI query into segments. Each segment is preceded + * by an option pseudo-header with delta-value 0 and the actual length + * of the respective query term. + * + * @param s The query string to split. + * @param length The actual length of @p s. + * @param buf Result buffer for parsed segments. + * @param buflen Maximum length of @p buf. Will be set to the actual number + * of bytes written into buf on success. + * + * @return The number of segments created or @c -1 on error. + * + * @bug This function does not reserve additional space for delta > 12. + */ +int coap_split_query(const unsigned char *s, size_t length, unsigned char *buf, size_t *buflen); + +/** @} */ + +#endif /* _COAP_URI_H_ */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/uthash.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/uthash.h new file mode 100644 index 000000000..21e81410d --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/uthash.h @@ -0,0 +1,974 @@ +/* + Copyright (c) 2003-2010, Troy D. Hanson http://uthash.sourceforge.net + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef UTHASH_H +#define UTHASH_H + +#include /* memcmp,strlen */ +#include /* ptrdiff_t */ + +/* These macros use decltype or the earlier __typeof GNU extension. + As decltype is only available in newer compilers (VS2010 or gcc 4.3+ + when compiling c++ source) this code uses whatever method is needed + or, for VS2008 where neither is available, uses casting workarounds. */ +#ifdef _MSC_VER /* MS compiler */ +#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ +#define DECLTYPE(x) (decltype(x)) +#else /* VS2008 or older (or VS2010 in C mode) */ +#define NO_DECLTYPE +#define DECLTYPE(x) +#endif +#else /* GNU, Sun and other compilers */ +#define DECLTYPE(x) (__typeof(x)) +#endif + +#ifdef NO_DECLTYPE +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + char **_da_dst = (char**)(&(dst)); \ + *_da_dst = (char*)(src); \ +} while(0) +#else +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + (dst) = DECLTYPE(dst)(src); \ +} while(0) +#endif + +/* a number of the hash function use uint32_t which isn't defined on win32 */ +#ifdef _MSC_VER +typedef unsigned int uint32_t; +#else +#include /* uint32_t */ +#endif + +#define UTHASH_VERSION 1.9.3 + +#ifndef uthash_fatal +#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */ +#endif +#define uthash_malloc(sz) malloc(sz) /* malloc fcn */ +#define uthash_free(ptr,sz) free(ptr) /* free fcn */ + +#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ +#define uthash_expand_fyi(tbl) /* can be defined to log expands */ + +/* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */ +#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */ + +/* calculate the element whose hash handle address is hhe */ +#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) + +#define HASH_FIND(hh,head,keyptr,keylen,out) \ +do { \ + unsigned _hf_bkt,_hf_hashv; \ + out=NULL; \ + if (head) { \ + HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \ + if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \ + HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \ + keyptr,keylen,out); \ + } \ + } \ +} while (0) + +#ifdef HASH_BLOOM +#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM) +#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0) +#define HASH_BLOOM_MAKE(tbl) \ +do { \ + (tbl)->bloom_nbits = HASH_BLOOM; \ + (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ + if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \ + memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \ + (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ +} while (0); + +#define HASH_BLOOM_FREE(tbl) \ +do { \ + uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ +} while (0); + +#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8))) +#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8))) + +#define HASH_BLOOM_ADD(tbl,hashv) \ + HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) + +#define HASH_BLOOM_TEST(tbl,hashv) \ + HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) + +#else +#define HASH_BLOOM_MAKE(tbl) +#define HASH_BLOOM_FREE(tbl) +#define HASH_BLOOM_ADD(tbl,hashv) +#define HASH_BLOOM_TEST(tbl,hashv) (1) +#endif + +#define HASH_MAKE_TABLE(hh,head) \ +do { \ + (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \ + sizeof(UT_hash_table)); \ + if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \ + memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \ + (head)->hh.tbl->tail = &((head)->hh); \ + (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ + (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ + (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ + (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ + HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ + if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \ + memset((head)->hh.tbl->buckets, 0, \ + HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ + HASH_BLOOM_MAKE((head)->hh.tbl); \ + (head)->hh.tbl->signature = HASH_SIGNATURE; \ +} while(0) + +#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ + HASH_ADD_KEYPTR(hh,head,&add->fieldname,keylen_in,add) + +#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ +do { \ + unsigned _ha_bkt; \ + (add)->hh.next = NULL; \ + (add)->hh.key = (char*)keyptr; \ + (add)->hh.keylen = keylen_in; \ + if (!(head)) { \ + head = (add); \ + (head)->hh.prev = NULL; \ + HASH_MAKE_TABLE(hh,head); \ + } else { \ + (head)->hh.tbl->tail->next = (add); \ + (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ + (head)->hh.tbl->tail = &((add)->hh); \ + } \ + (head)->hh.tbl->num_items++; \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \ + (add)->hh.hashv, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \ + HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \ + HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \ + HASH_FSCK(hh,head); \ +} while(0) + +#define HASH_TO_BKT( hashv, num_bkts, bkt ) \ +do { \ + bkt = ((hashv) & ((num_bkts) - 1)); \ +} while(0) + +/* delete "delptr" from the hash table. + * "the usual" patch-up process for the app-order doubly-linked-list. + * The use of _hd_hh_del below deserves special explanation. + * These used to be expressed using (delptr) but that led to a bug + * if someone used the same symbol for the head and deletee, like + * HASH_DELETE(hh,users,users); + * We want that to work, but by changing the head (users) below + * we were forfeiting our ability to further refer to the deletee (users) + * in the patch-up process. Solution: use scratch space to + * copy the deletee pointer, then the latter references are via that + * scratch pointer rather than through the repointed (users) symbol. + */ +#define HASH_DELETE(hh,head,delptr) \ +do { \ + unsigned _hd_bkt; \ + struct UT_hash_handle *_hd_hh_del; \ + if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + head = NULL; \ + } else { \ + _hd_hh_del = &((delptr)->hh); \ + if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \ + (head)->hh.tbl->tail = \ + (UT_hash_handle*)((char*)((delptr)->hh.prev) + \ + (head)->hh.tbl->hho); \ + } \ + if ((delptr)->hh.prev) { \ + ((UT_hash_handle*)((char*)((delptr)->hh.prev) + \ + (head)->hh.tbl->hho))->next = (delptr)->hh.next; \ + } else { \ + DECLTYPE_ASSIGN(head,(delptr)->hh.next); \ + } \ + if (_hd_hh_del->next) { \ + ((UT_hash_handle*)((char*)_hd_hh_del->next + \ + (head)->hh.tbl->hho))->prev = \ + _hd_hh_del->prev; \ + } \ + HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ + HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ + (head)->hh.tbl->num_items--; \ + } \ + HASH_FSCK(hh,head); \ +} while (0) + +/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ +#define HASH_FIND_STR(head,findstr,out) \ + HASH_FIND(hh,head,findstr,strlen(findstr),out) +#define HASH_ADD_STR(head,strfield,add) \ + HASH_ADD(hh,head,strfield,strlen(add->strfield),add) +#define HASH_FIND_INT(head,findint,out) \ + HASH_FIND(hh,head,findint,sizeof(int),out) +#define HASH_ADD_INT(head,intfield,add) \ + HASH_ADD(hh,head,intfield,sizeof(int),add) +#define HASH_FIND_PTR(head,findptr,out) \ + HASH_FIND(hh,head,findptr,sizeof(void *),out) +#define HASH_ADD_PTR(head,ptrfield,add) \ + HASH_ADD(hh,head,ptrfield,sizeof(void *),add) +#define HASH_DEL(head,delptr) \ + HASH_DELETE(hh,head,delptr) + +/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. + * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. + */ +#ifdef HASH_DEBUG +#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0) +#define HASH_FSCK(hh,head) \ +do { \ + unsigned _bkt_i; \ + unsigned _count, _bkt_count; \ + char *_prev; \ + struct UT_hash_handle *_thh; \ + if (head) { \ + _count = 0; \ + for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \ + _bkt_count = 0; \ + _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ + _prev = NULL; \ + while (_thh) { \ + if (_prev != (char*)(_thh->hh_prev)) { \ + HASH_OOPS("invalid hh_prev %p, actual %p\n", \ + _thh->hh_prev, _prev ); \ + } \ + _bkt_count++; \ + _prev = (char*)(_thh); \ + _thh = _thh->hh_next; \ + } \ + _count += _bkt_count; \ + if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ + HASH_OOPS("invalid bucket count %d, actual %d\n", \ + (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ + } \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("invalid hh item count %d, actual %d\n", \ + (head)->hh.tbl->num_items, _count ); \ + } \ + /* traverse hh in app order; check next/prev integrity, count */ \ + _count = 0; \ + _prev = NULL; \ + _thh = &(head)->hh; \ + while (_thh) { \ + _count++; \ + if (_prev !=(char*)(_thh->prev)) { \ + HASH_OOPS("invalid prev %p, actual %p\n", \ + _thh->prev, _prev ); \ + } \ + _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ + _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \ + (head)->hh.tbl->hho) : NULL ); \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("invalid app item count %d, actual %d\n", \ + (head)->hh.tbl->num_items, _count ); \ + } \ + } \ +} while (0) +#else +#define HASH_FSCK(hh,head) +#endif + +/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to + * the descriptor to which this macro is defined for tuning the hash function. + * The app can #include to get the prototype for write(2). */ +#ifdef HASH_EMIT_KEYS +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ +do { \ + unsigned _klen = fieldlen; \ + write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ + write(HASH_EMIT_KEYS, keyptr, fieldlen); \ +} while (0) +#else +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) +#endif + +/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */ +#ifdef HASH_FUNCTION +#define HASH_FCN HASH_FUNCTION +#else +#define HASH_FCN HASH_JEN +#endif + +/* The Bernstein hash function, used in Perl prior to v5.6 */ +#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \ +do { \ + unsigned _hb_keylen=keylen; \ + char *_hb_key=(char*)(key); \ + (hashv) = 0; \ + while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \ + bkt = (hashv) & (num_bkts-1); \ +} while (0) + +/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at + * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */ +#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \ +do { \ + unsigned _sx_i; \ + char *_hs_key=(char*)(key); \ + hashv = 0; \ + for(_sx_i=0; _sx_i < keylen; _sx_i++) \ + hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ + bkt = hashv & (num_bkts-1); \ +} while (0) + +#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \ +do { \ + unsigned _fn_i; \ + char *_hf_key=(char*)(key); \ + hashv = 2166136261UL; \ + for(_fn_i=0; _fn_i < keylen; _fn_i++) \ + hashv = (hashv * 16777619) ^ _hf_key[_fn_i]; \ + bkt = hashv & (num_bkts-1); \ +} while(0); + +#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \ +do { \ + unsigned _ho_i; \ + char *_ho_key=(char*)(key); \ + hashv = 0; \ + for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ + hashv += _ho_key[_ho_i]; \ + hashv += (hashv << 10); \ + hashv ^= (hashv >> 6); \ + } \ + hashv += (hashv << 3); \ + hashv ^= (hashv >> 11); \ + hashv += (hashv << 15); \ + bkt = hashv & (num_bkts-1); \ +} while(0) + +#define HASH_JEN_MIX(a,b,c) \ +do { \ + a -= b; a -= c; a ^= ( c >> 13 ); \ + b -= c; b -= a; b ^= ( a << 8 ); \ + c -= a; c -= b; c ^= ( b >> 13 ); \ + a -= b; a -= c; a ^= ( c >> 12 ); \ + b -= c; b -= a; b ^= ( a << 16 ); \ + c -= a; c -= b; c ^= ( b >> 5 ); \ + a -= b; a -= c; a ^= ( c >> 3 ); \ + b -= c; b -= a; b ^= ( a << 10 ); \ + c -= a; c -= b; c ^= ( b >> 15 ); \ +} while (0) + +#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \ +do { \ + unsigned _hj_i,_hj_j,_hj_k; \ + char *_hj_key=(char*)(key); \ + hashv = 0xfeedbeef; \ + _hj_i = _hj_j = 0x9e3779b9; \ + _hj_k = keylen; \ + while (_hj_k >= 12) { \ + _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ + + ( (unsigned)_hj_key[2] << 16 ) \ + + ( (unsigned)_hj_key[3] << 24 ) ); \ + _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ + + ( (unsigned)_hj_key[6] << 16 ) \ + + ( (unsigned)_hj_key[7] << 24 ) ); \ + hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ + + ( (unsigned)_hj_key[10] << 16 ) \ + + ( (unsigned)_hj_key[11] << 24 ) ); \ + \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ + \ + _hj_key += 12; \ + _hj_k -= 12; \ + } \ + hashv += keylen; \ + switch ( _hj_k ) { \ + case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \ + case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \ + case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \ + case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \ + case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \ + case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \ + case 5: _hj_j += _hj_key[4]; \ + case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \ + case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \ + case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \ + case 1: _hj_i += _hj_key[0]; \ + } \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ + bkt = hashv & (num_bkts-1); \ +} while(0) + +/* The Paul Hsieh hash function */ +#undef get16bits +#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ + || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) +#define get16bits(d) (*((const uint16_t *) (d))) +#endif + +#if !defined (get16bits) +#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ + +(uint32_t)(((const uint8_t *)(d))[0]) ) +#endif +#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \ +do { \ + char *_sfh_key=(char*)(key); \ + uint32_t _sfh_tmp, _sfh_len = keylen; \ + \ + int _sfh_rem = _sfh_len & 3; \ + _sfh_len >>= 2; \ + hashv = 0xcafebabe; \ + \ + /* Main loop */ \ + for (;_sfh_len > 0; _sfh_len--) { \ + hashv += get16bits (_sfh_key); \ + _sfh_tmp = (get16bits (_sfh_key+2) << 11) ^ hashv; \ + hashv = (hashv << 16) ^ _sfh_tmp; \ + _sfh_key += 2*sizeof (uint16_t); \ + hashv += hashv >> 11; \ + } \ + \ + /* Handle end cases */ \ + switch (_sfh_rem) { \ + case 3: hashv += get16bits (_sfh_key); \ + hashv ^= hashv << 16; \ + hashv ^= _sfh_key[sizeof (uint16_t)] << 18; \ + hashv += hashv >> 11; \ + break; \ + case 2: hashv += get16bits (_sfh_key); \ + hashv ^= hashv << 11; \ + hashv += hashv >> 17; \ + break; \ + case 1: hashv += *_sfh_key; \ + hashv ^= hashv << 10; \ + hashv += hashv >> 1; \ + } \ + \ + /* Force "avalanching" of final 127 bits */ \ + hashv ^= hashv << 3; \ + hashv += hashv >> 5; \ + hashv ^= hashv << 4; \ + hashv += hashv >> 17; \ + hashv ^= hashv << 25; \ + hashv += hashv >> 6; \ + bkt = hashv & (num_bkts-1); \ +} while(0); + +#ifdef HASH_USING_NO_STRICT_ALIASING +/* The MurmurHash exploits some CPU's (e.g. x86) tolerance for unaligned reads. + * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error. + * So MurmurHash comes in two versions, the faster unaligned one and the slower + * aligned one. We only use the faster one on CPU's where we know it's safe. + * + * Note the preprocessor built-in defines can be emitted using: + * + * gcc -m64 -dM -E - < /dev/null (on gcc) + * cc -## a.c (where a.c is a simple test file) (Sun Studio) + */ +#if (defined(__i386__) || defined(__x86_64__)) +#define HASH_MUR HASH_MUR_UNALIGNED +#else +#define HASH_MUR HASH_MUR_ALIGNED +#endif + +/* Appleby's MurmurHash fast version for unaligned-tolerant archs like i386 */ +#define HASH_MUR_UNALIGNED(key,keylen,num_bkts,hashv,bkt) \ +do { \ + const unsigned int _mur_m = 0x5bd1e995; \ + const int _mur_r = 24; \ + hashv = 0xcafebabe ^ keylen; \ + char *_mur_key = (char *)(key); \ + uint32_t _mur_tmp, _mur_len = keylen; \ + \ + for (;_mur_len >= 4; _mur_len-=4) { \ + _mur_tmp = *(uint32_t *)_mur_key; \ + _mur_tmp *= _mur_m; \ + _mur_tmp ^= _mur_tmp >> _mur_r; \ + _mur_tmp *= _mur_m; \ + hashv *= _mur_m; \ + hashv ^= _mur_tmp; \ + _mur_key += 4; \ + } \ + \ + switch(_mur_len) \ + { \ + case 3: hashv ^= _mur_key[2] << 16; \ + case 2: hashv ^= _mur_key[1] << 8; \ + case 1: hashv ^= _mur_key[0]; \ + hashv *= _mur_m; \ + }; \ + \ + hashv ^= hashv >> 13; \ + hashv *= _mur_m; \ + hashv ^= hashv >> 15; \ + \ + bkt = hashv & (num_bkts-1); \ +} while(0) + +/* Appleby's MurmurHash version for alignment-sensitive archs like Sparc */ +#define HASH_MUR_ALIGNED(key,keylen,num_bkts,hashv,bkt) \ +do { \ + const unsigned int _mur_m = 0x5bd1e995; \ + const int _mur_r = 24; \ + hashv = 0xcafebabe ^ (keylen); \ + char *_mur_key = (char *)(key); \ + uint32_t _mur_len = keylen; \ + int _mur_align = (int)_mur_key & 3; \ + \ + if (_mur_align && (_mur_len >= 4)) { \ + unsigned _mur_t = 0, _mur_d = 0; \ + switch(_mur_align) { \ + case 1: _mur_t |= _mur_key[2] << 16; \ + case 2: _mur_t |= _mur_key[1] << 8; \ + case 3: _mur_t |= _mur_key[0]; \ + } \ + _mur_t <<= (8 * _mur_align); \ + _mur_key += 4-_mur_align; \ + _mur_len -= 4-_mur_align; \ + int _mur_sl = 8 * (4-_mur_align); \ + int _mur_sr = 8 * _mur_align; \ + \ + for (;_mur_len >= 4; _mur_len-=4) { \ + _mur_d = *(unsigned *)_mur_key; \ + _mur_t = (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \ + unsigned _mur_k = _mur_t; \ + _mur_k *= _mur_m; \ + _mur_k ^= _mur_k >> _mur_r; \ + _mur_k *= _mur_m; \ + hashv *= _mur_m; \ + hashv ^= _mur_k; \ + _mur_t = _mur_d; \ + _mur_key += 4; \ + } \ + _mur_d = 0; \ + if(_mur_len >= _mur_align) { \ + switch(_mur_align) { \ + case 3: _mur_d |= _mur_key[2] << 16; \ + case 2: _mur_d |= _mur_key[1] << 8; \ + case 1: _mur_d |= _mur_key[0]; \ + } \ + unsigned _mur_k = (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \ + _mur_k *= _mur_m; \ + _mur_k ^= _mur_k >> _mur_r; \ + _mur_k *= _mur_m; \ + hashv *= _mur_m; \ + hashv ^= _mur_k; \ + _mur_k += _mur_align; \ + _mur_len -= _mur_align; \ + \ + switch(_mur_len) \ + { \ + case 3: hashv ^= _mur_key[2] << 16; \ + case 2: hashv ^= _mur_key[1] << 8; \ + case 1: hashv ^= _mur_key[0]; \ + hashv *= _mur_m; \ + } \ + } else { \ + switch(_mur_len) \ + { \ + case 3: _mur_d ^= _mur_key[2] << 16; \ + case 2: _mur_d ^= _mur_key[1] << 8; \ + case 1: _mur_d ^= _mur_key[0]; \ + case 0: hashv ^= (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \ + hashv *= _mur_m; \ + } \ + } \ + \ + hashv ^= hashv >> 13; \ + hashv *= _mur_m; \ + hashv ^= hashv >> 15; \ + } else { \ + for (;_mur_len >= 4; _mur_len-=4) { \ + unsigned _mur_k = *(unsigned*)_mur_key; \ + _mur_k *= _mur_m; \ + _mur_k ^= _mur_k >> _mur_r; \ + _mur_k *= _mur_m; \ + hashv *= _mur_m; \ + hashv ^= _mur_k; \ + _mur_key += 4; \ + } \ + switch(_mur_len) \ + { \ + case 3: hashv ^= _mur_key[2] << 16; \ + case 2: hashv ^= _mur_key[1] << 8; \ + case 1: hashv ^= _mur_key[0]; \ + hashv *= _mur_m; \ + } \ + \ + hashv ^= hashv >> 13; \ + hashv *= _mur_m; \ + hashv ^= hashv >> 15; \ + } \ + bkt = hashv & (num_bkts-1); \ +} while(0) +#endif /* HASH_USING_NO_STRICT_ALIASING */ + +/* key comparison function; return 0 if keys equal */ +#define HASH_KEYCMP(a,b,len) memcmp(a,b,len) + +/* iterate over items in a known bucket to find desired item */ +#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \ +do { \ + if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \ + else out=NULL; \ + while (out) { \ + if (out->hh.keylen == keylen_in) { \ + if ((HASH_KEYCMP(out->hh.key,keyptr,keylen_in)) == 0) break; \ + } \ + if (out->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,out->hh.hh_next)); \ + else out = NULL; \ + } \ +} while(0) + +/* add an item to a bucket */ +#define HASH_ADD_TO_BKT(head,addhh) \ +do { \ + head.count++; \ + (addhh)->hh_next = head.hh_head; \ + (addhh)->hh_prev = NULL; \ + if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \ + (head).hh_head=addhh; \ + if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \ + && (addhh)->tbl->noexpand != 1) { \ + HASH_EXPAND_BUCKETS((addhh)->tbl); \ + } \ +} while(0) + +/* remove an item from a given bucket */ +#define HASH_DEL_IN_BKT(hh,head,hh_del) \ + (head).count--; \ + if ((head).hh_head == hh_del) { \ + (head).hh_head = hh_del->hh_next; \ + } \ + if (hh_del->hh_prev) { \ + hh_del->hh_prev->hh_next = hh_del->hh_next; \ + } \ + if (hh_del->hh_next) { \ + hh_del->hh_next->hh_prev = hh_del->hh_prev; \ + } + +/* Bucket expansion has the effect of doubling the number of buckets + * and redistributing the items into the new buckets. Ideally the + * items will distribute more or less evenly into the new buckets + * (the extent to which this is true is a measure of the quality of + * the hash function as it applies to the key domain). + * + * With the items distributed into more buckets, the chain length + * (item count) in each bucket is reduced. Thus by expanding buckets + * the hash keeps a bound on the chain length. This bounded chain + * length is the essence of how a hash provides constant time lookup. + * + * The calculation of tbl->ideal_chain_maxlen below deserves some + * explanation. First, keep in mind that we're calculating the ideal + * maximum chain length based on the *new* (doubled) bucket count. + * In fractions this is just n/b (n=number of items,b=new num buckets). + * Since the ideal chain length is an integer, we want to calculate + * ceil(n/b). We don't depend on floating point arithmetic in this + * hash, so to calculate ceil(n/b) with integers we could write + * + * ceil(n/b) = (n/b) + ((n%b)?1:0) + * + * and in fact a previous version of this hash did just that. + * But now we have improved things a bit by recognizing that b is + * always a power of two. We keep its base 2 log handy (call it lb), + * so now we can write this with a bit shift and logical AND: + * + * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) + * + */ +#define HASH_EXPAND_BUCKETS(tbl) \ +do { \ + unsigned _he_bkt; \ + unsigned _he_bkt_i; \ + struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ + UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ + _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ + 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \ + memset(_he_new_buckets, 0, \ + 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + tbl->ideal_chain_maxlen = \ + (tbl->num_items >> (tbl->log2_num_buckets+1)) + \ + ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \ + tbl->nonideal_items = 0; \ + for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \ + { \ + _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \ + while (_he_thh) { \ + _he_hh_nxt = _he_thh->hh_next; \ + HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \ + _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \ + if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \ + tbl->nonideal_items++; \ + _he_newbkt->expand_mult = _he_newbkt->count / \ + tbl->ideal_chain_maxlen; \ + } \ + _he_thh->hh_prev = NULL; \ + _he_thh->hh_next = _he_newbkt->hh_head; \ + if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \ + _he_thh; \ + _he_newbkt->hh_head = _he_thh; \ + _he_thh = _he_hh_nxt; \ + } \ + } \ + uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ + tbl->num_buckets *= 2; \ + tbl->log2_num_buckets++; \ + tbl->buckets = _he_new_buckets; \ + tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \ + (tbl->ineff_expands+1) : 0; \ + if (tbl->ineff_expands > 1) { \ + tbl->noexpand=1; \ + uthash_noexpand_fyi(tbl); \ + } \ + uthash_expand_fyi(tbl); \ +} while(0) + +/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ +/* Note that HASH_SORT assumes the hash handle name to be hh. + * HASH_SRT was added to allow the hash handle name to be passed in. */ +#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) +#define HASH_SRT(hh,head,cmpfcn) \ +do { \ + unsigned _hs_i; \ + unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ + struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ + if (head) { \ + _hs_insize = 1; \ + _hs_looping = 1; \ + _hs_list = &((head)->hh); \ + while (_hs_looping) { \ + _hs_p = _hs_list; \ + _hs_list = NULL; \ + _hs_tail = NULL; \ + _hs_nmerges = 0; \ + while (_hs_p) { \ + _hs_nmerges++; \ + _hs_q = _hs_p; \ + _hs_psize = 0; \ + for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \ + _hs_psize++; \ + _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ + ((void*)((char*)(_hs_q->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + if (! (_hs_q) ) break; \ + } \ + _hs_qsize = _hs_insize; \ + while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \ + if (_hs_psize == 0) { \ + _hs_e = _hs_q; \ + _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ + ((void*)((char*)(_hs_q->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + _hs_qsize--; \ + } else if ( (_hs_qsize == 0) || !(_hs_q) ) { \ + _hs_e = _hs_p; \ + _hs_p = (UT_hash_handle*)((_hs_p->next) ? \ + ((void*)((char*)(_hs_p->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + _hs_psize--; \ + } else if (( \ + cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \ + DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \ + ) <= 0) { \ + _hs_e = _hs_p; \ + _hs_p = (UT_hash_handle*)((_hs_p->next) ? \ + ((void*)((char*)(_hs_p->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + _hs_psize--; \ + } else { \ + _hs_e = _hs_q; \ + _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ + ((void*)((char*)(_hs_q->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + _hs_qsize--; \ + } \ + if ( _hs_tail ) { \ + _hs_tail->next = ((_hs_e) ? \ + ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \ + } else { \ + _hs_list = _hs_e; \ + } \ + _hs_e->prev = ((_hs_tail) ? \ + ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \ + _hs_tail = _hs_e; \ + } \ + _hs_p = _hs_q; \ + } \ + _hs_tail->next = NULL; \ + if ( _hs_nmerges <= 1 ) { \ + _hs_looping=0; \ + (head)->hh.tbl->tail = _hs_tail; \ + DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ + } \ + _hs_insize *= 2; \ + } \ + HASH_FSCK(hh,head); \ + } \ +} while (0) + +/* This function selects items from one hash into another hash. + * The end result is that the selected items have dual presence + * in both hashes. There is no copy of the items made; rather + * they are added into the new hash through a secondary hash + * hash handle that must be present in the structure. */ +#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ +do { \ + unsigned _src_bkt, _dst_bkt; \ + void *_last_elt=NULL, *_elt; \ + UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ + ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ + if (src) { \ + for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ + for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ + _src_hh; \ + _src_hh = _src_hh->hh_next) { \ + _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ + if (cond(_elt)) { \ + _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \ + _dst_hh->key = _src_hh->key; \ + _dst_hh->keylen = _src_hh->keylen; \ + _dst_hh->hashv = _src_hh->hashv; \ + _dst_hh->prev = _last_elt; \ + _dst_hh->next = NULL; \ + if (_last_elt_hh) { _last_elt_hh->next = _elt; } \ + if (!dst) { \ + DECLTYPE_ASSIGN(dst,_elt); \ + HASH_MAKE_TABLE(hh_dst,dst); \ + } else { \ + _dst_hh->tbl = (dst)->hh_dst.tbl; \ + } \ + HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ + HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \ + (dst)->hh_dst.tbl->num_items++; \ + _last_elt = _elt; \ + _last_elt_hh = _dst_hh; \ + } \ + } \ + } \ + } \ + HASH_FSCK(hh_dst,dst); \ +} while (0) + +#define HASH_CLEAR(hh,head) \ +do { \ + if (head) { \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head)=NULL; \ + } \ +} while(0) + +#ifdef NO_DECLTYPE +#define HASH_ITER(hh,head,el,tmp) \ +for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \ + el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL)) +#else +#define HASH_ITER(hh,head,el,tmp) \ +for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \ + el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL)) +#endif + +/* obtain a count of items in the hash */ +#define HASH_COUNT(head) HASH_CNT(hh,head) +#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0) + +typedef struct UT_hash_bucket +{ + struct UT_hash_handle *hh_head; + unsigned count; + + /* expand_mult is normally set to 0. In this situation, the max chain length + * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If + * the bucket's chain exceeds this length, bucket expansion is triggered). + * However, setting expand_mult to a non-zero value delays bucket expansion + * (that would be triggered by additions to this particular bucket) + * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. + * (The multiplier is simply expand_mult+1). The whole idea of this + * multiplier is to reduce bucket expansions, since they are expensive, in + * situations where we know that a particular bucket tends to be overused. + * It is better to let its chain length grow to a longer yet-still-bounded + * value, than to do an O(n) bucket expansion too often. + */ + unsigned expand_mult; + +} UT_hash_bucket; + +/* random signature used only to find hash tables in external analysis */ +#define HASH_SIGNATURE 0xa0111fe1 +#define HASH_BLOOM_SIGNATURE 0xb12220f2 + +typedef struct UT_hash_table +{ + UT_hash_bucket *buckets; + unsigned num_buckets, log2_num_buckets; + unsigned num_items; + struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ + ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ + + /* in an ideal situation (all buckets used equally), no bucket would have + * more than ceil(#items/#buckets) items. that's the ideal chain length. */ + unsigned ideal_chain_maxlen; + + /* nonideal_items is the number of items in the hash whose chain position + * exceeds the ideal chain maxlen. these items pay the penalty for an uneven + * hash distribution; reaching them in a chain traversal takes >ideal steps */ + unsigned nonideal_items; + + /* ineffective expands occur when a bucket doubling was performed, but + * afterward, more than half the items in the hash had nonideal chain + * positions. If this happens on two consecutive expansions we inhibit any + * further expansion, as it's not helping; this happens when the hash + * function isn't a good fit for the key domain. When expansion is inhibited + * the hash will still work, albeit no longer in constant time. */ + unsigned ineff_expands, noexpand; + + uint32_t signature; /* used only to find hash tables in external analysis */ +#ifdef HASH_BLOOM + uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ + uint8_t *bloom_bv; + char bloom_nbits; +#endif + +} UT_hash_table; + +typedef struct UT_hash_handle +{ + struct UT_hash_table *tbl; + void *prev; /* prev element in app order */ + void *next; /* next element in app order */ + struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ + struct UT_hash_handle *hh_next; /* next hh in bucket order */ + void *key; /* ptr to enclosing struct's key */ + unsigned keylen; /* enclosing struct's key len */ + unsigned hashv; /* result of hash-fcn(key) */ +} UT_hash_handle; + +#endif /* UTHASH_H */ diff --git a/resource/csdk/connectivity/lib/libcoap-4.1.1/utlist.h b/resource/csdk/connectivity/lib/libcoap-4.1.1/utlist.h new file mode 100644 index 000000000..4073e041f --- /dev/null +++ b/resource/csdk/connectivity/lib/libcoap-4.1.1/utlist.h @@ -0,0 +1,489 @@ +/* + Copyright (c) 2007-2010, Troy D. Hanson http://uthash.sourceforge.net + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef UTLIST_H +#define UTLIST_H + +#define UTLIST_VERSION 1.9.1 + +/* + * This file contains macros to manipulate singly and doubly-linked lists. + * + * 1. LL_ macros: singly-linked lists. + * 2. DL_ macros: doubly-linked lists. + * 3. CDL_ macros: circular doubly-linked lists. + * + * To use singly-linked lists, your structure must have a "next" pointer. + * To use doubly-linked lists, your structure must "prev" and "next" pointers. + * Either way, the pointer to the head of the list must be initialized to NULL. + * + * ----------------.EXAMPLE ------------------------- + * struct item { + * int id; + * struct item *prev, *next; + * } + * + * struct item *list = NULL: + * + * int main() { + * struct item *item; + * ... allocate and populate item ... + * DL_APPEND(list, item); + * } + * -------------------------------------------------- + * + * For doubly-linked lists, the append and delete macros are O(1) + * For singly-linked lists, append and delete are O(n) but prepend is O(1) + * The sort macro is O(n log(n)) for all types of single/double/circular lists. + */ + +/* These macros use decltype or the earlier __typeof GNU extension. + As decltype is only available in newer compilers (VS2010 or gcc 4.3+ + when compiling c++ code), this code uses whatever method is needed + or, for VS2008 where neither is available, uses casting workarounds. */ +#ifdef _MSC_VER /* MS compiler */ +#if _MSC_VER >= 1600 && __cplusplus /* VS2010 and newer in C++ mode */ +#define LDECLTYPE(x) decltype(x) +#else /* VS2008 or older (or VS2010 in C mode) */ +#define NO_DECLTYPE +#define LDECLTYPE(x) char* +#endif +#else /* GNU, Sun and other compilers */ +#define LDECLTYPE(x) __typeof(x) +#endif + +/* for VS2008 we use some workarounds to get around the lack of decltype, + * namely, we always reassign our tmp variable to the list head if we need + * to dereference its prev/next pointers, and save/restore the real head.*/ +#ifdef NO_DECLTYPE +#define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); } +#define _NEXT(elt,list) ((char*)((list)->next)) +#define _NEXTASGN(elt,list,to) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); } +#define _PREV(elt,list) ((char*)((list)->prev)) +#define _PREVASGN(elt,list,to) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); } +#define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; } +#define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); } +#else +#define _SV(elt,list) +#define _NEXT(elt,list) ((elt)->next) +#define _NEXTASGN(elt,list,to) ((elt)->next)=(to) +#define _PREV(elt,list) ((elt)->prev) +#define _PREVASGN(elt,list,to) ((elt)->prev)=(to) +#define _RS(list) +#define _CASTASGN(a,b) (a)=(b) +#endif + +/****************************************************************************** + * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort * + * Unwieldy variable names used here to avoid shadowing passed-in variables. * + *****************************************************************************/ +#define LL_SORT(list, cmp) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + LDECLTYPE(list) _ls_oldhead; \ + LDECLTYPE(list) _tmp; \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + _CASTASGN(_ls_p,list); \ + _CASTASGN(_ls_oldhead,list); \ + list = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \ + } else if (_ls_qsize == 0 || !_ls_q) { \ + _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \ + } else { \ + _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \ + } \ + if (_ls_tail) { \ + _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \ + } else { \ + _CASTASGN(list,_ls_e); \ + } \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } else _tmp=NULL; /* quiet gcc unused variable warning */ \ +} while (0) + +#define DL_SORT(list, cmp) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + LDECLTYPE(list) _ls_oldhead; \ + LDECLTYPE(list) _tmp; \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + _CASTASGN(_ls_p,list); \ + _CASTASGN(_ls_oldhead,list); \ + list = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \ + } else if (_ls_qsize == 0 || !_ls_q) { \ + _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \ + } else { \ + _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \ + } \ + if (_ls_tail) { \ + _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \ + } else { \ + _CASTASGN(list,_ls_e); \ + } \ + _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + _CASTASGN(list->prev, _ls_tail); \ + _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } else _tmp=NULL; /* quiet gcc unused variable warning */ \ +} while (0) + +#define CDL_SORT(list, cmp) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + LDECLTYPE(list) _ls_oldhead; \ + LDECLTYPE(list) _tmp; \ + LDECLTYPE(list) _tmp2; \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + _CASTASGN(_ls_p,list); \ + _CASTASGN(_ls_oldhead,list); \ + list = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + _SV(_ls_q,list); \ + if (_NEXT(_ls_q,list) == _ls_oldhead) { \ + _ls_q = NULL; \ + } else { \ + _ls_q = _NEXT(_ls_q,list); \ + } \ + _RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \ + if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ + } else if (_ls_qsize == 0 || !_ls_q) { \ + _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \ + if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \ + if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ + } else { \ + _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \ + if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ + } \ + if (_ls_tail) { \ + _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \ + } else { \ + _CASTASGN(list,_ls_e); \ + } \ + _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + _CASTASGN(list->prev,_ls_tail); \ + _CASTASGN(_tmp2,list); \ + _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp2); _RS(list); \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } else _tmp=NULL; /* quiet gcc unused variable warning */ \ +} while (0) + +/****************************************************************************** + * singly linked list macros (non-circular) * + *****************************************************************************/ +#define LL_PREPEND(head,add) \ +do { \ + (add)->next = head; \ + head = add; \ +} while (0) + +#define LL_APPEND(head,add) \ +do { \ + LDECLTYPE(head) _tmp; \ + (add)->next=NULL; \ + if (head) { \ + _tmp = head; \ + while (_tmp->next) { _tmp = _tmp->next; } \ + _tmp->next=(add); \ + } else { \ + (head)=(add); \ + } \ +} while (0) + +#define LL_DELETE(head,del) \ +do { \ + LDECLTYPE(head) _tmp; \ + if ((head) == (del)) { \ + (head)=(head)->next; \ + } else { \ + _tmp = head; \ + while (_tmp->next && (_tmp->next != (del))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = ((del)->next); \ + } \ + } \ +} while (0) + +/* Here are VS2008 replacements for LL_APPEND and LL_DELETE */ +#define LL_APPEND_VS2008(head,add) \ +do { \ + if (head) { \ + (add)->next = head; /* use add->next as a temp variable */ \ + while ((add)->next->next) { (add)->next = (add)->next->next; } \ + (add)->next->next=(add); \ + } else { \ + (head)=(add); \ + } \ + (add)->next=NULL; \ +} while (0) + +#define LL_DELETE_VS2008(head,del) \ +do { \ + if ((head) == (del)) { \ + (head)=(head)->next; \ + } else { \ + char *_tmp = (char*)(head); \ + while (head->next && (head->next != (del))) { \ + head = head->next; \ + } \ + if (head->next) { \ + head->next = ((del)->next); \ + } \ + { \ + char **_head_alias = (char**)&(head); \ + *_head_alias = _tmp; \ + } \ + } \ +} while (0) +#ifdef NO_DECLTYPE +#undef LL_APPEND +#define LL_APPEND LL_APPEND_VS2008 +#undef LL_DELETE +#define LL_DELETE LL_DELETE_VS2008 +#endif +/* end VS2008 replacements */ + +#define LL_FOREACH(head,el) \ + for(el=head;el;el=el->next) + +#define LL_FOREACH_SAFE(head,el,tmp) \ + for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp) + +#define LL_SEARCH_SCALAR(head,out,field,val) \ +do { \ + LL_FOREACH(head,out) { \ + if ((out)->field == (val)) break; \ + } \ +} while(0) + +#define LL_SEARCH(head,out,elt,cmp) \ +do { \ + LL_FOREACH(head,out) { \ + if ((cmp(out,elt))==0) break; \ + } \ +} while(0) + +/****************************************************************************** + * doubly linked list macros (non-circular) * + *****************************************************************************/ +#define DL_PREPEND(head,add) \ +do { \ + (add)->next = head; \ + if (head) { \ + (add)->prev = (head)->prev; \ + (head)->prev = (add); \ + } else { \ + (add)->prev = (add); \ + } \ + (head) = (add); \ +} while (0) + +#define DL_APPEND(head,add) \ +do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (head)->prev->next = (add); \ + (head)->prev = (add); \ + (add)->next = NULL; \ + } else { \ + (head)=(add); \ + (head)->prev = (head); \ + (head)->next = NULL; \ + } \ +} while (0); + +#define DL_DELETE(head,del) \ +do { \ + if ((del)->prev == (del)) { \ + (head)=NULL; \ + } else if ((del)==(head)) { \ + (del)->next->prev = (del)->prev; \ + (head) = (del)->next; \ + } else { \ + (del)->prev->next = (del)->next; \ + if ((del)->next) { \ + (del)->next->prev = (del)->prev; \ + } else { \ + (head)->prev = (del)->prev; \ + } \ + } \ +} while (0); + +#define DL_FOREACH(head,el) \ + for(el=head;el;el=el->next) + +/* this version is safe for deleting the elements during iteration */ +#define DL_FOREACH_SAFE(head,el,tmp) \ + for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp) + +/* these are identical to their singly-linked list counterparts */ +#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR +#define DL_SEARCH LL_SEARCH + +/****************************************************************************** + * circular doubly linked list macros * + *****************************************************************************/ +#define CDL_PREPEND(head,add) \ +do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (add)->prev->next = (add); \ + } else { \ + (add)->prev = (add); \ + (add)->next = (add); \ + } \ +(head)=(add); \ +} while (0) + +#define CDL_DELETE(head,del) \ +do { \ + if ( ((head)==(del)) && ((head)->next == (head))) { \ + (head) = 0L; \ + } else { \ + (del)->next->prev = (del)->prev; \ + (del)->prev->next = (del)->next; \ + if ((del) == (head)) (head)=(del)->next; \ + } \ +} while (0); + +#define CDL_FOREACH(head,el) \ + for(el=head;el;el=(el->next==head ? 0L : el->next)) + +#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \ + for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \ + (el) && ((tmp2)=(el)->next, 1); \ + ((el) = (((el)==(tmp1)) ? 0L : (tmp2)))) + +#define CDL_SEARCH_SCALAR(head,out,field,val) \ +do { \ + CDL_FOREACH(head,out) { \ + if ((out)->field == (val)) break; \ + } \ +} while(0) + +#define CDL_SEARCH(head,out,elt,cmp) \ +do { \ + CDL_FOREACH(head,out) { \ + if ((cmp(out,elt))==0) break; \ + } \ +} while(0) + +#endif /* UTLIST_H */ + diff --git a/resource/csdk/connectivity/samples/linux/.gitignore b/resource/csdk/connectivity/samples/linux/.gitignore new file mode 100644 index 000000000..1ec70a539 --- /dev/null +++ b/resource/csdk/connectivity/samples/linux/.gitignore @@ -0,0 +1,2 @@ +/.objs/ +/out/ diff --git a/resource/csdk/connectivity/samples/linux/Makefile b/resource/csdk/connectivity/samples/linux/Makefile new file mode 100644 index 000000000..74197a0b5 --- /dev/null +++ b/resource/csdk/connectivity/samples/linux/Makefile @@ -0,0 +1,120 @@ +#/****************************************************************** +# * +# * Copyright 2014 Samsung Electronics All Rights Reserved. +# * +# * +# * +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# * +#******************************************************************/ + +## +## Definitions +## +SHELL = /bin/bash +PROJECT_NAME = connectivity_abstraction +PROJECT_ROOT_PATH = ../.. +PROJECT_API_PATH = $(PROJECT_ROOT_PATH)/api +PROJECT_INC_PATH = $(PROJECT_ROOT_PATH)/inc +PROJECT_SRC_PATH = $(PROJECT_ROOT_PATH)/src +PROJECT_COMMON_PATH = $(PROJECT_ROOT_PATH)/common +PROJECT_OUT_PATH = $(PROJECT_ROOT_PATH)/build/out +COMPONENT_OUT_PATH = ./out +COMPONENT_OBJ_PATH = ./.objs + +TARGET = sample_main + +## +## Commands +## +CC = gcc +CXX = g++ +RM = rm -rf +CP = cp +MV = mv +AR = ar +LD = ld +LN = ln +CD = cd +RANLIB = ranlib + +## +## file declaration +## +COMPONENT_SRCS = sample_main.c \ + +COMPONENT_OBJS = $(COMPONENT_SRCS:%.c=$(COMPONENT_OBJ_PATH)/%.o) + +## +## compiler flags +## +LIBS = -L$(PROJECT_OUT_PATH) -lconnectivity_abstraction + +CFLAGS = -g -c -Wall -fPIC + +LFLAGS = -ldl -lpthread + +IFLAGS = -I$(PROJECT_API_PATH) \ + +DFLAGS = -DLINUX -DTB_LOG + +## +## compile and link rules +## +vpath %.c ./ + +$(COMPONENT_OBJ_PATH)/%.o: %.c + @$(MAKE_OBJ_PATH) + $(CC) -o $@ $(CFLAGS) $(DFLAGS) $(IFLAGS) $< + +all : $(TARGET) + @echo " " + @echo "======================" + @echo " Success!!" + @echo "======================" + +$(TARGET) : $(COMPONENT_OBJS) + @$(MAKE_COMPONENT_OUT_PATH) + $(CC) -o $@ $(COMPONENT_OBJS) $(LIBS) $(LFLAGS) + @$(MV) $(TARGET) $(COMPONENT_OUT_PATH)/. + +clean : + @$(RM) $(COMPONENT_OBJ_PATH) \ + $(COMPONENT_OUT_PATH) + +install : + @$(MAKE_COMPONENT_OUT_PATH) + @$(CP) $(PROJECT_OUT_PATH)/* $(COMPONENT_OUT_PATH)/. + +## +## macros +## +define MAKE_OBJ_PATH + @if [ ! -d $(COMPONENT_OBJ_PATH) ]; then \ + mkdir $(COMPONENT_OBJ_PATH); \ + fi +endef + + +## +## macro +## +define MAKE_COMPONENT_OUT_PATH + @if [ ! -d $(COMPONENT_OUT_PATH) ]; then \ + mkdir $(COMPONENT_OUT_PATH); \ + fi +endef + +.PHONY: all clean install + + diff --git a/resource/csdk/connectivity/samples/linux/README b/resource/csdk/connectivity/samples/linux/README new file mode 100644 index 000000000..239ddbcf7 --- /dev/null +++ b/resource/csdk/connectivity/samples/linux/README @@ -0,0 +1,26 @@ +//---------------------------------------------------------------------- +// NOTICE - Transition to SCONS +//---------------------------------------------------------------------- + +The IoTivity build system is transitioning to SCONS. Although the +makefiles are still available (until v1.0) and some developers are +still using them, they are currently no longer supported. To learn more +about building using SCONS see Readme.scons.txt in the repository root +directory. The build steps used in continuous integration can be found +in auto_build.sh which is also in the the repository root directory. + +//---------------------------------------------------------------------- + +#1. build "connectivity" project + - execute make command in "connectivity/build/" folder. + +#2. build "example" for linux + - execute make command in "connectivity/samples/linux/" folder. + +#3. execute sample program + - you should link the "connectivity_abstraction" library. + ex. LD_LIBRARY_PATH=../../../build/out ./sample_main + +#4 execute sample.sh in "connectivity/samples/linux/" folder + ex. $./sample.sh (This will make a clean build and execute application) + diff --git a/resource/csdk/connectivity/samples/linux/sample.sh b/resource/csdk/connectivity/samples/linux/sample.sh new file mode 100644 index 000000000..3d85b4080 --- /dev/null +++ b/resource/csdk/connectivity/samples/linux/sample.sh @@ -0,0 +1,35 @@ +#/****************************************************************** +# * +# * Copyright 2014 Samsung Electronics All Rights Reserved. +# * +# * +# * +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# * +#******************************************************************/ + +cd ../../lib/libcoap-4.1.1 +make clean +make + +cd ../../build/linux +make clean +make + + +cd ../../samples/linux +make clean +make + +cd out +LD_LIBRARY_PATH=../../../build/out ./sample_main diff --git a/resource/csdk/connectivity/samples/linux/sample_main.c b/resource/csdk/connectivity/samples/linux/sample_main.c new file mode 100644 index 000000000..17992e232 --- /dev/null +++ b/resource/csdk/connectivity/samples/linux/sample_main.c @@ -0,0 +1,395 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +#include +#include +#include +#include "cacommon.h" +#include "cainterface.h" + +#define MAX_BUF_LEN 1024 + +char get_menu(); +void process(); + +void start_listening_server(); +void start_discovery_server(); +void find_resource(); +void send_request(); +void send_response(); +void advertise_resource(); +void select_network(); +void unselect_network(); +void handle_request_response(); + +void request_handler(CARemoteEndpoint_t* object, CARequestInfo_t* requestInfo); +void response_handler(CARemoteEndpoint_t* object, CAResponseInfo_t* responseInfo); +void send_request_tmp(CARemoteEndpoint_t* endpoint, CAToken_t token); + +int main() +{ + system("clear"); + + printf("=============================================\n"); + printf("\t\tsample main\n"); + printf("=============================================\n"); + + CAInitialize(); + + // network enable + // default + printf("select default network(WIFI)\n"); + CASelectNetwork(CA_WIFI); + + // set handler. + CARegisterHandler(request_handler, response_handler); + + process(); + + CATerminate(); + + return 0; +} + +void process() +{ + while (1) + { + char menu = get_menu(); + + switch (menu) + { + case 'm': // menu + case 'M': + continue; + + case 'q': // quit + case 'Q': + printf("quit..!!\n"); + return; + + case 's': // start listening server + case 'S': + start_listening_server(); + break; + + case 'd': // start discovery server + case 'D': + start_discovery_server(); + break; + + case 'f': // find resource + case 'F': + find_resource(); + break; + + case 'r': // send request + case 'R': + send_request(); + break; + + case 'a': // advertise resource + case 'A': + advertise_resource(); + break; + + case 'n': // select network + case 'N': + select_network(); + break; + + case 'x': // unselect network + case 'X': + unselect_network(); + break; + + case 'h': // handle request response + case 'H': + handle_request_response(); + break; + + default: + printf("not supported menu!!\n"); + break; + } + } + +} + +void start_listening_server() +{ + printf("start listening server!!\n"); + + CAStartListeningServer(); +} + +void start_discovery_server() +{ + printf("start discovery server!!\n"); + + CAStartDiscoveryServer(); +} + +void find_resource() +{ + char buf[MAX_BUF_LEN]; + + memset(buf, 0, sizeof(char) * MAX_BUF_LEN); + + printf("\n=============================================\n"); + printf("ex) a/light\n"); + printf("reference uri : "); + + gets(buf); + + CAResult_t res = CAFindResource(buf); + + if (res != CA_STATUS_OK) + { + printf("find resource error!!\n"); + } + else + { + printf("find resource fo %s URI\n", buf); + } + + printf("=============================================\n"); +} + +void send_request() +{ + char buf[MAX_BUF_LEN]; + + memset(buf, 0, sizeof(char) * MAX_BUF_LEN); + + printf("\n=============================================\n"); + printf("coap://10.11.12.13:4545/resource_uri ( for IP )\n"); + printf("coap://10:11:12:13:45:45/resource_uri ( for BT )\n"); + printf("uri : "); + + gets(buf); + + // create remote endpoint + CARemoteEndpoint_t* endpoint = NULL; + CAResult_t res = CACreateRemoteEndpoint(buf, &endpoint); + endpoint->connectivityType = CA_WIFI; // + + if (res != CA_STATUS_OK) + { + printf("create remote endpoint error!!"); + return; + } + + // create token + CAToken_t token = NULL; + res = CAGenerateToken(&token); + + if (res != CA_STATUS_OK) + { + printf("token generate error!!"); + token = NULL; + } + + printf("generated token %s\n", (token != NULL) ? token : ""); + + CAInfo_t requestData; + memset(&requestData, 0, sizeof(CAInfo_t)); + requestData.token = token; + requestData.payload = "Temp Json Payload"; + + CARequestInfo_t requestInfo; + memset(&requestInfo, 0, sizeof(CARequestInfo_t)); + requestInfo.method = CA_GET; + requestInfo.info = requestData; + + // send request + CASendRequest(endpoint, &requestInfo); + + if (token != NULL) + { + CADestroyToken(token); + } + + // destroy remote endpoint + if (endpoint != NULL) + { + CADestroyRemoteEndpoint(endpoint); + } + + printf("=============================================\n"); +} + +void advertise_resource() +{ + printf("\n=============================================\n"); + + printf("not implemented yet.\n"); + + printf("=============================================\n"); +} + +void select_network() +{ + char buf[MAX_BUF_LEN]; + + printf("\n=============================================\n"); + printf("\tselect network\n"); + printf("ETHERNET : 0\n"); + printf("WIFI : 1\n"); + printf("EDR : 2\n"); + printf("LE : 3\n"); + printf("select : "); + + memset(buf, 0, sizeof(char) * MAX_BUF_LEN); + gets(buf); + + int number = buf[0] - '0'; + + number = (number < 0 || number > 3) ? 1 : number; + + CASelectNetwork(1 << number); + + printf("=============================================\n"); +} + +void unselect_network() +{ + char buf[MAX_BUF_LEN]; + + printf("\n=============================================\n"); + printf("\tunselect enabled network\n"); + printf("ETHERNET : 0\n"); + printf("WIFI : 1\n"); + printf("EDR : 2\n"); + printf("LE : 3\n"); + printf("select : "); + + memset(buf, 0, sizeof(char) * MAX_BUF_LEN); + gets(buf); + + int number = buf[0] - '0'; + + number = (number < 0 || number > 3) ? 1 : number; + + CAUnSelectNetwork(1 << number); + + printf("=============================================\n"); +} + +char get_menu() +{ + char buf[MAX_BUF_LEN]; + + printf("\n=============================================\n"); + printf("\t\tMenu\n"); + printf("\ts : start listening server\n"); + printf("\td : start discovery server\n"); + printf("\tf : find resource\n"); + printf("\tr : send request\n"); + printf("\ta : advertise resource\n"); + printf("\tn : select network\n"); + printf("\tx : unselect network\n"); + printf("\th : handle request response\n"); + printf("\tq : quit\n"); + printf("=============================================\n"); + printf("select : "); + + memset(buf, 0, sizeof(char) * MAX_BUF_LEN); + + gets(buf); + + return buf[0]; +} + +void handle_request_response() +{ + printf("handle_request_response\n"); + CAHandleRequestResponse(); +} + +void request_handler(CARemoteEndpoint_t* object, CARequestInfo_t* requestInfo) +{ + + printf("request_handler, uri : %s, data : %s\n", (object != NULL) ? object->resourceUri : "", + (requestInfo != NULL) ? requestInfo->info.payload : ""); + + printf("send response with URI\n"); + send_response(object, (requestInfo != NULL) ? requestInfo->info.token : ""); + +} + +void response_handler(CARemoteEndpoint_t* object, CAResponseInfo_t* responseInfo) +{ + + printf("response_handler, uri : %s, data : %s\n", (object != NULL) ? object->resourceUri : "", + (responseInfo != NULL) ? responseInfo->info.payload : ""); + + printf("send request after receivce response data\n"); + send_request_tmp(object, (responseInfo != NULL) ? responseInfo->info.token : ""); +} + +void send_response(CARemoteEndpoint_t* endpoint, CAToken_t request_token) +{ + + printf("\n=============================================\n"); + + CAInfo_t responseData; + //responseData = (CAInfo*) malloc(sizeof(CAInfo)); + memset(&responseData, 0, sizeof(CAInfo_t)); + responseData.token = request_token; + responseData.payload = "response payload"; + + CAResponseInfo_t responseInfo; + //responseInfo = (CAResponseInfo*) malloc(sizeof(CAResponseInfo)); + memset(&responseInfo, 0, sizeof(CAResponseInfo_t)); + responseInfo.result = 203; + responseInfo.info = responseData; + + // send request + endpoint->connectivityType = CA_WIFI; + CASendResponse(endpoint, &responseInfo); + + printf("=============================================\n"); + +} + +void send_request_tmp(CARemoteEndpoint_t* endpoint, CAToken_t token) +{ + + printf("\n=============================================\n"); + + CAInfo_t requestData; + memset(&requestData, 0, sizeof(CAInfo_t)); + requestData.token = token; + requestData.payload = "Temp Json Payload"; + + CARequestInfo_t requestInfo; + memset(&requestInfo, 0, sizeof(CARequestInfo_t)); + requestInfo.method = CA_GET; + requestInfo.info = requestData; + + // send request + endpoint->connectivityType = CA_WIFI; + CASendRequest(endpoint, &requestInfo); + + printf("=============================================\n"); + +} + diff --git a/resource/csdk/connectivity/samples/linux/threadpool/Makefile b/resource/csdk/connectivity/samples/linux/threadpool/Makefile new file mode 100644 index 000000000..74abc3d0a --- /dev/null +++ b/resource/csdk/connectivity/samples/linux/threadpool/Makefile @@ -0,0 +1,14 @@ +CC=gcc +ROOT_DIR = ../../.. +INC_DIR := -I$(ROOT_DIR)/api -I$(ROOT_DIR)/inc -I$(ROOT_DIR)/common/inc +SRC_DIR := $(ROOT_DIR)/common/src/ +CFLAGS = -Wall +COMPILEFLAGS = `pkg-config --cflags glib-2.0` +LDFLAGS = `pkg-config --libs glib-2.0` + +OUT = threadpool + +all: + $(CC) $(CFLAGS) $(INC_DIR) $(COMPILEFLAGS) $(SRC_DIR)uthreadpool.c $(SRC_DIR)umutex.c $(SRC_DIR)/../logger.c main.c -o $(OUT) $(LDFLAGS) +clean: + rm -f $(OUT) diff --git a/resource/csdk/connectivity/samples/linux/threadpool/main.c b/resource/csdk/connectivity/samples/linux/threadpool/main.c new file mode 100644 index 000000000..3b83fa06b --- /dev/null +++ b/resource/csdk/connectivity/samples/linux/threadpool/main.c @@ -0,0 +1,127 @@ +#include +#include + +#include "uthreadpool.h" +#include "umutex.h" + +u_thread_pool_t gThreadPoolHandle = NULL; + +u_mutex gMutex = NULL; +u_cond gCond = NULL; + +void task(void *data) +{ + printf("[TASK] Task is executing: data: %s\n", (char *) data); + + //Signal the condition that task has been completed + printf("[TASK] Signaling the condition\n"); + u_cond_signal(gCond); +} + +void testThreadPool(void) +{ + char *string = "Test glib thread pool"; + + //Initialize the mutex + printf("[testThreadPool] Initializing mutex\n"); + u_mutex_init(); + + //Initialize the thread pool + printf("[testThreadPool] Initializing thread pool\n"); + if (CA_STATUS_OK != u_thread_pool_init(2, &gThreadPoolHandle)) + { + printf("thread_pool_init failed!\n"); + return; + } + + //Create the mutex + printf("[testThreadPool] Creating mutex\n"); + gMutex = u_mutex_new(); + if (NULL == gMutex) + { + printf("[testThreadPool] Failed to create mutex!\n"); + return; + } + + //Create the condition + printf("[testThreadPool] Creating Condition\n"); + gCond = u_cond_new(); + if (NULL == gCond) + { + printf("[testThreadPool] Failed to create condition!\n"); + + u_mutex_free(gMutex); + return; + } + + //Lock the mutex + printf("[testThreadPool] Locking the mutex\n"); + u_mutex_lock(gMutex); + + //Add task to thread pool + printf("[testThreadPool] Adding the task to thread pool\n"); + if (CA_STATUS_OK != u_thread_pool_add_task(gThreadPoolHandle, task, (void *) string)) + { + printf("[testThreadPool] thread_pool_add_task failed!\n"); + + u_mutex_unlock(gMutex); + u_mutex_free(gMutex); + u_cond_free(gCond); + return; + } + + //Wait for the task to be executed + printf("[testThreadPool] Waiting for the task to be completed\n"); + u_cond_wait(gCond, gMutex); + + //Unlock the mutex + printf("[testThreadPool] Got the signal and unlock the mutex\n"); + u_mutex_unlock(gMutex); + + printf("[testThreadPool] Task is completed and terminating threadpool\n"); + u_mutex_free(gMutex); + u_cond_free(gCond); + u_thread_pool_free(gThreadPoolHandle); + + printf("Exiting from testThreadPool\n"); +} + +static void menu() +{ + printf(" =====================================================================\n"); + printf("| Welcome to Theadpool testing |\n"); + printf("|---------------------------------------------------------------------|\n"); + printf("| ** Options ** |\n"); + printf("| 1 - Test Threadpool functionality |\n"); + printf("| 0 - Terminate test |\n"); +} + +static void startTesting(void) +{ + while (1) + { + int choice = -1; + scanf("%d", &choice); + + switch (choice) + { + case 0: + printf("Terminating test.....\n"); + return; + case 1: + testThreadPool(); + break; + default: + printf("Invalid input...\n"); + menu(); + break; + } + } +} + +int main() +{ + menu(); + startTesting(); + return 0; +} diff --git a/resource/csdk/connectivity/src/bt_edr_adapter/linux/caedradapter.c b/resource/csdk/connectivity/src/bt_edr_adapter/linux/caedradapter.c new file mode 100644 index 000000000..3a31a8198 --- /dev/null +++ b/resource/csdk/connectivity/src/bt_edr_adapter/linux/caedradapter.c @@ -0,0 +1,133 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +#include +#include +#include + +#include "caedradapter.h" +#include "logger.h" + +#define TAG PCF("CA") + +static CANetworkPacketReceivedCallback gEDRReceivedCallback = NULL; + +CAResult_t CAInitializeEDR(CARegisterConnectivityCallback registerCallback, + CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback) +{ + OIC_LOG_V(DEBUG, TAG, "CAInitializeEDR"); + + gEDRReceivedCallback = reqRespCallback; + + // register handlers + CAConnectivityHandler_t handler; + memset(&handler, 0, sizeof(CAConnectivityHandler_t)); + + handler.startAdapter = CAStartEDR; + handler.startListenServer = CAStartEDRListeningServer; + handler.startDiscoverServer = CAStartEDRDiscoveryServer; + handler.sendData = CASendEDRUnicastData; + handler.sendDataToAll = CASendEDRMulticastData; + handler.startNotifyServer = CAStartEDRNotifyServer; + handler.sendNotification = CASendEDRNotification; + handler.GetnetInfo = CAGetEDRInterfaceInformation; + handler.readData = CAReadEDRData; + handler.stopAdapter = CAStopEDR; + handler.terminate = CATerminateEDR; + + registerCallback(handler, CA_EDR); + + return CA_STATUS_OK; +} + +CAResult_t CAStartEDR() +{ + OIC_LOG_V(DEBUG, TAG, "CAStartEDR"); + + return CA_STATUS_OK; +} + +CAResult_t CAStartEDRListeningServer() +{ + OIC_LOG_V(DEBUG, TAG, "CAStartEDRListeningServer"); + + return CA_STATUS_OK; +} + +CAResult_t CAStartEDRDiscoveryServer() +{ + OIC_LOG_V(DEBUG, TAG, "CAStartEDRDiscoveryServer"); + + return CA_STATUS_OK; +} + +uint32_t CASendEDRUnicastData(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen) +{ + OIC_LOG_V(DEBUG, TAG, "CASendEDRUnicastData"); + + return 0; +} + +uint32_t CASendEDRMulticastData(void* data, uint32_t dataLen) +{ + OIC_LOG_V(DEBUG, TAG, "CASendEDRMulticastData"); + + return 0; +} + +CAResult_t CAStartEDRNotifyServer() +{ + OIC_LOG_V(DEBUG, TAG, "CAStartEDRNotifyServer"); + + return CA_STATUS_OK; +} + +uint32_t CASendEDRNotification(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen) +{ + OIC_LOG_V(DEBUG, TAG, "CASendEDRNotification"); + + return 0; +} + +CAResult_t CAGetEDRInterfaceInformation(CALocalConnectivityt_t** info, uint32_t* size) +{ + OIC_LOG_V(DEBUG, TAG, "CAGetEDRInterfaceInformation"); + + return CA_STATUS_OK; +} + +CAResult_t CAReadEDRData() +{ + OIC_LOG_V(DEBUG, TAG, "Read EDR Data"); + + return CA_STATUS_OK; +} + +CAResult_t CAStopEDR() +{ + OIC_LOG_V(DEBUG, TAG, "CAStopEDR"); + + return CA_STATUS_OK; +} + +void CATerminateEDR() +{ + OIC_LOG_V(DEBUG, TAG, "CATerminateEDR"); +} diff --git a/resource/csdk/connectivity/src/bt_le_adapter/caleadapter.c b/resource/csdk/connectivity/src/bt_le_adapter/caleadapter.c new file mode 100644 index 000000000..ff60572af --- /dev/null +++ b/resource/csdk/connectivity/src/bt_le_adapter/caleadapter.c @@ -0,0 +1,417 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ +#include "caleadapter.h" + +#ifdef __TIZEN__ +#include +#include +#include +#include +#include +#include +#endif //#ifdef __TIZEN__ +#include +#include + +#ifdef __TIZEN__ +#include "cableserver.h" +#include "cableclient.h" +#include "cacommon.h" +#else // __ARDUINO__ +#include "BLEAdapterArduino.h" +#include "caadapterutils.h" +#endif //#ifdef __TIZEN__ +#define CALEADAPTER_TAG "CA_BLE_ADAPTER" + +static CANetworkChangeCallback gNetworkCallback = NULL; +static char gLocalBLEAddress[16] = +{ 0, }; + +static int gIsServer = 0; + +int CALERegisterNetworkNotifications(CANetworkChangeCallback netCallback); + +#ifdef __TIZEN__ +int CALEDeviceStateChangedCb(int result, bt_adapter_state_e adapter_state, void *user_data); +#endif //#ifdef __TIZEN__ + +pthread_mutex_t gBleIsServerMutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + +pthread_mutex_t gBleNetworkCbMutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + +pthread_mutex_t gBleLocalAddressMutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + +CAResult_t CAInitializeLE(CARegisterConnectivityCallback registerCallback, + CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback) +{ + OCLog(DEBUG, CALEADAPTER_TAG, "IN"); + + //Input validation + VERIFY_NON_NULL(registerCallback, NULL, "RegisterConnectivity callback is null"); + VERIFY_NON_NULL(reqRespCallback, NULL, "PacketReceived Callback is null"); + VERIFY_NON_NULL(netCallback, NULL, "NetworkChange Callback is null"); + +#ifdef __TIZEN__ + + int ret = bt_initialize(); + if (0 != ret) + { + OCLog(ERROR, CALEADAPTER_TAG, "bt_initialize failed!"); + return CA_STATUS_FAILED; + } + +#endif //#ifdef __TIZEN__ + CASetBLEReqRescallback(reqRespCallback); + CALERegisterNetworkNotifications(netCallback); + + CAConnectivityHandler_t connHandler; + connHandler.startListenServer = CAStartLEListeningServer; + connHandler.startDiscoverServer = CAStartLEDiscoveryServer; + connHandler.sendData = CASendLEUnicastData; + connHandler.sendDataToAll = CASendLEMulticastData; + connHandler.startNotifyServer = CAStartLENotifyServer; + connHandler.sendNotification = CASendLENotification; + connHandler.GetnetInfo = CAGetLEInterfaceInformation; + connHandler.readData = CAReadLEData; + connHandler.terminate = CATerminateLE; + registerCallback(connHandler, CA_LE); + + OCLog(DEBUG, CALEADAPTER_TAG, "OUT"); + + return CA_STATUS_OK; +} + +void CATerminateLE() +{ + OCLog(DEBUG, CALEADAPTER_TAG, "IN"); + + CASetBLEReqRescallback(NULL); + CALERegisterNetworkNotifications(NULL); + + pthread_mutex_lock(&gBleIsServerMutex); + if (gIsServer == 1) + { + CAStopBleGattServer(); + } + else + { + CAStopBLEGattClient(); + } + pthread_mutex_unlock(&gBleIsServerMutex); + + OCLog(DEBUG, CALEADAPTER_TAG, "OUT"); + return; +} + +void CALEServerInitThreadFunc(void *param) +{ + OCLog(DEBUG, CALEADAPTER_TAG, "[CALEServerInitThreadFunc]IN"); + + CAStartBleGattServer(); + + OCLog(DEBUG, CALEADAPTER_TAG, "[CALEServerInitThreadFunc] OUT"); +} + +void CALEClientInitThreadFunc(void *param) +{ + OCLog(DEBUG, CALEADAPTER_TAG, "[CALEClientInitThreadFunc]IN"); + + CAStartBLEGattClient(); + + OCLog(DEBUG, CALEADAPTER_TAG, "[CALEClientInitThreadFunc] OUT"); +} + +CAResult_t CAStartLEListeningServer() +{ + OCLog(DEBUG, CALEADAPTER_TAG, "IN"); + + int init_pthread_status = 0; + pthread_t pthread_id = 0; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + init_pthread_status = pthread_create(&pthread_id, &attr, CALEServerInitThreadFunc, NULL); + + if (init_pthread_status != 0) + { + OCLog(ERROR, CALEADAPTER_TAG, "pthread_create failed!"); + return CA_STATUS_FAILED; + } + + OCLog(DEBUG, CALEADAPTER_TAG, "OUT"); + pthread_mutex_lock(&gBleIsServerMutex); + gIsServer = 1; + pthread_mutex_unlock(&gBleIsServerMutex); + return CA_STATUS_OK; +} + +CAResult_t CAStartLEDiscoveryServer() +{ + OCLog(DEBUG, CALEADAPTER_TAG, "IN"); + + int init_pthread_status = 0; + pthread_t pthread_id = 0; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + init_pthread_status = pthread_create(&pthread_id, &attr, CALEClientInitThreadFunc, NULL); + + if (init_pthread_status != 0) + { + OCLog(ERROR, CALEADAPTER_TAG, "pthread_create failed!"); + return CA_STATUS_FAILED; + } + + OCLog(DEBUG, CALEADAPTER_TAG, "OUT"); + pthread_mutex_lock(&gBleIsServerMutex); + gIsServer = 0; + pthread_mutex_unlock(&gBleIsServerMutex); + return CA_STATUS_OK; +} + +CAResult_t CAStartLENotifyServer() +{ + OCLog(DEBUG, CALEADAPTER_TAG, "IN"); + + OCLog(DEBUG, CALEADAPTER_TAG, "OUT"); + + return CA_STATUS_OK; +} + +uint32_t CASendLENotification(const CARemoteEndpoint_t *endpoint, void *data, uint32_t dataLen) +{ + OCLog(DEBUG, CALEADAPTER_TAG, "IN"); + + OCLog(DEBUG, CALEADAPTER_TAG, "OUT"); + + return CA_STATUS_OK; +} + +CAResult_t CAReadLEData() +{ + OCLog(DEBUG, CALEADAPTER_TAG, "IN"); + + OCLog(DEBUG, CALEADAPTER_TAG, "OUT"); + + return CA_STATUS_OK; +} + +uint32_t CASendLEUnicastData(const CARemoteEndpoint_t *endpoint, void *data, uint32_t dataLen) +{ + OCLog(DEBUG, CALEADAPTER_TAG, "IN"); + + //Input validation + VERIFY_NON_NULL(endpoint, NULL, "Remote endpoint is null"); + VERIFY_NON_NULL(data, NULL, "Data is null"); + + CAResult_t result = CA_STATUS_FAILED; + +#ifdef __TIZEN__ + pthread_mutex_lock(&gBleIsServerMutex); + if (gIsServer) + { + result = CAUpdateCharacteristicsInGattServer(data, dataLen); + if (CA_STATUS_OK != result) + { + OCLogv(ERROR, CALEADAPTER_TAG, + "[SendLEUnicastData] sending unicast data to [%s] failed\n", endpoint->addressInfo.BT.btMacAddress); + pthread_mutex_unlock(&gBleIsServerMutex); + return 0; + } + } + else + { + + result = CAUpdateCharacteristicsToGattServer(endpoint->addressInfo.BT.btMacAddress, data, + dataLen, UNICAST, 0); + if (CA_STATUS_OK != result) + { + OCLogv(ERROR, CALEADAPTER_TAG, + "[SendLEUnicastData] sending unicast data to [%s] failed\n", endpoint->addressInfo.BT.btMacAddress); + pthread_mutex_unlock(&gBleIsServerMutex); + return 0; + } + } + pthread_mutex_unlock(&gBleIsServerMutex); +#else + char *tempPath = "temp_path"; + updateCharacteristicsInGattServer(tempPath, (char *) data, dataLen); +#endif //#ifdef __TIZEN__ + OCLog(DEBUG, CALEADAPTER_TAG, "OUT"); + + return dataLen; +} + +uint32_t CASendLEMulticastData(void *data, uint32_t dataLen) +{ + OCLog(DEBUG, CALEADAPTER_TAG, "IN"); + + //Input validation + VERIFY_NON_NULL(data, NULL, "Data is null"); + + if (0 >= dataLen) + { + OCLog(ERROR, CALEADAPTER_TAG, "Invalid Parameter"); + return 0; + } + + CAResult_t result = CA_STATUS_FAILED; +#ifdef __TIZEN__ + pthread_mutex_lock(&gBleIsServerMutex); + if (gIsServer) + { + result = CAUpdateCharacteristicsInGattServer(data, dataLen); + if (CA_STATUS_OK != result) + { + OCLogv(ERROR, CALEADAPTER_TAG, + "[CASendLEMulticastData] updating data in server is failed"); + pthread_mutex_unlock(&gBleIsServerMutex); + return 0; + } + } + else + { + result = CAUpdateCharacteristicsToAllGattServers(data, dataLen); + if (CA_STATUS_OK != result) + { + OCLogv(ERROR, CALEADAPTER_TAG, + "[SendLEMulticastDataToAll] multicasting data to servers failed" ); + pthread_mutex_unlock(&gBleIsServerMutex); + return 0; + } + } + pthread_mutex_unlock(&gBleIsServerMutex); +#else + char *tempPath = "temp_path"; + updateCharacteristicsInGattServer(tempPath, (char *) data, dataLen); +#endif //#ifdef __TIZEN__ + OCLog(DEBUG, CALEADAPTER_TAG, "OUT"); + return dataLen; +} + +CAResult_t CAGetLEInterfaceInformation(CALocalConnectivityt_t **info, uint32_t *size) +{ + OCLog(DEBUG, CALEADAPTER_TAG, "IN"); + + VERIFY_NON_NULL(info, NULL, "CALocalConnectivity info is null"); + +#ifdef OIC_ARDUINODUE + OCLog(DEBUG, CALEADAPTER_TAG, "Info from ARDUINO"); + //1: call corresponding Arduino API +#endif + +#if __TIZEN__ + + char *local_address = NULL; + + bt_adapter_get_address(&local_address); + if (NULL == local_address) + { + OCLog(ERROR, CALEADAPTER_TAG, "Get local bt adapter address failed"); + return CA_STATUS_FAILED; + } + +#endif //#if ARDUINODUE + *size = 0; + (*info) = (CALocalConnectivityt_t *) OICMalloc(sizeof(CALocalConnectivityt_t)); + if (NULL == (*info)) + { + OCLog(ERROR, CALEADAPTER_TAG, "Malloc failure!"); + return CA_STATUS_FAILED; + } + memset((*info), 0x0, sizeof(CALocalConnectivityt_t)); + + strncpy((*info)->addressInfo.BT.btMacAddress, local_address, strlen(local_address)); + pthread_mutex_lock(&gBleLocalAddressMutex); + strncpy(gLocalBLEAddress, local_address, sizeof(gLocalBLEAddress)); + pthread_mutex_unlock(&gBleLocalAddressMutex); + + (*info)->type = CA_LE; + *size = 1; + OICFree(local_address); + + OCLog(DEBUG, CALEADAPTER_TAG, "OUT"); + return CA_STATUS_OK; +} + +int CALERegisterNetworkNotifications(CANetworkChangeCallback netCallback) +{ + OCLog(DEBUG, CALEADAPTER_TAG, "IN"); + + pthread_mutex_lock(&gBleNetworkCbMutex); + gNetworkCallback = netCallback; + pthread_mutex_unlock(&gBleNetworkCbMutex); + int ret = 0; +#ifdef __TIZEN__ + if (netCallback) + { + ret = bt_adapter_set_state_changed_cb(CALEDeviceStateChangedCb, NULL); + if(ret != 0) + { + OCLog(ERROR, CALEADAPTER_TAG, "bt_adapter_set_state_changed_cb failed!"); + } + } + else + { + ret = bt_adapter_unset_state_changed_cb(); + if(ret != 0) + { + OCLog(ERROR, CALEADAPTER_TAG, "bt_adapter_set_state_changed_cb failed!"); + } + } +#endif //#ifdef __TIZEN__ + OCLog(DEBUG, CALEADAPTER_TAG, "OUT"); + return CA_STATUS_OK; +} + +#ifdef __TIZEN__ + +int CALEDeviceStateChangedCb(int result, bt_adapter_state_e adapter_state, void *user_data) +{ + OCLog(DEBUG, CALEADAPTER_TAG, "IN"); + + bt_adapter_state_e btAdaptorState = BT_ADAPTER_DISABLED; + if (BT_ADAPTER_ENABLED == adapter_state) + { + btAdaptorState = BT_ADAPTER_ENABLED; + } + + CALocalConnectivityt_t localEndpoint; + + pthread_mutex_lock(&gBleLocalAddressMutex); + strncpy(localEndpoint.addressInfo.BT.btMacAddress, gLocalBLEAddress, strlen(gLocalBLEAddress)); + pthread_mutex_unlock(&gBleLocalAddressMutex); + + pthread_mutex_lock(&gBleNetworkCbMutex); + if(NULL != gNetworkCallback) + { + gNetworkCallback(&localEndpoint, adapter_state); + } + else + { + OCLog(ERROR, CALEADAPTER_TAG, "gNetworkCallback is NULL"); + } + pthread_mutex_unlock(&gBleNetworkCbMutex); + OCLog(DEBUG, CALEADAPTER_TAG, "OUT"); + return CA_STATUS_OK; +} +#endif //#ifdef OIC_TIZEN diff --git a/resource/csdk/connectivity/src/bt_le_adapter/linux/caleadapter.c b/resource/csdk/connectivity/src/bt_le_adapter/linux/caleadapter.c new file mode 100644 index 000000000..fb7ec92b9 --- /dev/null +++ b/resource/csdk/connectivity/src/bt_le_adapter/linux/caleadapter.c @@ -0,0 +1,133 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +#include +#include +#include + +#include "caleadapter.h" +#include "logger.h" + +#define TAG PCF("CA") + +static CANetworkPacketReceivedCallback gLEReceivedCallback = NULL; + +CAResult_t CAInitializeLE(CARegisterConnectivityCallback registerCallback, + CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback) +{ + OIC_LOG_V(DEBUG, TAG, "CAInitializeLE"); + + gLEReceivedCallback = reqRespCallback; + + // register handlers + CAConnectivityHandler_t handler; + memset(&handler, 0, sizeof(CAConnectivityHandler_t)); + + handler.startAdapter = CAStartLE; + handler.startListenServer = CAStartLEListeningServer; + handler.startDiscoverServer = CAStartLEDiscoveryServer; + handler.sendData = CASendLEUnicastData; + handler.sendDataToAll = CASendLEMulticastData; + handler.startNotifyServer = CAStartLENotifyServer; + handler.sendNotification = CASendLENotification; + handler.GetnetInfo = CAGetLEInterfaceInformation; + handler.readData = CAReadLEData; + handler.stopAdapter = CAStopLE; + handler.terminate = CATerminateLE; + + registerCallback(handler, CA_LE); + + return CA_STATUS_OK; +} + +CAResult_t CAStartLE() +{ + OIC_LOG_V(DEBUG, TAG, "CAStartLE"); + + return CA_STATUS_OK; +} + +CAResult_t CAStartLEListeningServer() +{ + OIC_LOG_V(DEBUG, TAG, "CAStartLEListeningServer"); + + return CA_STATUS_OK; +} + +CAResult_t CAStartLEDiscoveryServer() +{ + OIC_LOG_V(DEBUG, TAG, "CAStartLEDiscoveryServer"); + + return CA_STATUS_OK; +} + +uint32_t CASendLEUnicastData(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen) +{ + OIC_LOG_V(DEBUG, TAG, "CASendLEUnicastData"); + + return 0; +} + +uint32_t CASendLEMulticastData(void* data, uint32_t dataLen) +{ + OIC_LOG_V(DEBUG, TAG, "CASendLEMulticastData"); + + return 0; +} + +CAResult_t CAStartLENotifyServer() +{ + OIC_LOG_V(DEBUG, TAG, "CAStartLENotifyServer"); + + return CA_STATUS_OK; +} + +uint32_t CASendLENotification(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen) +{ + OIC_LOG_V(DEBUG, TAG, "CASendLENotification"); + + return 0; +} + +CAResult_t CAGetLEInterfaceInformation(CALocalConnectivityt_t** info, uint32_t* size) +{ + OIC_LOG_V(DEBUG, TAG, "CAGetLEInterfaceInformation"); + + return CA_STATUS_OK; +} + +CAResult_t CAReadLEData() +{ + OIC_LOG_V(DEBUG, TAG, "Read LE Data"); + + return CA_STATUS_OK; +} + +CAResult_t CAStopLE() +{ + OIC_LOG_V(DEBUG, TAG, "CAStopLE"); + + return CA_STATUS_OK; +} + +void CATerminateLE() +{ + OIC_LOG_V(DEBUG, TAG, "TerminatLE"); +} diff --git a/resource/csdk/connectivity/src/caconnectivitymanager.c b/resource/csdk/connectivity/src/caconnectivitymanager.c new file mode 100644 index 000000000..29da71302 --- /dev/null +++ b/resource/csdk/connectivity/src/caconnectivitymanager.c @@ -0,0 +1,295 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +#include +#include +#include + +#include "cainterface.h" +#include "caremotehandler.h" +#include "camessagehandler.h" +#include "canetworkconfigurator.h" +#include "cainterfacecontroller.h" +#include "logger.h" + +#define TAG PCF("CA") + +static void CAMessageHandler(int32_t id, CADetachErrorCode code) +{ +} + +CAResult_t CAInitialize() +{ + OIC_LOG_V(DEBUG, TAG, "CAInitialize"); + + CASetMessageHandlerCallback(CAMessageHandler); + + CAResult_t res = CAInitializeMessageHandler(); + + if (res != CA_STATUS_OK) + { + return res; + } + + return CA_STATUS_OK; +} + +void CATerminate() +{ + OIC_LOG_V(DEBUG, TAG, "CATerminate"); + + CATerminateMessageHandler(); +} + +CAResult_t CAStartListeningServer() +{ + OIC_LOG_V(DEBUG, TAG, "CAStartListeningServer"); + + return CAStartListeningServerAdapters(); +} + +CAResult_t CAStartDiscoveryServer() +{ + OIC_LOG_V(DEBUG, TAG, "CAStartDiscoveryServer"); + + return CAStartDiscoveryServerAdapters(); +} + +CAResult_t CARegisterHandler(CARequestCallback ReqHandler, CAResponseCallback RespHandler) +{ + OIC_LOG_V(DEBUG, TAG, "CARegisterHandler"); + + CASetRequestResponseCallbacks(ReqHandler, RespHandler); + + return CA_STATUS_OK; +} + +CAResult_t CACreateRemoteEndpoint(const CAURI_t uri, CARemoteEndpoint_t** remoteEndpoint) +{ + OIC_LOG_V(DEBUG, TAG, "CACreateRemoteEndpoint"); + + CARemoteEndpoint_t* remote = CACreateRemoteEndpointUriInternal(uri); + + *remoteEndpoint = remote; + + if (remote == NULL) + return CA_STATUS_FAILED; + + return CA_STATUS_OK; +} + +void CADestroyRemoteEndpoint(CARemoteEndpoint_t* rep) +{ + OIC_LOG_V(DEBUG, TAG, "CADestroyRemoteEndpoint"); + + CADestroyRemoteEndpointInternal(rep); +} + +CAResult_t CAGenerateToken(CAToken_t* token) +{ + OIC_LOG_V(DEBUG, TAG, "CAGenerateToken"); + + return CAGenerateTokenInternal(token); +} + +void CADestroyToken(CAToken_t token) +{ + OIC_LOG_V(DEBUG, TAG, "CADestroyToken"); + + CADestroyTokenInternal(token); +} + +CAResult_t CAGetNetworkInformation(CALocalConnectivityt_t **info, uint32_t* size) +{ + OIC_LOG_V(DEBUG, TAG, "CAGetNetworkInformation"); + + return CA_NOT_SUPPORTED; +} + +CAResult_t CAFindResource(const CAURI_t resourceUri) +{ + OIC_LOG_V(DEBUG, TAG, "CAFindResource"); + + int32_t actionId = -1; + + actionId = CADetachMessageResourceUri(resourceUri); + + if (actionId == -1) + return CA_SEND_FAILED; + + OIC_LOG_V(DEBUG, TAG, "action id : %d", actionId); + + return CA_STATUS_OK; +} + +CAResult_t CASendRequest(const CARemoteEndpoint_t* object, CARequestInfo_t* requestInfo) +{ + OIC_LOG_V(DEBUG, TAG, "CASendGetRequest"); + + int32_t actionId = -1; + + actionId = CADetachRequestMessage(object, requestInfo); + + if (actionId == -1) + return CA_SEND_FAILED; + + OIC_LOG_V(DEBUG, TAG, "action id : %d", actionId); + + return CA_STATUS_OK; +} + +CAResult_t CASendNotification(const CARemoteEndpoint_t* object, CAResponseInfo_t* responseInfo) +{ + OIC_LOG_V(DEBUG, TAG, "CASendNotification"); + + return CA_NOT_SUPPORTED; +} + +CAResult_t CASendResponse(const CARemoteEndpoint_t* object, CAResponseInfo_t* responseInfo) +{ + OIC_LOG_V(DEBUG, TAG, "CASendResponse"); + + int32_t actionId = -1; + + actionId = CADetachResponseMessage(object, responseInfo); + + if (actionId == -1) + return CA_SEND_FAILED; + + OIC_LOG_V(DEBUG, TAG, "action id : %d", actionId); + + return CA_STATUS_OK; +} + +CAResult_t CAAdvertiseResource(const CAURI_t uri, CAHeaderOption_t* options, uint8_t numOptions) +{ + OIC_LOG_V(DEBUG, TAG, "CAAdvertiseResource"); + + return CA_NOT_SUPPORTED; +} + +CAResult_t CASelectNetwork(const uint32_t interestedNetwork) +{ + OIC_LOG_V(DEBUG, TAG, "Selected network : %d", interestedNetwork); + + if (!(interestedNetwork & 0xf)) + { + return CA_NOT_SUPPORTED; + } + CAResult_t res; + + if (interestedNetwork & CA_ETHERNET) + { + res = CAAddNetworkType(CA_ETHERNET); + if (res != CA_STATUS_OK) + { + return res; + } + } + + if (interestedNetwork & CA_WIFI) + { + res = CAAddNetworkType(CA_WIFI); + if (res != CA_STATUS_OK) + { + return res; + } + } + + if (interestedNetwork & CA_EDR) + { + res = CAAddNetworkType(CA_EDR); + if (res != CA_STATUS_OK) + { + return res; + } + } + + if (interestedNetwork & CA_LE) + { + res = CAAddNetworkType(CA_LE); + if (res != CA_STATUS_OK) + { + return res; + } + } + + return CA_STATUS_OK; +} + +CAResult_t CAUnSelectNetwork(const uint32_t nonInterestedNetwork) +{ + OIC_LOG_V(DEBUG, TAG, "unselected network : %d", nonInterestedNetwork); + + if (!(nonInterestedNetwork & 0xf)) + { + return CA_NOT_SUPPORTED; + } + + CAResult_t res; + + if (nonInterestedNetwork & CA_ETHERNET) + { + res = CARemoveNetworkType(CA_ETHERNET); + if (res != CA_STATUS_OK) + { + return res; + } + } + + if (nonInterestedNetwork & CA_WIFI) + { + res = CARemoveNetworkType(CA_WIFI); + if (res != CA_STATUS_OK) + { + return res; + } + } + + if (nonInterestedNetwork & CA_EDR) + { + res = CARemoveNetworkType(CA_EDR); + if (res != CA_STATUS_OK) + { + return res; + } + } + + if (nonInterestedNetwork & CA_LE) + { + res = CARemoveNetworkType(CA_LE); + if (res != CA_STATUS_OK) + { + return res; + } + } + + return CA_STATUS_OK; +} + +CAResult_t CAHandleRequestResponse() +{ + OIC_LOG_V(DEBUG, TAG, "CAHandleRequestResponse"); + + CAHandleRequestResponseCallbacks(); + + return CA_STATUS_OK; +} + diff --git a/resource/csdk/connectivity/src/cainterfacecontroller.c b/resource/csdk/connectivity/src/cainterfacecontroller.c new file mode 100644 index 000000000..981eef906 --- /dev/null +++ b/resource/csdk/connectivity/src/cainterfacecontroller.c @@ -0,0 +1,312 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +#include +#include +#include +#include + +#include "cainterfacecontroller.h" +#include "caedradapter.h" +#include "caleadapter.h" +#include "cawifiethernetadapter.h" +#include "canetworkconfigurator.h" +#include "logger.h" + +#define TAG PCF("CA") + +#define CA_CONNECTIVITY_TYPE_NUM 4 + +static CAConnectivityHandler_t gAdapterHandler[CA_CONNECTIVITY_TYPE_NUM]; + +static CANetworkPacketReceivedCallback gNetworkPacketReceivedCallback = NULL; + +static int8_t CAGetAdapterIndex(CAConnectivityType_t cType) +{ + switch (cType) + { + case CA_ETHERNET: + return 0; + case CA_WIFI: + return 1; + case CA_EDR: + return 2; + case CA_LE: + return 3; + } + return -1; +} + +static void CARegisterCallback(CAConnectivityHandler_t handler, CAConnectivityType_t cType) +{ + int8_t index = -1; + + index = CAGetAdapterIndex(cType); + + if (index == -1) + { + OIC_LOG(DEBUG, TAG, "unknown connectivity type!"); + return; + } + + memcpy(&gAdapterHandler[index], &handler, sizeof(CAConnectivityHandler_t)); + + OIC_LOG_V(DEBUG, TAG, "%d type adapter, register complete!", cType); +} + +static void CAReceivedPacketCallback(CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen) +{ + OIC_LOG(DEBUG, TAG, "receivedPacketCallback in interface controller"); + + // Call the callback. + if (gNetworkPacketReceivedCallback != NULL) + { + gNetworkPacketReceivedCallback(endpoint, data, dataLen); + } +} + +static void CANetworkChangedCallback(CALocalConnectivityt_t* info, CANetworkStatus_t status) +{ + OIC_LOG(DEBUG, TAG, "Network Changed callback"); +} + +void CAInitializeAdapters() +{ + OIC_LOG(DEBUG, TAG, "initialize adapters.."); + + memset(gAdapterHandler, 0, sizeof(CAConnectivityHandler_t) * CA_CONNECTIVITY_TYPE_NUM); + + // Initialize adapters and register callback. +#ifdef ETHERNET_ADAPTER + CAInitializeEthernet(CARegisterCallback, CAReceivedPacketCallback, CANetworkChangedCallback); +#endif /* ETHERNET_ADAPTER */ + +#ifdef WIFI_ADAPTER + CAInitializeWifi(CARegisterCallback, CAReceivedPacketCallback, CANetworkChangedCallback); +#endif /* WIFI_ADAPTER */ + +#ifdef EDR_ADAPTER + CAInitializeEDR(CARegisterCallback, CAReceivedPacketCallback, CANetworkChangedCallback); +#endif /* EDR_ADAPTER */ + +#ifdef LE_ADAPTER + CAInitializeLE(CARegisterCallback, CAReceivedPacketCallback, CANetworkChangedCallback); +#endif /* LE_ADAPTER */ + +} + +void CASetPacketReceivedCallback(CANetworkPacketReceivedCallback callback) +{ + OIC_LOG(DEBUG, TAG, "Set packet received callback"); + + gNetworkPacketReceivedCallback = callback; +} + +void CAStartAdapter(CAConnectivityType_t cType) +{ + OIC_LOG_V(DEBUG, TAG, "Start the adapter of CAConnectivityType[%d]", cType); + + int8_t index = -1; + + index = CAGetAdapterIndex(cType); + + if (index == -1) + { + OIC_LOG(DEBUG, TAG, "unknown connectivity type!"); + return; + } + + if (gAdapterHandler[index].startAdapter != NULL) + { + gAdapterHandler[index].startAdapter(); + } +} + +void CAStopAdapter(CAConnectivityType_t cType) +{ + OIC_LOG_V(DEBUG, TAG, "Stop the adapter of CAConnectivityType[%d]", cType); + + int8_t index = -1; + + index = CAGetAdapterIndex(cType); + + if (index == -1) + { + OIC_LOG(DEBUG, TAG, "unknown connectivity type!"); + return; + } + + if (gAdapterHandler[index].stopAdapter != NULL) + { + gAdapterHandler[index].stopAdapter(); + } +} + +CAResult_t CASendUnicastData(const CARemoteEndpoint_t* endpoint, void* data, uint32_t length) +{ + OIC_LOG(DEBUG, TAG, "Send unicast data to enabled interface.."); + + int8_t index = -1; + CAResult_t res = CA_STATUS_FAILED; + + if (endpoint == NULL) + { + OIC_LOG_V(DEBUG, TAG, "Invalid endpoint"); + return CA_STATUS_INVALID_PARAM; + } + + CAConnectivityType_t type = endpoint->connectivityType; + + index = CAGetAdapterIndex(type); + + if (index == -1) + { + OIC_LOG(DEBUG, TAG, "unknown connectivity type!"); + return CA_STATUS_INVALID_PARAM; + } + + if (gAdapterHandler[index].sendData != NULL) + { + res = gAdapterHandler[index].sendData(endpoint, data, length); + } + + return res; +} + +CAResult_t CASendMulticastData(void* data, uint32_t length) +{ + OIC_LOG(DEBUG, TAG, "Send multicast data to enabled interface.."); + + uint8_t i, type; + int8_t index = -1; + CAResult_t res = CA_STATUS_FAILED; + u_arraylist_t *list = CAGetSelectedNetworkList(); + + if (!list) + { + OIC_LOG(DEBUG, TAG, "No selected network"); + return CA_STATUS_FAILED; + } + + for (i = 0; i < u_arraylist_length(list); i++) + { + type = *(int*) u_arraylist_get(list, i); + + index = CAGetAdapterIndex(type); + + if (index == -1) + { + OIC_LOG(DEBUG, TAG, "unknown connectivity type!"); + continue; + } + + if (gAdapterHandler[index].sendDataToAll != NULL) + { + res = gAdapterHandler[index].sendDataToAll(data, length); + } + } + + return res; +} + +CAResult_t CAStartListeningServerAdapters() +{ + OIC_LOG(DEBUG, TAG, "Start listening server from adapters.."); + + uint8_t i, type; + int8_t index = -1; + u_arraylist_t *list = CAGetSelectedNetworkList(); + + if (!list) + { + OIC_LOG(DEBUG, TAG, "No selected network"); + return CA_STATUS_FAILED; + } + + for (i = 0; i < u_arraylist_length(list); i++) + { + type = *(int*) u_arraylist_get(list, i); + + index = CAGetAdapterIndex(type); + + if (index == -1) + { + OIC_LOG(DEBUG, TAG, "unknown connectivity type!"); + continue; + } + + if (gAdapterHandler[index].startListenServer != NULL) + { + gAdapterHandler[index].startListenServer(); + } + } + + return CA_STATUS_OK; +} + +CAResult_t CAStartDiscoveryServerAdapters() +{ + OIC_LOG(DEBUG, TAG, "Start discovery server from adapters.."); + + uint8_t i, type; + int8_t index = -1; + u_arraylist_t *list = CAGetSelectedNetworkList(); + + if (!list) + { + OIC_LOG(DEBUG, TAG, "No selected network"); + return CA_STATUS_FAILED; + } + + for (i = 0; i < u_arraylist_length(list); i++) + { + type = *(int*) u_arraylist_get(list, i); + + index = CAGetAdapterIndex(type); + + if (index == -1) + { + OIC_LOG_V(DEBUG, TAG, "unknown connectivity type!"); + continue; + } + + if (gAdapterHandler[index].startDiscoverServer != NULL) + { + gAdapterHandler[index].startDiscoverServer(); + } + } + + return CA_STATUS_OK; +} + +void CATerminateAdapters() +{ + OIC_LOG(DEBUG, TAG, "terminate all adapters.."); + + uint8_t index; + + for (index = 0; index < CA_CONNECTIVITY_TYPE_NUM; index++) + { + if (gAdapterHandler[index].terminate != NULL) + { + gAdapterHandler[index].terminate(); + } + } +} diff --git a/resource/csdk/connectivity/src/camessagehandler.c b/resource/csdk/connectivity/src/camessagehandler.c new file mode 100644 index 000000000..955282759 --- /dev/null +++ b/resource/csdk/connectivity/src/camessagehandler.c @@ -0,0 +1,686 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +#include +#include +#include +#include + +#include "cainterface.h" +#include "camessagehandler.h" +#include "caremotehandler.h" +#include "cainterfacecontroller.h" +#include "uqueue.h" +#include "logger.h" +#include "config.h" /* for coap protocol */ +#include "coap.h" +#include "uthreadpool.h" /* for thread pool */ +#include "umutex.h" +#include "oic_malloc.h" + +#define TAG PCF("CA") + +#define MEMORY_ALLOCK_CHECK(arg) { if (arg == NULL) {OIC_LOG_V(DEBUG, TAG, "memory error"); goto memory_error_exit;} } +#define MAX_ACTION_NUM 300 + +#define MAX_THREAD_POOL_SIZE 10 + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +typedef struct +{ + int32_t actionId; + CARemoteEndpoint_t* remoteEndpoint; + CARequestInfo_t* requestInfo; + CAResponseInfo_t* responseInfo; +} CAData_t; + +typedef void (*CAThreadTask)(CAData_t* data); + +typedef struct +{ + u_mutex threadMutex; + u_cond threadCond; + CAThreadTask threadTask; + int32_t isStop; + u_queue_t* dataQueue; +} CAThread_t; + +// thread pool handle +static u_thread_pool_t gThreadPoolHandle = NULL; + +// message handler main thread +static CAThread_t gSendThread; + +// message handler callback +static int32_t gCurrentActionId = 0; +static CAMessageHandlerCallback gHandlerCallback = NULL; + +// handler field +static CARequestCallback gRequestHandler = NULL; +static CAResponseCallback gResponseHandler = NULL; + +static u_queue_t* gMessageQueue = NULL; +static u_mutex gMessageQueueMutex = NULL; + +static void CAAddReceiveData(CAData_t* data) +{ + OIC_LOG_V(DEBUG, TAG, "CAAddReceiveData"); + + // create thread data + u_queue_message_t* message = (u_queue_message_t*) OICMalloc(sizeof(u_queue_message_t)); + + if (message == NULL) + { + OIC_LOG_V(DEBUG, TAG, "memory error!!"); + return; + } + memset(message, 0, sizeof(u_queue_message_t)); + + message->msg = data; + message->size = sizeof(CAData_t); + + // mutex lock + u_mutex_lock(gMessageQueueMutex); + + // add thread data into list + u_queue_add_element(gMessageQueue, message); + + // mutex unlock + u_mutex_unlock(gMessageQueueMutex); +} + +static void CAAddSendData(CAData_t* data) +{ + OIC_LOG_V(DEBUG, TAG, "CAAddSendData!!"); + + // create thread data + u_queue_message_t* message = (u_queue_message_t*) OICMalloc(sizeof(u_queue_message_t)); + + if (message == NULL) + { + OIC_LOG_V(DEBUG, TAG, "memory error!!"); + return; + } + memset(message, 0, sizeof(u_queue_message_t)); + + message->msg = data; + message->size = sizeof(CAData_t); + + // mutex lock + u_mutex_lock(gSendThread.threadMutex); + + // add thread data into list + u_queue_add_element(gSendThread.dataQueue, message); + + // notity the thread + u_cond_signal(gSendThread.threadCond); + + // mutex unlock + u_mutex_unlock(gSendThread.threadMutex); +} + +static void CAStopSendThread() +{ + OIC_LOG_V(DEBUG, TAG, "CAStopSendThread request!!"); + + // mutex lock + u_mutex_lock(gSendThread.threadMutex); + + // set stop flag + gSendThread.isStop = TRUE; + + // notity the thread + u_cond_signal(gSendThread.threadCond); + + // mutex unlock + u_mutex_unlock(gSendThread.threadMutex); +} + +static void CASendThreadProcess(CAData_t* data) +{ + if (data == NULL) + { + OIC_LOG(DEBUG, TAG, "thread data error!!"); + return; + } + + if (NULL == data->remoteEndpoint) + { + OIC_LOG(DEBUG, TAG, "remoteEndpoint is null"); + return; + } + + OIC_LOG_V(DEBUG, TAG, "thread action id : %d", data->actionId); + + CADetachErrorCode code = FAIL; + int32_t res = 0; + + if (data->requestInfo != NULL) + { + OIC_LOG(DEBUG, TAG, "requestInfo is available"); + + coap_pdu_t* pdu = NULL; + pdu = CAGeneratePdu(data->remoteEndpoint->resourceUri, data->requestInfo->method, + data->requestInfo->info); + + // interface controller function call. + if (NULL != pdu) + { + OIC_LOG_V(DEBUG, TAG, "PDU Maker - payload : %s", pdu->data); + + OIC_LOG_V(DEBUG, TAG, "PDU Maker - code : %d", pdu->hdr->code); + + OIC_LOG_V(DEBUG, TAG, "PDU Maker - buffer data : %s", pdu->hdr); + + res = CASendUnicastData(data->remoteEndpoint, pdu->hdr, pdu->length); + } + } + else if (data->responseInfo != NULL) + { + OIC_LOG_V(DEBUG, TAG, "responseInfo is available.."); + + coap_pdu_t* pdu = NULL; + + pdu = CAGeneratePdu(data->remoteEndpoint->resourceUri, data->responseInfo->result, + data->responseInfo->info); + + // interface controller function call. + if (NULL != pdu) + { + OIC_LOG_V(DEBUG, TAG, "PDU Maker - payload : %s", pdu->data); + + OIC_LOG_V(DEBUG, TAG, "PDU Maker - code : %d", pdu->hdr->code); + + OIC_LOG_V(DEBUG, TAG, "PDU Maker - buffer data : %x", pdu->hdr); + + res = CASendUnicastData(data->remoteEndpoint, pdu->hdr, pdu->length); + } + } + else + { + OIC_LOG(DEBUG, TAG, "both requestInfo & responseInfo is not available"); + + coap_pdu_t* pdu = NULL; + CAInfo_t info; + memset(&info, 0, sizeof(CAInfo_t)); + pdu = CAGeneratePdu(data->remoteEndpoint->resourceUri, CA_GET, info); + + if (NULL != pdu) + { + OIC_LOG_V(DEBUG, TAG, "PDU Maker - payload : %s", pdu->data); + + OIC_LOG_V(DEBUG, TAG, "PDU Maker - type : %d", pdu->hdr->type); + + OIC_LOG_V(DEBUG, TAG, "PDU Maker - code : %d", pdu->hdr->code); + + OIC_LOG_V(DEBUG, TAG, "PDU Maker - id : %d", pdu->hdr->id); + + OIC_LOG_V(DEBUG, TAG, "PDU Maker - buffer data : %x", pdu->hdr); + + res = CASendMulticastData(pdu->hdr, pdu->length); + } + + } + + if (res) + { + code = SUCCESS; + } + + if (gHandlerCallback != NULL) + { + gHandlerCallback(data->actionId, code); + } +} + +static void* CAThreadBaseRoutine(void* treadData) +{ + OIC_LOG_V(DEBUG, TAG, "message handler main thread start.."); + + CAThread_t* thread = (CAThread_t*) treadData; + + if (thread == NULL) + { + OIC_LOG_V(DEBUG, TAG, "thread data passing error!!"); + + return NULL; + } + + while (!thread->isStop) + { + // mutex lock + u_mutex_lock(thread->threadMutex); + + // if queue is empty, thread will wait + if (u_queue_get_size(thread->dataQueue) <= 0) + { + OIC_LOG_V(DEBUG, TAG, "wait.."); + // wait + u_cond_wait(thread->threadCond, thread->threadMutex); + + OIC_LOG_V(DEBUG, TAG, "wake up.."); + } + + // mutex unlock + u_mutex_unlock(thread->threadMutex); + + // check stop flag + if (thread->isStop) + continue; + + // get data + u_queue_message_t* message = u_queue_get_element(thread->dataQueue); + + CAData_t* data = (CAData_t*) message->msg; + + // process data + thread->threadTask(data); + } + + OIC_LOG_V(DEBUG, TAG, "message handler main thread end.."); + + return NULL; +} + +static int32_t CAIncreaseActionId() +{ + ++gCurrentActionId; + + gCurrentActionId = (gCurrentActionId > MAX_ACTION_NUM) ? 0 : gCurrentActionId; + + return gCurrentActionId; +} + +static void CAReceivedPacketCallback(CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen) +{ + OIC_LOG(DEBUG, TAG, "receivedPacketCallback in message handler!!"); + + if (NULL == data) + { + OIC_LOG(DEBUG, TAG, "received data is null"); + return; + } + + coap_pdu_t* pdu; + uint32_t code = CA_NOT_FOUND; + pdu = CAParsePDU(data, &code); + + if (code == CA_GET || code == CA_POST || code == CA_PUT || code == CA_DELETE) + { + CARequestInfo_t ReqInfo; + memset(&ReqInfo, 0, sizeof(CARequestInfo_t)); + CAGetRequestInfoFromPdu(pdu, &ReqInfo); + + if (NULL != ReqInfo.info.options && NULL != endpoint) + { + OIC_LOG_V(DEBUG, TAG, "Request PDU - optionID: %d", ReqInfo.info.options->optionID); + + OIC_LOG_V(DEBUG, TAG, "Request PDU - optionlist: %s", ReqInfo.info.options->optionData); + + OIC_LOG_V(DEBUG, TAG, "Request PDU - payload: %s", ReqInfo.info.payload); + + OIC_LOG_V(DEBUG, TAG, "Request PDU - code: %d", ReqInfo.method); + + endpoint->resourceUri = (char*) OICMalloc(strlen(ReqInfo.info.options->optionData) + 1); + memcpy(endpoint->resourceUri, ReqInfo.info.options->optionData, + strlen(ReqInfo.info.options->optionData)); + OIC_LOG_V(DEBUG, TAG, "added resource URI : %s", endpoint->resourceUri); + } + + // store the data at queue. + CAData_t* cadata = NULL; + cadata = (CAData_t*) OICMalloc(sizeof(CAData_t)); + memset(cadata, 0, sizeof(CAData_t)); + cadata->actionId = 1; + cadata->remoteEndpoint = endpoint; + cadata->requestInfo = &ReqInfo; + cadata->responseInfo = NULL; + CAAddReceiveData(cadata); + + } + else + { + CAResponseInfo_t ResInfo; + memset(&ResInfo, 0, sizeof(CARequestInfo_t)); + CAGetResponseInfoFromPdu(pdu, &ResInfo); + + if (NULL != ResInfo.info.options && NULL != endpoint) + { + OIC_LOG_V(DEBUG, TAG, "Response PDU - optionID: %d", ResInfo.info.options->optionID); + + OIC_LOG_V(DEBUG, TAG, "Response PDU - optionlist: %s", ResInfo.info.options->optionData); + + OIC_LOG_V(DEBUG, TAG, "Response PDU - payload: %s", ResInfo.info.payload); + + OIC_LOG_V(DEBUG, TAG, "Response PDU - code: %d", ResInfo.result); + + endpoint->resourceUri = (char*) OICMalloc(strlen(ResInfo.info.options->optionData) + 1); + memcpy(endpoint->resourceUri, ResInfo.info.options->optionData, + strlen(ResInfo.info.options->optionData)); + OIC_LOG_V(DEBUG, TAG, "added resource URI : %s", endpoint->resourceUri); + } + + // store the data at queue. + CAData_t* cadata = NULL; + cadata = (CAData_t*) OICMalloc(sizeof(CAData_t)); + memset(cadata, 0, sizeof(CAData_t)); + cadata->actionId = 1; + cadata->remoteEndpoint = endpoint; + cadata->requestInfo = NULL; + cadata->responseInfo = &ResInfo; + CAAddReceiveData(cadata); + } +} + +void CAHandleRequestResponseCallbacks() +{ + OIC_LOG_V(DEBUG, TAG, "CAHandleRequestResponseCallbacks"); + + // parse the data and call the callbacks. + // #1 parse the data + // #2 get endpoint + + u_mutex_lock(gMessageQueueMutex); + + u_queue_message_t* item = u_queue_get_element(gMessageQueue); + + u_mutex_unlock(gMessageQueueMutex); + + if (item == NULL) + return; + + // get values + void* msg = item->msg; + + if (msg == NULL) + return; + + // get endpoint + CAData_t* td = (CAData_t*) msg; + + CARemoteEndpoint_t* rep = td->remoteEndpoint; + + if (rep == NULL) + return; + + if (td->requestInfo != NULL) + { + if (gRequestHandler) + { + gRequestHandler(rep, NULL); + } + } + + if (td->responseInfo != NULL) + { + if (gResponseHandler) + { + gResponseHandler(rep, NULL); + } + } + + u_queue_remove_element(gMessageQueue); +} + +int32_t CADetachRequestMessage(const CARemoteEndpoint_t* object, const CARequestInfo_t* request) +{ + OIC_LOG_V(DEBUG, TAG, "CADetachRequestMessage"); + + if (object == NULL || request == NULL) + { + return -1; + } + + int32_t id = 0; + + // create action id + id = CAIncreaseActionId(); + + CAData_t* data = (CAData_t*) OICMalloc(sizeof(CAData_t)); + MEMORY_ALLOCK_CHECK(data); + + // initialize + memset(data, 0, sizeof(CAData_t)); + + // clone remote endpoint + CARemoteEndpoint_t* remoteEndpoint = CACloneRemoteEndpoint(object); + MEMORY_ALLOCK_CHECK(remoteEndpoint); + + // clone request info + CARequestInfo_t* requestInfo = CACloneRequestInfo(request); + MEMORY_ALLOCK_CHECK(requestInfo); + + // save data + data->actionId = id; + data->remoteEndpoint = remoteEndpoint; + data->requestInfo = requestInfo; + data->responseInfo = NULL; + + // add thread + CAAddSendData(data); + + return id; + + // memory error label. + memory_error_exit: + + CADestroyRemoteEndpointInternal(remoteEndpoint); + + CADestroyRequestInfoInternal(requestInfo); + + if (data != NULL) + { + OICFree(data); + } + + return -1; +} + +int32_t CADetachResponseMessage(const CARemoteEndpoint_t* object, const CAResponseInfo_t* response) +{ + OIC_LOG_V(DEBUG, TAG, "CADetachResponseMessage"); + + if (object == NULL || response == NULL) + { + return -1; + } + + int32_t id = 0; + + // create action id + id = CAIncreaseActionId(); + + CAData_t* data = (CAData_t*) OICMalloc(sizeof(CAData_t)); + MEMORY_ALLOCK_CHECK(data); + + // initialize + memset(data, 0, sizeof(CAData_t)); + + // clone remote endpoint + CARemoteEndpoint_t* remoteEndpoint = CACloneRemoteEndpoint(object); + MEMORY_ALLOCK_CHECK(remoteEndpoint); + + // clone response info + CAResponseInfo_t* responseInfo = CACloneResponseInfo(response); + MEMORY_ALLOCK_CHECK(responseInfo); + + // save data + data->actionId = id; + data->remoteEndpoint = remoteEndpoint; + data->requestInfo = NULL; + data->responseInfo = responseInfo; + + // add thread + CAAddSendData(data); + + return id; + + // memory error label. + memory_error_exit: + + CADestroyRemoteEndpointInternal(remoteEndpoint); + + CADestroyResponseInfoInternal(responseInfo); + + if (data != NULL) + { + OICFree(data); + } + + return -1; +} + +int32_t CADetachMessageResourceUri(const CAURI_t resourceUri) +{ + if (resourceUri == NULL) + { + return -1; + } + + int32_t id = 0; + + // create action id + id = CAIncreaseActionId(); + + CAData_t* data = (CAData_t*) OICMalloc(sizeof(CAData_t)); + MEMORY_ALLOCK_CHECK(data); + + // initialize + memset(data, 0, sizeof(CAData_t)); + + CAAddress_t addr; + memset(&addr, 0, sizeof(CAAddress_t)); + CARemoteEndpoint_t* remoteEndpoint = CACreateRemoteEndpointInternal(resourceUri, addr, + CA_ETHERNET | CA_WIFI | CA_EDR | CA_LE); + + // save data + data->actionId = id; + data->remoteEndpoint = remoteEndpoint; + data->requestInfo = NULL; + data->responseInfo = NULL; + + // add thread + CAAddSendData(data); + + return id; + + // memory error label. + memory_error_exit: + + CADestroyRemoteEndpointInternal(remoteEndpoint); + + if (data != NULL) + { + OICFree(data); + } + + return -1; +} + +void CASetMessageHandlerCallback(CAMessageHandlerCallback callback) +{ + OIC_LOG_V(DEBUG, TAG, "set message handler callback."); + + gHandlerCallback = callback; +} + +void CASetRequestResponseCallbacks(CARequestCallback ReqHandler, CAResponseCallback RespHandler) +{ + OIC_LOG_V(DEBUG, TAG, "set request, response handler callback."); + + gRequestHandler = ReqHandler; + gResponseHandler = RespHandler; +} + +CAResult_t CAInitializeMessageHandler() +{ + CASetPacketReceivedCallback(CAReceivedPacketCallback); + + // create thread pool + CAResult_t res; + res = u_thread_pool_init(MAX_THREAD_POOL_SIZE, &gThreadPoolHandle); + + if (res != CA_STATUS_OK) + { + OIC_LOG_V(DEBUG, TAG, "thread pool initialize error."); + return res; + } + + // send thread initialize + memset(&gSendThread, 0, sizeof(CAThread_t)); + + // mutex init + u_mutex_init(); + + // set send thread data + gSendThread.dataQueue = u_queue_create(); + gSendThread.threadMutex = u_mutex_new(); + gSendThread.threadCond = u_cond_new(); + gSendThread.isStop = FALSE; + gSendThread.threadTask = CASendThreadProcess; + + // start send thread + res = u_thread_pool_add_task(gThreadPoolHandle, CAThreadBaseRoutine, &gSendThread); + + if (res != CA_STATUS_OK) + { + OIC_LOG_V(DEBUG, TAG, "thread pool add task error."); + return res; + } + + // set receive queue + gMessageQueue = u_queue_create(); + gMessageQueueMutex = u_mutex_new(); + + // initialize interface adapters by controller + CAInitializeAdapters(); + + return CA_STATUS_OK; +} + +void CATerminateMessageHandler() +{ + // terminate interface adapters by controller + CATerminateAdapters(); + + // stop thread + CAStopSendThread(); + + // delete thread data + u_mutex_free(gSendThread.threadMutex); + u_cond_free(gSendThread.threadCond); + u_queue_delete(gSendThread.dataQueue); + + // destroy thread pool + u_thread_pool_free(gThreadPoolHandle); + + OIC_LOG_V(DEBUG, TAG, "message handler terminate completed!"); + + u_queue_delete(gMessageQueue); + u_mutex_free(gMessageQueueMutex); +} + diff --git a/resource/csdk/connectivity/src/canetworkconfigurator.c b/resource/csdk/connectivity/src/canetworkconfigurator.c new file mode 100644 index 000000000..0efe11841 --- /dev/null +++ b/resource/csdk/connectivity/src/canetworkconfigurator.c @@ -0,0 +1,173 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +#include + +#include "canetworkconfigurator.h" +#include "uarraylist.h" +#include "logger.h" +#include "cainterfacecontroller.h" + +#define TAG PCF("CA") + +static u_arraylist_t *gSelectedNetworkList = NULL; + +CAResult_t CAAddNetworkType(uint32_t ConnectivityType) +{ + if (gSelectedNetworkList == NULL) + { + OIC_LOG_V(DEBUG, TAG, "Create network list"); + + gSelectedNetworkList = u_arraylist_create(); + } + + switch (ConnectivityType) + { + case CA_ETHERNET: + +#ifndef ETHERNET_ADAPTER + OIC_LOG_V(DEBUG, TAG, "Add network type(ETHERNET) - Not Supported"); + return CA_NOT_SUPPORTED; +#endif /* ETHERNET_ADAPTER */ + + OIC_LOG_V(DEBUG, TAG, "Add network type(ETHERNET)"); + u_arraylist_add(gSelectedNetworkList, &NETWORK_ETHERNET); + + break; + + case CA_WIFI: + +#ifndef WIFI_ADAPTER + OIC_LOG_V(DEBUG, TAG, "Add network type(WIFI) - Not Supported"); + return CA_NOT_SUPPORTED; +#endif /* WIFI_ADAPTER */ + + OIC_LOG_V(DEBUG, TAG, "Add network type(WIFI)"); + u_arraylist_add(gSelectedNetworkList, &NETWORK_WIFI); + + break; + + case CA_EDR: + +#ifndef EDR_ADAPTER + OIC_LOG_V(DEBUG, TAG, "Add network type(EDR) - Not Supported"); + return CA_NOT_SUPPORTED; +#endif /* EDR_ADAPTER */ + + OIC_LOG_V(DEBUG, TAG, "Add network type(EDR)"); + u_arraylist_add(gSelectedNetworkList, &NETWORK_EDR); + break; + + case CA_LE: + +#ifdef LE_ADAPTER + OIC_LOG_V(DEBUG, TAG, "Add network type(LE) - Not Supported"); + return CA_NOT_SUPPORTED; +#endif /* LE_ADAPTER */ + + OIC_LOG_V(DEBUG, TAG, "Add network type(LE)"); + u_arraylist_add(gSelectedNetworkList, &NETWORK_LE); + break; + + } + + // start selected interface adapter + CAStartAdapter(ConnectivityType); + + return CA_STATUS_OK; +} + +CAResult_t CARemoveNetworkType(uint32_t ConnectivityType) +{ + if (gSelectedNetworkList == NULL) + { + OIC_LOG_V(DEBUG, TAG, "Selected network not found"); + + return CA_STATUS_FAILED; + } + + switch (ConnectivityType) + { + case CA_ETHERNET: + +#ifndef ETHERNET_ADAPTER + OIC_LOG_V(DEBUG, TAG, "Remove network type(ETHERNET) - Not Supported"); + return CA_NOT_SUPPORTED; +#else + + OIC_LOG_V(DEBUG, TAG, "Remove network type(ETHERNET)"); + u_arraylist_remove(gSelectedNetworkList, &NETWORK_ETHERNET); +#endif /* ETHERNET_ADAPTER */ + break; + + case CA_WIFI: + +#ifndef WIFI_ADAPTER + OIC_LOG_V(DEBUG, TAG, "Remove network type(WIFI) - Not Supported"); + return CA_NOT_SUPPORTED; +#else + OIC_LOG_V(DEBUG, TAG, "Remove network type(WIFI)"); + u_arraylist_remove(gSelectedNetworkList, &NETWORK_WIFI); +#endif /* WIFI_ADAPTER */ + + break; + + case CA_EDR: + +#ifndef EDR_ADAPTER + OIC_LOG_V(DEBUG, TAG, "Remove network type(EDR) - Not Supported"); + return CA_NOT_SUPPORTED; +#else + OIC_LOG_V(DEBUG, TAG, "Remove network type(EDR)"); + u_arraylist_remove(gSelectedNetworkList, &NETWORK_EDR); +#endif /* EDR_ADAPTER */ + + break; + + case CA_LE: + +#ifdef LE_ADAPTER + OIC_LOG_V(DEBUG, TAG, "Remove network type(LE) - Not Supported"); + return CA_NOT_SUPPORTED; +#else + OIC_LOG_V(DEBUG, TAG, "Remove network type(LE)"); + u_arraylist_remove(gSelectedNetworkList, &NETWORK_LE); +#endif /* LE_ADAPTER */ + + break; + } + + // stop selected interface adapter + CAStopAdapter(ConnectivityType); + + return CA_STATUS_OK; +} + +u_arraylist_t* CAGetSelectedNetworkList() +{ + if (gSelectedNetworkList == NULL) + { + OIC_LOG_V(DEBUG, TAG, "Selected network not found"); + + return NULL; + } + + return gSelectedNetworkList; +} diff --git a/resource/csdk/connectivity/src/caprotocolmessage.c b/resource/csdk/connectivity/src/caprotocolmessage.c new file mode 100644 index 000000000..fb5a3d549 --- /dev/null +++ b/resource/csdk/connectivity/src/caprotocolmessage.c @@ -0,0 +1,403 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +#include +#include +#include + +#include "caprotocolmessage.h" +#include "logger.h" +#include "oic_malloc.h" + +#define TAG PCF("CA") + +#define CA_MAX_TOKEN_LEN 8 +#define CA_FLAGS_BLOCK 0x01 +#define CA_URI_MAX_SIZE 256 +#define CA_BUFSIZE 40 + +uint32_t CAGetRequestInfoFromPdu(const coap_pdu_t *pdu, CARequestInfo_t* outReqInfo) +{ + OIC_LOG(DEBUG, TAG, "get request info from PDU"); + if (NULL == pdu) + return 0; + + uint32_t code = CA_NOT_FOUND; + CAGetRequestPDUInfo(pdu, &code, &(outReqInfo->info)); + outReqInfo->method = code; + return 1; +} + +uint32_t CAGetResponseInfoFromPdu(const coap_pdu_t *pdu, CAResponseInfo_t* outResInfo) +{ + OIC_LOG(DEBUG, TAG, "get response info from PDU"); + if (NULL == pdu) + return 0; + + uint32_t code = CA_NOT_FOUND; + CAGetRequestPDUInfo(pdu, &code, &(outResInfo->info)); + outResInfo->result = code; + + return 1; +} + +coap_pdu_t* CAGeneratePdu(const char* uri, const uint32_t code, const CAInfo_t info) +{ + OIC_LOG(DEBUG, TAG, "generate PDU"); + + coap_pdu_t *pdu; + char* coapUri = NULL; + uint32_t coapHeaderLength = 12; + uint32_t length; + coap_list_t *optlist = NULL; + + if (NULL == uri) + return NULL; + + length = strlen(uri); + coapUri = (char*) OICMalloc(length + coapHeaderLength + 1); + memset(coapUri, 0, length + coapHeaderLength + 1); + + if (NULL != coapUri) + { + + memcpy(coapUri, "coap://[::]/", coapHeaderLength); + memcpy(coapUri + coapHeaderLength, uri, length); + + // parsing options in URI + CAParseURI(coapUri, &optlist); + + // parsing options in HeadOption + if (NULL != &info) + { + CAParseHeadOption(code, info, &optlist); + } + + OICFree(coapUri); + } + + if (NULL != info.payload) + { + if (!(pdu = CACreatePDUforRequestWithPayload((code_t) code, optlist, info.payload))) + return NULL; + } + else + { + if (!(pdu = CACreatePDUforRequest((code_t) code, optlist))) + return NULL; + } + + // pdu print method : coap_show_pdu(pdu); + + return pdu; +} + +coap_pdu_t* CAParsePDU(const char* data, uint32_t* outCode) +{ + coap_pdu_t* outpdu = coap_new_pdu(); + coap_pdu_parse((unsigned char *) data, strlen(data), outpdu); + (*outCode) = (uint32_t) outpdu->hdr->code; + + return outpdu; +} + +coap_pdu_t* CACreatePDUforRequestWithPayload(const code_t code, coap_list_t *options, + const char* payload) +{ + OIC_LOG(DEBUG, TAG, "CACreatePDUforRequestWithPayload"); + + coap_pdu_t *pdu; + coap_list_t *opt; + unsigned char _token_data[8]; + str the_token = + { 0, _token_data }; + + if (!(pdu = coap_new_pdu())) + return NULL; + + /* initialize message id */ + unsigned short message_id; + prng((unsigned char *)&message_id, sizeof(unsigned short)); + + pdu->hdr->type = msgtype; + pdu->hdr->id = htons(++message_id); + pdu->hdr->code = code; + + pdu->hdr->token_length = the_token.length; + if (!coap_add_token(pdu, the_token.length, the_token.s)) + { + OIC_LOG(DEBUG, TAG,"cannot add token to request"); + } + + for (opt = options; opt; opt = opt->next) + { + coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option *)opt->data), + COAP_OPTION_LENGTH(*(coap_option *)opt->data), + COAP_OPTION_DATA(*(coap_option *)opt->data)); + } + + if (NULL != payload) + { + uint32_t len = strlen(payload); + if ((flags & CA_FLAGS_BLOCK) == 0) + { + OIC_LOG_V(DEBUG, TAG, "coap_add_data, payload: %s", payload); + coap_add_data(pdu, len, payload); + } + else + { + OIC_LOG_V(DEBUG, TAG, "coap_add_block, payload: %s", payload); + coap_add_block(pdu, len, payload, block.num, block.szx); + } + } + return pdu; +} + +coap_pdu_t* CACreatePDUforRequest(const code_t code, coap_list_t *options) +{ + OIC_LOG(DEBUG, TAG, "CACreatePDUforRequest"); + + coap_pdu_t *pdu; + coap_list_t *opt; + unsigned char _token_data[8]; + str the_token = + { 0, _token_data }; + + if (!(pdu = coap_new_pdu())) + return NULL; + + /* initialize message id */ + unsigned short message_id; + prng((unsigned char *)&message_id, sizeof(unsigned short)); + + pdu->hdr->type = msgtype; + pdu->hdr->id = htons(++message_id); + pdu->hdr->code = code; + + pdu->hdr->token_length = the_token.length; + if (!coap_add_token(pdu, the_token.length, the_token.s)) + { + OIC_LOG(DEBUG, TAG, "cannot add token to request"); + } + + for (opt = options; opt; opt = opt->next) + { + coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option *)opt->data), + COAP_OPTION_LENGTH(*(coap_option *)opt->data), + COAP_OPTION_DATA(*(coap_option *)opt->data)); + } + + return pdu; +} + +void CAParseURI(const char* uriInfo, coap_list_t **optlist) +{ + OIC_LOG(DEBUG, TAG, "parse URI"); + + unsigned char portbuf[2]; + unsigned char _buf[CA_BUFSIZE]; + unsigned char *buf = _buf; + coap_uri_t uri; + size_t buflen; + uint32_t res; + + OIC_LOG_V(DEBUG, TAG, "url : %s", uriInfo); + + /* split arg into Uri-* options */ + coap_split_uri((unsigned char *) uriInfo, strlen(uriInfo), &uri); + + if (uri.port != COAP_DEFAULT_PORT) + { + coap_insert(optlist, + CACreateNewOptionNode(COAP_OPTION_URI_PORT, + coap_encode_var_bytes(portbuf, uri.port), portbuf), CAOrderOpts); + } + + if (uri.path.length) + { + buflen = CA_BUFSIZE; + res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); + + while (res--) + { + coap_insert(optlist, + CACreateNewOptionNode(COAP_OPTION_URI_PATH, COAP_OPT_LENGTH(buf), + COAP_OPT_VALUE(buf)), CAOrderOpts); + buf += COAP_OPT_SIZE(buf); + } + } + + if (uri.query.length) + { + buflen = CA_BUFSIZE; + buf = _buf; + res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen); + + while (res--) + { + coap_insert(optlist, + CACreateNewOptionNode(COAP_OPTION_URI_QUERY, COAP_OPT_LENGTH(buf), + COAP_OPT_VALUE(buf)), CAOrderOpts); + + buf += COAP_OPT_SIZE(buf); + } + } + +} + +void CAParseHeadOption(const uint32_t code, const CAInfo_t info, coap_list_t **optlist) +{ + OIC_LOG_V(DEBUG, TAG, "start parse Head Option : %d", info.numOptions); + + uint32_t i; + for (i = 0; i < info.numOptions; i++) + { + coap_insert(optlist, + CACreateNewOptionNode(info.options->optionID, info.options->optionLength, + info.options->optionData), CAOrderOpts); + } +} + +coap_list_t* CACreateNewOptionNode(const uint16_t key, const uint32_t length, const uint8_t *data) +{ + coap_option *option; + coap_list_t *node; + + option = coap_malloc(sizeof(coap_option) + length); + if (!option) + goto error; + + COAP_OPTION_KEY(*option) = key; + COAP_OPTION_LENGTH(*option) = length; + memcpy(COAP_OPTION_DATA(*option), data, length); + + /* we can pass NULL here as delete function since option is released automatically */ + node = coap_new_listnode(option, NULL); + + if (node) + return node; + + error: perror("new_option_node: malloc"); + coap_free( option); + return NULL; +} + +int32_t CAOrderOpts(void *a, void *b) +{ + if (!a || !b) + return a < b ? -1 : 1; + + if (COAP_OPTION_KEY(*(coap_option *)a) < COAP_OPTION_KEY(*(coap_option *)b)) + return -1; + + return COAP_OPTION_KEY(*(coap_option *)a) == COAP_OPTION_KEY(*(coap_option *)b); +} + +void CAGetRequestPDUInfo(const coap_pdu_t *pdu, uint32_t* outCode, CAInfo_t* outInfo) +{ + unsigned char buf[COAP_MAX_PDU_SIZE]; /* need some space for output creation */ + uint32_t encode = 0; + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + char optionResult[CA_URI_MAX_SIZE] = + { 0, }; + uint32_t count = 0; + uint32_t isfirstsetflag = 0; + + /* show options, if any */ + coap_option_iterator_init((coap_pdu_t *) pdu, &opt_iter, COAP_OPT_ALL); + + memset(optionResult, 0, sizeof(optionResult)); + while ((option = coap_option_next(&opt_iter))) + { + + if (print_readable(COAP_OPT_VALUE(option), COAP_OPT_LENGTH(option), buf, sizeof(buf), + encode)) + { + if (opt_iter.type == COAP_OPTION_URI_PATH || opt_iter.type == COAP_OPTION_URI_QUERY) + { + if (0 == isfirstsetflag) + { + isfirstsetflag = 1; + memcpy(optionResult + count, buf, strlen(buf)); + count += strlen(buf); + + } + else + { + if (opt_iter.type == COAP_OPTION_URI_PATH) + { + memcpy(optionResult + count, "/", 1); + count++; + } + else if (opt_iter.type == COAP_OPTION_URI_QUERY) + { + memcpy(optionResult + count, "?", 1); + count++; + } + memcpy(optionResult + count, buf, strlen(buf)); + count += strlen(buf); + } + } + } + } + + OIC_LOG(DEBUG, TAG, "set CAInfo_t after parsing"); + + // set pdu info + (*outCode) = (uint32_t) pdu->hdr->code; + memset(outInfo, 0, sizeof(CAInfo_t)); + + outInfo->options = (CAHeaderOption_t*) OICMalloc(sizeof(CAHeaderOption_t)); + memset(outInfo->options, 0, sizeof(CAHeaderOption_t)); + + outInfo->options->optionID = opt_iter.type; + outInfo->options->optionLength = count; + memcpy(outInfo->options->optionData, optionResult, CA_MAX_HEADER_OPTION_DATA_LENGTH); + + if (pdu->hdr->token_length > 0) + { + outInfo->token = (char*) OICMalloc(pdu->hdr->token_length); + memcpy(outInfo->token, pdu->hdr->token, pdu->hdr->token_length); + } + + if (NULL != pdu->data) + { + outInfo->payload = (char*) OICMalloc(strlen(pdu->data) + 1); + memcpy(outInfo->payload, pdu->data, strlen(pdu->data) + 1); + } +} + +CAResult_t CAGenerateTokenInternal(CAToken_t* token) +{ + OIC_LOG(DEBUG, TAG, "generate the token"); + + return CA_STATUS_OK; +} + +void CADestroyTokenInternal(CAToken_t token) +{ + OIC_LOG(DEBUG, TAG, "destroy the token!!"); + + if (token != NULL) + { + OICFree(token); + } +} diff --git a/resource/csdk/connectivity/src/caremotehandler.c b/resource/csdk/connectivity/src/caremotehandler.c new file mode 100644 index 000000000..f193168c6 --- /dev/null +++ b/resource/csdk/connectivity/src/caremotehandler.c @@ -0,0 +1,477 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +#include "oic_malloc.h" +#include "caremotehandler.h" +#include "logger.h" + +#define TAG PCF("CA") + +CARemoteEndpoint_t* CACloneRemoteEndpoint(const CARemoteEndpoint_t* rep) +{ + char* temp = NULL; + int len = 0; + + if (rep == NULL) + return NULL; + + // allocate the remote end point structure. + CARemoteEndpoint_t* clone = (CARemoteEndpoint_t*) OICMalloc(sizeof(CARemoteEndpoint_t)); + if (clone == NULL) + { + OIC_LOG_V(DEBUG, TAG, "memory alloc error!!"); + return NULL; + } + memset(clone, 0, sizeof(CARemoteEndpoint_t)); + memcpy(clone, rep, sizeof(CARemoteEndpoint_t)); + + if (rep->resourceUri != NULL) + { + // allocate reference uri field + len = strlen(rep->resourceUri); + + temp = (char*) OICMalloc(sizeof(char) * (len + 1)); + if (temp == NULL) + { + OIC_LOG_V(DEBUG, TAG, "memory alloc error!!"); + + CADestroyRemoteEndpointInternal(clone); + + return NULL; + } + memset(temp, 0, sizeof(char) * (len + 1)); + strncpy(temp, rep->resourceUri, len); + + // save the uri + clone->resourceUri = temp; + } + + return clone; +} + +#define COAP_PREFIX "coap://" +#define COAP_PREFIX_LEN 7 + +// return 1 : ip +// return 0 : mac +static int32_t getCAAddress(const char* pAddress, CAAddress_t* outAddress) +{ + if (pAddress == NULL || outAddress == NULL) + return -1; + + // simple parse, it will be change. + // 10.11.12.13:4545 (ip) + // 10:11:12:13:45:45 (mac) + + int32_t len = strlen(pAddress); + + int32_t isIp = 0; + int32_t ipLen = 0; + int32_t port = 0; + + int i = 0; + for (i = 0; i < len; i++) + { + if (pAddress[i] == '.') + { + isIp = 1; + } + + // found port number start index + if (isIp && pAddress[i] == ':') + { + ipLen = i; + break; + } + } + + if (isIp) + { + strncpy(outAddress->IP.ipAddress, pAddress, ipLen == 0 ? len : ipLen); + + if (ipLen > 0) + outAddress->IP.port = atoi(pAddress + ipLen + 1); + + OIC_LOG_V(DEBUG, TAG, "ip: %s,port: %d", outAddress->IP.ipAddress, outAddress->IP.port); + } + else + { + strncpy(outAddress->BT.btMacAddress, pAddress, CA_MACADDR_SIZE - 1); + + OIC_LOG_V(DEBUG, TAG, "mac address : %s", outAddress->BT.btMacAddress); + } + + return isIp; +} + +CARemoteEndpoint_t* CACreateRemoteEndpointUriInternal(const CAURI_t uri) +{ + // support URI type + // coap://10.11.12.13:4545/resource_uri + // coap://10:11:12:13:45:45/resource_uri + + if (uri == NULL) + return NULL; + + // parse uri + // #1. check prefix + int startIndex = 0; + + if (strncmp(COAP_PREFIX, uri, COAP_PREFIX_LEN) == 0) + { + OIC_LOG_V(DEBUG, TAG, "uri has '%s' prefix.", COAP_PREFIX); + startIndex = COAP_PREFIX_LEN; + } + + // #2. copy uri for parse + char* cloneUri = NULL; + int32_t len = strlen(uri) - startIndex; + + if (len <= 0) + { + OIC_LOG_V(DEBUG, TAG, "uri length is 0!"); + return NULL; + } + + cloneUri = (char*) OICMalloc(sizeof(char) * (len + 1)); + if (cloneUri == NULL) + { + OIC_LOG_V(DEBUG, TAG, "memory error!!"); + return NULL; + } + memset(cloneUri, 0, sizeof(char) * (len + 1)); + memcpy(cloneUri, &uri[startIndex], sizeof(char) * (len + 1)); + + // #3. parse address + // #4. parse resource uri + char* pAddress = cloneUri; + char* pResourceUri = NULL; + + int32_t i = 0; + for (i = 0; i < len; i++) + { + if (cloneUri[i] == '/') + { + // separate + cloneUri[i] = 0; + + pResourceUri = &cloneUri[i + 1]; + + break; + } + + } + + OIC_LOG_V(DEBUG, TAG, "pAddress : %s", pAddress); + + OIC_LOG_V(DEBUG, TAG, "pResourceUri : %s", pResourceUri == NULL ? "" : pResourceUri); + + // address + CAAddress_t address; + memset(&address, 0, sizeof(CAAddress_t)); + + int resType = getCAAddress(pAddress, &address); + if (resType == -1) + { + OIC_LOG_V(DEBUG, TAG, "address parse error"); + + OICFree(cloneUri); + return NULL; + } + + // resource uri + CAURI_t resourceUri = pResourceUri; + + // connectivity type + CAConnectivityType_t type; + + if (resType == 1) + { + type = CA_WIFI; + } + else + { + type = CA_EDR; + } + + CARemoteEndpoint_t* remoteEndpoint = CACreateRemoteEndpointInternal(resourceUri, address, type); + + OICFree(cloneUri); + + return remoteEndpoint; +} + +CARemoteEndpoint_t* CACreateRemoteEndpointInternal(const CAURI_t resourceUri, + const CAAddress_t addr, const CAConnectivityType_t type) +{ + char* temp = NULL; + int len = 0; + + if (resourceUri == NULL) + { + OIC_LOG_V(DEBUG, TAG, "uri is null value"); + return NULL; + } + + // allocate the remote end point structure. + CARemoteEndpoint_t* rep = (CARemoteEndpoint_t*) OICMalloc(sizeof(CARemoteEndpoint_t)); + + if (rep == NULL) + { + OIC_LOG_V(DEBUG, TAG, "memory alloc error"); + return NULL; + } + memset(rep, 0, sizeof(CARemoteEndpoint_t)); + + // allocate reference uri field + len = strlen(resourceUri); + + temp = (char*) OICMalloc(sizeof(char) * (len + 1)); + if (temp == NULL) + { + OIC_LOG_V(DEBUG, TAG, "memory alloc error"); + + CADestroyRemoteEndpointInternal(rep); + + return NULL; + } + memset(temp, 0, sizeof(char) * (len + 1)); + strncpy(temp, resourceUri, len); + + // save the uri + rep->resourceUri = temp; + + // save the addressInfo + memcpy(&(rep->addressInfo), &addr, sizeof(CAAddress_t)); + + // save the type + rep->connectivityType = type; + + return rep; +} + +CARequestInfo_t* CACloneRequestInfo(const CARequestInfo_t* rep) +{ + char* temp = NULL; + int len = 0; + + if (rep == NULL) + return NULL; + + // allocate the request info structure. + CARequestInfo_t* clone = (CARequestInfo_t*) OICMalloc(sizeof(CARequestInfo_t)); + if (clone == NULL) + { + OIC_LOG_V(DEBUG, TAG, "memory alloc error!!"); + return NULL; + } + memset(clone, 0, sizeof(CARequestInfo_t)); + memcpy(clone, rep, sizeof(CARequestInfo_t)); + + if (rep->info.token != NULL) + { + // allocate token field + len = strlen(rep->info.token); + + temp = (char*) OICMalloc(sizeof(char) * (len + 1)); + if (temp == NULL) + { + OIC_LOG_V(DEBUG, TAG, "memory alloc error!!"); + + CADestroyRequestInfoInternal(clone); + + return NULL; + } + memset(temp, 0, sizeof(char) * (len + 1)); + strncpy(temp, rep->info.token, len); + + // save the token + clone->info.token = temp; + } + + if (rep->info.options != NULL) + { + // save the options + clone->info.options = (CAHeaderOption_t*) OICMalloc(sizeof(CAHeaderOption_t)); + memset(clone->info.options, 0, sizeof(CAHeaderOption_t)); + memcpy(clone->info.options, rep->info.options, sizeof(CAHeaderOption_t)); + } + + if (rep->info.payload != NULL) + { + // allocate payload field + len = strlen(rep->info.payload); + + temp = (char*) OICMalloc(sizeof(char) * (len + 1)); + if (temp == NULL) + { + OIC_LOG_V(DEBUG, TAG, "memory alloc error!!"); + + CADestroyRequestInfoInternal(clone); + + return NULL; + } + memset(temp, 0, sizeof(char) * (len + 1)); + strncpy(temp, rep->info.payload, len); + + // save the payload + clone->info.payload = temp; + } + + return clone; +} + +CAResponseInfo_t* CACloneResponseInfo(const CAResponseInfo_t* rep) +{ + char* temp = NULL; + int len = 0; + + if (rep == NULL) + return NULL; + + // allocate the response info structure. + CAResponseInfo_t* clone = (CAResponseInfo_t*) OICMalloc(sizeof(CAResponseInfo_t)); + if (clone == NULL) + { + OIC_LOG_V(DEBUG, TAG, "memory alloc error!!"); + return NULL; + } + memset(clone, 0, sizeof(CAResponseInfo_t)); + memcpy(clone, rep, sizeof(CAResponseInfo_t)); + + if (rep->info.token != NULL) + { + // allocate token field + len = strlen(rep->info.token); + + temp = (char*) OICMalloc(sizeof(char) * (len + 1)); + if (temp == NULL) + { + OIC_LOG_V(DEBUG, TAG, "memory alloc error!!"); + + CADestroyResponseInfoInternal(clone); + + return NULL; + } + memset(temp, 0, sizeof(char) * (len + 1)); + strncpy(temp, rep->info.token, len); + + // save the token + clone->info.token = temp; + } + + if (rep->info.options != NULL) + { + // save the options + clone->info.options = (CAHeaderOption_t*) OICMalloc(sizeof(CAHeaderOption_t)); + memset(clone->info.options, 0, sizeof(CAHeaderOption_t)); + memcpy(clone->info.options, rep->info.options, sizeof(CAHeaderOption_t)); + } + + if (rep->info.payload != NULL) + { + // allocate payload field + len = strlen(rep->info.payload); + + temp = (char*) OICMalloc(sizeof(char) * (len + 1)); + if (temp == NULL) + { + OIC_LOG_V(DEBUG, TAG, "memory alloc error!!"); + + CADestroyResponseInfoInternal(clone); + + return NULL; + } + memset(temp, 0, sizeof(char) * (len + 1)); + strncpy(temp, rep->info.payload, len); + + // save the payload + clone->info.payload = temp; + } + + return clone; +} + +void CADestroyRemoteEndpointInternal(CARemoteEndpoint_t* rep) +{ + if (rep == NULL) + return; + + // free uri field + if (rep->resourceUri != NULL) + { + OICFree((char*) rep->resourceUri); + } + + // free remote end point structure. + OICFree(rep); +} + +void CADestroyRequestInfoInternal(CARequestInfo_t* rep) +{ + if (rep == NULL) + return; + + // free token field + if (rep->info.token != NULL) + { + OICFree((char*) rep->info.token); + } + + // free options field + if (rep->info.options != NULL) + { + OICFree((CAHeaderOption_t*) rep->info.options); + } + + // free payload field + if (rep->info.payload != NULL) + { + OICFree((char*) rep->info.payload); + } + + OICFree(rep); +} + +void CADestroyResponseInfoInternal(CAResponseInfo_t* rep) +{ + if (rep == NULL) + return; + + // free token field + if (rep->info.token != NULL) + { + OICFree((char*) rep->info.token); + } + + // free options field + if (rep->info.options != NULL) + { + OICFree((CAHeaderOption_t*) rep->info.options); + } + + // free payload field + if (rep->info.payload != NULL) + { + OICFree((char*) rep->info.payload); + } + + OICFree(rep); +} diff --git a/resource/csdk/connectivity/src/ethernet_adapter/linux/caethernetadapter.c b/resource/csdk/connectivity/src/ethernet_adapter/linux/caethernetadapter.c new file mode 100644 index 000000000..e73c2fdf9 --- /dev/null +++ b/resource/csdk/connectivity/src/ethernet_adapter/linux/caethernetadapter.c @@ -0,0 +1,134 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +#include +#include +#include + +#include "caethernetadapter.h" +#include "logger.h" + +#define TAG PCF("CA") + +static CANetworkPacketReceivedCallback gEthernetReceivedCallback = NULL; + +CAResult_t CAInitializeEthernet(CARegisterConnectivityCallback registerCallback, + CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback) +{ + OIC_LOG_V(DEBUG, TAG, "CAInitializeEthernet"); + + gEthernetReceivedCallback = reqRespCallback; + + // register handlers + CAConnectivityHandler_t handler; + memset(&handler, 0, sizeof(CAConnectivityHandler_t)); + + handler.startAdapter = CAStartEthernet; + handler.startListenServer = CAStartEthernetListeningServer; + handler.startDiscoverServer = CAStartEthernetDiscoveryServer; + handler.sendData = CASendEthernetUnicastData; + handler.sendDataToAll = CASendEthernetMulticastData; + handler.startNotifyServer = CAStartEthernetNotifyServer; + handler.sendNotification = CASendEthernetNotification; + handler.GetnetInfo = CAGetEthernetInterfaceInformation; + handler.readData = CAReadEthernetData; + handler.stopAdapter = CAStopEthernet; + handler.terminate = CATerminateEthernet; + + registerCallback(handler, CA_ETHERNET); + + return CA_STATUS_OK; +} + +CAResult_t CAStartEthernet() +{ + OIC_LOG_V(DEBUG, TAG, "CAStartEthernet"); + + return CA_STATUS_OK; +} + +CAResult_t CAStartEthernetListeningServer() +{ + OIC_LOG_V(DEBUG, TAG, "CAStartEthernetListeningServer"); + + return CA_STATUS_OK; +} + +CAResult_t CAStartEthernetDiscoveryServer() +{ + OIC_LOG_V(DEBUG, TAG, "CAStartEthernetDiscoveryServer"); + + return CA_STATUS_OK; +} + +uint32_t CASendEthernetUnicastData(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen) +{ + OIC_LOG_V(DEBUG, TAG, "CASendEthernetUnicastData"); + + return 0; +} + +uint32_t CASendEthernetMulticastData(void* data, uint32_t dataLen) +{ + OIC_LOG_V(DEBUG, TAG, "CASendEthernetMulticastData"); + + return 0; +} + +CAResult_t CAStartEthernetNotifyServer() +{ + OIC_LOG_V(DEBUG, TAG, "CAStartEthernetNotifyServer"); + + return CA_STATUS_OK; +} + +uint32_t CASendEthernetNotification(const CARemoteEndpoint_t* endpoint, void* data, + uint32_t dataLen) +{ + OIC_LOG_V(DEBUG, TAG, "CASendEthernetNotification"); + + return 0; +} + +CAResult_t CAGetEthernetInterfaceInformation(CALocalConnectivityt_t** info, uint32_t* size) +{ + OIC_LOG_V(DEBUG, TAG, "CAGetEthernetInterfaceInformation"); + + return CA_STATUS_OK; +} + +CAResult_t CAReadEthernetData() +{ + OIC_LOG_V(DEBUG, TAG, "Read Ethernet Data"); + + return CA_STATUS_OK; +} + +CAResult_t CAStopEthernet() +{ + OIC_LOG_V(DEBUG, TAG, "CAStopEthernet"); + + return CA_STATUS_OK; +} + +void CATerminateEthernet() +{ + OIC_LOG_V(DEBUG, TAG, "CATerminateEthernet"); +} diff --git a/resource/csdk/connectivity/src/wifi_adapter/cawifiethernetadapter.c b/resource/csdk/connectivity/src/wifi_adapter/cawifiethernetadapter.c new file mode 100644 index 000000000..a6033ccee --- /dev/null +++ b/resource/csdk/connectivity/src/wifi_adapter/cawifiethernetadapter.c @@ -0,0 +1,371 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ +#include "cawifiethernetadapter.h" + +#include +#include +#include +#include +#include "caadapterutils.h" +#include "umutex.h" + +#ifdef __TIZEN__ +#include "cawifiserver.h" +#include "cawificlient.h" +#include "cawifimonitor.h" +#elif defined(OIC_ARDUINODUE) +#include +#include +#include "cawifiadapter.h" +#endif //#ifdef __TIZEN__ +/** + * @def WIFI_ETHERNET_ADAPTER_TAG + * @brief Logging tag for module name + */ +#define WIFI_ETHERNET_ADAPTER_TAG "WIFI_ETHERNET_ADAPTER" + +/** + * @def CA_PORT + * @brief Port to listen for incoming data + */ +#define CA_PORT 5283 + +#define CA_MCAST_PORT 5298 + +/** + * @def CA_MULTICAST_IP + * @brief Multicast IP Address + */ +#define CA_MULTICAST_IP "224.0.1.187" + +/** + * @var gNetworkCallback + * @brief Network callback + */ +static CANetworkChangeCallback gNetworkCallback = NULL; + +/** + * @var gIsMulticastServerStarted + * @brief Flag to check if multicast server is started + */ +static int gIsMulticastServerStarted = 0; +static u_mutex gMutexIsMulticastServerStarted = NULL; + +void CAInitializeMutex() +{ + u_mutex_init(); + gMutexIsMulticastServerStarted = u_mutex_new(); +} + +int CAWIFIRegisterNetworkNotifications(CANetworkChangeCallback netCallback) +{ + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN"); + + gNetworkCallback = netCallback; //TODO: Remove and set using API define in arduino specific file +#ifdef __TIZEN__ + if (netCallback != NULL) + { + CAInitializeWIFIAdapter(); + CASetWIFINetworkChangeCallback(netCallback); + } + else + { + CADeinitializeWIFIAdapter(); + } +#endif + + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT"); + return CA_STATUS_OK; +} + +CAResult_t CAInitializeWifi(CARegisterConnectivityCallback registerCallback, + CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback) +{ + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN"); + CAResult_t ret = CA_STATUS_OK; + + VERIFY_NON_NULL(registerCallback, WIFI_ETHERNET_ADAPTER_TAG, "Invalid argument"); + VERIFY_NON_NULL(reqRespCallback, WIFI_ETHERNET_ADAPTER_TAG, "Invalid argument"); + VERIFY_NON_NULL(netCallback, WIFI_ETHERNET_ADAPTER_TAG, "Invalid argument"); + + CAConnectivityHandler_t wifiHandler; + wifiHandler.startAdapter = CAStartWIFI; + wifiHandler.startListenServer = CAStartWIFIListeningServer; + wifiHandler.startDiscoverServer = CAStartWIFIDiscoveryServer; + wifiHandler.sendData = CASendWIFIUnicastData; + wifiHandler.sendDataToAll = CASendWIFIMulticastData; + wifiHandler.startNotifyServer = CAStartWIFINotifyRecvServers; + wifiHandler.sendNotification = CASendWIFINotification; + wifiHandler.GetnetInfo = CAGetWIFIInterfaceInformation; + wifiHandler.readData = CAReadWIFIData; + wifiHandler.stopAdapter = CAStopWIFI; + wifiHandler.terminate = CATerminateWifi; + registerCallback(wifiHandler, CA_WIFI); + + CASetWIFINetworkPacketCallback(reqRespCallback); + CAWIFIRegisterNetworkNotifications(netCallback); + CAInitializeMutex(); + CAInitializeServerMutex(); + //ret = CAStartWIFIUnicastServer(); + + OCLog(INFO, WIFI_ETHERNET_ADAPTER_TAG, "IntializeWifi Success"); + + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT"); + return ret; +} + +CAResult_t CAStartWIFI() +{ + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN"); + int16_t unicastPort = CA_PORT; + CAResult_t ret = CA_STATUS_OK; + +#ifdef __TIZEN__ + CASetIsStartServerInvoked(); + int retVal = CAIsWIFIConnected(); + if(retVal == 0) + { + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "WIFI is not Connected"); + return ret; + } +#endif + /*Address is hardcoded as we are using Single Interface*/ + ret = CAStartUnicastServer("0.0.0.0", &unicastPort); + + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT"); + return ret; +} + +CAResult_t CAStartWIFIListeningServer() +{ + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN"); + + CAResult_t ret = CA_STATUS_OK; + int16_t multicastPort = CA_MCAST_PORT; + + if (gIsMulticastServerStarted == 1) + { + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "Server is already Started"); + return CA_STATUS_OK; + } +#ifdef __TIZEN__ + int retVal = CAIsWIFIConnected(); + if(retVal == 0) + { + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "WIFI is not Connected"); + return CA_STATUS_FAILED; + } +#endif + ret = CAStartMulticastServer(CA_MULTICAST_IP, "0.0.0.0", &multicastPort); + if (ret == CA_STATUS_OK) + { + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "Multicast Server is Started Successfully"); + u_mutex_lock(gMutexIsMulticastServerStarted); + gIsMulticastServerStarted = 1; + u_mutex_unlock(gMutexIsMulticastServerStarted); + } + + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT"); + return ret; +} + +CAResult_t CAStartWIFIDiscoveryServer() +{ + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN"); + + CAResult_t ret = CA_STATUS_OK; + int16_t multicastPort = CA_MCAST_PORT; + + if (gIsMulticastServerStarted == 1) + { + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "Server is already Started"); + return CA_STATUS_OK; + } +#ifdef __TIZEN__ + /*int retVal = CAIsWIFIConnected(); + if(retVal == 0) + { + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "WIFI is not Connected"); + return CA_STATUS_FAILED; + }*/ //VV +#endif + ret = CAStartMulticastServer(CA_MULTICAST_IP, "0.0.0.0", &multicastPort); + if (ret == CA_STATUS_OK) + { + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "Multicast Server is Started Successfully"); + u_mutex_lock(gMutexIsMulticastServerStarted); + gIsMulticastServerStarted = 1; + u_mutex_unlock(gMutexIsMulticastServerStarted); + } + + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT"); + return ret; +} + +uint32_t CASendWIFIUnicastData(const CARemoteEndpoint_t *remoteEndpoint, void *data, + uint32_t dataLen) +{ + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN"); + + uint32_t dataSize = 0; + + VERIFY_NON_NULL_RET(remoteEndpoint, WIFI_ETHERNET_ADAPTER_TAG, "Invalid argument", dataSize); + VERIFY_NON_NULL_RET(data, WIFI_ETHERNET_ADAPTER_TAG, "Invalid argument", dataSize); + + if (dataLen <= 0) + { + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "Data Length is 0"); + return dataSize; + + } + + dataSize = CAWIFISendData(remoteEndpoint->addressInfo.IP.ipAddress, + remoteEndpoint->addressInfo.IP.port, data, dataLen, 0); + + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT"); + return dataSize; +} + +uint32_t CASendWIFIMulticastData(void *data, uint32_t dataLength) +{ + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN"); + + uint32_t dataSize = 0; + + VERIFY_NON_NULL_RET(data, WIFI_ETHERNET_ADAPTER_TAG, "Invalid argument", dataSize); + + if (dataLength <= 0) + { + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "Data Length is 0"); + return 0; + + } + dataSize = CAWIFISendData(CA_MULTICAST_IP, CA_MCAST_PORT, data, dataLength, 1); + + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT"); + return dataSize; +} + +CAResult_t CAStartWIFINotifyRecvServers() +{ + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN"); + + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT"); + return CA_STATUS_OK; +} + +uint32_t CASendWIFINotification(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen) +{ + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN"); + + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT"); + return CA_STATUS_OK; +} + +CAResult_t CAGetWIFIInterfaceInformation(CALocalConnectivityt_t **info, uint32_t* size) +{ + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN"); + + VERIFY_NON_NULL(info, WIFI_ETHERNET_ADAPTER_TAG, "Invalid argument"); + //VERIFY_NON_NULL(size, WIFI_ETHERNET_ADAPTER_TAG, "Invalid argument"); + char localIpAddress[CA_IPADDR_SIZE]; + int32_t localIpAddressLen = sizeof(localIpAddress); +#ifdef __TIZEN__ + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "Getting WIFI address"); + CAGetInterfaceAddress(localIpAddress, localIpAddressLen); + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "Got WIFI address"); +#else + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "Getting shield address"); + arduinoGetInterfaceAddress(localIpAddress, localIpAddressLen); + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "Got shield address"); +#endif //#if __ARDUINO__ + /** + * Create local endpoint using util function + */ + (*info) = CreateLocalEndpoint(CA_WIFI, localIpAddress, "WiFi"); + if (NULL == (*info)) + { + OCLog(ERROR, WIFI_ETHERNET_ADAPTER_TAG, "Error while Createing Memory"); + return CA_STATUS_FAILED; + } + + (*size) = 1; + + OCLog(INFO, WIFI_ETHERNET_ADAPTER_TAG, "GetWIFIInterfaceInformation success"); + + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT"); + return CA_STATUS_OK; +} + +CAResult_t CAReadWIFIData() +{ + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN"); +#ifdef __ARDUINO__ + arduoinoCheckServerData(); +#endif //#ifdef __ARDUINO__ + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT"); + return CA_STATUS_OK; +} + +CAResult_t CAStopWIFI() +{ + CAResult_t result = CA_STATUS_FAILED; + result = CAStopUnicastServer(); + if (result != CA_STATUS_OK) + { + OCLog(ERROR, WIFI_ETHERNET_ADAPTER_TAG, "Error while stopping UnicastServer"); + return CA_STATUS_FAILED; + } +#ifdef __TIZEN__ + CAUnsetIsStartServerInvoked(); +#endif + result = CAStopMulticastServer(); + if (result != CA_STATUS_OK) + { + OCLog(ERROR, WIFI_ETHERNET_ADAPTER_TAG, "Error while stopping MulticastServer"); + return CA_STATUS_FAILED; + } + else + { + u_mutex_lock(gMutexIsMulticastServerStarted); + gIsMulticastServerStarted = 0; + u_mutex_unlock(gMutexIsMulticastServerStarted); + } + return CA_STATUS_OK; +} + +void CATerminateWifi() +{ + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "IN"); + CAResult_t result = CA_STATUS_FAILED; + + CASetWIFINetworkPacketCallback(NULL); + result = CAWIFIRegisterNetworkNotifications(NULL); + if (result != CA_STATUS_OK) + { + OCLog(ERROR, WIFI_ETHERNET_ADAPTER_TAG, + "Error while wifiRegisterNetworkNotifications(NULL)"); + } + + OCLog(INFO, WIFI_ETHERNET_ADAPTER_TAG, "TerminateWifi Success"); + + OCLog(DEBUG, WIFI_ETHERNET_ADAPTER_TAG, "OUT"); + return; +} diff --git a/resource/csdk/connectivity/src/wifi_adapter/linux/cawifiadapter.c b/resource/csdk/connectivity/src/wifi_adapter/linux/cawifiadapter.c new file mode 100644 index 000000000..298f50f87 --- /dev/null +++ b/resource/csdk/connectivity/src/wifi_adapter/linux/cawifiadapter.c @@ -0,0 +1,190 @@ +/****************************************************************** + * + * Copyright 2014 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +#include +#include +#include + +#include "cawifiadapter.h" + +#include "config.h" +#include "coap.h" + +#include "cawificore.h" + +#include "logger.h" + +#define TAG PCF("CA") + +// received packet callback +static CANetworkPacketReceivedCallback gWifiReceivedCallback = NULL; + +static void CAWiFiPacketReceiveCallback(const char* address, const char* data) +{ + OIC_LOG_V(DEBUG, TAG, + "CAWiFiPacketReceiveCallback, from: %s, data: %s", address, data); + + // call the callback + if (gWifiReceivedCallback != NULL) + { + CARemoteEndpoint_t* endpoint = NULL; + endpoint = (CARemoteEndpoint_t*) OICMalloc(sizeof(CARemoteEndpoint_t)); + + // set address + memset((void*) endpoint->addressInfo.IP.ipAddress, 0, CA_IPADDR_SIZE); + if (CA_IPADDR_SIZE > strlen(address)) + strcpy((char*) endpoint->addressInfo.IP.ipAddress, address); + + // set connectivity type + endpoint->connectivityType = CA_WIFI; + + gWifiReceivedCallback(endpoint, data, strlen(data)); + } +} + +CAResult_t CAInitializeWifi(CARegisterConnectivityCallback registerCallback, + CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback) +{ + OIC_LOG(DEBUG, TAG, "IntializeWifi"); + + gWifiReceivedCallback = reqRespCallback; + + // register handlers + CAConnectivityHandler_t handler; + memset(&handler, 0, sizeof(CAConnectivityHandler_t)); + + handler.startAdapter = CAStartWIFI; + handler.startListenServer = CAStartWIFIListeningServer; + handler.startDiscoverServer = CAStartWIFIDiscoveryServer; + handler.sendData = CASendWIFIUnicastData; + handler.sendDataToAll = CASendWIFIMulticastData; + handler.startNotifyServer = CAStartWIFINotifyRecvServers; + handler.sendNotification = CASendWIFINotification; + handler.GetnetInfo = CAGetWIFIInterfaceInformation; + handler.readData = CAReadWIFIData; + handler.stopAdapter = CAStopWIFI; + handler.terminate = CATerminateWIfI; + + registerCallback(handler, CA_WIFI); + + CAWiFiSetCallback(CAWiFiPacketReceiveCallback); + + return 0; +} + +void CATerminateWIfI() +{ + OIC_LOG(DEBUG, TAG, "TerminateWifi"); + + CAWiFiTerminate(); +} + +CAResult_t CAStartWIFI() +{ + OIC_LOG(DEBUG, TAG, "CAStartWIFI"); + CAWiFiInitialize(); + + OIC_LOG(DEBUG, TAG, "CAWiFiStartUnicastServer"); + CAWiFiStartUnicastServer("0.0.0.0", atoi("5283")); + + return 0; +} + +CAResult_t CAStopWIFI() +{ + OIC_LOG(DEBUG, TAG, "CAStopWIFI"); + + // ToDo: + + return 0; +} + +CAResult_t CAStartWIFIListeningServer() +{ + OIC_LOG(DEBUG, TAG, "StartWIFIListeningServer"); + + CAWiFiStartMulticastServer("0.0.0.0", atoi("5283")); + + return 0; +} + +CAResult_t CAStartWIFIDiscoveryServer() +{ + OIC_LOG(DEBUG, TAG, "StartWIFIDiscoveryServer"); + + CAWiFiStartMulticastServer("0.0.0.0", atoi("5283")); + + return 0; +} + +uint32_t CASendWIFIUnicastData(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen) +{ + OIC_LOG(DEBUG, TAG, "SendWIFIUnicastData"); + + CAWiFiSendUnicastMessage(endpoint->addressInfo.IP.ipAddress, data, dataLen); + + return 0; +} + +uint32_t CASendWIFIMulticastData(void* data, uint32_t dataLen) +{ + OIC_LOG(DEBUG, TAG, "CASendWIFIMulticastData"); + + CAWiFiSendMulticastMessage("0.0.0.0", (char*) data); + + return 0; +} + +CAResult_t CAStartWIFINotifyRecvServers() +{ + OIC_LOG(DEBUG, TAG, "StartWIFINotifyRecvServers"); + + // ToDo: + + return 0; +} + +uint32_t CASendWIFINotification(const CARemoteEndpoint_t* endpoint, void* data, uint32_t dataLen) +{ + OIC_LOG(DEBUG, TAG, "SendWIFINotification"); + + // ToDo: + + return 0; +} + +CAResult_t CAGetWIFIInterfaceInformation(CALocalConnectivityt_t** info, uint32_t* size) +{ + OIC_LOG(DEBUG, TAG, "GetWIFIInterfaceInformation"); + + // ToDo: + + return 0; +} + +CAResult_t CAReadWIFIData() +{ + OIC_LOG(DEBUG, TAG, "Read WIFI Data"); + + // ToDo: + + return 0; +} + diff --git a/resource/csdk/connectivity/src/wifi_adapter/linux/cawificore.c b/resource/csdk/connectivity/src/wifi_adapter/linux/cawificore.c new file mode 100644 index 000000000..f3d4f5f43 --- /dev/null +++ b/resource/csdk/connectivity/src/wifi_adapter/linux/cawificore.c @@ -0,0 +1,500 @@ +#include +#include +#include +#include +#include +#include +#include "cawificore.h" +#include +#include +#include +#include +#include +#include +#include "logger.h" + +#define TAG PCF("CA") + +#define CA_MAX_BUFFER_SIZE 512 // Max length of buffer +#define CA_UNICAST_PORT 5283 // The port on which to listen for incoming data +int32_t unicast_socket; +pthread_t pthread_unicast_server; +pthread_t pthread_unicast_client; +pthread_mutex_t mutex_unicast; +pthread_cond_t sync_cond_unicast; +int32_t unicast_send_thread_flag = 0; // 0: run, 1: stop + +char* target = NULL; +void* list = NULL; + +#define CA_MULTICAST_ADDR "224.0.1.187" +#define CA_MULTICAST_PORT 5683 + +int32_t multicast_send_socket; +struct sockaddr_in multicast_send_interface_addr; + +pthread_t pthread_multicast_server; +pthread_t pthread_multicast_client; + +int32_t multicast_receive_socket; +struct sockaddr_in multicast_receive_interface_addr; + +void* data_list = NULL; + +pthread_mutex_t mutex_multicast; +pthread_cond_t sync_cond_multicast; +int32_t multicast_send_thread_flag = 0; // 0: run, 1: stop + +CAPacketReceiveCallback gPacketReceiveCallback = NULL; + +void CAWiFiInitialize() +{ + OIC_LOG(DEBUG, TAG, "CAWiFiInitialize"); + + pthread_mutex_init(&mutex_unicast, NULL); + + pthread_mutex_init(&mutex_multicast, NULL); + + // [UDP Server] + struct sockaddr_in si_me; + + // create a UDP socket + if ((unicast_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) + { + OIC_LOG_V(DEBUG, TAG, "CAWiFiInit, creating socket failed"); + + return; + } + + OIC_LOG_V(DEBUG, TAG, "CAWiFiInit, socket created"); + + // zero out the structure + memset((char *) &si_me, 0, sizeof(si_me)); + + si_me.sin_family = AF_INET; + si_me.sin_port = htons(CA_UNICAST_PORT); + si_me.sin_addr.s_addr = htonl(INADDR_ANY); + + // bind socket to port + if (bind(unicast_socket, (struct sockaddr*) &si_me, sizeof(si_me)) == -1) + { + OIC_LOG(DEBUG, TAG, "CAWiFiInit, binding socket failed"); + + return; + } + + OIC_LOG(DEBUG, TAG, "CAWiFiInit, socket binded"); + + // [multicast sender] + uint32_t multiTTL = 1; + + // 1. Set up a typical UDP socket + multicast_send_socket = socket(AF_INET, SOCK_DGRAM, 0); + if (multicast_send_socket < 0) + { + OIC_LOG(DEBUG, TAG, "CAWiFiInit, Socket error"); + + return; + } + + memset(&multicast_send_interface_addr, 0, sizeof(multicast_send_interface_addr)); + multicast_send_interface_addr.sin_family = AF_INET; + multicast_send_interface_addr.sin_addr.s_addr = inet_addr(CA_MULTICAST_ADDR); + multicast_send_interface_addr.sin_port = htons(CA_MULTICAST_PORT); + + // [multicast receiver] + // 1. Create a typical UDP socket and set Non-blocking for reading + multicast_receive_socket = socket(AF_INET, SOCK_DGRAM, 0); + if (multicast_receive_socket < 0) + { + OIC_LOG(DEBUG, TAG, "CAWiFiInit, Socket error"); + + return; + } + + // 2. Allow multiple sockets to use the same port number + int32_t ret_val = setsockopt(multicast_receive_socket, SOL_SOCKET, SO_REUSEADDR, &multiTTL, + sizeof(multiTTL)); + if (ret_val < 0) + { + OIC_LOG(DEBUG, TAG, "CAWiFiInit, Failed to set REUSEADDR"); + } + + // 3. Set up the interface + memset(&multicast_receive_interface_addr, 0, sizeof(multicast_receive_interface_addr)); + multicast_receive_interface_addr.sin_family = AF_INET; + multicast_receive_interface_addr.sin_addr.s_addr = htonl(INADDR_ANY); + multicast_receive_interface_addr.sin_port = htons(CA_MULTICAST_PORT); + + // 4. Bind to the interface + ret_val = bind(multicast_receive_socket, (struct sockaddr *) &multicast_receive_interface_addr, + sizeof(multicast_receive_interface_addr)); + if (ret_val < 0) + { + OIC_LOG(DEBUG, TAG, "CAWiFiInit, Failed to bind socket"); + + return; + } + + // 5. Join the multicast group + struct ip_mreq mreq; + memset(&mreq, 0, sizeof(mreq)); + mreq.imr_multiaddr.s_addr = inet_addr(CA_MULTICAST_ADDR); + mreq.imr_interface.s_addr = htonl(INADDR_ANY); + ret_val = setsockopt(multicast_receive_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, + sizeof(mreq)); + if (ret_val < 0) + { + OIC_LOG(DEBUG, TAG, "CAWiFiInit, Failed to join multicast group"); + + return; + } +} + +void CAWiFiTerminate() +{ + OIC_LOG(DEBUG, TAG, "CAWiFiTerminate"); + + pthread_mutex_destroy(&mutex_unicast); + + pthread_mutex_destroy(&mutex_multicast); + + close(unicast_socket); + + close(multicast_send_socket); + + close(multicast_receive_socket); +} + +int32_t CAWiFiSendUnicastMessage(const char* address, const char* data, int lengh) +{ + CASendUnicastMessage(address, data); + + return 0; +} + +int32_t CAWiFiSendMulticastMessage(const char* m_address, const char* data) +{ + CASendMulticastMessage(data); + + return 0; +} + +int32_t CAWiFiStartUnicastServer(const char* address, int port) +{ + OIC_LOG_V(DEBUG, TAG, "CAWiFiStartUnicastServer(%s, %d)", address, port); + + int32_t result = pthread_create(&pthread_unicast_server, NULL, (void *) &CAUnicastReceiveThread, + (void *) NULL); + if (result < 0) + { + OIC_LOG(DEBUG, TAG, "CAWiFiStartUnicastServer, creating unicast_receive_thread failed"); + + return -1; + } + + result = pthread_create(&pthread_unicast_client, NULL, (void *) &CAUnicastSendThread, + (void *) NULL); + if (result < 0) + { + OIC_LOG(DEBUG, TAG, "CAWiFiStartUnicastServer, creating unicast_send_thread failed"); + + return -1; + } + + OIC_LOG(DEBUG, TAG, "CAWiFiStartUnicastServer, receive & send thread created"); + + return 0; +} + +int32_t CAWiFiStartMulticastServer(const char* m_address, int port) +{ + OIC_LOG_V(DEBUG, TAG, "CAWiFiStartMulticastServer(%s, %d)", m_address, port); + + int32_t result = pthread_create(&pthread_multicast_server, NULL, + (void *) &CAMulticastReceiveThread, (void *) NULL); + if (result < 0) + { + + return -1; + } + + result = pthread_create(&pthread_multicast_client, NULL, (void *) &CAMulticastSendThread, + (void *) NULL); + if (result < 0) + { + OIC_LOG(DEBUG, TAG, "creating receive_thread failed"); + + return -1; + } + + return 0; +} + +int32_t CAWiFiStopUnicastServer(int32_t server_id) +{ + + CAStopUnicastSendThread(); + + return 0; +} + +int32_t CAWiFiStopMulticastServer(int32_t server_id) +{ + + CAStopMulticastSendThread(); + + return 0; +} + +void CAWiFiSetCallback(CAPacketReceiveCallback callback) +{ + gPacketReceiveCallback = callback; +} + +void* CAUnicastReceiveThread(void* data) +{ + OIC_LOG(DEBUG, TAG, "CAUnicastReceiveThread"); + + char buf[CA_MAX_BUFFER_SIZE]; + int32_t recv_len; + + struct sockaddr_in si_other; + int32_t slen = sizeof(si_other); + + // keep listening for data + while (1) + { + OIC_LOG(DEBUG, TAG, "CAUnicastReceiveThread, Waiting for data..."); + fflush(stdout); + + memset(buf, 0, sizeof(char) * CA_MAX_BUFFER_SIZE); + + // try to receive some data, this is a blocking call + if ((recv_len = recvfrom(unicast_socket, buf, CA_MAX_BUFFER_SIZE, 0, + (struct sockaddr *) &si_other, &slen)) == -1) + { + OIC_LOG(DEBUG, TAG, "CAUnicastReceiveThread, recv_len() error"); + continue; + } + + // print details of the client/peer and the data received + OIC_LOG_V(DEBUG, TAG, "CAUnicastReceiveThread, Received packet from %s:%d", + inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port)); + OIC_LOG_V(DEBUG, TAG, "CAUnicastReceiveThread, Data: %s", buf); + + if (gPacketReceiveCallback != NULL) + { + gPacketReceiveCallback(inet_ntoa(si_other.sin_addr), buf); + } + } + + return (void*) 0; +} + +void* CAUnicastSendThread(void* data) +{ + OIC_LOG(DEBUG, TAG, "CAUnicastSendThread"); + + while (!unicast_send_thread_flag) + { + pthread_mutex_lock(&mutex_unicast); + + pthread_cond_wait(&sync_cond_unicast, &mutex_unicast); + + pthread_mutex_unlock(&mutex_unicast); + + if (unicast_send_thread_flag) + return (void*) 0; + + CASendUnicastMessageImpl(target, list, strlen(list)); + } + + return (void*) 0; +} + +void CASendUnicastMessage(char* address, void* data) +{ + target = address; + list = data; + unicast_send_thread_flag = 0; + + pthread_cond_signal(&sync_cond_unicast); +} + +int32_t CASendUnicastMessageImpl(const char* address, const char* data, int32_t lengh) +{ + OIC_LOG_V(DEBUG, TAG, "CASendUnicastMessageImpl, address: %s, data: %s", address, data); + + // [UDP Client] + struct sockaddr_in si_other; + int32_t slen = sizeof(si_other); + + memset((char *) &si_other, 0, sizeof(si_other)); + + si_other.sin_family = AF_INET; + si_other.sin_port = htons(CA_UNICAST_PORT); + if (inet_aton(address, &si_other.sin_addr) == 0) + { + OIC_LOG(DEBUG, TAG, "CASendUnicastMessageImpl, inet_aton, error..."); + return 0; + } + + OIC_LOG_V(DEBUG, TAG, "CASendUnicastMessageImpl, sendto, to: %s, data: %s", address, data); + if (sendto(unicast_socket, data, strlen(data), 0, (struct sockaddr *) &si_other, slen) == -1) + { + OIC_LOG(DEBUG, TAG, "CASendUnicastMessageImpl, sendto, error..."); + + return 0; + } + + return 0; +} + +void CAStopUnicastSendThread() +{ + unicast_send_thread_flag = 1; + + pthread_cond_signal(&sync_cond_unicast); +} + +void* CAMulticastReceiveThread(void* data) +{ + OIC_LOG(DEBUG, TAG, "CAMulticastReceiveThread"); + + // 6. Read from the socket and print out a message when one is received + char msgbuf[CA_MAX_BUFFER_SIZE]; + + struct sockaddr_in client; + int32_t addrlen = sizeof(client); + + OIC_LOG(DEBUG, TAG, "CAMulticastReceiveThread, waiting for input..."); + + while (1) + { + int32_t recv_bytes = recvfrom(multicast_receive_socket, msgbuf, CA_MAX_BUFFER_SIZE, 0, + (struct sockaddr *) &client, (socklen_t *) &addrlen); + if (recv_bytes < 0) + { + if (errno != EAGAIN) + { + OIC_LOG(DEBUG, TAG, "CAMulticastReceiveThread, error recvfrom"); + + return (void*) 0; + } + + continue; + } + + msgbuf[recv_bytes] = 0; + + OIC_LOG_V(DEBUG, TAG, "Received msg: %s, size: %d", msgbuf, recv_bytes); + + char* sender = inet_ntoa(client.sin_addr); + char local[INET_ADDRSTRLEN]; + CAGetLocalAddress(local); + if (strcmp(sender, local) == 0) + { + OIC_LOG_V(DEBUG, TAG, "skip the local request (via multicast)"); + } + else + { + if (gPacketReceiveCallback != NULL) + { + gPacketReceiveCallback(inet_ntoa(client.sin_addr), msgbuf); + } + } + + } + + return (void*) 0; +} + +void* CAMulticastSendThread(void* data) +{ + OIC_LOG(DEBUG, TAG, "CAMulticastSendThread"); + + while (!multicast_send_thread_flag) + { + pthread_mutex_lock(&mutex_multicast); + + pthread_cond_wait(&sync_cond_multicast, &mutex_multicast); + + pthread_mutex_unlock(&mutex_multicast); + + if (multicast_send_thread_flag) + return (void*) 0; + + CASendMulticastMessageImpl(data_list); + } + + return (void*) 0; +} + +void CASendMulticastMessage(void* data) +{ + data_list = data; + multicast_send_thread_flag = 0; + + pthread_cond_signal(&sync_cond_multicast); +} + +int32_t CASendMulticastMessageImpl(const char* msg) +{ + OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, sendto, data: %s", msg); + + int32_t result = sendto(multicast_send_socket, msg, strlen(msg), 0, + (struct sockaddr *) &multicast_send_interface_addr, + sizeof(multicast_send_interface_addr)); + if (result < 0) + { + OIC_LOG(DEBUG, TAG, "CASendMulticastMessageImpl, sending message error..."); + + return -1; + } + + return 0; +} + +void CAStopMulticastSendThread() +{ + multicast_send_thread_flag = 1; + + pthread_cond_signal(&sync_cond_multicast); +} + +void CAGetLocalAddress(char* addressBuffer) +{ + //char addressBuffer[INET_ADDRSTRLEN]; + memset(addressBuffer, 0, INET_ADDRSTRLEN); + + struct ifaddrs* ifAddrStruct = NULL; + struct ifaddrs* ifa = NULL; + void* tmpAddrPtr = NULL; + + getifaddrs(&ifAddrStruct); + + for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) + { + if (!ifa->ifa_addr) + { + continue; + } + + if (ifa->ifa_addr->sa_family == AF_INET) + { // check it is IP4 + // is a valid IP4 Address + tmpAddrPtr = &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr; + + memset(addressBuffer, 0, INET_ADDRSTRLEN); + inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN); + + if (strcmp(addressBuffer, "127.0.0.1") == 0) + continue; + } + } + + if (ifAddrStruct != NULL) + freeifaddrs(ifAddrStruct); +} + diff --git a/resource/csdk/connectivity/unittests/linux/sample1_unittest.cc b/resource/csdk/connectivity/unittests/linux/sample1_unittest.cc new file mode 100644 index 000000000..6d8be536d --- /dev/null +++ b/resource/csdk/connectivity/unittests/linux/sample1_unittest.cc @@ -0,0 +1,366 @@ +#include "gtest/gtest.h" +#include "cainterface.h" +#include "cacommon.h" +#include + +using namespace std; + +void request_handler(CARemoteEndpoint* object, CARequestInfo* requestInfo); +void response_handler(CARemoteEndpoint* object, CAResponseInfo* responseInfo); + +void request_handler(CARemoteEndpoint* object, CARequestInfo* requestInfo) +{ + cout << "request_handler, uri : " << (object != NULL) ? object->resourceUri : ""; + cout << ", data : " << (requestInfo != NULL) ? requestInfo->info.payload : ""; + cout << endl; +} + +void response_handler(CARemoteEndpoint* object, CAResponseInfo* responseInfo) +{ + cout << "response_handler, uri : " << (object != NULL) ? object->resourceUri : ""; + cout << ", data : " << (responseInfo != NULL) ? responseInfo->info.payload : ""; + cout << endl; +} + +char* uri; +CARemoteEndpoint* tempRep = NULL; +CARequestInfo requestInfo; +CAInfo responseData; +CAResponseInfo responseInfo; +CAToken tempToken; + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + +// CAInitialize TC +// check return value +TEST(InitializeTest, TC_01_Positive_01) +{ + EXPECT_EQ(CA_STATUS_OK, CAInitialize()); +} + +//CATerminate TC +TEST(TerminateTest, TC_02_Positive_01) +{ + CATerminate(); + + char* check = (char *) "terminate success"; + EXPECT_STREQ(check, "terminate success"); + + CAInitialize(); +} +// CAStartListeningServer TC +// check return value +TEST(StartListeningServerTest, TC_03_Positive_01) +{ + CASelectNetwork(CA_WIFI); + EXPECT_EQ(CA_STATUS_OK, CAStartListeningServer()); +} + +// CAStartDiscoveryServer TC +// check return value +TEST(StartDiscoveryServerTest, TC_04_Positive_01) +{ + EXPECT_EQ(CA_STATUS_OK, CAStartDiscoveryServer()); +} + +// CARegisterHandlerTest TC +// check return value +TEST(RegisterHandlerTest, TC_05_Positive_01) +{ + EXPECT_EQ(CA_STATUS_OK, CARegisterHandler(request_handler, response_handler)); +} + +// CACreateRemoteEndpoint TC +// check return value +TEST(CreateRemoteEndpointTest, TC_06_Positive_01) +{ + uri = (char *) "referenceUri"; + + EXPECT_EQ(CA_STATUS_OK, CACreateRemoteEndpoint(uri, &tempRep)); + + CADestroyRemoteEndpoint(tempRep); +} + +// check remoteEndpoint and values of remoteEndpoint +TEST(CreateRemoteEndpointTest, TC_07_Positive_02) +{ + uri = (char *) "referenceUri"; + CACreateRemoteEndpoint(uri, &tempRep); + + EXPECT_TRUE(tempRep != NULL); + + if (tempRep != NULL) + { + EXPECT_STRNE(NULL, tempRep->resourceUri); + } + + CADestroyRemoteEndpoint(tempRep); +} + +// check return value if uri is NULL +TEST(CreateRemoteEndpointTest, TC_08_Nagative_01) +{ + uri = NULL; + + EXPECT_EQ(CA_STATUS_FAILED, CACreateRemoteEndpoint(uri, &tempRep)); + + CADestroyRemoteEndpoint(tempRep); +} + +// check values of remoteEndpoint if uri is NULL +TEST(CreateRemoteEndpointTest, TC_09_Nagative_02) +{ + uri = NULL; + CACreateRemoteEndpoint(uri, &tempRep); + + if (tempRep != NULL) + { + EXPECT_STREQ(NULL, tempRep->resourceUri); + } + + CADestroyRemoteEndpoint(tempRep); +} + +// CADestroyRemoteEndpoint TC +// check destroyed remoteEndpoint +TEST(DestroyRemoteEndpointTest, TC_10_Positive_01) +{ + uri = (char *) "referenceUri"; + CACreateRemoteEndpoint(uri, &tempRep); + + CADestroyRemoteEndpoint(tempRep); + + char * check = (char *) "destroy success"; + EXPECT_STREQ(check, "destroy success"); +} + +// CAGerateToken TC +// check return value +TEST(GenerateTokenTest, TC_11_Positive_01) +{ + EXPECT_EQ(CA_STATUS_OK, CAGenerateToken(&tempToken)); + + CADestroyToken(tempToken); +} + +// CADestroyToken TC +// check destroyed token +TEST(DestroyTokenTest, TC_12_Positive_01) +{ + CAGenerateToken(&tempToken); + CADestroyToken(tempToken); + + char * check = (char *) "destroy success"; + EXPECT_STREQ(check, "destroy success"); +} + +// CAFindResource TC +// check return value +TEST(FindResourceTest, TC_13_Positive_01) +{ + CARegisterHandler(request_handler, response_handler); + uri = (char *) "referenceUri"; + EXPECT_EQ(CA_STATUS_OK, CAFindResource(uri)); +} + +// check return value if uri is NULL +TEST(FindResourceTest, TC_14_Nagative_01) +{ + CARegisterHandler(request_handler, response_handler); + uri = NULL; + EXPECT_EQ(CA_SEND_FAILED, CAFindResource(uri)); +} + +// CASendRequest TC +// check return value +TEST(SendRequestTest, TC_15_Positive_01) +{ + uri = (char *) "referenceUri"; + memset(&requestInfo, 0, sizeof(CARequestInfo)); + CACreateRemoteEndpoint(uri, &tempRep); + CAGenerateToken(&tempToken); + requestInfo.method = CA_GET; + requestInfo.info.token = tempToken; + requestInfo.info.payload = (char *) "request payload"; + + EXPECT_EQ(CA_STATUS_OK, CASendRequest(tempRep, &requestInfo)); + + CADestroyToken(tempToken); + CADestroyRemoteEndpoint(tempRep); +} + +// check return value if uri is NULL +TEST(SendRequestTest, TC_16_Nagative_01) +{ + uri = NULL; + memset(&requestInfo, 0, sizeof(CARequestInfo)); + CACreateRemoteEndpoint(uri, &tempRep); + CAGenerateToken(&tempToken); + requestInfo.method = CA_GET; + requestInfo.info.token = tempToken; + requestInfo.info.payload = (char *) "request payload"; + + EXPECT_EQ(CA_SEND_FAILED, CASendRequest(tempRep, &requestInfo)); + + CADestroyToken(tempToken); + CADestroyRemoteEndpoint(tempRep); +} + +// CASendResponse TC +// check return value +TEST(SendResponseTest, TC_17_Positive_01) +{ + uri = (char *) "referenceUri"; + CACreateRemoteEndpoint(uri, &tempRep); + + memset(&responseData, 0, sizeof(CAInfo)); + CAGenerateToken(&tempToken); + responseData.token = tempToken; + responseData.payload = (char *) "response payload"; + + memset(&responseInfo, 0, sizeof(CAResponseInfo)); + responseInfo.result = CA_SUCCESS; + responseInfo.info = responseData; + + EXPECT_EQ(CA_STATUS_OK, CASendResponse(tempRep, &responseInfo)); + + CADestroyToken(tempToken); + CADestroyRemoteEndpoint(tempRep); +} + +// check return value if uri is NULL +TEST(SendResponseTest, TC_18_Nagative_01) +{ + uri = NULL; + CACreateRemoteEndpoint(uri, &tempRep); + + memset(&responseData, 0, sizeof(CAInfo)); + CAGenerateToken(&tempToken); + responseData.token = tempToken; + responseData.payload = (char *) "response payload"; + + memset(&responseInfo, 0, sizeof(CAResponseInfo)); + responseInfo.result = CA_SUCCESS; + responseInfo.info = responseData; + + EXPECT_EQ(CA_SEND_FAILED, CASendResponse(tempRep, &responseInfo)); + + CADestroyToken(tempToken); + CADestroyRemoteEndpoint(tempRep); +} + +// CASendNotification TC +// check return value +TEST(SendNotificationTest, TC_19_Positive_01) +{ + uri = (char *) "referenceUri"; + CACreateRemoteEndpoint(uri, &tempRep); + + memset(&responseData, 0, sizeof(CAInfo)); + CAGenerateToken(&tempToken); + responseData.token = tempToken; + responseData.payload = (char *) "response payload"; + + memset(&responseInfo, 0, sizeof(CAResponseInfo)); + responseInfo.result = CA_SUCCESS; + responseInfo.info = responseData; + + EXPECT_EQ(CA_NOT_SUPPORTED, CASendNotification(tempRep, &responseInfo)); + + CADestroyToken(tempToken); + CADestroyRemoteEndpoint(tempRep); +} + +// check return value if uri is NULL +TEST(SendNotificationTest, TC_20_Nagative_01) +{ + uri = NULL; + CACreateRemoteEndpoint(uri, &tempRep); + + memset(&responseData, 0, sizeof(CAInfo)); + CAGenerateToken(&tempToken); + responseData.token = tempToken; + responseData.payload = (char *) "response payload"; + + memset(&responseInfo, 0, sizeof(CAResponseInfo)); + responseInfo.result = CA_SUCCESS; + responseInfo.info = responseData; + + EXPECT_EQ(CA_NOT_SUPPORTED, CASendNotification(tempRep, &responseInfo)); + + CADestroyToken(tempToken); + CADestroyRemoteEndpoint(tempRep); +} + +// CAAdvertiseResource TC +// check return value +TEST(AdvertiseResourceTest, TC_21_Positive_01) +{ + CAURI uri = (char *) "resourceUri"; + CAHeaderOption* options = NULL; + uint8_t numOptions = 0; + + EXPECT_EQ(CA_NOT_SUPPORTED, CAAdvertiseResource(uri, options, numOptions)); +} + +// check return value if token is NULL +TEST(AdvertiseResourceTest, TC_22_Nagative_01) +{ + CAURI uri = NULL; + CAHeaderOption* options = NULL; + uint8_t numOptions = 0; + + EXPECT_EQ(CA_NOT_SUPPORTED, CAAdvertiseResource(uri, options, numOptions)); +} + +// CASelectNewwork TC +// check return value +TEST(SelectNetworkTest, TC_23_Positive_01) +{ + //Select wifi network + EXPECT_EQ(CA_STATUS_OK, CASelectNetwork(CA_WIFI)); +} + +// check return value if selected network is disable +TEST(SelectNetworkTest, TC_24_Nagative_01) +{ + //Select disable network + EXPECT_EQ(CA_NOT_SUPPORTED, CASelectNetwork(20)); +} + +// CAUnSelectNewwork TC +// check return value +TEST(UnSelectNetworkTest, TC_25_Positive_01) +{ + //Unselect wifi network + EXPECT_EQ(CA_STATUS_OK, CAUnSelectNetwork(CA_WIFI)); +} + +// check return value if selected network is disable +TEST(UnSelectNetworkTest, TC_26_Nagative_01) +{ + //UnSelect disable network + EXPECT_EQ(CA_NOT_SUPPORTED, CAUnSelectNetwork(20)); +} + +// CAGetNetworkInfomation TC +// check return value +TEST (GetNetworkInfomation, TC_27_Positive_01) +{ + CALocalConnectivity* info = NULL; + uint32_t* size = NULL; + + EXPECT_EQ(CA_NOT_SUPPORTED, CAGetNetworkInformation(&info, size)); +} + +// CAHandlerRequestResponse TC +// check return value +TEST (HandlerRequestResponseTest, TC_28_Positive_01) +{ + EXPECT_EQ(CA_STATUS_OK, CAHandleRequestResponse()); +} + diff --git a/resource/csdk/doc/CCF Lite GIT Repo Layout.docx b/resource/csdk/doc/CCF Lite GIT Repo Layout.docx new file mode 100644 index 0000000000000000000000000000000000000000..0020cc5c13b3572de951647038f81e9047061c30 GIT binary patch literal 127908 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'=I3%wXZ-m9 z?1A2A+HOVdy0aY_Er&yEvxRyLn=@vr{j=B-&F>t~IoM}6D*aQJgAd~s3$wg8LkMiP ze>zaJwJwdU-QM$9r-C#Y%mr4I;V~!eEC`r1FAXdXy`+WtDUR-bC4_FGwxXKUY=_D4 zP3qWED_Z`!_@yh0^fRZ*U@H+xBTruF*vpM1%We-kQehf)-1$L}wa-34;g?UZ#VTQ8 zSTx{|j&Frdw9jZu;icciqeoRlG|2+idID0?D$3wc9qe7$b0jcB(Rh{4>2NDcJ9dl7 zF7peh8CY^J>_b={Zf&32abUoE2yBAF{Y@U#!Byt$Td#&&7A0Ne!49VKyPWhg)1`ZL z5P|InqFhA|m2<5p5cy9`ebvqh5R^q*^3(rkP5F|qH>z&`m&oXdD+J8AAC9%Rz ziPD`+?PN|%I^Gg+jrME{RAxh3&p}(Woc>!ELd$y$8XdVtO7X11Pr|xcz?ZbkcrrNr zz~>`t-b;Vcx#?hpJr(}fNtg>3^~#Q3|AU`PF7R;^AHv zxvc2>{i{2r6wo9&&>S<}vnmvxIQX?^%8tHjcBZp4F@ue?LvX zC+FytmZl(uIdI3V{HuU!mMZ07T=-0|nZcWslD2OcB&G!YB95yD_3J;Hy4K zTtHmUqwju_pF415n+A6|vRfHn@gq5lhdAZvY)X?>Ww4x@HM^{uF>TYNl)M6ys{XKQ zXcZH3E=-ny0ir3-RXPVu{Y!4vQ}fZ*;Lr2C2d~of7}uMF|I~T&a%E)Z_@C1c{Pl{Q z%^mB7nj)pfG1>C>t)HSTy39wz*lG!7=p<;qiV`J@*V^VsLm&Jopdft8Va6d*Pb*uFSLL%j#|y5bQ%xg?s`Qy{!L zrjJ(RDwYb_;N(BNN6t2Ig+y-d7?+kRzCuwuT#li)PB^%`C@Vn75>hr z)_(D;Y;J@pSL9``-1-(9t2a!x*238OU)SyLYcKgIyl%NX{S%Hw@9WzAXH9ZuA??tHvCj^t>4HX zkO;9fxXG!%YrobK%m_ZSpWd)`T^f1Vz@AEJ8ui7I^%I&L2R|1q{H$k%XPB`8FL-?* z0Tb%nhatnrd)9M+1ZT zJ`R{1G<9*>`G0d#W3t+K4ABLJqeubTo93{?c&|5&!MA)7-8?1!)w%uv142H|^Y|Hm z0!=#e9(Nuu!qFwd_V=&Xc7~$yT`3Koxd6qw(7j(8W4V)~b38O0@|q>($xrn^=GTAd zSx?4q7hh#$8!;~n`miOibVUKe3g={8sF){w1iV2}uH>&?7e-08dlN15cX&Uw2VA;= z_h?tN=0`s6P6$rxhJvq?U0l0zJi9LH$gU^V-G^JA+H?~do}SKK`PX?MAfyNSGR(L2 zPzKU-1Go9>ue+=i4PBnXs$>$|FRus$(3PP-r!NDc4MI5xy%-e!yt}6JfP9pr{6E7wZ}6?} zHje{aNIkEM0WUQwn|Hm&pG`o{BD)toSkHT`p2k3JZ=m*Ob9=nd=>=?ahpe*ayHdd0 z#ztU}anDO`P|z&c7z!bec=Po95+)Yty#G|=GwuA)1beJZCd&5QMYaY)XP-s9gYE_} zjh?nZUMWbx#+rbGXeK~OAYuZ8Q^(skw#>@J8nKwmO?XhhanIGFPtpa>pY^(30IT4O zbShraBsB7$ljO3Qk*pZXx$_fza~;%rO9IZ^J9qA6r{1|b^&<@IBwn5$T^@o1UeKGK zF!D}$oJ8*XQ}qKMUrKqWv!B;AHtK2}aYYSrMf3SWNwwTR3^L&nTi7rnv@pXbhRzs6 zyF|TnH$Ef3Dv4DLKXnd*YqC&Piv*a6Rj2#{*N}Z!~Q|{s4<}``wvdgvvH?R zZ#JNSt?0opUl`tnXxv?Q5;uSZ1z@qeF8g+qE4Dy;aKc7Aa|8EERnT3w{EoeXZF_$d zVhrprzx3;$xMu2lS^prxyRG_D6B3q@uubJ-q)uz4+6^vwMul;7_s+Ect zw?yP?Q$zULVCPIrE2|{x?~I7U+XF1&z2;Y^n%s-CbR!4y>JUx0 zUmJx=e36jq?+JQC$`6q{6}T}DFk%MpPlaJ8$7L=%WZ>CJ%M)FvfF zmDes2VB4?}!Ufu?kRRTd&W=OPZK=0MR=30vQu_#D-^mW{;H<`N`MOPnP)CQy&j$Lg zrnC5;&R8VEn5mhfY}N{fWY26LXHZ8doUY>boK?KZ?s6teOlSnX2*`Hc8(jd- z{9Vp#zRkxfSFS$Z_= z2Y{#Jz&P!)?krI!z7u9(L}Q1ig+ZnErjFy1%NEZ{NATkTo710;!|XJGQ_~w3%gF6& zX339%bbL<1y;1X-ndhLz`7IR@BnBCE{M z_%6$f#1kS$dm)__AmLI(jN|&vu$2DoZ#u^PdE%4 zU3v!MAn8U4vD!OBM?k0Lprf&fe^IrlQ%GdK^FDzi z?sQ&&P5=3_5$~H+w+m~ftXp%bER;R>kD2=bT@=`$uk3wUqhhjl+L`2Bz}mx^pt*aU z?l9q8vPhOvE*nTS4venZ?wyhXHBi(;6C8J*jg(;Iz#r-g3s;YknR=Ho^8BSH)_Gl7 zDSa3v;w9|2t1) z*4#&D93`SiI?26{fMka6zsC24U42&^^QWWR`Of5xxL zb3u_4+UwM3MT3lp$`4 zC-MBd@7vRAyGzs)ka)qTqv$|bt1yx|HpoIBDrx=OjDt{pd^^SlvJ(|B>hul6^H=XcYa>mxPI8~$WT|1e8()Vb4Yx!57hU%A% zPdS;^J0>1WZg-}h$TZc%7zom(eByLO7=kwuw>se~n(+TR(ym9Zg~+qu`KtE?wnADa zg3%T}B*T8?9ni1MY@8za24U_7qOqEn~R&o9M=`qw+j4F^S$)FgYW}f~{WI*0rE_G{&$UsXIKL zP{FIuNT-eC)lX|#L_vE?3@gfJr_cR4v5O4DIXn3IzE@JEu=(QC25(XIQo*1evrRHB z=4U<+W{R`QihuvjOfQfr1F9MOk^(lH;}sULt+^h!l6R-OVfNY@eUvI&Pu-YD)&AeP z`M^{wvP*Fh*_(-#Mz?PyL^v%j?Icy6G?`m2vzf-u>)7Qg8<0K)`s|5eYu*zk!Mycf zO2G3`em$d?K9-!0%O@Qgr)1*n#ODda zWmF?F%`z@W=pceA5xWST7x-Z0 zu*$^G8s^85j;+T{9ERLyI)hJ;px665zRo*x*yEgSO`a!=z-RDbBdEXJx#wzuiB0%m z3})mFgB%4|b*%|MWHZsTfY~>{f&k`ILR!2=9MK6+;M^t79^1g(G5OX6yz}42%66{@ z@<6D9V+S}-=YcL^S}Z>F=yzmV^Xo8pdO<7{ZFy6v@P86 zPiE^i@Wk_09oP<*u8c0FO_qk&S-DG15thRpG<2>YHiLfHfEm6Q=IrLCg5cj@(CaQO zONS*ZfyQSyMCQWevQVB@84}kc#vz}L)*hFBe5@5s7BoD<7TORGzP%#o(U;6)cAJl_ z6)2@bk-R!2^<<3m5BB6##?X+2AZ+O{X(ry!K5r3Y4SYT73r!^Ez3E@xNOJw?yAgdC zWrS~#D0mtK;VfI&H-W>!EICDVz4L``@2U8W1_cDD4RLht(7i^9J~9GLLOeuJ{b$r< za7Ay9zsSsiXcDT){4}96g(&2nMS^~x650zRm%yns3u^oc3&Y7W-RdGIDg963p}BDe z92^iDnd9Na1qsSO7iGU8G86()DP>~RvMm?2zljkh%i4UOC@k4;Y97c%Z9ugQ&3TWH zu!I%g%cz`(j~cLJ*Nzs{x$^MaPoNAq>l~=Fo$I<}rtDkoX=YQNpmn9AkO8#CRfQjx ziCfdPd+Yr=7*(b5;svT=rNB;;`Z0xlDNtj(@5=`8-FjHN_8*8o`t13z)ztxb8=YRL zFcR*5Ntsc>8sF>dwXuWW>ydqTMYX^Y1FrY- zKSA1w{$Wj^1H>?~rrZ9cbw~K`Ai0B6@I;p15mC$Q9-9~R_3-I5w#L~uu&ez^rJ{!q zHf0}pQ>GqdaQz2t{07c*T!S+*TNIz3?RCsFSGxL79rW(dGzE4`aN9MWRk_Vn74pE_{3<=o?Si7d7fcw56eDFFKg zgDkG+{aL^54N~5GEAQy`#*BaqyuYt8_8TueJ@FTPjjow~SzuXr((7<7c&2kj23Y;A z6NT-ylynZs1=|Rr!?_UiJ0 z3WNl!Gio1>eklR^@wGOK4voBxOVjQ(*MId0Jvp+?ZY4zGeF1vKCR|myW-Ymwx<3GK z+1@TH^<^D~t*s4Vmwc7}dgpJOrBl$q89lFuYyjw5rWk9R2Xp!0HPmi6NA+~1{_{=; z$)%k@i)=`d$q#nk4u5i8flE4^&u|KL_$kF7>U|ZCO7XHvJkSct2P}uG_kUQ>5~-_; zr9y%g*82IVy1}#qo{2(Ft4n;eljSlZuS39UfemhHZii`R2R%k1*~`v{4JYKGuB_ha zN|kD#?A7Rpk|y`1&X!FgQ?n!Zbg7DT2r9tK2WYswBZ)JtzAcF(gvIn7APsN)CCB6N zsnGZ(ZT6_?#`PJjH{4kbiCgZ1#6|OO-PcDu3mp)qMqmxm+{uU)!usSd*iUBRXHsex z_}_MMp^hJg-YR3aE)ukj?!4SP-_C1__V(-c1iFQEwzvBpEA2Z^BF*|k{g>wbRE{k(sD z|CsAK-1@@_Szq8D`E%52gB}h?J?7GeAH}(bX(Guy+#Wbge9HuaOYk6jF>8AfQEIL`f zCr;KCeSOy9zH5^`M=naVWKpDV`Op1!g4;2MY_gohiSrCgn|~^HwJx zg21=pe@;%?MPCV`D43g%C5vL2&l+Imd|CBDcm#wp0oQsRmwn9b+sa0lC0m)wM^{IM zh)nc53Tu&%nd6}{rypR47hNr8ZQlxB8FtI|W2(%zb$mBr;-GkSivxCo>F)*O(D-m2JI_%r4#UI#a3!{0(Am~}~S93y?VWjO4X zxMVMnh)jKt!2;UHCl zqYp~E*@?md0uXMRc_C5DrNJ@*s1ELhONP^!_sxB^G<$L{= zn!HJPWpSAuxaLwjUHSB*g6?kvqQA4#S6~#yafX#KYUUBTZ#SmvuYmQ}$($p68mUFg z@dSJ2p4$z|9-qIaf}))oN&D8sfYa124}x$;w~g^<;iOUr&Y^kXq+P**WMRY;*!B0= zS9sTj6jwO`j{*K%uXA;Qv>QL}wPseOwSEi<7-akjfyLKHcFMPZ!=GXFysNJOoJ%q& zhA~ReKx(?f7zzvwau_5I1Q}RvEg&S)M@=ugV=EwLUc_gkH~Y(%E9-B!1V_+{Z*%2h zzpH2USV+_GS;OJwm={qix0^2SjMz=_mp1R+DQ&@$(yhm5B^*ay$yTnRk z+bZ$WQ3kq8E;7et;pi&Nme!+f05|Tv6m^=1)*Q);u`Cxh(`6#h%}JW?RGFN@yQeM$w9wp;vK3tl^?v&)hA{Kh5UWBlsWKvdOc73W{Ye3jIdqVOz*v4 zYEzRjGMPWT<1fNO9B^A?7MwcPEv>Wr(rL46i!7FHd(SX4YqRG|e-^CrG2NBK-1fi|waA5yw5=U2bOe3*X>@5@=Uf0asU zd+%W<-Ep)jSrZwS&f_)V^!LCvC68n7mv-r9(Um3LJAeVt72Q*oGzJ}t2&qY2!d}7O zRrqx!qgVR}PV3-;UomVfs<&xC9K>@{3DUgc&M|%D8&#zMYFCzod9p2kaWTW?o~(Q5 znOPr8m3+&u^RRx;uD0;m0j)38c$l?x-g7^%PX=la8(!88AITL<&~G-oc=2n6y8&(- zOS92EOjE}>+gbcTYAg^w#@EQDs1Vd&A_olkoUA* zQ}v}r+|;-qa;ZC@!cVrrra^oG_$RE_j(;IFLC-+B=hj>`~JSmx~i)t z19n+!x#4)dairbqZ$$1B-=yWQZp0ICQzwZd)`xku`XxAG)JHt)>?` zkZ#p@h|Dj`TRd$a_TO)0Hakn5@gKVxqAsoA6lL<->WS>Q27!JDvZjWKtTol_HRdSP zA5{Sx1#VVC6dWWP8!P;#49=!tMgfJ2y>iy--dSodC!)b-h}hS2>{>?Jk0 z_Ev=rF8;lk&+P+jWxy|TMoDmrerGKa@P}@TwDk%_DiNebz4oAE|9!78O`g9=tCXg6 zqViGUoBB_xe+_e;#%1u8=r~co-s+O7Lybg!Ge7szon~clGBQtQ7LBs1%{(mMqi-Rw z)t|2d6)Zg3SxHxoT4B`@p>!Xsta$}r-#v%$3u_3wn+1#IuFZV@+_Tr1(UfD0GteXN zK?=B?S`g^C2t>4Ex8-lTQUgon0~fhLz|Dax?<6UXwpy3J6?7+F*SuOxfinYF+XgWs z)?%@Ny`?7?epI)61(%dvE{iqFj4l^H6W=hzM1y>MaAVzey+?+Wv+QES+%iHejdi=F zG&r-)P7{%42+77>cDY!Y^S6Yuo>SZf9O|+@*FAkF+i`S(wiv+dFYTnsRroZ0=rF(Cc&*%s+FQW4v}jm^rV zEY1;Jlrp|*_K?_f@mieo+xMUbn*cYxV2RdX45?YiN+nFw@bn%QFTUeTGSGIkveCq& zc>X+w2n+X+V_?=lDH-rvMmOZNABN{l@B^#H7q3(0ms%0o5>@LtGW;@G4q!+1!3@t4 zI?fFM9C$EN@K{5x#%HT_>pIh^{oJi13;II~(jp@<;ybozHvUHfXg{5xSAoKM%(Y6a z!V0z8)PSd?PAwQSNQECr#%n3#=u+=cdIowl)hJWU+T6Z>2R;KtFFDNsn9y)1j0pSAcGTRUAO;)nCkGH(oPJW8Lx% z4qF5=RskIzFS;w-VC|S&E%Cr3PhRA;6Y!G4TJC({B>HIF_jaEYOpIumZwwen!U9}+ z*XrCmj?j(9ZAfM?wn$H#8DwNpdfO&5O^;a44d0mVq3@7HTw6%)wypE(wWA%`P%&87 zGiuX->ufmCca0h`l~U!62)tf-BZl2Z*t;Lo8WkOt`N^FMz!JDneRklx2!iu^H96Wy zkTtiPARyq(=#AX*0Blii^N198QaQQ(rro1|io1#OQ^pe7ByjXE3fW(X2tc(AKmeyB zyl}T~Dz;mEygz||P}GS6AL0Jj8nRWZ%G$61t0kYq#18+-z`)H9j)uk2g1hrxrSweM zu4CaD9<(p}(LWaLuxAnorXr)p@EOzVV&>CcFVHPWZ8Z0}*Rc(M^5W_rua@cte$Q(6 zq0`wfL$WW*T?cQDetwO!S~78a<*|tTJ9==QsX=(oq2q^&w3T%BXbe`S5Qj0CNRP`JCSeA)Y8smZ~_cUMxXX%$bgqWgPi z($}5|grlbZix!}O-Re!=z{`H-0Q3}CzV1OWO!0|gEQu5Q;6Oyr-){YyUqf6q;Lu}r ztVK^kW+F3q{h{g7vS+vt+x_$=MfeI`k(iZL+}h^M9D~UDZzB1ci-``|Ms(V@D$=8kj%g!#EI4QJ!>100sTjY2)3j&GBz~K{%;twK z*GDr>H>iOQW9MGT0R(PkL3@@Z6lgO7XV@P;%V&O*$dXe-=eS?~QgB|gnWJx+)TOTM z^-(rlGA+7_x4V)~@xZWZrOLv&r~!DEu)8;uvFujv0JSHbzZQ>64G2lHIh56$ZYV>3 zf8oSyVHZ&u-v|2?9koXn)4kiD=Or8RL+H7~dE3-Q(j;|5)eS_V><)Q67C6a470zo0 z=}g@qL*;zX2X+C#%Wdp>h{YQY{c8`e+x0Aje7Ib=*JCjHw<0VFqKm#BQU(Q1|EYjW z@o=$vS;5IL@7!b*^)9D98`$Yne`wcmNIf$^OeS{Rto$}wZrPydVh=jFXd1d@0*1nd zONyjXYnQ`Fxy_79_XADe-I?m%KZQ?<*g^;AUvH;7sm9%^u=wdl^__Kh%=VuV<|u{1 zHK663l=aP29Mjon?Uheo$hCfA|Cp(dYu4mS8Nl*D>(w_JN8Ij;ow<<5+YrLl45odG zbvj{Df2XQyrWW#ir=^R{N2YQzI*E+~Lh4SYZ=rhCAU@!{l~0ytTjO*xu}z;jZ7qy1 z3;gL#l>3_WBsV7$a7HbR(F^&Lg}O^Jk#F5u*W8jrlx*<_`xGgKM8$lemjy++_j%D* zzFnWnJmfsH-}TL& z>1_uOc!T_`>h$gyw1{onhb=XUTaOqW9<<}6_uC$MPdV}%p!9vtAXCnq-R<~YGI?;G z$DY4N+YY=bx$nnlP0mPB-4E6EY>_Gr88SULaq5?&5PV?$?$F11wWpQ8Wxahp0+F?} z>Uv;f>vZIRUBp)#yT}2lFW!s<24Jxd$oaD`562`J5w(XAaA&{*x&MMVa~JPg`)wZk zUEMcn&(5kk1npVE(4KIFW2oO4ojkSK?&b||>zt+qtw?8RUe=@Y&5vA3SiOV`QpSoK_D&8^=m6}-wtb4)^n)@=5FgTBd24v6o8bOPQ%>rt zDpcF6q3!l$F%m26Fm-q#IkA1k4Iav=|M`cu{gozR;_Eu`YMnG!bLK)(Bd$V zHtY-g*maG+FP)y<<0GkwwKvhOfqTL=@$Qo~OnB|ZGH1Ml*UfQR zhwNUh*Fl61C{;9TMxc61lfj94%nR;7U)z|A@x^y|6;VkDx(6YArt|%Lmvh*?3Y-Bs zj*A&KeyVNI*{4}pH})8^ch2|IoB;7q2?%i~JQmr(NxcoWW4Z(unkM=Xe?R;(HvOq; z`2B*%jb-kzA9?Oe>u1T;7kG2-Bf=>SkDui(CVUhMZphgXQIJdk*P-*U(t&3iGRwg8 z2tq64doOF_mXPsMZH4*oD8Q~aVia*PpTo{A=q){^JLXf;z>K}}QTBurPdhLs z#P@5tcSKmaMwpT@hYF~dOPI1j$J=lF3k)ChN1TLW-4(Bs& zh(&$N4k}4ORY0FF+*|MrR}GPwwl9`pLhg(=FE(w~ngSt_EjJ-WklNk4KoHxSpSOq1 z*DL;~^dB@bP%W*Uo?0vPD^y+03=EqDF2^?Q!J#kI&vJGFKNA*{ESE=^@UzE#GzG>577zCkJoZ&j4>{ z!Kb`}Lzg-^V+P4i;gW4%_iT=%iK!@3zRa?ZpnekRDv#^Tj;=!P8--I82~ldYM3jIs zxC6w6${z<*KedvsYKT*d`0m@g8mk@g5!eCNndY##CVpU@SdRjPUf~wD;Ba#V-Fsf( z_0)M`-MOfc^7x}G$&%LZ%d7m#n_}EizPR1T6Hn9|xLpPK^~x3BqJ1B6o(`S^Z1t*9 ze293<$G#kXt-2)5c%@-YPt<+&3SbGQlkWv7obZ;a-JEOLL!y{Zx5LkN zgfHxzyl$@jx!Rd(ZKVAI4-{-9?U8lQx~J}Ow;j%&)va zXG8s?$LmOeGIFJr0cRUcS&lL!#a=x+8S8>u_T7+cJd!J=9_=PSm8O>sfxn&YCig>k z_<@>R(j-&Dbf*#mW!dP_-6mv{z|fLi`MRvL6+N|SYg}t;%bWDCw=&For{0s?0{lfR z*s6ndz%#pSf(Rih9G0sodOR1Ynzfsw=z=h9TAhJkYrFxyT<{|kcXzEjDE9=q_P2&u zlmA=0-zWL+xerB=@d+K%?L|I&kG7ZuVdmk|FK(ylgevSE0_=N9r;=H&*D2>Nn$BA(E(Kg{fbsKfpXfgK@_I zO0ze$0q%-qI2qE65po*%qS$mVKJRG;A3Dp0w%pLdC`F~;;nT*D z21M0*MngQ@v*F^hSCBznywIp_us&-sXph#FeMq#RPhIf&q1d07xb$uQnqbKJkpnRb z=f(U>{6|&#N*>(~%P&5{!=)?1pJCaOn-C&7{%0A8y8dOSpR=Zo8ntpY>&RjP^DPe7 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%0DDM7#Bf5Y%yebQ|HQbAIGW6kB+i65xaG@y&N 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