From effa193386c92937230ae14e679bb9be94f1deef Mon Sep 17 00:00:00 2001 From: Yogesh Pande Date: Mon, 25 Jul 2016 15:21:32 +0300 Subject: [PATCH] This commit includes Replacing with source code replicated from respective repositories including mbed-client - TAG mbed-os-5.0-rc1 mbed-client-c - TAG mbed-os-5.0-rc1 mbed-client-classic - TAG mbed-os-5.0-rc2 mbed-client-mbed-tls - TAG mbed-os-5.0-rc1 mbed-client-randlib - TAG mbed-os-5.0-rc1 coap-service - TAG mbed-os-5.0-rc1 Adding CONTRIBUTING.md file explaining how to submit patches for any of the components belonging to FEATURE_CLIENT --- features/FEATURE_CLIENT/CONTRIBUTING.md | 83 + .../FEATURE_CLIENT/coap-service/.gitignore | 10 + .../FEATURE_CLIENT/coap-service/.mbedignore | 1 + .../FEATURE_CLIENT/coap-service/.yotta_ignore | 4 + features/FEATURE_CLIENT/coap-service/LICENSE | 2 + .../FEATURE_CLIENT/coap-service/Makefile.test | 51 + .../coap-service/apache-2.0.txt | 56 + .../coap-service/coap_service_api.h | 270 ++ .../coap-service/junit_xsl.xslt | 101 + .../FEATURE_CLIENT/coap-service/module.json | 27 + .../coap-service/run_unit_tests.sh | 23 + .../source/coap_connection_handler.c | 797 +++++ .../source/coap_message_handler.c | 398 +++ .../source/coap_security_handler.c | 579 ++++ .../coap-service/source/coap_service_api.c | 473 +++ .../source/include/coap_connection_handler.h | 71 + .../source/include/coap_message_handler.h | 84 + .../source/include/coap_security_handler.h | 123 + .../include/coap_service_api_internal.h | 25 + .../coap-service/unittest/MakefileWorker.mk | 562 ++++ .../coap_connection_handlertest.cpp | 62 + .../unittest/coap_connection_handler/main.cpp | 15 + .../test_coap_connection_handler.c | 469 +++ .../test_coap_connection_handler.h | 50 + .../coap_message_handlertest.cpp | 52 + .../unittest/coap_message_handler/main.cpp | 15 + .../test_coap_message_handler.c | 300 ++ .../test_coap_message_handler.h | 40 + .../coap_security_handlertest.cpp | 55 + .../unittest/coap_security_handler/main.cpp | 15 + .../test_coap_security_handler.c | 286 ++ .../test_coap_security_handler.h | 47 + .../coap_service_api/coap_service_apitest.cpp | 72 + .../unittest/coap_service_api/main.cpp | 15 + .../coap_service_api/test_coap_service_api.c | 418 +++ .../coap_service_api/test_coap_service_api.h | 55 + .../unittest/makefile_defines.txt | 40 + .../test/coap-service/unittest/run_tests | 35 + .../stub/coap_connection_handler_stub.c | 67 + .../stub/coap_connection_handler_stub.h | 49 + .../unittest/stub/coap_message_handler_stub.c | 58 + .../unittest/stub/coap_message_handler_stub.h | 43 + .../stub/coap_security_handler_stub.c | 74 + .../stub/coap_security_handler_stub.h | 38 + .../unittest/stub/coap_service_api_stub.c | 64 + .../unittest/stub/eventOS_event_stub.c | 21 + .../unittest/stub/eventOS_event_stub.h | 39 + .../unittest/stub/mbed_trace_stub.c | 116 + .../coap-service/unittest/stub/mbedtls_stub.c | 310 ++ .../coap-service/unittest/stub/mbedtls_stub.h | 53 + .../coap-service/unittest/stub/ns_list_stub.c | 9 + .../unittest/stub/ns_timer_stub.c | 45 + .../unittest/stub/ns_timer_stub.h | 36 + .../unittest/stub/nsdynmemLIB_stub.c | 46 + .../unittest/stub/nsdynmemLIB_stub.h | 43 + .../coap-service/unittest/stub/randLIB_stub.c | 52 + .../unittest/stub/sn_coap_builder_stub.c | 43 + .../unittest/stub/sn_coap_builder_stub.h | 30 + .../unittest/stub/sn_coap_parser_stub.c | 95 + .../unittest/stub/sn_coap_parser_stub.h | 30 + .../unittest/stub/sn_coap_protocol_stub.c | 96 + .../unittest/stub/sn_coap_protocol_stub.h | 35 + .../unittest/stub/socket_api_stub.c | 118 + .../unittest/stub/socket_api_stub.h | 45 + .../unittest/stub/system_timer_stub.c | 58 + .../coap-service/unittest/stub/timeout_stub.c | 22 + .../FEATURE_CLIENT/coap-service/xsl_script.sh | 35 + .../mbed-client-c/.gitattributes | 2 + .../FEATURE_CLIENT/mbed-client-c/.gitignore | 36 + .../FEATURE_CLIENT/mbed-client-c/.mbedignore | 2 + .../mbed-client-c/.yotta_ignore | 5 + features/FEATURE_CLIENT/mbed-client-c/LICENSE | 2 + .../mbed-client-c/Makefile.test | 51 + .../FEATURE_CLIENT/mbed-client-c/README.txt | 2 + .../mbed-client-c/apache-2.0.txt | 56 + .../mbed-client-c/doxygen/client-c_doxy | 1846 ++++++++++ .../mbed-client-c/junit_xsl.xslt | 101 + .../FEATURE_CLIENT/mbed-client-c/module.json | 20 + .../mbed-client-c/nsdl-c/sn_coap_header.h | 398 +++ .../mbed-client-c/nsdl-c/sn_coap_protocol.h | 195 ++ .../mbed-client-c/nsdl-c/sn_nsdl.h | 102 + .../mbed-client-c/nsdl-c/sn_nsdl_lib.h | 684 ++++ .../mbed-client-c/run_unit_tests.sh | 23 + .../run_unit_tests_with_valgrind.sh | 14 + .../src/include/sn_coap_header_internal.h | 80 + .../src/include/sn_coap_protocol_internal.h | 211 ++ .../source/libCoap/src/sn_coap_builder.c | 1180 +++++++ .../source/libCoap/src/sn_coap_header_check.c | 100 + .../source/libCoap/src/sn_coap_parser.c | 843 +++++ .../source/libCoap/src/sn_coap_protocol.c | 2362 +++++++++++++ .../source/libNsdl/src/include/sn_grs.h | 132 + .../mbed-client-c/source/libNsdl/src/sn_grs.c | 1027 ++++++ .../source/libNsdl/src/sn_nsdl.c | 2532 ++++++++++++++ .../multithread-linux-test/CMakeLists.txt | 15 + .../test/multithread-linux-test/arguments.h | 38 + .../test/multithread-linux-test/main.c | 164 + .../test/multithread-linux-test/mbed_client.c | 518 +++ .../test/multithread-linux-test/module.json | 13 + .../resource_generation_help.h | 82 + .../test/multithread-linux-test/tester.sh | 76 + .../test/nsdl-c/unittest/MakefileWorker.mk | 562 ++++ .../test/nsdl-c/unittest/makefile_defines.txt | 23 + .../test/nsdl-c/unittest/run_tests | 44 + .../sn_coap_builder/libCoap_builder_test.cpp | 510 +++ .../nsdl-c/unittest/sn_coap_builder/main.cpp | 29 + .../libCoap_header_test.cpp | 58 + .../unittest/sn_coap_header_check/main.cpp | 29 + .../nsdl-c/unittest/sn_coap_parser/main.cpp | 15 + .../sn_coap_parser/sn_coap_parsertest.cpp | 51 + .../sn_coap_parser/test_sn_coap_parser.c | 1020 ++++++ .../sn_coap_parser/test_sn_coap_parser.h | 34 + .../libCoap_protocol_test.cpp | 2295 +++++++++++++ .../nsdl-c/unittest/sn_coap_protocol/main.cpp | 29 + .../test/nsdl-c/unittest/sn_grs/main.cpp | 15 + .../nsdl-c/unittest/sn_grs/sn_grstest.cpp | 83 + .../test/nsdl-c/unittest/sn_grs/test_sn_grs.c | 1191 +++++++ .../test/nsdl-c/unittest/sn_grs/test_sn_grs.h | 32 + .../test/nsdl-c/unittest/sn_nsdl/main.cpp | 15 + .../nsdl-c/unittest/sn_nsdl/sn_nsdltest.cpp | 185 + .../nsdl-c/unittest/sn_nsdl/test_sn_nsdl.c | 2968 +++++++++++++++++ .../nsdl-c/unittest/sn_nsdl/test_sn_nsdl.h | 84 + .../test/nsdl-c/unittest/stubs/ns_list_stub.c | 19 + .../unittest/stubs/sn_coap_builder_stub.c | 65 + .../unittest/stubs/sn_coap_builder_stub.h | 27 + .../stubs/sn_coap_header_check_stub.c | 36 + .../stubs/sn_coap_header_check_stub.h | 27 + .../unittest/stubs/sn_coap_parser_stub.c | 163 + .../unittest/stubs/sn_coap_parser_stub.h | 25 + .../unittest/stubs/sn_coap_protocol_stub.c | 109 + .../unittest/stubs/sn_coap_protocol_stub.h | 32 + .../test/nsdl-c/unittest/stubs/sn_grs_stub.c | 172 + .../test/nsdl-c/unittest/stubs/sn_grs_stub.h | 39 + .../test/nsdl-c/unittest/stubs/sn_nsdl_stub.c | 224 ++ .../test/nsdl-c/unittest/stubs/sn_nsdl_stub.h | 27 + .../unittest/test_libCoap/Test.c | 622 ++++ .../unittest/test_libCoap/makefile | 31 + .../unittest/test_libNsdl/Test.c | 676 ++++ .../unittest/test_libNsdl/makefile | 33 + .../mbed-client-c/xsl_script.sh | 35 + .../mbed-client-classic/LICENSE | 201 ++ .../m2mconnectionhandlerpimpl.h | 246 ++ .../mbed-client-classic/m2mtimerpimpl.h | 116 + .../source/m2mconnectionhandler.cpp | 95 + .../source/m2mconnectionhandlerpimpl.cpp | 574 ++++ .../mbed-client-classic/source/m2mtimer.cpp | 57 + .../source/m2mtimerpimpl.cpp | 198 ++ .../mbed-client-mbed-tls/.gitignore | 7 + .../mbed-client-mbed-tls/.mbedignore | 1 + .../mbed-client-mbed-tls/LICENSE | 2 + .../mbed-client-mbed-tls/README.md | 2 + .../mbed-client-mbed-tls/apache-2.0.txt | 56 + .../mbed-client-mbed-tls/include_dirs.mk | 15 + .../mbed-client-mbed-tls/junit_xsl.xslt | 101 + .../m2mconnectionsecuritypimpl.h | 161 + .../mbed-client-mbed-tls/module.json | 19 + .../run_unit_tests_with_valgrind.sh | 14 + .../source/m2mconnectionsecurity.cpp | 71 + .../source/m2mconnectionsecuritypimpl.cpp | 454 +++ .../mbed-client-mbed-tls/sources.mk | 7 + .../unittest/MakefileWorker.mk | 562 ++++ .../unittest/common/CThunk.h | 202 ++ .../unittest/common/FunctionPointer.h | 604 ++++ .../unittest/common/FunctionPointerBase.h | 89 + .../unittest/common/FunctionPointerBind.h | 112 + .../unittest/common/Ticker.h | 36 + .../unittest/common/alltests.cpp | 26 + .../unittest/common/ip6string.h | 48 + .../unittest/common/mbed.h | 22 + .../unittest/common/ns_list.h | 736 ++++ .../unittest/common/ns_types.h | 392 +++ .../unittest/common/sal/socket_api.h | 164 + .../unittest/common/sal/socket_types.h | 181 + .../unittest/common/sockets/Socket.h | 32 + .../unittest/common/sockets/SocketAddr.h | 32 + .../unittest/common/sockets/UDPSocket.h | 32 + .../unittest/common/sockets/v0/Socket.h | 268 ++ .../unittest/common/sockets/v0/SocketAddr.h | 43 + .../unittest/common/sockets/v0/TCPAsynch.h | 47 + .../unittest/common/sockets/v0/TCPListener.h | 86 + .../unittest/common/sockets/v0/TCPStream.h | 83 + .../unittest/common/sockets/v0/UDPSocket.h | 64 + .../CMakeLists.txt | 27 + .../m2mconnectionsecurity_mbedtlstest.cpp | 94 + .../m2mconnectionsecurity_mbedtls/main.cpp | 25 + .../test_m2mconnectionsecurity_mbedtls.cpp | 135 + .../test_m2mconnectionsecurity_mbedtls.h | 54 + .../CMakeLists.txt | 28 + ...m2mconnectionsecuritypimpl_mbedtlstest.cpp | 99 + .../main.cpp | 25 + ...est_m2mconnectionsecuritypimpl_mbedtls.cpp | 409 +++ .../test_m2mconnectionsecuritypimpl_mbedtls.h | 57 + .../unittest/makefile_defines.txt | 28 + .../unittest/stub/common_stub.cpp | 436 +++ .../unittest/stub/common_stub.h | 48 + .../unittest/stub/m2mbase_stub.cpp | 336 ++ .../unittest/stub/m2mbase_stub.h | 43 + .../stub/m2mconnectionhandler_stub.cpp | 100 + .../unittest/stub/m2mconnectionhandler_stub.h | 31 + .../stub/m2mconnectionsecurity_stub.cpp | 88 + .../stub/m2mconnectionsecurity_stub.h | 32 + .../stub/m2mconnectionsecuritypimpl_stub.cpp | 76 + .../stub/m2mconnectionsecuritypimpl_stub.h | 30 + .../unittest/stub/m2mobject_stub.cpp | 120 + .../unittest/stub/m2mobject_stub.h | 35 + .../unittest/stub/m2msecurity_stub.cpp | 116 + .../unittest/stub/m2msecurity_stub.h | 33 + .../unittest/stub/m2mstring_stub.cpp | 419 +++ .../unittest/stub/m2mtimer_stub.cpp | 70 + .../unittest/stub/m2mtimer_stub.h | 30 + .../unittest/stub/mbedtls_stub.cpp | 286 ++ .../unittest/stub/mbedtls_stub.h | 38 + .../mbed-client-mbed-tls/toolchain_rules.mk | 293 ++ .../mbed-client-mbed-tls/xsl_script.sh | 35 + .../mbed-client-randlib/.gitignore | 1 + .../mbed-client-randlib/.mbedignore | 2 + .../mbed-client-randlib/LICENSE | 2 + .../mbed-client-randlib/apache-2.0.txt | 56 + .../mbed-client-randlib/linux/randLIB.c | 168 + .../platform/arm_hal_random.h | 33 + .../mbed-client-randlib/randLIB.h | 123 + .../mbed-client-randlib/module.json | 13 + .../mbed-client-randlib/source/randLIB.c | 224 ++ .../unittest/MakefileWorker.mk | 562 ++++ .../unittest/makefile_defines.txt | 18 + .../unittest/randlib/main.cpp | 15 + .../unittest/randlib/randlibtest.cpp | 51 + .../unittest/randlib/test_randlib.c | 97 + .../unittest/randlib/test_randlib.h | 33 + .../unittest/randlib_linux/main.cpp | 14 + .../unittest/randlib_linux/randlibtest.cpp | 69 + .../mbed-client-randlib/unittest/run_tests | 43 + .../unittest/stubs/open_stub.c | 24 + .../unittest/stubs/random_stub.c | 15 + .../FEATURE_CLIENT/mbed-client/.gitignore | 36 + .../FEATURE_CLIENT/mbed-client/.mbedignore | 4 + .../FEATURE_CLIENT/mbed-client/.yotta_ignore | 7 + .../mbed-client/DOXYGEN_FRONTPAGE.md | 11 + features/FEATURE_CLIENT/mbed-client/LICENSE | 202 ++ features/FEATURE_CLIENT/mbed-client/README.md | 7 + .../mbed-client/config/linux.mk | 2 + .../FEATURE_CLIENT/mbed-client/docs/Howto.md | 417 +++ .../mbed-client/docs/Introduction.md | 144 + .../mbed-client/docs/client_reg_dereg.md | 171 + .../mbed-client/docs/data_types.md | 162 + .../mbed-client/docs/dev_man_serv_enable.md | 191 ++ .../mbed-client/docs/further-reading.md | 14 + .../FEATURE_CLIENT/mbed-client/docs/index.md | 15 + .../mbed-client/docs/info_reporting.md | 20 + .../docs/known-issues-mbed-client1511.md | 59 + .../docs/mbed_Client_Known_Issues_16_03.md | 42 + .../docs/mbed_Client_Release_Note_16_03.md | 79 + .../mbed-client/docs/porting-guide.md | 558 ++++ .../docs/release-note-mbed-client-1511.md | 56 + .../mbed-client/doxygen/mbedclient_doxy | 1850 ++++++++++ .../FEATURE_CLIENT/mbed-client/get_sizes.sh | 88 + .../mbed-client/include_dirs.mk | 14 + .../FEATURE_CLIENT/mbed-client/junit_xsl.xslt | 101 + .../mbed-client/mbed-client/functionpointer.h | 197 ++ .../mbed-client/mbed-client/m2mbase.h | 498 +++ .../mbed-client/mbed-client/m2mconfig.h | 91 + .../mbed-client/m2mconnectionhandler.h | 174 + .../mbed-client/m2mconnectionobserver.h | 85 + .../mbed-client/m2mconnectionsecurity.h | 131 + .../mbed-client/mbed-client/m2mconstants.h | 151 + .../mbed-client/mbed-client/m2mdevice.h | 250 ++ .../mbed-client/mbed-client/m2mfirmware.h | 236 ++ .../mbed-client/mbed-client/m2minterface.h | 183 + .../mbed-client/m2minterfacefactory.h | 120 + .../mbed-client/m2minterfaceobserver.h | 86 + .../mbed-client/mbed-client/m2mobject.h | 171 + .../mbed-client/m2mobjectinstance.h | 261 ++ .../mbed-client/m2mobservationhandler.h | 76 + .../mbed-client/m2mreportobserver.h | 43 + .../mbed-client/mbed-client/m2mresource.h | 317 ++ .../mbed-client/m2mresourceinstance.h | 281 ++ .../mbed-client/mbed-client/m2msecurity.h | 232 ++ .../mbed-client/mbed-client/m2mserver.h | 165 + .../mbed-client/mbed-client/m2mstring.h | 136 + .../mbed-client/mbed-client/m2mtimer.h | 89 + .../mbed-client/m2mtimerobserver.h | 50 + .../mbed-client/mbed-client/m2mvector.h | 160 + .../FEATURE_CLIENT/mbed-client/mbed_lib.json | 13 + .../FEATURE_CLIENT/mbed-client/mkdocs.yml | 17 + .../FEATURE_CLIENT/mbed-client/module.json | 23 + .../mbed-client/run_unit_tests.sh | 66 + .../run_unit_tests_with_valgrind.sh | 13 + .../mbed-client/source/include/eventdata.h | 93 + .../source/include/m2minterfaceimpl.h | 422 +++ .../source/include/m2mnsdlinterface.h | 379 +++ .../source/include/m2mnsdlobserver.h | 95 + .../source/include/m2mreporthandler.h | 182 + .../source/include/m2mtlvdeserializer.h | 184 + .../source/include/m2mtlvserializer.h | 108 + .../source/include/nsdlaccesshelper.h | 56 + .../mbed-client/source/include/nsdllinker.h | 26 + .../mbed-client/source/include/smartpointer.h | 118 + .../mbed-client/source/m2mbase.cpp | 479 +++ .../mbed-client/source/m2mdevice.cpp | 562 ++++ .../mbed-client/source/m2mfirmware.cpp | 434 +++ .../source/m2minterfacefactory.cpp | 114 + .../mbed-client/source/m2minterfaceimpl.cpp | 973 ++++++ .../mbed-client/source/m2mnsdlinterface.cpp | 1786 ++++++++++ .../mbed-client/source/m2mobject.cpp | 511 +++ .../mbed-client/source/m2mobjectinstance.cpp | 693 ++++ .../mbed-client/source/m2mreporthandler.cpp | 487 +++ .../mbed-client/source/m2mresource.cpp | 633 ++++ .../source/m2mresourceinstance.cpp | 507 +++ .../mbed-client/source/m2msecurity.cpp | 369 ++ .../mbed-client/source/m2mserver.cpp | 290 ++ .../mbed-client/source/m2mstring.cpp | 419 +++ .../mbed-client/source/m2mtlvdeserializer.cpp | 431 +++ .../mbed-client/source/m2mtlvserializer.cpp | 237 ++ .../mbed-client/source/nsdlaccesshelper.cpp | 138 + .../FEATURE_CLIENT/mbed-client/sources.mk | 23 + .../mbed-client/test/CMakeLists.txt | 108 + .../test/helloworld-mbedclient/main.cpp | 445 +++ .../test/helloworld-mbedclient/mbedclient.cpp | 333 ++ .../test/helloworld-mbedclient/mbedclient.h | 120 + .../test/helloworld-mbedclient/to_be_ported.c | 27 + .../lwm2mtestapplication/cmd_commands.cpp | 106 + .../test/lwm2mtestapplication/cmd_commands.h | 26 + .../test/lwm2mtestapplication/cmd_lwm2m.cpp | 875 +++++ .../test/lwm2mtestapplication/cmd_lwm2m.h | 29 + .../lwm2mtestapplication/generate_coverage.sh | 29 + .../test/lwm2mtestapplication/lwm2mtest.cpp | 859 +++++ .../test/lwm2mtestapplication/lwm2mtest.h | 244 ++ .../test/lwm2mtestapplication/main.cpp | 122 + .../test/mbedclient-smokeTest/main.cpp | 497 +++ .../test/mbedclient-smokeTest/security.h | 115 + .../test/mbedclient-smokeTest/testconfig.cpp | 79 + .../test/mbedclient-smokeTest/testconfig.h | 50 + .../test/mbedclient/utest/common/CThunk.h | 202 ++ .../mbedclient/utest/common/FunctionPointer.h | 604 ++++ .../utest/common/FunctionPointerBase.h | 89 + .../utest/common/FunctionPointerBind.h | 112 + .../test/mbedclient/utest/common/Ticker.h | 36 + .../mbed-net-socket-abstract/socket_api.h | 164 + .../mbed-net-socket-abstract/socket_types.h | 181 + .../test/mbedclient/utest/common/mbed.h | 22 + .../mbedclient/utest/common/sockets/Socket.h | 32 + .../utest/common/sockets/SocketAddr.h | 32 + .../utest/common/sockets/UDPSocket.h | 32 + .../utest/common/sockets/v0/Socket.h | 268 ++ .../utest/common/sockets/v0/SocketAddr.h | 43 + .../utest/common/sockets/v0/TCPAsynch.h | 47 + .../utest/common/sockets/v0/TCPListener.h | 86 + .../utest/common/sockets/v0/TCPStream.h | 83 + .../utest/common/sockets/v0/UDPSocket.h | 64 + .../test/mbedclient/utest/includes.txt | 17 + .../mbedclient/utest/m2mbase/CMakeLists.txt | 22 + .../mbedclient/utest/m2mbase/m2mbasetest.cpp | 272 ++ .../test/mbedclient/utest/m2mbase/main.cpp | 25 + .../mbedclient/utest/m2mbase/test_m2mbase.cpp | 606 ++++ .../mbedclient/utest/m2mbase/test_m2mbase.h | 124 + .../mbedclient/utest/m2mdevice/CMakeLists.txt | 25 + .../utest/m2mdevice/m2mdevicetest.cpp | 102 + .../test/mbedclient/utest/m2mdevice/main.cpp | 25 + .../utest/m2mdevice/test_m2mdevice.cpp | 500 +++ .../utest/m2mdevice/test_m2mdevice.h | 60 + .../utest/m2mfirmware/CMakeLists.txt | 25 + .../utest/m2mfirmware/m2mfirmwaretest.cpp | 104 + .../mbedclient/utest/m2mfirmware/main.cpp | 25 + .../utest/m2mfirmware/test_m2mfirmware.cpp | 425 +++ .../utest/m2mfirmware/test_m2mfirmware.h | 60 + .../utest/m2minterfacefactory/CMakeLists.txt | 30 + .../m2minterfacefactorytest.cpp | 63 + .../utest/m2minterfacefactory/main.cpp | 25 + .../test_m2minterfacefactory.cpp | 128 + .../test_m2minterfacefactory.h | 41 + .../utest/m2minterfaceimpl/CMakeLists.txt | 32 + .../m2minterfaceimpl/m2minterfaceimpltest.cpp | 157 + .../utest/m2minterfaceimpl/main.cpp | 25 + .../test_m2minterfaceimpl.cpp | 756 +++++ .../m2minterfaceimpl/test_m2minterfaceimpl.h | 87 + .../utest/m2mnsdlinterface/CMakeLists.txt | 34 + .../m2mnsdlinterface/m2mnsdlinterfacetest.cpp | 191 ++ .../utest/m2mnsdlinterface/main.cpp | 25 + .../test_m2mnsdlinterface.cpp | 1705 ++++++++++ .../m2mnsdlinterface/test_m2mnsdlinterface.h | 98 + .../mbedclient/utest/m2mobject/CMakeLists.txt | 30 + .../utest/m2mobject/m2mobjecttest.cpp | 93 + .../test/mbedclient/utest/m2mobject/main.cpp | 25 + .../utest/m2mobject/test_m2mobject.cpp | 874 +++++ .../utest/m2mobject/test_m2mobject.h | 56 + .../utest/m2mobjectinstance/CMakeLists.txt | 28 + .../m2mobjectinstancetest.cpp | 118 + .../utest/m2mobjectinstance/main.cpp | 25 + .../test_m2mobjectinstance.cpp | 1162 +++++++ .../test_m2mobjectinstance.h | 70 + .../utest/m2mreporthandler/CMakeLists.txt | 25 + .../m2mreporthandler/m2mreporthandlertest.cpp | 79 + .../utest/m2mreporthandler/main.cpp | 25 + .../test_m2mreporthandler.cpp | 422 +++ .../m2mreporthandler/test_m2mreporthandler.h | 51 + .../utest/m2mresource/CMakeLists.txt | 27 + .../utest/m2mresource/m2mresourcetest.cpp | 142 + .../mbedclient/utest/m2mresource/main.cpp | 25 + .../utest/m2mresource/test_m2mresource.cpp | 839 +++++ .../utest/m2mresource/test_m2mresource.h | 80 + .../utest/m2mresourceinstance/CMakeLists.txt | 26 + .../m2mresourceinstancetest.cpp | 127 + .../utest/m2mresourceinstance/main.cpp | 25 + .../test_m2mresourceinstance.cpp | 782 +++++ .../test_m2mresourceinstance.h | 75 + .../utest/m2msecurity/CMakeLists.txt | 26 + .../utest/m2msecurity/m2msecuritytest.cpp | 97 + .../mbedclient/utest/m2msecurity/main.cpp | 25 + .../utest/m2msecurity/test_m2msecurity.cpp | 356 ++ .../utest/m2msecurity/test_m2msecurity.h | 59 + .../mbedclient/utest/m2mserver/CMakeLists.txt | 26 + .../utest/m2mserver/m2mservertest.cpp | 82 + .../test/mbedclient/utest/m2mserver/main.cpp | 25 + .../utest/m2mserver/test_m2mserver.cpp | 245 ++ .../utest/m2mserver/test_m2mserver.h | 52 + .../mbedclient/utest/m2mstring/CMakeLists.txt | 21 + .../utest/m2mstring/m2mstringtest.cpp | 172 + .../test/mbedclient/utest/m2mstring/main.cpp | 26 + .../utest/m2mstring/test_m2mstring.cpp | 412 +++ .../utest/m2mstring/test_m2mstring.h | 60 + .../utest/m2mtlvdeserializer/CMakeLists.txt | 29 + .../m2mtlvdeserializertest.cpp | 123 + .../utest/m2mtlvdeserializer/main.cpp | 26 + .../test_m2mtlvdeserializer.cpp | 642 ++++ .../test_m2mtlvdeserializer.h | 49 + .../test_m2mtlvserializer.cpp | 305 ++ .../test_m2mtlvserializer.h | 39 + .../utest/nsdlaccesshelper/CMakeLists.txt | 26 + .../utest/nsdlaccesshelper/main.cpp | 25 + .../nsdlaccesshelper/nsdlaccesshelpertest.cpp | 84 + .../test_nsdlaccesshelper.cpp | 239 ++ .../nsdlaccesshelper/test_nsdlaccesshelper.h | 54 + .../mbedclient/utest/stub/common_stub.cpp | 458 +++ .../test/mbedclient/utest/stub/common_stub.h | 47 + .../mbedclient/utest/stub/m2mbase_stub.cpp | 336 ++ .../test/mbedclient/utest/stub/m2mbase_stub.h | 43 + .../utest/stub/m2mconnectionhandler_stub.cpp | 94 + .../utest/stub/m2mconnectionhandler_stub.h | 31 + .../utest/stub/m2mconnectionsecurity_stub.cpp | 98 + .../utest/stub/m2mconnectionsecurity_stub.h | 32 + .../mbedclient/utest/stub/m2mdevice_stub.cpp | 108 + .../mbedclient/utest/stub/m2mdevice_stub.h | 32 + .../utest/stub/m2mfirmware_stub.cpp | 113 + .../mbedclient/utest/stub/m2mfirmware_stub.h | 33 + .../utest/stub/m2minterfaceimpl_stub.cpp | 163 + .../utest/stub/m2minterfaceimpl_stub.h | 31 + .../utest/stub/m2mnsdlinterface_stub.cpp | 200 ++ .../utest/stub/m2mnsdlinterface_stub.h | 32 + .../mbedclient/utest/stub/m2mobject_stub.cpp | 124 + .../mbedclient/utest/stub/m2mobject_stub.h | 35 + .../utest/stub/m2mobjectinstance_stub.cpp | 173 + .../utest/stub/m2mobjectinstance_stub.h | 36 + .../utest/stub/m2mreporthandler_stub.cpp | 66 + .../utest/stub/m2mreporthandler_stub.h | 30 + .../utest/stub/m2mresource_stub.cpp | 162 + .../mbedclient/utest/stub/m2mresource_stub.h | 35 + .../utest/stub/m2mresourceinstance_stub.cpp | 215 ++ .../utest/stub/m2mresourceinstance_stub.h | 35 + .../utest/stub/m2msecurity_stub.cpp | 135 + .../mbedclient/utest/stub/m2msecurity_stub.h | 34 + .../mbedclient/utest/stub/m2mserver_stub.cpp | 86 + .../mbedclient/utest/stub/m2mserver_stub.h | 33 + .../mbedclient/utest/stub/m2mstring_stub.cpp | 419 +++ .../mbedclient/utest/stub/m2mtimer_stub.cpp | 70 + .../mbedclient/utest/stub/m2mtimer_stub.h | 30 + .../utest/stub/m2mtlvdeserializer_stub.cpp | 105 + .../utest/stub/m2mtlvdeserializer_stub.h | 32 + .../utest/stub/m2mtlvserializer_stub.cpp | 46 + .../utest/stub/m2mtlvserializer_stub.h | 29 + .../utest/stub/nsdlaccesshelper_stub.cpp | 83 + .../utest/stub/nsdlaccesshelper_stub.h | 29 + .../test/mbedclient_linux/main.cpp | 429 +++ .../mbed-client/version_check.sh | 58 + .../FEATURE_CLIENT/mbed-client/xsl_script.sh | 35 + 473 files changed, 87854 insertions(+) create mode 100644 features/FEATURE_CLIENT/CONTRIBUTING.md create mode 100644 features/FEATURE_CLIENT/coap-service/.gitignore create mode 100644 features/FEATURE_CLIENT/coap-service/.mbedignore create mode 100644 features/FEATURE_CLIENT/coap-service/.yotta_ignore create mode 100644 features/FEATURE_CLIENT/coap-service/LICENSE create mode 100644 features/FEATURE_CLIENT/coap-service/Makefile.test create mode 100644 features/FEATURE_CLIENT/coap-service/apache-2.0.txt create mode 100644 features/FEATURE_CLIENT/coap-service/coap-service/coap_service_api.h create mode 100644 features/FEATURE_CLIENT/coap-service/junit_xsl.xslt create mode 100644 features/FEATURE_CLIENT/coap-service/module.json create mode 100755 features/FEATURE_CLIENT/coap-service/run_unit_tests.sh create mode 100644 features/FEATURE_CLIENT/coap-service/source/coap_connection_handler.c create mode 100644 features/FEATURE_CLIENT/coap-service/source/coap_message_handler.c create mode 100644 features/FEATURE_CLIENT/coap-service/source/coap_security_handler.c create mode 100644 features/FEATURE_CLIENT/coap-service/source/coap_service_api.c create mode 100644 features/FEATURE_CLIENT/coap-service/source/include/coap_connection_handler.h create mode 100644 features/FEATURE_CLIENT/coap-service/source/include/coap_message_handler.h create mode 100644 features/FEATURE_CLIENT/coap-service/source/include/coap_security_handler.h create mode 100644 features/FEATURE_CLIENT/coap-service/source/include/coap_service_api_internal.h create mode 100755 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/MakefileWorker.mk create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_connection_handler/coap_connection_handlertest.cpp create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_connection_handler/main.cpp create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_connection_handler/test_coap_connection_handler.c create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_connection_handler/test_coap_connection_handler.h create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_message_handler/coap_message_handlertest.cpp create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_message_handler/main.cpp create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_message_handler/test_coap_message_handler.c create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_message_handler/test_coap_message_handler.h create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_security_handler/coap_security_handlertest.cpp create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_security_handler/main.cpp create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_security_handler/test_coap_security_handler.c create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_security_handler/test_coap_security_handler.h create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_service_api/coap_service_apitest.cpp create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_service_api/main.cpp create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_service_api/test_coap_service_api.c create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_service_api/test_coap_service_api.h create mode 100755 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/makefile_defines.txt create mode 100755 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/run_tests create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_connection_handler_stub.c create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_connection_handler_stub.h create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_message_handler_stub.c create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_message_handler_stub.h create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_security_handler_stub.c create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_security_handler_stub.h create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_service_api_stub.c create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/eventOS_event_stub.c create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/eventOS_event_stub.h create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/mbed_trace_stub.c create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/mbedtls_stub.h create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/ns_list_stub.c create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/ns_timer_stub.c create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/ns_timer_stub.h create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/nsdynmemLIB_stub.c create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/nsdynmemLIB_stub.h create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/randLIB_stub.c create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_builder_stub.c create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_builder_stub.h create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_parser_stub.c create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_parser_stub.h create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_protocol_stub.c create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_protocol_stub.h create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/socket_api_stub.c create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/socket_api_stub.h create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/system_timer_stub.c create mode 100644 features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/timeout_stub.c create mode 100755 features/FEATURE_CLIENT/coap-service/xsl_script.sh create mode 100644 features/FEATURE_CLIENT/mbed-client-c/.gitattributes create mode 100644 features/FEATURE_CLIENT/mbed-client-c/.gitignore create mode 100644 features/FEATURE_CLIENT/mbed-client-c/.mbedignore create mode 100644 features/FEATURE_CLIENT/mbed-client-c/.yotta_ignore create mode 100644 features/FEATURE_CLIENT/mbed-client-c/LICENSE create mode 100644 features/FEATURE_CLIENT/mbed-client-c/Makefile.test create mode 100644 features/FEATURE_CLIENT/mbed-client-c/README.txt create mode 100644 features/FEATURE_CLIENT/mbed-client-c/apache-2.0.txt create mode 100644 features/FEATURE_CLIENT/mbed-client-c/doxygen/client-c_doxy create mode 100644 features/FEATURE_CLIENT/mbed-client-c/junit_xsl.xslt create mode 100644 features/FEATURE_CLIENT/mbed-client-c/module.json create mode 100644 features/FEATURE_CLIENT/mbed-client-c/nsdl-c/sn_coap_header.h create mode 100644 features/FEATURE_CLIENT/mbed-client-c/nsdl-c/sn_coap_protocol.h create mode 100644 features/FEATURE_CLIENT/mbed-client-c/nsdl-c/sn_nsdl.h create mode 100755 features/FEATURE_CLIENT/mbed-client-c/nsdl-c/sn_nsdl_lib.h create mode 100755 features/FEATURE_CLIENT/mbed-client-c/run_unit_tests.sh create mode 100755 features/FEATURE_CLIENT/mbed-client-c/run_unit_tests_with_valgrind.sh create mode 100644 features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/include/sn_coap_header_internal.h create mode 100644 features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/include/sn_coap_protocol_internal.h create mode 100644 features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/sn_coap_builder.c create mode 100644 features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/sn_coap_header_check.c create mode 100644 features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/sn_coap_parser.c create mode 100644 features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/sn_coap_protocol.c create mode 100755 features/FEATURE_CLIENT/mbed-client-c/source/libNsdl/src/include/sn_grs.h create mode 100755 features/FEATURE_CLIENT/mbed-client-c/source/libNsdl/src/sn_grs.c create mode 100755 features/FEATURE_CLIENT/mbed-client-c/source/libNsdl/src/sn_nsdl.c create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/CMakeLists.txt create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/arguments.h create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/main.c create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/mbed_client.c create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/module.json create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/resource_generation_help.h create mode 100755 features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/tester.sh create mode 100755 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/MakefileWorker.mk create mode 100755 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/makefile_defines.txt create mode 100755 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/run_tests create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_builder/libCoap_builder_test.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_builder/main.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_header_check/libCoap_header_test.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_header_check/main.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/main.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/sn_coap_parsertest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/test_sn_coap_parser.c create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/test_sn_coap_parser.h create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_protocol/libCoap_protocol_test.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_protocol/main.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_grs/main.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_grs/sn_grstest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_grs/test_sn_grs.c create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_grs/test_sn_grs.h create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_nsdl/main.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_nsdl/sn_nsdltest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_nsdl/test_sn_nsdl.c create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_nsdl/test_sn_nsdl.h create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/ns_list_stub.c create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_builder_stub.c create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_builder_stub.h create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_header_check_stub.c create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_header_check_stub.h create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_parser_stub.c create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_parser_stub.h create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_protocol_stub.c create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_protocol_stub.h create mode 100755 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_grs_stub.c create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_grs_stub.h create mode 100755 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_nsdl_stub.c create mode 100644 features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_nsdl_stub.h create mode 100644 features/FEATURE_CLIENT/mbed-client-c/unittest/test_libCoap/Test.c create mode 100644 features/FEATURE_CLIENT/mbed-client-c/unittest/test_libCoap/makefile create mode 100644 features/FEATURE_CLIENT/mbed-client-c/unittest/test_libNsdl/Test.c create mode 100644 features/FEATURE_CLIENT/mbed-client-c/unittest/test_libNsdl/makefile create mode 100755 features/FEATURE_CLIENT/mbed-client-c/xsl_script.sh create mode 100644 features/FEATURE_CLIENT/mbed-client-classic/LICENSE create mode 100644 features/FEATURE_CLIENT/mbed-client-classic/mbed-client-classic/m2mconnectionhandlerpimpl.h create mode 100644 features/FEATURE_CLIENT/mbed-client-classic/mbed-client-classic/m2mtimerpimpl.h create mode 100644 features/FEATURE_CLIENT/mbed-client-classic/source/m2mconnectionhandler.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-classic/source/m2mconnectionhandlerpimpl.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-classic/source/m2mtimer.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-classic/source/m2mtimerpimpl.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/.gitignore create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/.mbedignore create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/LICENSE create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/README.md create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/apache-2.0.txt create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/include_dirs.mk create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/junit_xsl.xslt create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/mbed-client-mbedtls/m2mconnectionsecuritypimpl.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/module.json create mode 100755 features/FEATURE_CLIENT/mbed-client-mbed-tls/run_unit_tests_with_valgrind.sh create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/source/m2mconnectionsecurity.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/source/m2mconnectionsecuritypimpl.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/sources.mk create mode 100755 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/MakefileWorker.mk create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/CThunk.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/FunctionPointer.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/FunctionPointerBase.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/FunctionPointerBind.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/Ticker.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/alltests.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/ip6string.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/mbed.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/ns_list.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/ns_types.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sal/socket_api.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sal/socket_types.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/Socket.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/SocketAddr.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/UDPSocket.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/Socket.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/SocketAddr.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/TCPAsynch.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/TCPListener.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/TCPStream.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/UDPSocket.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecurity_mbedtls/CMakeLists.txt create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecurity_mbedtls/m2mconnectionsecurity_mbedtlstest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecurity_mbedtls/main.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecurity_mbedtls/test_m2mconnectionsecurity_mbedtls.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecurity_mbedtls/test_m2mconnectionsecurity_mbedtls.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecuritypimpl_mbedtls/CMakeLists.txt create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecuritypimpl_mbedtls/m2mconnectionsecuritypimpl_mbedtlstest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecuritypimpl_mbedtls/main.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecuritypimpl_mbedtls/test_m2mconnectionsecuritypimpl_mbedtls.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecuritypimpl_mbedtls/test_m2mconnectionsecuritypimpl_mbedtls.h create mode 100755 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/makefile_defines.txt create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/common_stub.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/common_stub.h create mode 100755 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mbase_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mbase_stub.h create mode 100755 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionhandler_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionhandler_stub.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionsecurity_stub.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionsecurity_stub.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionsecuritypimpl_stub.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionsecuritypimpl_stub.h create mode 100755 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mobject_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mobject_stub.h create mode 100755 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2msecurity_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2msecurity_stub.h create mode 100755 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mstring_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mtimer_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mtimer_stub.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/mbedtls_stub.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/mbedtls_stub.h create mode 100644 features/FEATURE_CLIENT/mbed-client-mbed-tls/toolchain_rules.mk create mode 100755 features/FEATURE_CLIENT/mbed-client-mbed-tls/xsl_script.sh create mode 100644 features/FEATURE_CLIENT/mbed-client-randlib/.gitignore create mode 100644 features/FEATURE_CLIENT/mbed-client-randlib/.mbedignore create mode 100644 features/FEATURE_CLIENT/mbed-client-randlib/LICENSE create mode 100644 features/FEATURE_CLIENT/mbed-client-randlib/apache-2.0.txt create mode 100644 features/FEATURE_CLIENT/mbed-client-randlib/linux/randLIB.c create mode 100644 features/FEATURE_CLIENT/mbed-client-randlib/mbed-client-randlib/platform/arm_hal_random.h create mode 100644 features/FEATURE_CLIENT/mbed-client-randlib/mbed-client-randlib/randLIB.h create mode 100644 features/FEATURE_CLIENT/mbed-client-randlib/module.json create mode 100644 features/FEATURE_CLIENT/mbed-client-randlib/source/randLIB.c create mode 100644 features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/MakefileWorker.mk create mode 100644 features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/makefile_defines.txt create mode 100644 features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/main.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/randlibtest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/test_randlib.c create mode 100644 features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/test_randlib.h create mode 100644 features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib_linux/main.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib_linux/randlibtest.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/run_tests create mode 100644 features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/stubs/open_stub.c create mode 100644 features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/stubs/random_stub.c create mode 100644 features/FEATURE_CLIENT/mbed-client/.gitignore create mode 100644 features/FEATURE_CLIENT/mbed-client/.mbedignore create mode 100644 features/FEATURE_CLIENT/mbed-client/.yotta_ignore create mode 100644 features/FEATURE_CLIENT/mbed-client/DOXYGEN_FRONTPAGE.md create mode 100644 features/FEATURE_CLIENT/mbed-client/LICENSE create mode 100644 features/FEATURE_CLIENT/mbed-client/README.md create mode 100644 features/FEATURE_CLIENT/mbed-client/config/linux.mk create mode 100644 features/FEATURE_CLIENT/mbed-client/docs/Howto.md create mode 100644 features/FEATURE_CLIENT/mbed-client/docs/Introduction.md create mode 100644 features/FEATURE_CLIENT/mbed-client/docs/client_reg_dereg.md create mode 100644 features/FEATURE_CLIENT/mbed-client/docs/data_types.md create mode 100644 features/FEATURE_CLIENT/mbed-client/docs/dev_man_serv_enable.md create mode 100644 features/FEATURE_CLIENT/mbed-client/docs/further-reading.md create mode 100644 features/FEATURE_CLIENT/mbed-client/docs/index.md create mode 100644 features/FEATURE_CLIENT/mbed-client/docs/info_reporting.md create mode 100644 features/FEATURE_CLIENT/mbed-client/docs/known-issues-mbed-client1511.md create mode 100644 features/FEATURE_CLIENT/mbed-client/docs/mbed_Client_Known_Issues_16_03.md create mode 100644 features/FEATURE_CLIENT/mbed-client/docs/mbed_Client_Release_Note_16_03.md create mode 100644 features/FEATURE_CLIENT/mbed-client/docs/porting-guide.md create mode 100644 features/FEATURE_CLIENT/mbed-client/docs/release-note-mbed-client-1511.md create mode 100644 features/FEATURE_CLIENT/mbed-client/doxygen/mbedclient_doxy create mode 100755 features/FEATURE_CLIENT/mbed-client/get_sizes.sh create mode 100644 features/FEATURE_CLIENT/mbed-client/include_dirs.mk create mode 100644 features/FEATURE_CLIENT/mbed-client/junit_xsl.xslt create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/functionpointer.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2mbase.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2mconfig.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2mconnectionhandler.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2mconnectionobserver.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2mconnectionsecurity.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2mconstants.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2mdevice.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2mfirmware.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2minterface.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2minterfacefactory.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2minterfaceobserver.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2mobject.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2mobjectinstance.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2mobservationhandler.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2mreportobserver.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2mresource.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2mresourceinstance.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2msecurity.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2mserver.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2mstring.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2mtimer.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2mtimerobserver.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed-client/m2mvector.h create mode 100644 features/FEATURE_CLIENT/mbed-client/mbed_lib.json create mode 100644 features/FEATURE_CLIENT/mbed-client/mkdocs.yml create mode 100644 features/FEATURE_CLIENT/mbed-client/module.json create mode 100755 features/FEATURE_CLIENT/mbed-client/run_unit_tests.sh create mode 100755 features/FEATURE_CLIENT/mbed-client/run_unit_tests_with_valgrind.sh create mode 100644 features/FEATURE_CLIENT/mbed-client/source/include/eventdata.h create mode 100644 features/FEATURE_CLIENT/mbed-client/source/include/m2minterfaceimpl.h create mode 100644 features/FEATURE_CLIENT/mbed-client/source/include/m2mnsdlinterface.h create mode 100644 features/FEATURE_CLIENT/mbed-client/source/include/m2mnsdlobserver.h create mode 100644 features/FEATURE_CLIENT/mbed-client/source/include/m2mreporthandler.h create mode 100644 features/FEATURE_CLIENT/mbed-client/source/include/m2mtlvdeserializer.h create mode 100644 features/FEATURE_CLIENT/mbed-client/source/include/m2mtlvserializer.h create mode 100644 features/FEATURE_CLIENT/mbed-client/source/include/nsdlaccesshelper.h create mode 100644 features/FEATURE_CLIENT/mbed-client/source/include/nsdllinker.h create mode 100644 features/FEATURE_CLIENT/mbed-client/source/include/smartpointer.h create mode 100644 features/FEATURE_CLIENT/mbed-client/source/m2mbase.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/source/m2mdevice.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/source/m2mfirmware.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/source/m2minterfacefactory.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/source/m2minterfaceimpl.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/source/m2mnsdlinterface.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/source/m2mobject.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/source/m2mobjectinstance.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/source/m2mreporthandler.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/source/m2mresource.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/source/m2mresourceinstance.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/source/m2msecurity.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/source/m2mserver.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/source/m2mstring.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/source/m2mtlvdeserializer.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/source/m2mtlvserializer.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/source/nsdlaccesshelper.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/sources.mk create mode 100644 features/FEATURE_CLIENT/mbed-client/test/CMakeLists.txt create mode 100755 features/FEATURE_CLIENT/mbed-client/test/helloworld-mbedclient/main.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/helloworld-mbedclient/mbedclient.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/helloworld-mbedclient/mbedclient.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/helloworld-mbedclient/to_be_ported.c create mode 100644 features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/cmd_commands.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/cmd_commands.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/cmd_lwm2m.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/cmd_lwm2m.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/generate_coverage.sh create mode 100644 features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/lwm2mtest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/lwm2mtest.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/main.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient-smokeTest/main.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient-smokeTest/security.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient-smokeTest/testconfig.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient-smokeTest/testconfig.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/CThunk.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/FunctionPointer.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/FunctionPointerBase.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/FunctionPointerBind.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/Ticker.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/mbed-net-socket-abstract/socket_api.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/mbed-net-socket-abstract/socket_types.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/mbed.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/Socket.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/SocketAddr.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/UDPSocket.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/Socket.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/SocketAddr.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/TCPAsynch.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/TCPListener.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/TCPStream.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/UDPSocket.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/includes.txt create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mbase/CMakeLists.txt create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mbase/m2mbasetest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mbase/main.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mbase/test_m2mbase.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mbase/test_m2mbase.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mdevice/CMakeLists.txt create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mdevice/m2mdevicetest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mdevice/main.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mdevice/test_m2mdevice.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mdevice/test_m2mdevice.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mfirmware/CMakeLists.txt create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mfirmware/m2mfirmwaretest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mfirmware/main.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mfirmware/test_m2mfirmware.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mfirmware/test_m2mfirmware.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfacefactory/CMakeLists.txt create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfacefactory/m2minterfacefactorytest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfacefactory/main.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfacefactory/test_m2minterfacefactory.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfacefactory/test_m2minterfacefactory.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfaceimpl/CMakeLists.txt create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfaceimpl/m2minterfaceimpltest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfaceimpl/main.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfaceimpl/test_m2minterfaceimpl.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfaceimpl/test_m2minterfaceimpl.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mnsdlinterface/CMakeLists.txt create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mnsdlinterface/m2mnsdlinterfacetest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mnsdlinterface/main.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mnsdlinterface/test_m2mnsdlinterface.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mnsdlinterface/test_m2mnsdlinterface.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobject/CMakeLists.txt create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobject/m2mobjecttest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobject/main.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobject/test_m2mobject.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobject/test_m2mobject.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobjectinstance/CMakeLists.txt create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobjectinstance/m2mobjectinstancetest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobjectinstance/main.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobjectinstance/test_m2mobjectinstance.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobjectinstance/test_m2mobjectinstance.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mreporthandler/CMakeLists.txt create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mreporthandler/m2mreporthandlertest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mreporthandler/main.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mreporthandler/test_m2mreporthandler.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mreporthandler/test_m2mreporthandler.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresource/CMakeLists.txt create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresource/m2mresourcetest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresource/main.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresource/test_m2mresource.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresource/test_m2mresource.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresourceinstance/CMakeLists.txt create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresourceinstance/m2mresourceinstancetest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresourceinstance/main.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresourceinstance/test_m2mresourceinstance.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresourceinstance/test_m2mresourceinstance.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2msecurity/CMakeLists.txt create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2msecurity/m2msecuritytest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2msecurity/main.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2msecurity/test_m2msecurity.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2msecurity/test_m2msecurity.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mserver/CMakeLists.txt create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mserver/m2mservertest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mserver/main.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mserver/test_m2mserver.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mserver/test_m2mserver.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mstring/CMakeLists.txt create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mstring/m2mstringtest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mstring/main.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mstring/test_m2mstring.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mstring/test_m2mstring.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/CMakeLists.txt create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/m2mtlvdeserializertest.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/main.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/test_m2mtlvdeserializer.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/test_m2mtlvdeserializer.h create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/test_m2mtlvserializer.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/test_m2mtlvserializer.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/nsdlaccesshelper/CMakeLists.txt create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/nsdlaccesshelper/main.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/nsdlaccesshelper/nsdlaccesshelpertest.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/nsdlaccesshelper/test_nsdlaccesshelper.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/nsdlaccesshelper/test_nsdlaccesshelper.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/common_stub.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/common_stub.h create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mbase_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mbase_stub.h create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mconnectionhandler_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mconnectionhandler_stub.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mconnectionsecurity_stub.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mconnectionsecurity_stub.h create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mdevice_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mdevice_stub.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mfirmware_stub.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mfirmware_stub.h create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2minterfaceimpl_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2minterfaceimpl_stub.h create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mnsdlinterface_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mnsdlinterface_stub.h create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mobject_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mobject_stub.h create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mobjectinstance_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mobjectinstance_stub.h create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mreporthandler_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mreporthandler_stub.h create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mresource_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mresource_stub.h create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mresourceinstance_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mresourceinstance_stub.h create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2msecurity_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2msecurity_stub.h create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mserver_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mserver_stub.h create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mstring_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtimer_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtimer_stub.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtlvdeserializer_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtlvdeserializer_stub.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtlvserializer_stub.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtlvserializer_stub.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/nsdlaccesshelper_stub.cpp create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/nsdlaccesshelper_stub.h create mode 100644 features/FEATURE_CLIENT/mbed-client/test/mbedclient_linux/main.cpp create mode 100755 features/FEATURE_CLIENT/mbed-client/version_check.sh create mode 100755 features/FEATURE_CLIENT/mbed-client/xsl_script.sh diff --git a/features/FEATURE_CLIENT/CONTRIBUTING.md b/features/FEATURE_CLIENT/CONTRIBUTING.md new file mode 100644 index 0000000000..2e9b3618ca --- /dev/null +++ b/features/FEATURE_CLIENT/CONTRIBUTING.md @@ -0,0 +1,83 @@ +# How to contribute + +This directory structure is entirely generated or copied from another repositories. Do not send patches against it, they cannot be accepted because all code will be entirely overwritten on next release. + +Instead follow these instructions to send and test your contributions against master repositories. + +## Directory structure + +This directory consist of following modules + +* [mbed-client](#mbed-client) +* [mbed-client-c](#mbed-client-c) +* [mbed-client-mbed-tls](#mbed-client-mbed-tls) +* [mbed-client-classic](#mbed-client-classic) +* [mbed-client-randlib](#mbed-client-randlib) +* [coap-service](#coap-service) + + +## mbed-client + +mbed-cient is copied from master repository from here: https://github.com/ARMmbed/mbed-client + +To replace the copied version with master repository follow these steps: + +* Remove mbed-client directory: `rm -rf mbed-client` +* Clone from the master: `git clone git@github.com:ARMmbed/mbed-client.git` + +Now you have mbed-client directory replaced with Git repository cloned from original. You can build and test your changes against it and send patches normally to Github as a pull requests. + +## mbed-client-c + +mbed-client-c is copied from master repository from here: https://github.com/ARMmbed/mbed-client-c + +To replace the copied version with master repository follow these steps: + +* Remove mbed-client-c directory: `rm -rf mbed-client-c` +* Clone from the master: `git clone git@github.com:ARMmbed/mbed-client-c.git` + +Now you have mbed-client-c directory replaced with Git repository cloned from original. You can build and test your changes against it and send patches normally to Github as a pull requests. + +## mbed-client-classic + +mbed-client-classic is copied from master repository from here: https://github.com/ARMmbed/mbed-client-classic + +To replace the copied version with master repository follow these steps: + +* Remove mbed-client-classic directory: `rm -rf mbed-client-classic` +* Clone from the master: `git clone git@github.com:ARMmbed/mbed-client-classic.git` + +Now you have mbed-client-classic directory replaced with Git repository cloned from original. You can build and test your changes against it and send patches normally to Github as a pull requests. + +## mbed-client-mbed-tls + +mbed-client-mbed-tls is copied from master repository from here: https://github.com/ARMmbed/mbed-client-mbed-tls + +To replace the copied version with master repository follow these steps: + +* Remove mbed-client-mbed-tls directory: `rm -rf mbed-client-mbed-tls` +* Clone from the master: `git clone git@github.com:ARMmbed/mbed-client-mbed-tls.git` + +Now you have mbed-client-mbed-tls directory replaced with Git repository cloned from original. You can build and test your changes against it and send patches normally to Github as a pull requests. + +## mbed-client-randlib + +mbed-client-randlib is copied from master repository from here: https://github.com/ARMmbed/mbed-client-randlib + +To replace the copied version with master repository follow these steps: + +* Remove mbed-client-randlib directory: `rm -rf mbed-client-randlib` +* Clone from the master: `git clone git@github.com:ARMmbed/mbed-client-randlib.git` + +Now you have mbed-client-randlib directory replaced with Git repository cloned from original. You can build and test your changes against it and send patches normally to Github as a pull requests. + +## coap-service + +coap-service is copied from master repository from here: https://github.com/ARMmbed/coap-service + +To replace the copied version with master repository follow these steps: + +* Remove coap-service directory: `rm -rf coap-service` +* Clone from the master: `git clone git@github.com:ARMmbed/coap-service.git` + +Now you have coap-service directory replaced with Git repository cloned from original. You can build and test your changes against it and send patches normally to Github as a pull requests. diff --git a/features/FEATURE_CLIENT/coap-service/.gitignore b/features/FEATURE_CLIENT/coap-service/.gitignore new file mode 100644 index 0000000000..7da85016ee --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/.gitignore @@ -0,0 +1,10 @@ +*.a +*.lib +output +lcov +coverage +.yotta.json +build/ +yotta_modules/ +yotta_targets/ +upload.tar.gz diff --git a/features/FEATURE_CLIENT/coap-service/.mbedignore b/features/FEATURE_CLIENT/coap-service/.mbedignore new file mode 100644 index 0000000000..ab1cfb4ef2 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/.mbedignore @@ -0,0 +1 @@ +test/* diff --git a/features/FEATURE_CLIENT/coap-service/.yotta_ignore b/features/FEATURE_CLIENT/coap-service/.yotta_ignore new file mode 100644 index 0000000000..ab97c1af02 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/.yotta_ignore @@ -0,0 +1,4 @@ +unittest/* +test/* +doxygen/* + diff --git a/features/FEATURE_CLIENT/coap-service/LICENSE b/features/FEATURE_CLIENT/coap-service/LICENSE new file mode 100644 index 0000000000..97df0e645d --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/LICENSE @@ -0,0 +1,2 @@ +Unless specifically indicated otherwise in a file, files are licensed +under the Apache 2.0 license, as can be found in: apache-2.0.txt \ No newline at end of file diff --git a/features/FEATURE_CLIENT/coap-service/Makefile.test b/features/FEATURE_CLIENT/coap-service/Makefile.test new file mode 100644 index 0000000000..8a1c3063f7 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/Makefile.test @@ -0,0 +1,51 @@ +# +# Makefile.test for COAP service unit tests +# + +# List of subdirectories to build +TEST_FOLDER := ./test/ +# List of unit test directories for libraries +UNITTESTS := $(sort $(dir $(wildcard $(TEST_FOLDER)*/unittest/*))) +TESTDIRS := $(UNITTESTS:%=build-%) +CLEANTESTDIRS := $(UNITTESTS:%=clean-%) +COVERAGEFILE := ./lcov/coverage.info + +.PHONY: test +test: $(TESTDIRS) + @rm -rf ./lcov + @rm -rf ./coverage + @mkdir -p lcov + @mkdir -p lcov/results + @mkdir coverage + @find ./test -name '*.xml' | xargs cp -t ./lcov/results/ + @rm -f lcov/index.xml + @./xsl_script.sh + @cp junit_xsl.xslt lcov/. + @xsltproc -o lcov/testresults.html lcov/junit_xsl.xslt lcov/index.xml + @rm -f lcov/junit_xsl.xslt + @rm -f lcov/index.xml + @find ./ -name '*.gcno' | xargs cp --backup=numbered -t ./coverage/ + @find ./ -name '*.gcda' | xargs cp --backup=numbered -t ./coverage/ + @gcovr --object-directory ./coverage --exclude-unreachable-branches -e '.*/builds/.*' -e '.*/test/.*' -e '.*/yotta_modules/.*' -e '.*/stub/.*' -x -o ./lcov/gcovr.xml + @lcov -d test/. -c -o $(COVERAGEFILE) + @lcov -q -r $(COVERAGEFILE) "/usr*" -o $(COVERAGEFILE) + @lcov -q -r $(COVERAGEFILE) "/test*" -o $(COVERAGEFILE) + @lcov -q -r $(COVERAGEFILE) "/mbed-client-libservice*" -o $(COVERAGEFILE) + @lcov -q -r $(COVERAGEFILE) "/libService*" -o $(COVERAGEFILE) + @genhtml -q $(COVERAGEFILE) --show-details --output-directory lcov/html + @echo coap-service unit tests built + +$(TESTDIRS): + @make -C $(@:build-%=%) + +$(CLEANDIRS): + @make -C $(@:clean-%=%) clean + +$(CLEANTESTDIRS): + @make -C $(@:clean-%=%) clean + +# Extend default clean rule +clean: clean-extra + +clean-extra: $(CLEANDIRS) \ + $(CLEANTESTDIRS) diff --git a/features/FEATURE_CLIENT/coap-service/apache-2.0.txt b/features/FEATURE_CLIENT/coap-service/apache-2.0.txt new file mode 100644 index 0000000000..a2fecaf5f8 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/apache-2.0.txt @@ -0,0 +1,56 @@ + + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + You must give any other recipients of the Work or Derivative Works a copy of this License; and + You must cause any modified files to carry prominent notices stating that You changed the files; and + You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/features/FEATURE_CLIENT/coap-service/coap-service/coap_service_api.h b/features/FEATURE_CLIENT/coap-service/coap-service/coap_service_api.h new file mode 100644 index 0000000000..9924d1f311 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/coap-service/coap_service_api.h @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2015-2016 ARM Limited. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 COAP_SERVICE_API_H_ +#define COAP_SERVICE_API_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include "ns_types.h" +#include "sn_coap_header.h" +#include "ns_address.h" + +/** + * This interface is used in sending and receiving of CoAP messages to multicast address and receive multiple responses. + */ + +// Allowed_methods +#define COAP_SERVICE_ACCESS_ALL_ALLOWED 0x0F +#define COAP_SERVICE_ACCESS_GET_ALLOWED 0x01 +#define COAP_SERVICE_ACCESS_PUT_ALLOWED 0x02 +#define COAP_SERVICE_ACCESS_POST_ALLOWED 0x04 +#define COAP_SERVICE_ACCESS_DELETE_ALLOWED 0x08 + +// Bits for service options +#define COAP_SERVICE_OPTIONS_NONE 0x00 +#define COAP_SERVICE_OPTIONS_VIRTUAL_SOCKET 0x01 +#define COAP_SERVICE_OPTIONS_SECURE 0x02 +#define COAP_SERVICE_OPTIONS_EPHEMERAL_PORT 0x04 +/** Link-layer security bypass option is set*/ +#define COAP_SERVICE_OPTIONS_SECURE_BYPASS 0x80 + +// Bits for request options +#define COAP_REQUEST_OPTIONS_NONE 0x00 +#define COAP_REQUEST_OPTIONS_ADDRESS_DEFAULT 0x00//!< default is not setting either short or long. +#define COAP_REQUEST_OPTIONS_ADDRESS_LONG 0x01 +#define COAP_REQUEST_OPTIONS_ADDRESS_SHORT 0x02 +#define COAP_REQUEST_OPTIONS_MULTICAST 0x04 //!< indicates that CoAP library support multicasting +#define COAP_REQUEST_OPTIONS_SECURE_BYPASS 0x08 + +/** + * \brief Service message response receive callback. + * + * Function that handles CoAP service message receiving and parsing + * + * \param msg_id Id number of the current message. + * \param source_address IPv6 source address. + * \param source_port Source port + * \param response_ptr Pointer to CoAP header structure. + * + * \return 0 for success / -1 for failure + */ +typedef int coap_service_response_recv(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr); + +/** + * \brief CoAP service request callback + * + * CoAP service request message receiving and parsing function + * + * \param service_id Id number of the current service. + * \param source_address IPv6 source address. + * \param source_port Source port + * \param request_ptr Pointer to CoAP header structure. + * + * \return Status + */ +typedef int coap_service_request_recv_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *request_ptr); + +/** + * \brief Security service start callback + * + * Starts security service handling and fetches device password. + * + * \param service_id Id number of the current service. + * \param address Address of sender + * \param port Port of the device + * + * \return 0 for success / -1 for failure + */ +typedef int coap_service_security_start_cb(int8_t service_id, uint8_t address[static 16], uint16_t port, uint8_t* pw, uint8_t *pw_len); + +/** + * \brief CoAP service security done callback + * + * CoAP service security done callback function. + * + * \param service_id Id number of the current service. + * \param address Address of sender + * \param keyblock Security key (40 bits) + * + * \return 0 for success / -1 for failure + */ +typedef int coap_service_security_done_cb(int8_t service_id, uint8_t address[static 16], uint8_t keyblock[static 40]); + +/** + * \brief Initialise server instance. + * + * Initialise Thread services for the registered application. + * + * \param interface_id Informs registered application interface id. This parameter is passed to socket implementation. + * \param listen_port Port that Application wants to use for communicate with coap server. + * \param service_options Options of the current service. + * \param *start_ptr Callback to inform security handling is started and to fetch device password. + * \param *coap_security_done_cb Callback to inform security handling is done. + * + * \return service_id / -1 for failure + */ +extern int8_t coap_service_initialize(int8_t interface_id, uint16_t listen_port, uint8_t service_options, coap_service_security_start_cb *start_ptr, coap_service_security_done_cb *coap_security_done_cb); + +/** + * \brief Service delete + * + * Removes all data related to this instance + * + * \param service_id Id number of the current service. + */ +extern void coap_service_delete( int8_t service_id ); + +/** + * \brief Close secure connection + * + * Closes secure connection (if present), but leaves socket open. + * + * \param service_id Id number of the current service. + */ +extern void coap_service_close_secure_connection(int8_t service_id, uint8_t destination_addr_ptr[static 16], uint16_t port); + +/** + * \brief Sets password for device + * + * \param service_id Service id + * \param address Device address + * \param port Device port + * \param pw_ptr Pointer to password. + * \param pw_len Lenght of password. + * + * \return 0 for success / -1 for failure + */ +//int coap_service_security_key_set(int8_t service_id, uint8_t address[static 16], uint16_t port, uint8_t *pw_ptr, uint8_t pw_len); + +/** + * \brief Virtual socket sent callback. + * + * Sent data to virtual socket. + * + * \param service_id Id number of the current service. + * \param destination_addr_ptr Receiver IPv6 address. + * \param port Receiver port number. + * \param *data_ptr Pointer to the data. + * \param data_len Lenght of the data. + * + * \return 0 for success / -1 for failure + */ +typedef int coap_service_virtual_socket_send_cb(int8_t service_id, uint8_t destination_addr_ptr[static 16], uint16_t port, const uint8_t *data_ptr, uint16_t data_len); + +/** + * \brief Virtual socket read. + * + * Receive data from virtual socket. + * + * \param service_id Id number of the current service. + * \param source_addr_ptr Receiver IPv6 address. + * \param port Receiver port number. + * \param *data_ptr Pointer to the data + * \param data_len Lenght of the data + * + * \return 0 for success / -1 for failure + */ +extern int16_t coap_service_virtual_socket_recv(int8_t service_id, uint8_t source_addr_ptr[static 16], uint16_t port, uint8_t *data_ptr, uint16_t data_len); + +/** + * \brief Set virtual socket + * + * Sets virtual socket for CoAP services. + * + * \param service_id Id number of the current service. + * \param *send_method_ptr Callback to coap virtual socket. + * + * \return 0 for success / -1 for failure + */ +extern int16_t coap_service_virtual_socket_set_cb(int8_t service_id, coap_service_virtual_socket_send_cb *send_method_ptr); + +/** + * \brief Register unsecure callback methods to CoAP server + * + * Register application and informs CoAP services unsecure registery callback function. + * + * \param service_id Id number of the current service. + * \param *uri Uri address. + * \param port port that Application wants to use for communicate with coap server. + * \param allowed_method Informs method that is allowed to use (used defines described above). + * \param *request_recv_cb CoAP service request receive callback function pointer. + * + * \return 0 for success / -1 for failure + */ +extern int8_t coap_service_register_uri(int8_t service_id, const char *uri, uint8_t allowed_method, coap_service_request_recv_cb *request_recv_cb); + +/** + * \brief Unregister unsecure callback methods to CoAP server + * + * Register application and informs CoAP services unsecure registery callback function. + * + * \param service_id Id number of the current service. + * \param *uri Uri address. + * + * \return 0 for success / -1 for failure + */ +extern int8_t coap_service_unregister_uri(int8_t service_id, const char *uri); + +/** + * \brief Sends CoAP service request + * + * Build and sends CoAP service request message. + * + * \param service_id Id number of the current service. + * \param options Options defined above. + * \param destination_addr IPv6 address. + * \param destination_port Destination port + * \param msg_type Message type can be found from sn_coap_header. + * \param msg_code Message code can be found from sn_coap_header. + * \param *uri Uri address. + * \param cont_type Content type can be found from sn_coap_header. + * \param payload_ptr Pointer to message content. + * \param payload_len Lenght of the message. + * \param *request_response_cb Callback to inform result of the request. + * + * \return msg_id Id number of the current message. + */ +extern uint16_t coap_service_request_send(int8_t service_id, uint8_t options, const uint8_t destination_addr[static 16], uint16_t destination_port, sn_coap_msg_type_e msg_type, sn_coap_msg_code_e msg_code, const char *uri, + sn_coap_content_format_e cont_type, const uint8_t *payload_ptr, uint16_t payload_len, coap_service_response_recv *request_response_cb); + +/** + * \brief Sends CoAP service response + * + * Build and sends CoAP service response message. + * + * \param service_id Id number of the current service. + * \param msg_id Message ID number. + * \param options Options defined above. + * \param response_ptr Pointer to CoAP header structure. + * + * \return -1 For failure + *- 0 For success + */ +extern int8_t coap_service_response_send(int8_t service_id, uint8_t options, sn_coap_hdr_s *request_ptr, sn_coap_msg_code_e message_code, sn_coap_content_format_e content_type, const uint8_t *payload_ptr,uint16_t payload_len); + +extern int8_t coap_service_set_handshake_timeout(int8_t service_id, uint32_t min, uint32_t max); +#ifdef __cplusplus +} +#endif + +#endif /* COAP_SERVICE_API_H_ */ diff --git a/features/FEATURE_CLIENT/coap-service/junit_xsl.xslt b/features/FEATURE_CLIENT/coap-service/junit_xsl.xslt new file mode 100644 index 0000000000..7376b27f26 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/junit_xsl.xslt @@ -0,0 +1,101 @@ + + + + + + + + + +

+ Unittest report +

+ +

+ + Total tests run + , failures: + + + + + +

+
+ + +

+ +

+ + + + + + + + + + + +
Tests runTests failedOther errors
+
+ + + + + + + + +
Tests namePASS/FAILFailing caseReason
+
+ + + + + + + + + + + PASS + + + + + + + FAIL + + + + + + + + + + + + + + + + FAIL + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/features/FEATURE_CLIENT/coap-service/module.json b/features/FEATURE_CLIENT/coap-service/module.json new file mode 100644 index 0000000000..1491beb176 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/module.json @@ -0,0 +1,27 @@ +{ + "name": "coap-service", + "version": "4.0.1", + "description": "CoAP Service library", + "keywords": [ + "coap", + "service" + ], + "repository": { + "url": "git@github.com:ARMmbed/coap-service.git", + "type": "git" + }, + "homepage": "https://github.com/ARMmbed/coap-service", + "license": "Apache-2.0", + "extraIncludes": [ + "coap-service", + "nanostack-event-loop", + "source/include" + ], + "dependencies": { + "nanostack-libservice": "^3.0.0", + "mbed-client-c": "^2.0.0", + "sal-stack-nanostack": "^5.0.0", + "mbedtls": "^2.0.0" + }, + "targetDependencies": {} +} diff --git a/features/FEATURE_CLIENT/coap-service/run_unit_tests.sh b/features/FEATURE_CLIENT/coap-service/run_unit_tests.sh new file mode 100755 index 0000000000..0fed9ad320 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/run_unit_tests.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Copyright (c) 2015 ARM Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# * http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +echo +echo "Build coap service unit tests" +echo + +yt target x86-linux-native +yt up +make -f Makefile.test test +make -f Makefile.test test clean diff --git a/features/FEATURE_CLIENT/coap-service/source/coap_connection_handler.c b/features/FEATURE_CLIENT/coap-service/source/coap_connection_handler.c new file mode 100644 index 0000000000..4bbe7d0856 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/source/coap_connection_handler.c @@ -0,0 +1,797 @@ +/* + * Copyright (c) 2015-2016 ARM Limited. All Rights Reserved. + */ + +#include +#include "coap_connection_handler.h" +#include "coap_security_handler.h" +#include "ns_list.h" +#include "ns_trace.h" +#include "nsdynmemLIB.h" +#include "socket_api.h" +#include "net_interface.h" +#include "eventOS_event_timer.h" +#include "coap_service_api_internal.h" + +#define TRACE_GROUP "ThCH" + +typedef enum session_state_e { + SECURE_SESSION_HANDSHAKE_ONGOING = 0, + SECURE_SESSION_OK, + SECURE_SESSION_CLOSED +}session_state_t; + +typedef struct internal_socket_s { + coap_conn_handler_t *parent; + + uint32_t timeout_min; + uint32_t timeout_max; + + uint16_t listen_port; + int8_t listen_socket; + + ns_address_t dest_addr; + size_t data_len; + uint8_t *data; + + bool real_socket; + uint8_t usage_counter; + bool is_secure; + + bool bypass_link_sec; + + ns_list_link_t link; +} internal_socket_t; + +static NS_LIST_DEFINE(socket_list, internal_socket_t, link); + +static void timer_cb(void* param); + +#define TIMER_STATE_CANCELLED -1 /* cancelled */ +#define TIMER_STATE_NO_EXPIRY 0 /* none of the delays is expired */ +#define TIMER_STATE_INT_EXPIRY 1 /* the intermediate delay only is expired */ +#define TIMER_STATE_FIN_EXPIRY 2 /* the final delay is expired */ + +typedef struct secure_timer_s { + uint8_t id; + timeout_t *timer; + int8_t state; + uint32_t fin_ms; + uint32_t int_ms; +} secure_timer_t; + +typedef struct secure_session { + coap_security_t *sec_handler; //owned + internal_socket_t *parent; //not owned + + secure_timer_t timer; + + session_state_t session_state; + uint32_t last_contact_time; + ns_list_link_t link; +} secure_session_t; + +static NS_LIST_DEFINE(secure_session_list, secure_session_t, link); +static int send_to_socket(int8_t socket_id, uint8_t *address_ptr, uint16_t port, const unsigned char *buf, size_t len); +static int receive_from_socket(int8_t socket_id, unsigned char *buf, size_t len); +static void start_timer(int8_t timer_id, uint32_t int_ms, uint32_t fin_ms); +static int timer_status(int8_t timer_id); + +static secure_session_t *secure_session_find_by_timer_id(int8_t timer_id) +{ + secure_session_t *this = NULL; + ns_list_foreach(secure_session_t, cur_ptr, &secure_session_list) { + if (cur_ptr->timer.id == timer_id) { + this = cur_ptr; + break; + } + } + return this; +} + +static void secure_session_delete(secure_session_t *this) +{ + if (this) { + ns_list_remove(&secure_session_list, this); + if( this->sec_handler ){ + coap_security_destroy(this->sec_handler); + this->sec_handler = NULL; + } + if(this->timer.timer){ + eventOS_timeout_cancel(this->timer.timer); + } + ns_dyn_mem_free(this); + this = NULL; + } + + return; +} + +static secure_session_t *secure_session_create(internal_socket_t *parent, uint8_t *address_ptr, uint16_t port) +{ + if(!address_ptr){ + return NULL; + } + + if(MAX_SECURE_SESSION_COUNT <= ns_list_count(&secure_session_list)){ + // Seek & destroy oldest session where close notify have been sent + secure_session_t *to_be_removed = NULL; + ns_list_foreach(secure_session_t, cur_ptr, &secure_session_list) { + if(cur_ptr->session_state == SECURE_SESSION_CLOSED){ + if(!to_be_removed || cur_ptr->last_contact_time < to_be_removed->last_contact_time){ + to_be_removed = cur_ptr; + } + } + } + if(!to_be_removed){ + return NULL; + } + + secure_session_delete(to_be_removed); + } + + secure_session_t *this = ns_dyn_mem_alloc(sizeof(secure_session_t)); + if (!this) { + return NULL; + } + memset(this, 0, sizeof(secure_session_t)); + + uint8_t timer_id = 1; + + while(secure_session_find_by_timer_id(timer_id)){ + if(timer_id == 0xff){ + ns_dyn_mem_free(this); + return NULL; + } + timer_id++; + } + this->timer.id = timer_id; + + this->sec_handler = coap_security_create(parent->listen_socket, this->timer.id, address_ptr, port, ECJPAKE, + &send_to_socket, &receive_from_socket, &start_timer, &timer_status); + if( !this->sec_handler ){ + ns_dyn_mem_free(this); + return NULL; + } + this->parent = parent; + + this->session_state = SECURE_SESSION_HANDSHAKE_ONGOING; + ns_list_add_to_start(&secure_session_list, this); + + return this; +} + + +static void clear_secure_sessions(internal_socket_t *this){ + if( this ){ + ns_list_foreach_safe(secure_session_t, cur_ptr, &secure_session_list) { + if( cur_ptr->parent == this ){ + coap_security_send_close_alert( cur_ptr->sec_handler ); + secure_session_delete(cur_ptr); + } + } + } +} + +static secure_session_t *secure_session_find(internal_socket_t *parent, uint8_t *address_ptr, uint16_t port) +{ + secure_session_t *this = NULL; + ns_list_foreach(secure_session_t, cur_ptr, &secure_session_list) { + if( cur_ptr->sec_handler ){ + if (cur_ptr->parent == parent && cur_ptr->sec_handler->_remote_port == port && + memcmp(cur_ptr->sec_handler->_remote_address, address_ptr, 16) == 0) { + this = cur_ptr; + // hack_save_remote_address(address_ptr, port); + break; + } + } + } + return this; +} + + + +static void recv_sckt_msg(void *cb_res); +static void secure_recv_sckt_msg(void *cb_res); + +static internal_socket_t *int_socket_create(uint16_t listen_port, bool use_ephemeral_port, bool is_secure, bool real_socket, bool bypassSec) +{ + internal_socket_t *this = ns_dyn_mem_alloc(sizeof(internal_socket_t)); + if (!this) { + return NULL; + } + memset(this, 0, sizeof(internal_socket_t)); + + this->data_len = 0; + this->data = NULL; + + this->is_secure = is_secure; + this->usage_counter = 1; + + this->listen_port = listen_port; + this->real_socket = real_socket; + this->bypass_link_sec = bypassSec; + this->listen_socket = -1; + if( real_socket ){ + if( use_ephemeral_port ){ //socket_api creates ephemeral port if the one provided is 0 + listen_port = 0; + } + if( !is_secure ){ + this->listen_socket = socket_open(SOCKET_UDP, listen_port, recv_sckt_msg); + }else{ + this->listen_socket = socket_open(SOCKET_UDP, listen_port, secure_recv_sckt_msg); + } + // Socket create failed + if(this->listen_socket < 0){ + ns_dyn_mem_free(this); + return NULL; + } + // XXX API for this? May want to get clever to do recommended first query = 1 hop, retries = whole PAN + socket_setsockopt(this->listen_socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_MULTICAST_HOPS, &(const int16_t) { + 16 + }, sizeof(int16_t)); + }else{ + this->listen_socket = -1; + } + + ns_list_add_to_start(&socket_list, this); + return this; +} + +static void int_socket_delete(internal_socket_t *this) +{ + if (this) { + this->usage_counter--; + if(this->usage_counter == 0){ + clear_secure_sessions(this); + socket_free(this->listen_socket); + ns_list_remove(&socket_list, this); + if( this->data ){ + ns_dyn_mem_free(this->data); + this->data = NULL; + } + if(this->parent){ + ns_dyn_mem_free(this->parent); + } + ns_dyn_mem_free(this); + } + } +} + +static internal_socket_t *int_socket_find_by_socket_id(int8_t id) +{ + internal_socket_t *this = NULL; + ns_list_foreach(internal_socket_t, cur_ptr, &socket_list) { + if( cur_ptr->listen_socket == id ) { + this = cur_ptr; + break; + } + } + return this; +} + +static internal_socket_t *int_socket_find(uint16_t port, bool is_secure, bool is_real_socket, bool bypassSec) +{ + (void) bypassSec; + + internal_socket_t *this = NULL; + ns_list_foreach(internal_socket_t, cur_ptr, &socket_list) { + if( cur_ptr->listen_port == port && cur_ptr->real_socket == is_real_socket && + is_secure == cur_ptr->is_secure /*&& bypass_link_sec == bypassSec*/) { + this = cur_ptr; + break; + } + } + return this; +} + +static int send_to_socket(int8_t socket_id, uint8_t *address_ptr, uint16_t port, const unsigned char *buf, size_t len) +{ + internal_socket_t *sock = int_socket_find_by_socket_id(socket_id); + if(!sock){ + return -1; + } + if(!sock->real_socket){ + //In this case all clients will have socket_id -1 and socket will not have a real address + //so sock->dest_addr cannot be used here + int ret = sock->parent->_send_cb(sock->listen_socket, address_ptr, port, buf, len); + if( ret < 0 ) + return ret; + return len; + } + + int opt_name = SOCKET_IPV6_PREFER_SRC_6LOWPAN_SHORT; + int8_t securityLinkLayer = 1; + if( sock->bypass_link_sec ){ + securityLinkLayer = 0; + } + socket_setsockopt(sock->listen_socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_ADDR_PREFERENCES, &opt_name, sizeof(int)); + socket_setsockopt(sock->listen_socket, SOCKET_IPPROTO_IPV6, SOCKET_LINK_LAYER_SECURITY, &securityLinkLayer, sizeof(int8_t)); + //For some reason socket_sendto returns 0 in success, while other socket impls return number of bytes sent!!! + //TODO: check if address_ptr is valid and use that instead if it is + int ret = socket_sendto(sock->listen_socket, &sock->dest_addr, (unsigned char*)buf, len); + if( ret < 0 ) + return ret; + return len; +} + +static int receive_from_socket(int8_t socket_id, unsigned char *buf, size_t len) +{ + (void)len; + internal_socket_t *sock = int_socket_find_by_socket_id(socket_id); + if( sock->data && sock->data_len > 0 ){ + memcpy( buf, sock->data, sock->data_len ); + int l = sock->data_len; + ns_dyn_mem_free(sock->data); + sock->data = NULL; + sock->data_len = 0; + return l; + } + return MBEDTLS_ERR_SSL_WANT_READ; +} + +/** + * Callback timer. Maybe called in interrupt context + * so keep it simple. + * TODO - might be better to use an event timer in conjunction with + * CoAP tasklet + */ +static void timer_cb(void *param) +{ + secure_session_t *sec = param; + if( sec ){ + if(sec->timer.fin_ms > sec->timer.int_ms){ + /* Intermediate expiry */ + sec->timer.fin_ms -= sec->timer.int_ms; + sec->timer.state = TIMER_STATE_INT_EXPIRY; + int error = coap_security_handler_continue_connecting(sec->sec_handler); + if(MBEDTLS_ERR_SSL_TIMEOUT == error) { + //TODO: How do we handle timeouts? + secure_session_delete(sec); + } + else{ + sec->timer.timer = eventOS_timeout_ms(timer_cb, sec->timer.int_ms, (void*)sec); + } + } + else{ + /* We have counted the number of cycles - finish */ + eventOS_timeout_cancel(sec->timer.timer); + sec->timer.fin_ms = 0; + sec->timer.int_ms = 0; + sec->timer.timer = NULL; + sec->timer.state = TIMER_STATE_FIN_EXPIRY; + int error = coap_security_handler_continue_connecting(sec->sec_handler); + if(MBEDTLS_ERR_SSL_TIMEOUT == error) { + //TODO: How do we handle timeouts? + secure_session_delete(sec); + } + } + } +} + +static void start_timer(int8_t timer_id, uint32_t int_ms, uint32_t fin_ms) +{ + secure_session_t *sec = secure_session_find_by_timer_id(timer_id); + if( sec ){ + if ((int_ms > 0) && (fin_ms > 0)) { + sec->timer.int_ms = int_ms; + sec->timer.fin_ms = fin_ms; + sec->timer.state = TIMER_STATE_NO_EXPIRY; + if(sec->timer.timer){ + eventOS_timeout_cancel(sec->timer.timer); + } + sec->timer.timer = eventOS_timeout_ms(timer_cb, int_ms, sec); + } else if (fin_ms == 0) { + /* fin_ms == 0 means cancel the timer */ + sec->timer.state = TIMER_STATE_CANCELLED; + eventOS_timeout_cancel(sec->timer.timer); + sec->timer.fin_ms = 0; + sec->timer.int_ms = 0; + sec->timer.timer = NULL; + } + } +} + +static int timer_status(int8_t timer_id) +{ + secure_session_t *sec = secure_session_find_by_timer_id(timer_id); + if( sec ){ + return (int)sec->timer.state; + } + return TIMER_STATE_CANCELLED; +} + +static int read_data(socket_callback_t *sckt_data, internal_socket_t *sock, ns_address_t *src_address) +{ + sock->data_len = 0; + if (sckt_data->event_type == SOCKET_DATA && sckt_data->d_len > 0) { + if( sock->data ){ + ns_dyn_mem_free(sock->data); + sock->data = NULL; + } + sock->data = ns_dyn_mem_temporary_alloc(sckt_data->d_len); + if( !sock->data ){ + sock->data = NULL; + return -1; + } + sock->data_len = socket_read(sckt_data->socket_id, src_address, sock->data, sckt_data->d_len); + } + if( sock->data_len < 1){ + ns_dyn_mem_free(sock->data); + sock->data = NULL; + sock->data_len = 0; + return -1; + } + return 0; +} + +static void secure_recv_sckt_msg(void *cb_res) +{ + socket_callback_t *sckt_data = cb_res; + internal_socket_t *sock = int_socket_find_by_socket_id(sckt_data->socket_id); + ns_address_t src_address; + + if( sock && read_data(sckt_data, sock, &src_address) == 0 ){ + secure_session_t *session = secure_session_find(sock, src_address.address, src_address.identifier); + + // Create session + if( !session ){ + memcpy( sock->dest_addr.address, src_address.address, 16 ); + sock->dest_addr.identifier = src_address.identifier; + sock->dest_addr.type = src_address.type; + session = secure_session_create(sock, src_address.address, src_address.identifier); + } + if( !session ){ + tr_err("secure_recv_sckt_msg session creation failed - OOM"); + return; + } + session->last_contact_time = coap_service_get_internal_timer_ticks(); + // Start handshake + if( !session->sec_handler->_is_started ){ + uint8_t *pw = (uint8_t *)ns_dyn_mem_alloc(64); + uint8_t pw_len; + if( sock->parent->_get_password_cb && 0 == sock->parent->_get_password_cb(sock->listen_socket, src_address.address, src_address.identifier, pw, &pw_len)){ + //TODO: get_password_cb should support certs and PSK also + coap_security_keys_t keys; + keys._priv = pw; + keys._priv_len = pw_len; + coap_security_handler_connect_non_blocking(session->sec_handler, true, DTLS, keys, sock->timeout_min, sock->timeout_max); + //TODO: error handling + } + ns_dyn_mem_free(pw); + }else{ + //Continue handshake + if(session->session_state == SECURE_SESSION_HANDSHAKE_ONGOING){ + int ret = coap_security_handler_continue_connecting(session->sec_handler); + // Handshake done + if(ret == 0){ + eventOS_timeout_cancel(session->timer.timer); + session->timer.timer = NULL; + session->session_state = SECURE_SESSION_OK; + if( sock->parent->_security_done_cb ){ + sock->parent->_security_done_cb(sock->listen_socket, src_address.address, + src_address.identifier, + session->sec_handler->_keyblk.value); + } + } + else if (ret < 0){ + // error handling + // TODO: here we also should clear CoAP retransmission buffer and inform that CoAP request sending is failed. + secure_session_delete(session); + } + //Session valid + }else{ + unsigned char *data = ns_dyn_mem_temporary_alloc(sock->data_len); + int len = 0; + len = coap_security_handler_read(session->sec_handler, data, sock->data_len); + if( len < 0 ){ + ns_dyn_mem_free(data); + secure_session_delete( session ); + }else{ + if( sock->parent->_recv_cb ){ + sock->parent->_recv_cb(sock->listen_socket, src_address.address, src_address.identifier, data, len); + } + ns_dyn_mem_free(data); + } + } + } + } +} + +static void recv_sckt_msg(void *cb_res) +{ + socket_callback_t *sckt_data = cb_res; + internal_socket_t *sock = int_socket_find_by_socket_id(sckt_data->socket_id); + ns_address_t src_address; + if( sock && read_data(sckt_data, sock, &src_address) == 0 ){ + if(sock->parent && sock->parent->_recv_cb){ + sock->parent->_recv_cb(sock->listen_socket, src_address.address, src_address.identifier, sock->data, sock->data_len); + } + ns_dyn_mem_free(sock->data); + sock->data = NULL; + } +} + +int coap_connection_handler_virtual_recv(coap_conn_handler_t *handler, uint8_t address[static 16], uint16_t port, uint8_t *data_ptr, uint16_t data_len) +{ + if( !handler || !handler->socket ){ + return -1; + } + internal_socket_t *sock = handler->socket; + sock->data_len = data_len; + if( sock->data ){ + ns_dyn_mem_free(sock->data); + sock->data = NULL; + } + sock->data = ns_dyn_mem_temporary_alloc(data_len); + if( data_len > 0 && !sock->data ){ + return -1; + } + if( data_ptr ){ + memcpy(sock->data, data_ptr, data_len); + }else{ + if( sock->data ){ + ns_dyn_mem_free(sock->data); + sock->data = NULL; + } + } + + if( handler->socket->is_secure ){ + secure_session_t *session = secure_session_find(sock, address, port); + if( !session ){ + session = secure_session_create(sock, address, port); + } + if( !session ){ + tr_err("coap_connection_handler_virtual_recv session creation failed - OOM"); + return -1; + } + + session->last_contact_time = coap_service_get_internal_timer_ticks(); + + if( !session->sec_handler->_is_started ){ + uint8_t *pw = (uint8_t *)ns_dyn_mem_alloc(64); + uint8_t pw_len; + if( sock->parent->_get_password_cb && 0 == sock->parent->_get_password_cb(sock->listen_socket, address, port, pw, &pw_len)){ + //TODO: get_password_cb should support certs and PSK also + coap_security_keys_t keys; + keys._priv = pw; + keys._priv_len = pw_len; + coap_security_handler_connect_non_blocking(session->sec_handler, true, DTLS, keys, handler->socket->timeout_min, handler->socket->timeout_max); + //TODO: error handling + ns_dyn_mem_free(pw); + return 0; + }else{ + ns_dyn_mem_free(pw); + return -1; + } + }else{ + if(session->session_state == SECURE_SESSION_HANDSHAKE_ONGOING){ + int ret = coap_security_handler_continue_connecting(session->sec_handler); + if(ret == 0){ + session->session_state = SECURE_SESSION_OK; + if( handler->_security_done_cb ){ + handler->_security_done_cb(sock->listen_socket, + address, port, + session->sec_handler->_keyblk.value); + } + return 0; + } + else if(ret < 0) + { + // error handling + // TODO: here we also should clear CoAP retransmission buffer and inform that CoAP request sending is failed. + secure_session_delete(session); + } + //TODO: error handling + }else{ + unsigned char *data = ns_dyn_mem_temporary_alloc(sock->data_len); + int len = 0; + len = coap_security_handler_read(session->sec_handler, data, sock->data_len); + if( len < 0 ){ + ns_dyn_mem_free(data); + secure_session_delete( session ); + return 0; + }else{ + if( sock->parent->_recv_cb ){ + sock->parent->_recv_cb(sock->listen_socket, address, port, data, len); + } + ns_dyn_mem_free(data); + data = NULL; + } + return 0; + } + } + }else{ + if( sock->parent->_recv_cb ){ + sock->parent->_recv_cb(sock->listen_socket, address, port, sock->data, sock->data_len); + } + if( sock->data ){ + ns_dyn_mem_free(sock->data); + sock->data = NULL; + } + return 0; + } + return -1; +} + +coap_conn_handler_t *connection_handler_create(receive_from_socket_cb *recv_from_cb, + send_to_socket_cb *send_to_cb, + get_pw_cb *pw_cb, + security_done_cb *done_cb ) +{ + if( recv_from_cb == NULL ){ + return NULL; + } + + coap_conn_handler_t *handler = ns_dyn_mem_alloc(sizeof(coap_conn_handler_t)); + if(!handler){ + return NULL; + } + memset(handler, 0, sizeof(coap_conn_handler_t)); + handler->socket = NULL; + handler->_recv_cb = recv_from_cb; + handler->_send_cb = send_to_cb; + + handler->_get_password_cb = pw_cb; + handler->_security_done_cb = done_cb; + + return handler; +} +void connection_handler_destroy(coap_conn_handler_t *handler) +{ + if(handler){ + int_socket_delete(handler->socket); + ns_dyn_mem_free(handler); + } +} + +void connection_handler_close_secure_connection( coap_conn_handler_t *handler, uint8_t destination_addr_ptr[static 16], uint16_t port ) +{ + if(handler){ + if( handler->socket && handler->socket->is_secure){ + secure_session_t *session = secure_session_find( handler->socket, destination_addr_ptr, port); + if( session ){ + coap_security_send_close_alert( session->sec_handler ); + session->session_state = SECURE_SESSION_CLOSED; + session->last_contact_time = coap_service_get_internal_timer_ticks(); + } + } + } +} + +int coap_connection_handler_open_connection(coap_conn_handler_t *handler, uint16_t listen_port, bool use_ephemeral_port, bool is_secure, bool is_real_socket, bool bypassSec) +{ + if( !handler ){ + return -1; + } + //virtual socket must have send callback + if( !is_real_socket && !handler->_send_cb ){ + return -1; + } + if( handler->socket ){ + int_socket_delete(handler->socket); + } + + internal_socket_t *current = !use_ephemeral_port?int_socket_find(listen_port, is_secure, is_real_socket, bypassSec):NULL; + if(!current){ + handler->socket = int_socket_create(listen_port, use_ephemeral_port, is_secure, is_real_socket, bypassSec); + if(!handler->socket){ + return -1; + } + handler->socket->parent = ns_dyn_mem_alloc(sizeof(coap_conn_handler_t)); + if(!handler->socket->parent){ + int_socket_delete(handler->socket); + return -1; + } + *handler->socket->parent = *handler; + }else{ + current->usage_counter++; + handler->socket = current; + } + return 0; +} + +int coap_connection_handler_send_data(coap_conn_handler_t *handler, ns_address_t *dest_addr, uint8_t *data_ptr, uint16_t data_len, bool bypass_link_sec) +{ + if( !handler || !handler->socket || !dest_addr){ + return -1; + } + if(handler->socket->is_secure){ + handler->socket->bypass_link_sec = bypass_link_sec; + memcpy(handler->socket->dest_addr.address, dest_addr->address, 16); + handler->socket->dest_addr.identifier = dest_addr->identifier; + handler->socket->dest_addr.type = dest_addr->type; + secure_session_t *session = secure_session_find(handler->socket, dest_addr->address, dest_addr->identifier); + if( !session ){ + session = secure_session_create(handler->socket, dest_addr->address, dest_addr->identifier); + if( !session ){ + return -1; + } + session->last_contact_time = coap_service_get_internal_timer_ticks(); + memcpy( handler->socket->dest_addr.address, dest_addr->address, 16 ); + handler->socket->dest_addr.identifier = dest_addr->identifier; + handler->socket->dest_addr.type = dest_addr->type; + uint8_t *pw = (uint8_t *)ns_dyn_mem_alloc(64); + if(!pw){ + //todo: free secure session? + return -1; + } + uint8_t pw_len; + if( handler->_get_password_cb && 0 == handler->_get_password_cb(handler->socket->listen_socket, dest_addr->address, dest_addr->identifier, pw, &pw_len)){ + //TODO: get_password_cb should support certs and PSK also + coap_security_keys_t keys; + keys._priv = pw; + keys._priv_len = pw_len; + coap_security_handler_connect_non_blocking(session->sec_handler, false, DTLS, keys, handler->socket->timeout_min, handler->socket->timeout_max); + ns_dyn_mem_free(pw); + return -2; + }else{ + //free secure session? + ns_dyn_mem_free(pw); + return -1; + } + }else if( session->session_state == SECURE_SESSION_OK ){ + if( coap_security_handler_send_message(session->sec_handler, data_ptr, data_len ) > 0 ){ + session->last_contact_time = coap_service_get_internal_timer_ticks(); + return 0; + } + } + return -1; + }else{ + if( !handler->socket->real_socket && handler->_send_cb){ + return handler->_send_cb((int8_t)handler->socket->listen_socket, dest_addr->address, dest_addr->identifier, data_ptr, data_len); + } + int opt_name = SOCKET_IPV6_PREFER_SRC_6LOWPAN_SHORT; + int8_t securityLinkLayer = 1; + if( bypass_link_sec ){ + securityLinkLayer = 0; + } + socket_setsockopt(handler->socket->listen_socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_ADDR_PREFERENCES, &opt_name, sizeof(int)); + socket_setsockopt(handler->socket->listen_socket, SOCKET_IPPROTO_IPV6, SOCKET_LINK_LAYER_SECURITY, &securityLinkLayer, sizeof(int8_t)); + return socket_sendto(handler->socket->listen_socket, dest_addr, data_ptr, data_len); + } +} + +bool coap_connection_handler_socket_belongs_to(coap_conn_handler_t *handler, int8_t socket_id) +{ + if( !handler || !handler->socket){ + return false; + } + + if( handler->socket->listen_socket == socket_id){ + return true; + } + return false; +} + +int8_t coap_connection_handler_set_timeout(coap_conn_handler_t *handler, uint32_t min, uint32_t max) +{ + if(!handler || !handler->socket){ + return -1; + } + handler->socket->timeout_max = max; + handler->socket->timeout_min = min; + + return 0; +} + +/* No need to call every second - call rather like every minute (SECURE_SESSION_CLEAN_INTERVAL sets this) */ +void coap_connection_handler_exec(uint32_t time) +{ + if(ns_list_count(&secure_session_list)){ + // Seek & destroy old sessions where close notify have been sent + ns_list_foreach(secure_session_t, cur_ptr, &secure_session_list) { + if(cur_ptr->session_state == SECURE_SESSION_CLOSED || + cur_ptr->session_state == SECURE_SESSION_HANDSHAKE_ONGOING){ + if((cur_ptr->last_contact_time + CLOSED_SECURE_SESSION_TIMEOUT) <= time){ + secure_session_delete(cur_ptr); + } + } + if(cur_ptr->session_state == SECURE_SESSION_OK){ + if((cur_ptr->last_contact_time + OPEN_SECURE_SESSION_TIMEOUT) <= time){ + secure_session_delete(cur_ptr); + } + } + } + } +} diff --git a/features/FEATURE_CLIENT/coap-service/source/coap_message_handler.c b/features/FEATURE_CLIENT/coap-service/source/coap_message_handler.c new file mode 100644 index 0000000000..613547c8d2 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/source/coap_message_handler.c @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2015-2016 ARM Limited. All Rights Reserved. + */ + +#include +#include "nsdynmemLIB.h" +#include "coap_message_handler.h" +#include "sn_coap_protocol.h" +#include "ns_types.h" +#include "ns_list.h" +#include "ns_trace.h" +#include "randLIB.h" + +#define TRACE_GROUP "CoSA" + +static void *own_alloc(uint16_t size) +{ + if (size) { + return ns_dyn_mem_temporary_alloc(size); + } else { + return 0; + } +} + +static void own_free(void *ptr) +{ + if (ptr) { + ns_dyn_mem_free(ptr); + } +} + +static NS_LIST_DEFINE(request_list, coap_transaction_t, link); + +static coap_transaction_t *transaction_find_client_by_token(uint8_t token[4]) +{ + coap_transaction_t *this = NULL; + ns_list_foreach(coap_transaction_t, cur_ptr, &request_list) { + if (memcmp(cur_ptr->token,token,4) == 0 && cur_ptr->client_request) { + this = cur_ptr; + break; + } + } + return this; +} + +static coap_transaction_t *transaction_find_server(uint16_t msg_id) +{ + coap_transaction_t *this = NULL; + ns_list_foreach(coap_transaction_t, cur_ptr, &request_list) { + if (cur_ptr->msg_id == msg_id && !cur_ptr->client_request) { + this = cur_ptr; + break; + } + } + return this; +} + +static coap_transaction_t *transaction_find_by_address(uint8_t *address_ptr, uint16_t port) +{ + coap_transaction_t *this = NULL; + ns_list_foreach(coap_transaction_t, cur_ptr, &request_list) { + if (cur_ptr->remote_port == port && memcmp(cur_ptr->remote_address, address_ptr, 16) == 0) { + this = cur_ptr; + break; + } + } + return this; +} + +static coap_transaction_t *transaction_create(void) +{ + coap_transaction_t *this = ns_dyn_mem_alloc(sizeof(coap_transaction_t)); + if (this) { + memset(this, 0, sizeof(coap_transaction_t)); + this->client_request = true;// default to client initiated method + ns_list_add_to_start(&request_list, this); + } + + return this; +} +static void transaction_delete(coap_transaction_t *this) +{ + if (this) { + ns_list_remove(&request_list, this); + if(this->data_ptr){ + ns_dyn_mem_free(this->data_ptr); + } + ns_dyn_mem_free(this); + } + + return; +} + +static int8_t coap_rx_function(sn_coap_hdr_s *resp_ptr, sn_nsdl_addr_s *address_ptr, void *param) +{ + coap_transaction_t *this = NULL; + (void)address_ptr; + (void)param; + tr_warn("transaction was not handled"); + if (!resp_ptr) { + return -1; + } + if( resp_ptr->token_ptr ){ + this = transaction_find_client_by_token(resp_ptr->token_ptr); + } + if (this && this->resp_cb) { + this->resp_cb(this->service_id, address_ptr->addr_ptr, address_ptr->port, NULL); + } + transaction_delete(this); + return 0; +} + +static void coap_service_build_content_format(sn_coap_hdr_s *header, sn_coap_content_format_e format); + +coap_msg_handler_t *coap_message_handler_init(void *(*used_malloc_func_ptr)(uint16_t), void (*used_free_func_ptr)(void *), + uint8_t (*used_tx_callback_ptr)(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *)){ + + if ((used_malloc_func_ptr == NULL) || (used_free_func_ptr == NULL) || (used_tx_callback_ptr == NULL)) { + return NULL; + } + + coap_msg_handler_t *handle; + handle = used_malloc_func_ptr(sizeof(coap_msg_handler_t)); + if (handle == NULL) { + return NULL; + } + + memset(handle, 0, sizeof(coap_msg_handler_t)); + + handle->sn_coap_tx_callback = used_tx_callback_ptr; + + handle->sn_coap_service_free = used_free_func_ptr; + handle->sn_coap_service_malloc = used_malloc_func_ptr; + + handle->coap = sn_coap_protocol_init(used_malloc_func_ptr, used_free_func_ptr, used_tx_callback_ptr, &coap_rx_function); + if( !handle->coap ){ + used_free_func_ptr(handle); + return NULL; + } + return handle; +} + +int8_t coap_message_handler_destroy(coap_msg_handler_t *handle){ + if( !handle ){ + return -1; + } + + if( handle->coap ){ + sn_coap_protocol_destroy(handle->coap); + } + + //Destroy transactions + ns_list_foreach_safe(coap_transaction_t, cur_ptr, &request_list) { + ns_list_remove(&request_list, cur_ptr); + ns_dyn_mem_free(cur_ptr); + cur_ptr = NULL; + } + + handle->sn_coap_service_free(handle); + return 0; +} + +coap_transaction_t *coap_message_handler_transaction_valid(coap_transaction_t *tr_ptr) +{ + ns_list_foreach(coap_transaction_t, cur_ptr, &request_list) { + if (cur_ptr == tr_ptr) { + return tr_ptr; + } + } + return NULL; +} + +coap_transaction_t *coap_message_handler_find_transaction(uint8_t *address_ptr, uint16_t port) +{ + if( !address_ptr ) + return NULL; + return transaction_find_by_address( address_ptr, port ); +} + +int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t socket_id, uint8_t source_addr_ptr[static 16], uint16_t port, + uint8_t *data_ptr, uint16_t data_len, int16_t (cb)(int8_t, sn_coap_hdr_s *, coap_transaction_t *)) +{ + if( !cb || !handle ){ + return -1; + } + sn_nsdl_addr_s src_addr; + sn_coap_hdr_s *coap_message; + src_addr.addr_ptr = source_addr_ptr; + src_addr.addr_len = 16; + src_addr.type = SN_NSDL_ADDRESS_TYPE_IPV6; + src_addr.port = port; + + coap_message = sn_coap_protocol_parse(handle->coap, &src_addr, data_len, data_ptr, NULL); + if (coap_message == NULL) { + tr_err("CoAP Parsing failed"); + return -1; + } + tr_debug("CoAP status:%d, type:%d, code:%d, id:%d", coap_message->coap_status, coap_message->msg_type, coap_message->msg_code, coap_message->msg_id); + /* Check, if coap itself sends response, or block receiving is ongoing... */ + if (coap_message->coap_status != COAP_STATUS_OK && coap_message->coap_status != COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED) { + tr_debug("CoAP library responds"); + sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_message); + return -1; + } + if (coap_message->msg_code > 0 && coap_message->msg_code < 32) { + + //TODO Sorry + + coap_transaction_t *transaction_ptr = transaction_create(); + if (transaction_ptr) { + + transaction_ptr->msg_id = coap_message->msg_id; + transaction_ptr->client_request = false;// this is server transaction + memcpy(transaction_ptr->remote_address, source_addr_ptr, 16); + transaction_ptr->remote_port = port; + + int ret = cb(socket_id, coap_message, transaction_ptr); + if (ret != 0) { + tr_debug("Service %d, no response expected", transaction_ptr->service_id); + sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_message); + transaction_delete(transaction_ptr); + return -1; + } + }else{ + //TODO: handle error case + } + } else { + //response find by MSG id + coap_transaction_t *this = NULL; + if( coap_message->token_ptr ){ + this = transaction_find_client_by_token(coap_message->token_ptr); + } + if (!this) { + tr_error("client transaction not found"); + sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_message); + return -1; + } + tr_debug("Service %d, response received", this->service_id); + if (this->resp_cb) { + this->resp_cb(this->service_id, source_addr_ptr, port, coap_message); + } + sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_message); + transaction_delete(this); + } + return 0; + +} + +uint16_t coap_message_handler_request_send(coap_msg_handler_t *handle, int8_t service_id, uint8_t options, const uint8_t destination_addr[static 16], + uint16_t destination_port, sn_coap_msg_type_e msg_type, sn_coap_msg_code_e msg_code, const char *uri, + sn_coap_content_format_e cont_type, const uint8_t *payload_ptr, uint16_t payload_len, coap_message_handler_response_recv *request_response_cb) +{ + coap_transaction_t *transaction_ptr; + sn_coap_hdr_s request; + sn_nsdl_addr_s dst_addr; + uint8_t token[4]; + uint16_t data_len; + uint8_t *data_ptr; + + tr_debug("Service %d, send CoAP request payload_len %d", service_id, payload_len); + transaction_ptr = transaction_create(); + + if (!uri || !transaction_ptr) { + return 0; + } + + transaction_ptr->service_id = service_id; + transaction_ptr->client_request = true; + transaction_ptr->resp_cb = request_response_cb; + transaction_ptr->options = options; + memcpy(transaction_ptr->remote_address, destination_addr, 16); + transaction_ptr->remote_port = destination_port; + memset(&request, 0, sizeof(request)); + dst_addr.addr_ptr = (uint8_t *) destination_addr; // Cast away const and trust that nsdl doesn't modify... + dst_addr.addr_len = 16; + dst_addr.type = SN_NSDL_ADDRESS_TYPE_IPV6; + dst_addr.port = destination_port; + + request.msg_type = msg_type; + request.msg_code = msg_code; + request.uri_path_ptr = (uint8_t *)uri; + request.uri_path_len = strlen(uri); + coap_service_build_content_format(&request, cont_type); + + do{ + randLIB_get_n_bytes_random(token,4); + }while(transaction_find_client_by_token(token)); + memcpy(transaction_ptr->token,token,4); + request.token_ptr = transaction_ptr->token; + request.token_len = 4; + + request.payload_len = payload_len; + request.payload_ptr = (uint8_t *) payload_ptr; // Cast away const and trust that nsdl doesn't modify... + data_len = sn_coap_builder_calc_needed_packet_data_size(&request); + data_ptr = own_alloc(data_len); + if(data_len > 0 && !data_ptr){ + own_free(request.content_type_ptr); + transaction_delete(transaction_ptr); + return 0; + } + sn_coap_protocol_build(handle->coap, &dst_addr, data_ptr, &request, transaction_ptr); + transaction_ptr->msg_id = request.msg_id; + handle->sn_coap_tx_callback(data_ptr, data_len, &dst_addr, transaction_ptr); + + // Free allocated data + own_free(request.content_type_ptr); + own_free(data_ptr); + if(request_response_cb == NULL){ + //No response expected + return 0; + } + return transaction_ptr->msg_id; +} + +//TODO: refactor this to use nsdl +int8_t coap_message_handler_response_send(coap_msg_handler_t *handle, int8_t service_id, uint8_t options, sn_coap_hdr_s *request_ptr, sn_coap_msg_code_e message_code, sn_coap_content_format_e content_type, const uint8_t *payload_ptr, uint16_t payload_len) +{ + coap_transaction_t *transaction_ptr; + sn_coap_hdr_s *response; + sn_nsdl_addr_s dst_addr; + uint16_t data_len; + uint8_t *data_ptr; + (void) options; + (void)service_id; + + tr_debug("Service %d, send CoAP response", service_id); + if (!request_ptr || !handle) { + tr_error("invalid params"); + return -1; + } + + transaction_ptr = transaction_find_server(request_ptr->msg_id); + + if (!transaction_ptr) { + tr_error("response transaction not found"); + return -2; + } + dst_addr.addr_ptr = transaction_ptr->remote_address; + dst_addr.addr_len = 16; + dst_addr.type = SN_NSDL_ADDRESS_TYPE_IPV6; + dst_addr.port = transaction_ptr->remote_port; + + response = sn_coap_build_response(handle->coap, request_ptr, message_code); + if( !response ){ + return -1; + } + response->payload_len = payload_len; + response->payload_ptr = (uint8_t *) payload_ptr; // Cast away const and trust that nsdl doesn't modify... + coap_service_build_content_format(response, content_type); + + data_len = sn_coap_builder_calc_needed_packet_data_size(response); + data_ptr = own_alloc(data_len); + if (data_len > 0 && !data_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response); + //TODO deallocate stuff i quess + return -1; + } + sn_coap_protocol_build(handle->coap, &dst_addr, data_ptr, response, transaction_ptr); + sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response); + handle->sn_coap_tx_callback(data_ptr, data_len, &dst_addr, transaction_ptr); + sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, request_ptr); + transaction_delete(transaction_ptr); + own_free(data_ptr); + return 0; +} + +int8_t coap_message_handler_exec(coap_msg_handler_t *handle, uint32_t current_time){ + if( !handle ){ + return -1; + } + return sn_coap_protocol_exec(handle->coap, current_time); +} + +static void coap_service_build_content_format(sn_coap_hdr_s *header, sn_coap_content_format_e format) +{ + if (format == COAP_CT_NONE) { + return; + } + + /* Always alloc - CoAP library needs a non-NULL pointer to trigger writing + * of a zero-length option, and it will free the pointer later. + */ + header->content_type_ptr = own_alloc(2); + if (!header->content_type_ptr) { + return; + } + + if (format == 0) { /* text/plain */ + header->content_type_len = 0; + } else if (format <= 0xff) { + header->content_type_ptr[0] = format; + header->content_type_len = 1; + } else { + header->content_type_ptr[0] = format >> 8; + header->content_type_ptr[1] = format & 0xff; + header->content_type_len = 2; + } +} diff --git a/features/FEATURE_CLIENT/coap-service/source/coap_security_handler.c b/features/FEATURE_CLIENT/coap-service/source/coap_security_handler.c new file mode 100644 index 0000000000..b235bea406 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/source/coap_security_handler.c @@ -0,0 +1,579 @@ +/* + * Copyright (c) 2015-2016 ARM Limited. All Rights Reserved. + */ + +#include +#include +#include + +#include "mbedtls/sha256.h" +#include "mbedtls/error.h" +#include "mbedtls/platform.h" +#include "mbedtls/ssl_cookie.h" +#include "mbedtls/entropy_poll.h" +#include "mbedtls/ssl.h" +#include "ns_trace.h" +#include "nsdynmemLIB.h" +#include "coap_connection_handler.h" +#include "coap_security_handler.h" +#include "randLIB.h" +#include "mbedtls/ssl_ciphersuites.h" + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +const int ECJPAKE_SUITES[] = { + MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, + 0 +}; +#endif + +static const int PSK_SUITES[] = { + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, + MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, + 0 +}; + + +static void set_timer( void *sec_obj, uint32_t int_ms, uint32_t fin_ms ); +static int get_timer( void *sec_obj ); +static int coap_security_handler_configure_keys( coap_security_t *sec, coap_security_keys_t keys ); + +int entropy_poll( void *data, unsigned char *output, size_t len, size_t *olen ); +//Point these back to M2MConnectionHandler!!! +int f_send( void *ctx, const unsigned char *buf, size_t len ); +int f_recv(void *ctx, unsigned char *buf, size_t len); + +static int coap_security_handler_init(coap_security_t *sec){ + const char *pers = "dtls_client"; + mbedtls_ssl_init( &sec->_ssl ); + mbedtls_ssl_config_init( &sec->_conf ); + mbedtls_ctr_drbg_init( &sec->_ctr_drbg ); + mbedtls_entropy_init( &sec->_entropy ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_init( &sec->_cacert ); + mbedtls_x509_crt_init( &sec->_owncert ); +#endif + mbedtls_pk_init( &sec->_pkey ); + + memset(&sec->_cookie, 0, sizeof(simple_cookie_t)); + memset(&sec->_keyblk, 0, sizeof(key_block_t)); + + sec->_is_started = false; + + //TODO: Must have at least 1 strong entropy source, otherwise DTLS will fail. + //This is NOT strong even we say it is! + if( mbedtls_entropy_add_source( &sec->_entropy, entropy_poll, NULL, + 128, 1 ) < 0 ){ + return -1; + } + + if( ( mbedtls_ctr_drbg_seed( &sec->_ctr_drbg, mbedtls_entropy_func, &sec->_entropy, + (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + return -1; + } + return 0; +} + +static void coap_security_handler_reset(coap_security_t *sec){ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_free(&sec->_cacert); + mbedtls_x509_crt_free(&sec->_owncert); +#endif + + mbedtls_pk_free(&sec->_pkey); + + mbedtls_entropy_free( &sec->_entropy ); + mbedtls_ctr_drbg_free( &sec->_ctr_drbg ); + mbedtls_ssl_config_free(&sec->_conf); + mbedtls_ssl_free(&sec->_ssl); +} + + +coap_security_t *coap_security_create(int8_t socket_id, int8_t timer_id, uint8_t *address_ptr, uint16_t port, SecureConnectionMode mode, + send_cb *send_cb, + receive_cb *receive_cb, + start_timer_cb *start_timer_cb, + timer_status_cb *timer_status_cb) +{ + if( !address_ptr || send_cb == NULL || receive_cb == NULL || start_timer_cb == NULL || timer_status_cb == NULL){ + return NULL; + } + coap_security_t *this = ns_dyn_mem_alloc(sizeof(coap_security_t)); + if( !this ){ + return NULL; + } + memset(this, 0, sizeof(coap_security_t)); + if( -1 == coap_security_handler_init(this) ){ + ns_dyn_mem_free(this); + return NULL; + } + this->_remote_port = port; + memcpy(this->_remote_address, address_ptr, 16); + this->_conn_mode = mode; + memset(this->_pw, 0, 64); + this->_pw_len = 0; + this->_socket_id = socket_id; + this->_timer_id = timer_id; + this->_send_cb = send_cb; + this->_receive_cb = receive_cb; + this->_start_timer_cb = start_timer_cb; + this->_timer_status_cb = timer_status_cb; + + return this; +} + +void coap_security_destroy(coap_security_t *sec){ + if( sec ){ + coap_security_handler_reset(sec); + ns_dyn_mem_free(sec); + sec = NULL; + } +} + +/**** Random number functions ****/ + +/** + * Get a random array of bytes. + * Called back by mbedtls when it wants to fill a buffer with random data + * Must return 0 on success. + */ +static int get_random(void *ctx, unsigned char *buf, size_t len) +{ + static int initialised = 0; + uint32_t i; + + (void)ctx; /* No context */ + + if (!initialised) { + randLIB_seed_random(); + initialised = 1; + } + + for (i = 0; i < len; i++) { + buf[i] = (uint8_t)randLIB_get_8bit(); + } + return 0; /* Success */ +} + +/**** Cookie functions ****/ +static int simple_cookie_write(void *ctx, + unsigned char **p, unsigned char *end, + const unsigned char *info, size_t ilen) +{ + //TODO: As per RFC 6347 cookie must be stateless. This is not the case in here! + //This should be fixed if we see that dos attack would be an issue. + //this is proposed solution in RFC: Cookie = HMAC(Secret, Client-IP, Client-Parameters) + //Secret is generated here and oftenly changed to prevent statistical attack + simple_cookie_t *p_cookie = (simple_cookie_t *)ctx; + + /* Not using additional info */ + (void)info; + (void)ilen; + + if ((size_t)(end - *p) < COOKIE_SIMPLE_LEN) { + return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + } + + /* Use a simple random number of length COOKIE_SIMPLE_LEN bytes */ + get_random(NULL, p_cookie->value, COOKIE_SIMPLE_LEN); + memcpy(*p, p_cookie->value, COOKIE_SIMPLE_LEN); + p_cookie->len = COOKIE_SIMPLE_LEN; + *p += COOKIE_SIMPLE_LEN; + return 0; +} + +static int simple_cookie_check(void *ctx, + const unsigned char *cookie, size_t clen, + const unsigned char *info, size_t ilen) +{ + simple_cookie_t *p_cookie = (simple_cookie_t *)ctx; + + /* Not using additional info */ + (void)info; + (void)ilen; + + if ((p_cookie->len == 0) || + (clen != p_cookie->len) || + (memcmp(cookie, p_cookie->value, p_cookie->len) != 0)) { + return -1; /* This is what it is in mbedtls... */ + } + return 0; +} + +/**** Key export function ****/ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int export_key_block(void *ctx, + const unsigned char *mk, const unsigned char *kb, + size_t maclen, size_t keylen, size_t ivlen) +{ + key_block_t *p_key_block = (key_block_t *)ctx; + + /* Not using master key */ + (void)mk; + + /* Sanity check MAC and key lengths */ + if ((maclen != 0) || (((2 * keylen) + (2 * ivlen)) != KEY_BLOCK_LEN)) { + return -1; /* Something seriously wrong! */ + } + + /* Copy the key block we are using */ + /* No need to skip over MAC keys, MAC len must be 0 if we are here */ + memcpy(p_key_block->value, kb /* + (2 * maclen)*/, (2 * keylen) + (2 * ivlen)); + return 0; +} +#endif + +int coap_security_handler_configure_keys( coap_security_t *sec, coap_security_keys_t keys ) +{ + int ret = -1; + switch( sec->_conn_mode ){ + case Certificate:{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( mbedtls_x509_crt_parse( &sec->_cacert, keys._server_cert, + keys._server_cert_len ) < 0 ){ + break; + } + if( mbedtls_x509_crt_parse( &sec->_owncert, keys._pub_cert_or_identifier, + keys._pub_len ) < 0 ){ + break; + } + if( mbedtls_pk_parse_key(&sec->_pkey, keys._priv, keys._priv_len, NULL, 0) < 0){ + break; + } + //TODO: If needed in server mode, this won't work + if( 0 != mbedtls_ssl_conf_own_cert(&sec->_conf, &sec->_owncert, &sec->_pkey) ){ + break; + } + //TODO: use MBEDTLS_SSL_VERIFY_REQUIRED instead of optional + mbedtls_ssl_conf_authmode( &sec->_conf, MBEDTLS_SSL_VERIFY_OPTIONAL ); + mbedtls_ssl_conf_ca_chain( &sec->_conf, &sec->_cacert, NULL ); + ret = 0; +#endif + break; + } + case PSK: { +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( 0 != mbedtls_ssl_conf_psk(&sec->_conf, keys._priv, keys._priv_len, keys._pub_cert_or_identifier, keys._pub_len) ){ + break; + } + mbedtls_ssl_conf_ciphersuites(&sec->_conf, PSK_SUITES); + ret = 0; +#endif + break; + } + case ECJPAKE: { +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( mbedtls_ssl_set_hs_ecjpake_password(&sec->_ssl, keys._priv, keys._priv_len) != 0 ){ + return -1; + } + mbedtls_ssl_conf_ciphersuites(&sec->_conf, ECJPAKE_SUITES); + + //NOTE: If thread starts supporting PSK in other modes, then this will be needed! + mbedtls_ssl_conf_export_keys_cb(&sec->_conf, + export_key_block, + &sec->_keyblk); + ret = 0; +#endif + break; + } + + default: + break; + } + return ret; +} + +int coap_security_handler_connect(coap_security_t *sec, bool is_server, SecureSocketMode sock_mode, coap_security_keys_t keys){ + int ret = -1; + + if( !sec ){ + return ret; + } + sec->_is_blocking = true; + + int endpoint = MBEDTLS_SSL_IS_CLIENT; + if( is_server ){ + endpoint = MBEDTLS_SSL_IS_SERVER; + } + + int mode = MBEDTLS_SSL_TRANSPORT_DATAGRAM; + if( sock_mode == TLS ){ + mode = MBEDTLS_SSL_TRANSPORT_STREAM; + } + + if( ( mbedtls_ssl_config_defaults( &sec->_conf, + endpoint, + mode, 0 ) ) != 0 ) + { + return -1; + } + + mbedtls_ssl_set_bio( &sec->_ssl, sec, + f_send, f_recv, NULL ); + + mbedtls_ssl_set_timer_cb( &sec->_ssl, sec, set_timer, + get_timer ); + + if( coap_security_handler_configure_keys( sec, keys ) != 0 ){ + return -1; + } + + //TODO: Only needed for server type? + mbedtls_ssl_conf_dtls_cookies(&sec->_conf, simple_cookie_write, + simple_cookie_check, + &sec->_cookie); + + sec->_is_started = true; + + do { + ret = mbedtls_ssl_handshake_step( &sec->_ssl ); + if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ){ //cookie check failed + if( is_server ){ + mbedtls_ssl_session_reset(&sec->_ssl); +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( mbedtls_ssl_set_hs_ecjpake_password(&sec->_ssl, keys._priv, keys._priv_len) != 0 ){ + return -1; + } +#endif + ret = MBEDTLS_ERR_SSL_WANT_READ; //needed to keep doing + }else{ + ret = -1; + } + } + }while( ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + + if( ret != 0){ + ret = -1; + }else{ + if( mbedtls_ssl_get_verify_result( &sec->_ssl ) != 0 ) + { + ret = -1; + } + } + + return ret; +} + +int coap_security_handler_connect_non_blocking(coap_security_t *sec, bool is_server, SecureSocketMode sock_mode, coap_security_keys_t keys, uint32_t timeout_min, uint32_t timeout_max) +{ + + if( !sec ){ + return -1; + } + sec->_is_blocking = false; + + int endpoint = MBEDTLS_SSL_IS_CLIENT; + if( is_server ){ + endpoint = MBEDTLS_SSL_IS_SERVER; + } + + int mode = MBEDTLS_SSL_TRANSPORT_DATAGRAM; + if( sock_mode == TLS ){ + mode = MBEDTLS_SSL_TRANSPORT_STREAM; + } + + if( ( mbedtls_ssl_config_defaults( &sec->_conf, + endpoint, + mode, 0 ) ) != 0 ) + { + return -1; + } + + if(!timeout_max && !timeout_min){ + mbedtls_ssl_conf_handshake_timeout( &sec->_conf, DTLS_HANDSHAKE_TIMEOUT_MIN, DTLS_HANDSHAKE_TIMEOUT_MAX ); + } + else{ + mbedtls_ssl_conf_handshake_timeout( &sec->_conf, timeout_min, timeout_max ); + } + + mbedtls_ssl_conf_rng( &sec->_conf, mbedtls_ctr_drbg_random, &sec->_ctr_drbg ); + + if( ( mbedtls_ssl_setup( &sec->_ssl, &sec->_conf ) ) != 0 ) + { + return -1; + } + + mbedtls_ssl_set_bio( &sec->_ssl, sec, + f_send, f_recv, NULL ); + + mbedtls_ssl_set_timer_cb( &sec->_ssl, sec, set_timer, + get_timer ); + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + //TODO: Figure out better way!!! + //Password should never be stored in multiple places!!! + if( is_server && keys._priv_len > 0){ + memcpy(sec->_pw, keys._priv, keys._priv_len); + sec->_pw_len = keys._priv_len; + } +#endif + + if( coap_security_handler_configure_keys( sec, keys ) != 0 ){ + return -1; + } + + //Only needed for server type? + mbedtls_ssl_conf_dtls_cookies(&sec->_conf, simple_cookie_write, + simple_cookie_check, + &sec->_cookie); + + mbedtls_ssl_conf_min_version(&sec->_conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MAJOR_VERSION_3); + mbedtls_ssl_conf_max_version(&sec->_conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MAJOR_VERSION_3); + + sec->_is_started = true; + + int ret = mbedtls_ssl_handshake_step( &sec->_ssl ); + if( ret == 0 ){ + ret = mbedtls_ssl_handshake_step( &sec->_ssl ); + if( is_server && 0 == ret){ + ret = coap_security_handler_continue_connecting( sec ); + } + } + + if( ret >= 0){ + ret = 1; + }else{ + ret = -1; + } + return ret; +} + +int coap_security_handler_continue_connecting(coap_security_t *sec){ + int ret = -1; + + while( ret != MBEDTLS_ERR_SSL_WANT_READ ){ + ret = mbedtls_ssl_handshake_step( &sec->_ssl ); + + if( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED == ret){ + mbedtls_ssl_session_reset(&sec->_ssl); +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( mbedtls_ssl_set_hs_ecjpake_password(&sec->_ssl, sec->_pw, sec->_pw_len) != 0 ){ + return -1; + } +#endif + return 1; + } + else if(ret && (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)){ + return ret; + } + + if( sec->_ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER ){ + return 0; + } + } + + if(ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE){ + return 1; + } + + return -1; +} + + +int coap_security_handler_send_message(coap_security_t *sec, unsigned char *message, size_t len){ + int ret=-1; + + if( sec ){ + do ret = mbedtls_ssl_write( &sec->_ssl, (unsigned char *) message, len ); + while( ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + } + + return ret; //bytes written +} + +int coap_security_send_close_alert(coap_security_t *sec) +{ + if( !sec ){ + return -1; + } + + if(!mbedtls_ssl_close_notify(&sec->_ssl)){ + return 0; + } + return -1; +} + +int coap_security_handler_read(coap_security_t *sec, unsigned char* buffer, size_t len){ + int ret=-1; + int max_loops = 100; + + if( sec && buffer ){ + memset( buffer, 0, len ); + do { + ret = mbedtls_ssl_read( &sec->_ssl, buffer, len ); + } while( (ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE) + && --max_loops); + } + return ret; //bytes read +} + +/**** Timer functions ****/ + +/** + * Set timer function. + * Called back by mbedtls when it wants to set a timer. + * Accepts an intermediate and a final delay in milliseconds + * If the final delay is 0, cancels the running timer. + * TODO - might be better to use an event timer in conjunction with + * CoAP tasklet + */ +static void set_timer(void *sec_obj, uint32_t int_ms, uint32_t fin_ms) +{ + coap_security_t *sec = (coap_security_t *)sec_obj; + if( sec->_start_timer_cb ){ + sec->_start_timer_cb( sec->_timer_id, int_ms, fin_ms); + } +} + +/** + * Get timer function. + * Called back by mbedtls when it wants to get a timer state. + * Returns the state of the current timer + * TODO - might be better to use an event timer in conjunction with + * CoAP tasklet + */ +static int get_timer(void *sec_obj) +{ + coap_security_t *sec = (coap_security_t *)sec_obj; + if( sec->_timer_status_cb ){ + return sec->_timer_status_cb(sec->_timer_id); + } + return -1; +} + +int f_send( void *ctx, const unsigned char *buf, size_t len){ + coap_security_t *sec = (coap_security_t *)ctx; + return sec->_send_cb(sec->_socket_id, sec->_remote_address, sec->_remote_port, buf, len); +} + +int f_recv(void *ctx, unsigned char *buf, size_t len){ + coap_security_t *sec = (coap_security_t *)ctx; + return sec->_receive_cb(sec->_socket_id, buf, len); +} + +int entropy_poll( void *ctx, unsigned char *output, size_t len, + size_t *olen ) +{ + (void)ctx; + //TODO: change to more secure random + randLIB_seed_random(); + char *c = (char*)ns_dyn_mem_temporary_alloc(len); + if( !c ){ + return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + } + memset(c, 0, len); + for(uint16_t i=0; i < len; i++){ + *(c + i) = (char)randLIB_get_8bit(); + } + memmove(output, c, len); + *olen = len; + + ns_dyn_mem_free(c); + return( 0 ); +} diff --git a/features/FEATURE_CLIENT/coap-service/source/coap_service_api.c b/features/FEATURE_CLIENT/coap-service/source/coap_service_api.c new file mode 100644 index 0000000000..ed5063ac4e --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/source/coap_service_api.c @@ -0,0 +1,473 @@ +/* + * Copyright (c) 2015-2016 ARM Limited. All Rights Reserved. + */ + + + +#include + +#include "ns_types.h" +#include "ns_list.h" +#include "ns_trace.h" +#include "nsdynmemLIB.h" +#include "sn_nsdl.h" +#include "sn_coap_header.h" +#include "coap_service_api.h" +#include "coap_message_handler.h" +#include "eventOS_event.h" +#include "eventOS_scheduler.h" +#include "eventOS_event_timer.h" +#include "common_functions.h" +#include "coap_connection_handler.h" +#include "net_interface.h" +#include "coap_service_api_internal.h" + +static int16_t coap_service_coap_msg_process(int8_t socket_id, uint8_t source_addr_ptr[static 16], uint16_t port, uint8_t *data_ptr, uint16_t data_len); +static int16_t coap_msg_process_callback(int8_t socket_id, sn_coap_hdr_s *coap_message, coap_transaction_t *transaction_ptr); + +typedef struct uri_registration { + char *uri_ptr; + uint16_t uri_len; + uint8_t allowed_method; + coap_service_request_recv_cb *request_recv_cb; + ns_list_link_t link; +} uri_registration_t; + +typedef NS_LIST_HEAD(uri_registration_t, link) uri_registration_list_t; + +typedef struct coap_service { + coap_service_security_done_cb *coap_security_done_cb; + coap_service_security_start_cb *security_start_cb; + coap_service_virtual_socket_send_cb *virtual_socket_send_cb; + uri_registration_list_t uri_list; + coap_conn_handler_t *conn_handler; + int8_t interface_id; + int8_t service_id; + int8_t listen_socket; + uint8_t service_options; + ns_list_link_t link; +} coap_service_t; + +#define TRACE_GROUP "ThSA" + +static NS_LIST_DEFINE(instance_list, coap_service_t, link); +static int8_t tasklet_id = -1; +coap_msg_handler_t *coap_service_handle = NULL; +static uint32_t coap_ticks = 1; + +#define COAP_TICK_TIMER 0xf1 + +static uri_registration_t *uri_registration_find(coap_service_t *this, const void *uri_ptr, uint16_t uri_len) +{ + ns_list_foreach(uri_registration_t, cur_ptr, &this->uri_list) { + if (cur_ptr->uri_len == uri_len && memcmp(cur_ptr->uri_ptr, uri_ptr, uri_len) == 0) { + return cur_ptr; + } + } + return NULL; +} +static coap_service_t *service_find(int8_t service_id) +{ + coap_service_t *this = NULL; + ns_list_foreach(coap_service_t, cur_ptr, &instance_list) { + if (cur_ptr->service_id == service_id) { + this = cur_ptr; + break; + } + } + return this; +} + +static coap_service_t *service_find_by_socket(int8_t socket_id) +{ + coap_service_t *this = NULL; + ns_list_foreach(coap_service_t, cur_ptr, &instance_list) { + if( coap_connection_handler_socket_belongs_to(cur_ptr->conn_handler, socket_id) ){ + this = cur_ptr; + break; + } + } + return this; +} + +static coap_service_t *service_find_by_uri(uint8_t socket_id, uint8_t *uri_ptr, uint16_t uri_len) +{ + ns_list_foreach(coap_service_t, cur_ptr, &instance_list) { + if (coap_connection_handler_socket_belongs_to(cur_ptr->conn_handler, socket_id) && uri_registration_find(cur_ptr, uri_ptr, uri_len)) { + return cur_ptr; + } + } + return NULL; +} + + +/** + * Coap handling functions + */ +static void *own_alloc(uint16_t size) +{ + if (size) { + return ns_dyn_mem_temporary_alloc(size); + } else { + return 0; + } +} + +static void own_free(void *ptr) +{ + if (ptr) { + ns_dyn_mem_free(ptr); + } +} + +static uint8_t coap_tx_function(uint8_t *data_ptr, uint16_t data_len, sn_nsdl_addr_s *address_ptr, void *param) +{ + coap_service_t *this; + coap_transaction_t *transaction_ptr = coap_message_handler_transaction_valid(param); + ns_address_t dest_addr; + + if (!transaction_ptr || !data_ptr) { + return -1; + } + + tr_debug("Service %d, CoAP TX Function", transaction_ptr->service_id); + + this = service_find(transaction_ptr->service_id); + if (!this) { + return -1; + } + + memcpy(&(dest_addr.address), address_ptr->addr_ptr, 16); + dest_addr.identifier = address_ptr->port; + dest_addr.type = ADDRESS_IPV6; + + if( -2 == coap_connection_handler_send_data(this->conn_handler, &dest_addr, data_ptr, data_len, (this->service_options & COAP_SERVICE_OPTIONS_SECURE_BYPASS) == COAP_SERVICE_OPTIONS_SECURE_BYPASS) ){ + transaction_ptr->data_ptr = ns_dyn_mem_alloc(data_len); + if (!transaction_ptr->data_ptr) { + tr_debug("coap tx out of memory"); + return 0; + + } + memcpy(transaction_ptr->data_ptr, data_ptr, data_len); + transaction_ptr->data_len = data_len; + } + + return 0; +} + +static void service_event_handler(arm_event_s *event) +{ + if (event->event_type == ARM_LIB_TASKLET_INIT_EVENT) { + tr_debug("service tasklet initialised"); + /*initialize coap service and listen socket*/ + } + if (event->event_type == ARM_LIB_SYSTEM_TIMER_EVENT && event->event_id == COAP_TICK_TIMER) { + coap_message_handler_exec(coap_service_handle, coap_ticks++); + if(coap_ticks && !coap_ticks % SECURE_SESSION_CLEAN_INTERVAL){ + coap_connection_handler_exec(coap_ticks); + } + } + eventOS_event_timer_request((uint8_t)COAP_TICK_TIMER, ARM_LIB_SYSTEM_TIMER_EVENT, tasklet_id, 1000); +} + +static int16_t coap_msg_process_callback(int8_t socket_id, sn_coap_hdr_s *coap_message, coap_transaction_t *transaction_ptr) +{ + coap_service_t *this; + if( !coap_message ){ + return -1; + } + // Message is request find correct handle + this = service_find_by_uri(socket_id, coap_message->uri_path_ptr, coap_message->uri_path_len); + if (!this) { + tr_warn("not registered uri %.*s", coap_message->uri_path_len, coap_message->uri_path_ptr); + return -1; + } + + uri_registration_t *uri_reg_ptr = uri_registration_find(this, coap_message->uri_path_ptr, coap_message->uri_path_len); + if (transaction_ptr && uri_reg_ptr && uri_reg_ptr->request_recv_cb) { + tr_debug("Service %d, call request recv cb uri %.*s", this->service_id, coap_message->uri_path_len, coap_message->uri_path_ptr); + + if ((this->service_options & COAP_SERVICE_OPTIONS_SECURE_BYPASS) == COAP_SERVICE_OPTIONS_SECURE_BYPASS ) {//TODO Add secure bypass option + // Service has secure bypass active TODO this is not defined in interface + // this check can be removed I think + transaction_ptr->options = COAP_REQUEST_OPTIONS_SECURE_BYPASS; + } + transaction_ptr->service_id = this->service_id; + return uri_reg_ptr->request_recv_cb(this->service_id, transaction_ptr->remote_address, transaction_ptr->remote_port, coap_message); + } + return -1; +} + +static int16_t coap_service_coap_msg_process(int8_t socket_id, uint8_t source_addr_ptr[static 16], uint16_t port, uint8_t *data_ptr, uint16_t data_len) +{ + return coap_message_handler_coap_msg_process( coap_service_handle, socket_id, source_addr_ptr, port, data_ptr, data_len, &coap_msg_process_callback); +} + +static int recv_cb(int8_t socket_id, uint8_t address[static 16], uint16_t port, unsigned char *data, int len) +{ + uint8_t *data_ptr = NULL; + uint16_t data_len = 0; + + data_ptr = own_alloc(len); + + if (!data_ptr || len < 1) { + return -1; + } + memcpy(data_ptr, data, len); + data_len = len; + tr_debug("service recv socket data len %d ", data_len); + + //parse coap message what CoAP to use + int ret = coap_service_coap_msg_process(socket_id, address, port, data_ptr, data_len); + own_free(data_ptr); + return ret; +} + +static int send_cb(int8_t socket_id, uint8_t address[static 16], uint16_t port, const unsigned char *data_ptr, int data_len) +{ + coap_service_t *this = service_find_by_socket(socket_id); + if (this && this->virtual_socket_send_cb) { + tr_debug("send to virtual socket"); + return this->virtual_socket_send_cb(this->service_id, address, port, data_ptr, data_len); + } + return -1; +} + +//static void sec_conn_closed_cb(int8_t socket_id) +//{ +// coap_service_t *this = service_find_by_socket(socket_id); + +// tr_debug("Secure socket was closed by end device"); +//} + +static void sec_done_cb(int8_t socket_id, uint8_t address[static 16], uint16_t port, uint8_t keyblock[static 40]) +{ + //TODO: this is not enough if shared socket. Inform all! + coap_service_t *this = service_find_by_socket(socket_id); + if (this && this->coap_security_done_cb) { // secure done callback + this->coap_security_done_cb(this->service_id, address, keyblock); + } + + //TODO refactor this away. There should be no transaction_ptr(s) before done_cb has been called + //TODO: send all unsend transactions if more than 1 + coap_transaction_t *transaction_ptr = coap_message_handler_find_transaction(address, port); + if (transaction_ptr && transaction_ptr->data_ptr) { + tr_debug("send delayed packet"); + ns_address_t dest_addr; + memcpy(dest_addr.address, address, 16); + dest_addr.identifier = port; + dest_addr.type = ADDRESS_IPV6; + + coap_connection_handler_send_data(this->conn_handler, &dest_addr, transaction_ptr->data_ptr, transaction_ptr->data_len, (this->service_options & COAP_SERVICE_OPTIONS_SECURE_BYPASS) == COAP_SERVICE_OPTIONS_SECURE_BYPASS); + ns_dyn_mem_free(transaction_ptr->data_ptr); + transaction_ptr->data_ptr = NULL; + transaction_ptr->data_len = 0; + //TODO: who deletes transaction incase no response is required + } +} + +static int get_passwd_cb(int8_t socket_id, uint8_t address[static 16], uint16_t port, uint8_t *pw_ptr, uint8_t *pw_len) +{ + coap_service_t *this = service_find_by_socket(socket_id); + if (this && this->security_start_cb) { + return this->security_start_cb(this->service_id, address, port, pw_ptr, pw_len); + } + return -1; +} + +int8_t coap_service_initialize(int8_t interface_id, uint16_t listen_port, uint8_t service_options, + coap_service_security_start_cb *start_ptr, coap_service_security_done_cb *coap_security_done_cb) +{ + (void) interface_id; + + coap_service_t *this = ns_dyn_mem_alloc(sizeof(coap_service_t)); + if (!this) { + return -1; + } + memset(this, 0, sizeof(coap_service_t)); + tr_debug("service init interface %d, port %d, options %d", interface_id, listen_port, service_options); + + int8_t id = 1;// get unique id + while (service_find(id) && id < 127) { + id++; + } + this->service_id = id; + this->service_options = service_options; + + this->security_start_cb = start_ptr; + this->coap_security_done_cb = coap_security_done_cb; + + if (tasklet_id == -1) { + tr_debug("service tasklet init"); + tasklet_id = eventOS_event_handler_create(&service_event_handler, ARM_LIB_TASKLET_INIT_EVENT); + } + + this->conn_handler = connection_handler_create(recv_cb, send_cb, get_passwd_cb, sec_done_cb); + if(!this->conn_handler){ + ns_dyn_mem_free(this); + return -1; + } + + if (0 > coap_connection_handler_open_connection(this->conn_handler, listen_port, ((this->service_options & COAP_SERVICE_OPTIONS_EPHEMERAL_PORT) == COAP_SERVICE_OPTIONS_EPHEMERAL_PORT), + ((this->service_options & COAP_SERVICE_OPTIONS_SECURE) == COAP_SERVICE_OPTIONS_SECURE), + ((this->service_options & COAP_SERVICE_OPTIONS_VIRTUAL_SOCKET) != COAP_SERVICE_OPTIONS_VIRTUAL_SOCKET), + ((this->service_options & COAP_SERVICE_OPTIONS_SECURE_BYPASS) == COAP_SERVICE_OPTIONS_SECURE_BYPASS))){ + ns_dyn_mem_free(this->conn_handler); + ns_dyn_mem_free(this); + return -1; + } + + if (!coap_service_handle) { + coap_service_handle = coap_message_handler_init(&own_alloc, &own_free, &coap_tx_function); + } + if (!coap_service_handle) { + tr_error("coap service alloc failed"); + //TODO proper handling + } + + ns_list_add_to_start(&instance_list, this); + + return id; +} + +void coap_service_delete(int8_t service_id) +{ + coap_service_t *this = service_find(service_id); + if (!this) { + return; + } + + if (this->conn_handler){ + connection_handler_destroy(this->conn_handler); + } + + //TODO clear all transactions + ns_list_foreach_safe(uri_registration_t, cur_ptr, &this->uri_list) { + ns_dyn_mem_free(cur_ptr->uri_ptr); + ns_list_remove(&this->uri_list, cur_ptr); + ns_dyn_mem_free(cur_ptr); + } + + ns_list_remove(&instance_list, this); + ns_dyn_mem_free(this); + return; +} + +extern void coap_service_close_secure_connection(int8_t service_id, uint8_t destination_addr_ptr[static 16], uint16_t port) +{ + coap_service_t *this = service_find(service_id); + if (!this || !destination_addr_ptr) { + return; + } + if (this->conn_handler){ + connection_handler_close_secure_connection(this->conn_handler, destination_addr_ptr, port); + } +} + +int16_t coap_service_virtual_socket_recv(int8_t service_id, uint8_t source_addr_ptr[static 16], uint16_t port, uint8_t *data_ptr, uint16_t data_len) +{ + coap_service_t *this = service_find(service_id); + tr_debug("Service %d, virtual socket received", service_id); + if (!this) { + return -1; + } + return coap_connection_handler_virtual_recv(this->conn_handler, source_addr_ptr, port, data_ptr, data_len); +} + +int16_t coap_service_virtual_socket_set_cb(int8_t service_id, coap_service_virtual_socket_send_cb *send_method_ptr) +{ + coap_service_t *this = service_find(service_id); + tr_debug("register virtual socket cb"); + if (!this) { + return -1; + } + this->virtual_socket_send_cb = send_method_ptr; + return 0; +} + +int8_t coap_service_register_uri(int8_t service_id, const char *uri, uint8_t allowed_method, coap_service_request_recv_cb *request_recv_cb) +{ + coap_service_t *this = service_find(service_id); + uri_registration_t *uri_reg_ptr; + char *uri_ptr = NULL; + uint16_t uri_len; + tr_debug("Service %d, Uri registration uri: %s", service_id, uri); + if (!this || !uri) { + return -1; + } + uri_len = strlen(uri); + + uri_reg_ptr = uri_registration_find(this, uri, uri_len); + if (!uri_reg_ptr) { + uri_reg_ptr = ns_dyn_mem_alloc(sizeof(uri_registration_t)); + if( !uri_reg_ptr ){ + tr_error("Uri registration failed, OOM"); + return -2; + } + uri_reg_ptr->uri_ptr = NULL; + } else { + ns_dyn_mem_free(uri_reg_ptr->uri_ptr); + ns_list_remove(&this->uri_list, uri_reg_ptr); + } + + uri_ptr = ns_dyn_mem_alloc(uri_len); + if (!uri_ptr) { + ns_dyn_mem_free(uri_reg_ptr); + tr_error("Uri registration failed, OOM"); + return -2; + } + + uri_reg_ptr->uri_ptr = memcpy(uri_ptr, uri, uri_len); + uri_reg_ptr->uri_len = uri_len; + uri_reg_ptr->request_recv_cb = request_recv_cb; + uri_reg_ptr->allowed_method = allowed_method; + ns_list_add_to_start(&this->uri_list, uri_reg_ptr); + return 0; +} + +int8_t coap_service_unregister_uri(int8_t service_id, const char *uri) +{ + coap_service_t *this = service_find(service_id); + uri_registration_t *uri_reg_ptr; + tr_debug("Service %d, Uri unregistration uri: %s", service_id, uri); + if (!this || !uri) { + return -1; + } + + uri_reg_ptr = uri_registration_find(this, uri, strlen(uri)); + if (!uri_reg_ptr) { + return -2; + } + + ns_dyn_mem_free(uri_reg_ptr->uri_ptr); + ns_list_remove(&this->uri_list, uri_reg_ptr); + ns_dyn_mem_free(uri_reg_ptr); + + return 0; +} + +uint16_t coap_service_request_send(int8_t service_id, uint8_t options, const uint8_t destination_addr[static 16], uint16_t destination_port, sn_coap_msg_type_e msg_type, sn_coap_msg_code_e msg_code, const char *uri, + sn_coap_content_format_e cont_type, const uint8_t *payload_ptr, uint16_t payload_len, coap_service_response_recv *request_response_cb){ + //TODO: coap_service_response_recv is an ugly cast, this should be refactored away + sn_coap_hdr_s MUST NOT be exposed to users of coap-service! + //Callback would be still needed, but where to store callback? + return coap_message_handler_request_send(coap_service_handle, service_id, options, destination_addr, destination_port, msg_type, msg_code, uri, cont_type, payload_ptr, payload_len, request_response_cb); +} + +int8_t coap_service_response_send(int8_t service_id, uint8_t options, sn_coap_hdr_s *request_ptr, sn_coap_msg_code_e message_code, sn_coap_content_format_e content_type, const uint8_t *payload_ptr,uint16_t payload_len){ + return coap_message_handler_response_send(coap_service_handle, service_id, options, request_ptr, message_code, content_type, payload_ptr, payload_len); +} + +int8_t coap_service_set_handshake_timeout(int8_t service_id, uint32_t min, uint32_t max) +{ + coap_service_t *this = service_find(service_id); + if(!this){ + return -1; + } + + return coap_connection_handler_set_timeout(this->conn_handler, min, max); +} + +uint32_t coap_service_get_internal_timer_ticks(void) +{ + return coap_ticks; +} diff --git a/features/FEATURE_CLIENT/coap-service/source/include/coap_connection_handler.h b/features/FEATURE_CLIENT/coap-service/source/include/coap_connection_handler.h new file mode 100644 index 0000000000..b866c609dd --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/source/include/coap_connection_handler.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 __COAP_CONNECTION_HANDLER_H__ +#define __COAP_CONNECTION_HANDLER_H__ + +#include +#include +#include +#include "ns_address.h" +#include "coap_service_api_internal.h" + +#define MAX_SECURE_SESSION_COUNT 3 +#define CLOSED_SECURE_SESSION_TIMEOUT 3600 // Seconds +#define OPEN_SECURE_SESSION_TIMEOUT 18000 // Seconds +#define SECURE_SESSION_CLEAN_INTERVAL 60 // Seconds + +struct internal_socket_s; + +typedef int send_to_socket_cb(int8_t socket_id, uint8_t address[static 16], uint16_t port, const unsigned char *, int); +typedef int receive_from_socket_cb(int8_t socket_id, uint8_t address[static 16], uint16_t port, unsigned char *, int); +typedef int get_pw_cb(int8_t socket_id, uint8_t address[static 16], uint16_t port, uint8_t *pw_ptr, uint8_t *pw_len); +typedef void security_done_cb(int8_t socket_id, uint8_t address[static 16], uint16_t port, uint8_t keyblock[static 40]); + +typedef struct coap_conn_handler_s{ + struct internal_socket_s *socket; + + receive_from_socket_cb *_recv_cb; + send_to_socket_cb *_send_cb; + get_pw_cb *_get_password_cb; + security_done_cb *_security_done_cb; +} coap_conn_handler_t; + +coap_conn_handler_t *connection_handler_create(receive_from_socket_cb *recv_from_cb, + send_to_socket_cb *send_to_cb, + get_pw_cb *pw_cb, + security_done_cb *done_cb); + +void connection_handler_destroy( coap_conn_handler_t *handler ); + +void connection_handler_close_secure_connection( coap_conn_handler_t *handler, uint8_t destination_addr_ptr[static 16], uint16_t port ); + +int coap_connection_handler_open_connection(coap_conn_handler_t *handler, uint16_t listen_port, bool use_ephemeral_port, bool is_secure, bool real_socket, bool bypassSec); + +//If returns -2, it means security was started and data was not send +int coap_connection_handler_send_data(coap_conn_handler_t *handler, ns_address_t *dest_addr, uint8_t *data_ptr, uint16_t data_len, bool bypass_link_sec); + +int coap_connection_handler_virtual_recv(coap_conn_handler_t *handler, uint8_t address[static 16], uint16_t port, uint8_t *data_ptr, uint16_t data_len); + +bool coap_connection_handler_socket_belongs_to(coap_conn_handler_t *handler, int8_t socket_id); + +int8_t coap_connection_handler_set_timeout(coap_conn_handler_t *handler, uint32_t min, uint32_t max); + +void coap_connection_handler_exec(uint32_t time); + +#endif diff --git a/features/FEATURE_CLIENT/coap-service/source/include/coap_message_handler.h b/features/FEATURE_CLIENT/coap-service/source/include/coap_message_handler.h new file mode 100644 index 0000000000..20a75d6cc7 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/source/include/coap_message_handler.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2015-2016 ARM Limited. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 __COAP_MESSAGE_HANDLER_H__ +#define __COAP_MESSAGE_HANDLER_H__ + +#include +#include "sn_coap_header.h" +#include "sn_nsdl.h" +#include "ns_list.h" + +/** + * \brief Service message response receive callback. + * + * Function that handles CoAP service message receiving and parsing + * + * \param msg_id Id number of the current message. + * \param response_ptr Pointer to CoAP header structure. + * + * \return 0 for success / -1 for failure + */ +typedef int coap_message_handler_response_recv(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr); + +typedef struct coap_msg_handler_s { + void *(*sn_coap_service_malloc)(uint16_t); + void (*sn_coap_service_free)(void *); + + uint8_t (*sn_coap_tx_callback)(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *); + + struct coap_s *coap; +} coap_msg_handler_t; + +typedef struct coap_transaction { + uint8_t remote_address[16]; + uint16_t remote_port; + uint8_t token[4]; + uint16_t msg_id; + int8_t service_id; + uint8_t options; + bool client_request: 1; + uint8_t *data_ptr; + uint16_t data_len; + coap_message_handler_response_recv *resp_cb; + ns_list_link_t link; +} coap_transaction_t; + + +extern coap_msg_handler_t *coap_message_handler_init(void *(*used_malloc_func_ptr)(uint16_t), void (*used_free_func_ptr)(void *), + uint8_t (*used_tx_callback_ptr)(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *)); + +extern int8_t coap_message_handler_destroy(coap_msg_handler_t *handle); + +extern coap_transaction_t *coap_message_handler_transaction_valid(coap_transaction_t *tr_ptr); + +extern coap_transaction_t *coap_message_handler_find_transaction(uint8_t *address_ptr, uint16_t port); + +extern int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t socket_id, uint8_t source_addr_ptr[static 16], uint16_t port, + uint8_t *data_ptr, uint16_t data_len, int16_t (cb)(int8_t, sn_coap_hdr_s *, coap_transaction_t *)); + +extern uint16_t coap_message_handler_request_send(coap_msg_handler_t *handle, int8_t service_id, uint8_t options, const uint8_t destination_addr[static 16], + uint16_t destination_port, sn_coap_msg_type_e msg_type, sn_coap_msg_code_e msg_code, const char *uri, sn_coap_content_format_e cont_type, + const uint8_t *payload_ptr, uint16_t payload_len, coap_message_handler_response_recv *request_response_cb); + +extern int8_t coap_message_handler_response_send(coap_msg_handler_t *handle, int8_t service_id, uint8_t options, sn_coap_hdr_s *request_ptr, sn_coap_msg_code_e message_code, + sn_coap_content_format_e content_type, const uint8_t *payload_ptr, uint16_t payload_len); + +extern int8_t coap_message_handler_exec(coap_msg_handler_t *handle, uint32_t current_time); + +#endif diff --git a/features/FEATURE_CLIENT/coap-service/source/include/coap_security_handler.h b/features/FEATURE_CLIENT/coap-service/source/include/coap_security_handler.h new file mode 100644 index 0000000000..e43c74bb7d --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/source/include/coap_security_handler.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2015-2016 ARM Limited. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 __COAP_SECURITY_HANDLER_H__ +#define __COAP_SECURITY_HANDLER_H__ + +#include +#include +#include +#include "mbedtls/platform.h" +#include "mbedtls/ssl.h" +#include "mbedtls/sha256.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" + +#define COOKIE_SIMPLE_LEN 8 +typedef struct simple_cookie { + unsigned char value[COOKIE_SIMPLE_LEN]; + size_t len; +} simple_cookie_t; + +#define KEY_BLOCK_LEN 40 +typedef struct key_block { + unsigned char value[KEY_BLOCK_LEN]; +} key_block_t; + +typedef int send_cb(int8_t socket_id, uint8_t *address_ptr, uint16_t port, const unsigned char *, size_t); +typedef int receive_cb(int8_t socket_id, unsigned char *, size_t); +typedef void start_timer_cb(int8_t timer_id, uint32_t min, uint32_t fin); +typedef int timer_status_cb(int8_t timer_id); + +#define DTLS_HANDSHAKE_TIMEOUT_MIN 25000 +#define DTLS_HANDSHAKE_TIMEOUT_MAX 201000 + +typedef enum { + DTLS = 0, + TLS = 1 +}SecureSocketMode; + +typedef enum { + Certificate, + PSK, + ECJPAKE +}SecureConnectionMode; + +typedef struct { + unsigned char *_server_cert; + uint8_t _server_cert_len; + unsigned char *_pub_cert_or_identifier; + uint8_t _pub_len; + unsigned char *_priv; + uint8_t _priv_len; +} coap_security_keys_t; + +typedef struct coap_security_s { + mbedtls_ssl_config _conf; + mbedtls_ssl_context _ssl; + + mbedtls_ctr_drbg_context _ctr_drbg; + mbedtls_entropy_context _entropy; + bool _is_started; + simple_cookie_t _cookie; + key_block_t _keyblk; + + SecureConnectionMode _conn_mode; +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt _cacert; + mbedtls_x509_crt _owncert; +#endif + mbedtls_pk_context _pkey; + + uint8_t _remote_address[16]; + uint16_t _remote_port; + + uint8_t _pw[64]; + uint8_t _pw_len; + + bool _is_blocking; + int8_t _socket_id; + int8_t _timer_id; + send_cb *_send_cb; + receive_cb *_receive_cb; + start_timer_cb *_start_timer_cb; + timer_status_cb *_timer_status_cb; + +} coap_security_t; + +coap_security_t *coap_security_create(int8_t socket_id, int8_t timer_id, uint8_t *address_ptr, uint16_t port, + SecureConnectionMode mode, + send_cb *send_cb, + receive_cb *receive_cb, + start_timer_cb *start_timer_cb, + timer_status_cb *timer_status_cb); + +void coap_security_destroy(coap_security_t *sec); + +int coap_security_handler_connect(coap_security_t *sec, bool is_server, SecureSocketMode sock_mode, coap_security_keys_t keys); + +int coap_security_handler_connect_non_blocking(coap_security_t *sec, bool is_server, SecureSocketMode sock_mode, coap_security_keys_t keys, uint32_t timeout_min, uint32_t timeout_max); + +int coap_security_handler_continue_connecting(coap_security_t *sec); + +int coap_security_handler_send_message(coap_security_t *sec, unsigned char *message, size_t len); + +int coap_security_send_close_alert(coap_security_t *sec); + +int coap_security_handler_read(coap_security_t *sec, unsigned char* buffer, size_t len); + +#endif diff --git a/features/FEATURE_CLIENT/coap-service/source/include/coap_service_api_internal.h b/features/FEATURE_CLIENT/coap-service/source/include/coap_service_api_internal.h new file mode 100644 index 0000000000..bface30bf5 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/source/include/coap_service_api_internal.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2016 ARM Limited. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 __COAP_SERVICE_API_INTERNAL_H__ +#define __COAP_SERVICE_API_INTERNAL_H__ + + +uint32_t coap_service_get_internal_timer_ticks(void); + +#endif diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/MakefileWorker.mk b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/MakefileWorker.mk new file mode 100755 index 0000000000..2096ced036 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/MakefileWorker.mk @@ -0,0 +1,562 @@ +#--------- +# +# MakefileWorker.mk +# +# Include this helper file in your makefile +# It makes +# A static library +# A test executable +# +# See this example for parameter settings +# examples/Makefile +# +#---------- +# Inputs - these variables describe what to build +# +# INCLUDE_DIRS - Directories used to search for include files. +# This generates a -I for each directory +# SRC_DIRS - Directories containing source file to built into the library +# SRC_FILES - Specific source files to build into library. Helpful when not all code +# in a directory can be built for test (hopefully a temporary situation) +# TEST_SRC_DIRS - Directories containing unit test code build into the unit test runner +# These do not go in a library. They are explicitly included in the test runner +# TEST_SRC_FILES - Specific source files to build into the unit test runner +# These do not go in a library. They are explicitly included in the test runner +# MOCKS_SRC_DIRS - Directories containing mock source files to build into the test runner +# These do not go in a library. They are explicitly included in the test runner +#---------- +# You can adjust these variables to influence how to build the test target +# and where to put and name outputs +# See below to determine defaults +# COMPONENT_NAME - the name of the thing being built +# TEST_TARGET - name the test executable. By default it is +# $(COMPONENT_NAME)_tests +# Helpful if you want 1 > make files in the same directory with different +# executables as output. +# CPPUTEST_HOME - where CppUTest home dir found +# TARGET_PLATFORM - Influences how the outputs are generated by modifying the +# CPPUTEST_OBJS_DIR and CPPUTEST_LIB_DIR to use a sub-directory under the +# normal objs and lib directories. Also modifies where to search for the +# CPPUTEST_LIB to link against. +# CPPUTEST_OBJS_DIR - a directory where o and d files go +# CPPUTEST_LIB_DIR - a directory where libs go +# CPPUTEST_ENABLE_DEBUG - build for debug +# CPPUTEST_USE_MEM_LEAK_DETECTION - Links with overridden new and delete +# CPPUTEST_USE_STD_CPP_LIB - Set to N to keep the standard C++ library out +# of the test harness +# CPPUTEST_USE_GCOV - Turn on coverage analysis +# Clean then build with this flag set to Y, then 'make gcov' +# CPPUTEST_MAPFILE - generate a map file +# CPPUTEST_WARNINGFLAGS - overly picky by default +# OTHER_MAKEFILE_TO_INCLUDE - a hook to use this makefile to make +# other targets. Like CSlim, which is part of fitnesse +# CPPUTEST_USE_VPATH - Use Make's VPATH functionality to support user +# specification of source files and directories that aren't below +# the user's Makefile in the directory tree, like: +# SRC_DIRS += ../../lib/foo +# It defaults to N, and shouldn't be necessary except in the above case. +#---------- +# +# Other flags users can initialize to sneak in their settings +# CPPUTEST_CXXFLAGS - flags for the C++ compiler +# CPPUTEST_CPPFLAGS - flags for the C++ AND C preprocessor +# CPPUTEST_CFLAGS - flags for the C complier +# CPPUTEST_LDFLAGS - Linker flags +#---------- + +# Some behavior is weird on some platforms. Need to discover the platform. + +# Platforms +UNAME_OUTPUT = "$(shell uname -a)" +MACOSX_STR = Darwin +MINGW_STR = MINGW +CYGWIN_STR = CYGWIN +LINUX_STR = Linux +SUNOS_STR = SunOS +UNKNWOWN_OS_STR = Unknown + +# Compilers +CC_VERSION_OUTPUT ="$(shell $(CXX) -v 2>&1)" +CLANG_STR = clang +SUNSTUDIO_CXX_STR = SunStudio + +UNAME_OS = $(UNKNWOWN_OS_STR) + +ifeq ($(findstring $(MINGW_STR),$(UNAME_OUTPUT)),$(MINGW_STR)) + UNAME_OS = $(MINGW_STR) +endif + +ifeq ($(findstring $(CYGWIN_STR),$(UNAME_OUTPUT)),$(CYGWIN_STR)) + UNAME_OS = $(CYGWIN_STR) +endif + +ifeq ($(findstring $(LINUX_STR),$(UNAME_OUTPUT)),$(LINUX_STR)) + UNAME_OS = $(LINUX_STR) +endif + +ifeq ($(findstring $(MACOSX_STR),$(UNAME_OUTPUT)),$(MACOSX_STR)) + UNAME_OS = $(MACOSX_STR) +#lion has a problem with the 'v' part of -a + UNAME_OUTPUT = "$(shell uname -pmnrs)" +endif + +ifeq ($(findstring $(SUNOS_STR),$(UNAME_OUTPUT)),$(SUNOS_STR)) + UNAME_OS = $(SUNOS_STR) + + SUNSTUDIO_CXX_ERR_STR = CC -flags +ifeq ($(findstring $(SUNSTUDIO_CXX_ERR_STR),$(CC_VERSION_OUTPUT)),$(SUNSTUDIO_CXX_ERR_STR)) + CC_VERSION_OUTPUT ="$(shell $(CXX) -V 2>&1)" + COMPILER_NAME = $(SUNSTUDIO_CXX_STR) +endif +endif + +ifeq ($(findstring $(CLANG_STR),$(CC_VERSION_OUTPUT)),$(CLANG_STR)) + COMPILER_NAME = $(CLANG_STR) +endif + +#Kludge for mingw, it does not have cc.exe, but gcc.exe will do +ifeq ($(UNAME_OS),$(MINGW_STR)) + CC := gcc +endif + +#And another kludge. Exception handling in gcc 4.6.2 is broken when linking the +# Standard C++ library as a shared library. Unbelievable. +ifeq ($(UNAME_OS),$(MINGW_STR)) + CPPUTEST_LDFLAGS += -static +endif +ifeq ($(UNAME_OS),$(CYGWIN_STR)) + CPPUTEST_LDFLAGS += -static +endif + + +#Kludge for MacOsX gcc compiler on Darwin9 who can't handle pendantic +ifeq ($(UNAME_OS),$(MACOSX_STR)) +ifeq ($(findstring Version 9,$(UNAME_OUTPUT)),Version 9) + CPPUTEST_PEDANTIC_ERRORS = N +endif +endif + +ifndef COMPONENT_NAME + COMPONENT_NAME = name_this_in_the_makefile +endif + +# Debug on by default +ifndef CPPUTEST_ENABLE_DEBUG + CPPUTEST_ENABLE_DEBUG = Y +endif + +# new and delete for memory leak detection on by default +ifndef CPPUTEST_USE_MEM_LEAK_DETECTION + CPPUTEST_USE_MEM_LEAK_DETECTION = Y +endif + +# Use the standard C library +ifndef CPPUTEST_USE_STD_C_LIB + CPPUTEST_USE_STD_C_LIB = Y +endif + +# Use the standard C++ library +ifndef CPPUTEST_USE_STD_CPP_LIB + CPPUTEST_USE_STD_CPP_LIB = Y +endif + +# Use gcov, off by default +ifndef CPPUTEST_USE_GCOV + CPPUTEST_USE_GCOV = N +endif + +ifndef CPPUTEST_PEDANTIC_ERRORS + CPPUTEST_PEDANTIC_ERRORS = Y +endif + +# Default warnings +ifndef CPPUTEST_WARNINGFLAGS + CPPUTEST_WARNINGFLAGS = -Wall -Wextra -Wshadow -Wswitch-default -Wswitch-enum -Wconversion +ifeq ($(CPPUTEST_PEDANTIC_ERRORS), Y) +# CPPUTEST_WARNINGFLAGS += -pedantic-errors + CPPUTEST_WARNINGFLAGS += -pedantic +endif +ifeq ($(UNAME_OS),$(LINUX_STR)) + CPPUTEST_WARNINGFLAGS += -Wsign-conversion +endif + CPPUTEST_CXX_WARNINGFLAGS = -Woverloaded-virtual + CPPUTEST_C_WARNINGFLAGS = -Wstrict-prototypes +endif + +#Wonderful extra compiler warnings with clang +ifeq ($(COMPILER_NAME),$(CLANG_STR)) +# -Wno-disabled-macro-expansion -> Have to disable the macro expansion warning as the operator new overload warns on that. +# -Wno-padded -> I sort-of like this warning but if there is a bool at the end of the class, it seems impossible to remove it! (except by making padding explicit) +# -Wno-global-constructors Wno-exit-time-destructors -> Great warnings, but in CppUTest it is impossible to avoid as the automatic test registration depends on the global ctor and dtor +# -Wno-weak-vtables -> The TEST_GROUP macro declares a class and will automatically inline its methods. Thats ok as they are only in one translation unit. Unfortunately, the warning can't detect that, so it must be disabled. + CPPUTEST_CXX_WARNINGFLAGS += -Weverything -Wno-disabled-macro-expansion -Wno-padded -Wno-global-constructors -Wno-exit-time-destructors -Wno-weak-vtables + CPPUTEST_C_WARNINGFLAGS += -Weverything -Wno-padded +endif + +# Uhm. Maybe put some warning flags for SunStudio here? +ifeq ($(COMPILER_NAME),$(SUNSTUDIO_CXX_STR)) + CPPUTEST_CXX_WARNINGFLAGS = + CPPUTEST_C_WARNINGFLAGS = +endif + +# Default dir for temporary files (d, o) +ifndef CPPUTEST_OBJS_DIR +ifndef TARGET_PLATFORM + CPPUTEST_OBJS_DIR = objs +else + CPPUTEST_OBJS_DIR = objs/$(TARGET_PLATFORM) +endif +endif + +# Default dir for the outout library +ifndef CPPUTEST_LIB_DIR +ifndef TARGET_PLATFORM + CPPUTEST_LIB_DIR = lib +else + CPPUTEST_LIB_DIR = lib/$(TARGET_PLATFORM) +endif +endif + +# No map by default +ifndef CPPUTEST_MAP_FILE + CPPUTEST_MAP_FILE = N +endif + +# No extentions is default +ifndef CPPUTEST_USE_EXTENSIONS + CPPUTEST_USE_EXTENSIONS = N +endif + +# No VPATH is default +ifndef CPPUTEST_USE_VPATH + CPPUTEST_USE_VPATH := N +endif +# Make empty, instead of 'N', for usage in $(if ) conditionals +ifneq ($(CPPUTEST_USE_VPATH), Y) + CPPUTEST_USE_VPATH := +endif + +ifndef TARGET_PLATFORM +#CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_HOME)/lib +CPPUTEST_LIB_LINK_DIR = /usr/lib/x86_64-linux-gnu +else +CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_HOME)/lib/$(TARGET_PLATFORM) +endif + +# -------------------------------------- +# derived flags in the following area +# -------------------------------------- + +# Without the C library, we'll need to disable the C++ library and ... +ifeq ($(CPPUTEST_USE_STD_C_LIB), N) + CPPUTEST_USE_STD_CPP_LIB = N + CPPUTEST_USE_MEM_LEAK_DETECTION = N + CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_C_LIB_DISABLED + CPPUTEST_CPPFLAGS += -nostdinc +endif + +CPPUTEST_CPPFLAGS += -DCPPUTEST_COMPILATION + +ifeq ($(CPPUTEST_USE_MEM_LEAK_DETECTION), N) + CPPUTEST_CPPFLAGS += -DCPPUTEST_MEM_LEAK_DETECTION_DISABLED +else + ifndef CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE + CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE = -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorNewMacros.h + endif + ifndef CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE + CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE = -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorMallocMacros.h + endif +endif + +ifeq ($(CPPUTEST_ENABLE_DEBUG), Y) + CPPUTEST_CXXFLAGS += -g + CPPUTEST_CFLAGS += -g + CPPUTEST_LDFLAGS += -g +endif + +ifeq ($(CPPUTEST_USE_STD_CPP_LIB), N) + CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_CPP_LIB_DISABLED +ifeq ($(CPPUTEST_USE_STD_C_LIB), Y) + CPPUTEST_CXXFLAGS += -nostdinc++ +endif +endif + +ifdef $(GMOCK_HOME) + GTEST_HOME = $(GMOCK_HOME)/gtest + CPPUTEST_CPPFLAGS += -I$(GMOCK_HOME)/include + GMOCK_LIBRARY = $(GMOCK_HOME)/lib/.libs/libgmock.a + LD_LIBRARIES += $(GMOCK_LIBRARY) + CPPUTEST_CPPFLAGS += -DINCLUDE_GTEST_TESTS + CPPUTEST_WARNINGFLAGS = + CPPUTEST_CPPFLAGS += -I$(GTEST_HOME)/include -I$(GTEST_HOME) + GTEST_LIBRARY = $(GTEST_HOME)/lib/.libs/libgtest.a + LD_LIBRARIES += $(GTEST_LIBRARY) +endif + + +ifeq ($(CPPUTEST_USE_GCOV), Y) + CPPUTEST_CXXFLAGS += -fprofile-arcs -ftest-coverage + CPPUTEST_CFLAGS += -fprofile-arcs -ftest-coverage +endif + +CPPUTEST_CXXFLAGS += $(CPPUTEST_WARNINGFLAGS) $(CPPUTEST_CXX_WARNINGFLAGS) +CPPUTEST_CPPFLAGS += $(CPPUTEST_WARNINGFLAGS) +CPPUTEST_CXXFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE) +CPPUTEST_CPPFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE) +CPPUTEST_CFLAGS += $(CPPUTEST_C_WARNINGFLAGS) + +TARGET_MAP = $(COMPONENT_NAME).map.txt +ifeq ($(CPPUTEST_MAP_FILE), Y) + CPPUTEST_LDFLAGS += -Wl,-map,$(TARGET_MAP) +endif + +# Link with CppUTest lib +CPPUTEST_LIB = $(CPPUTEST_LIB_LINK_DIR)/libCppUTest.a + +ifeq ($(CPPUTEST_USE_EXTENSIONS), Y) +CPPUTEST_LIB += $(CPPUTEST_LIB_LINK_DIR)/libCppUTestExt.a +endif + +ifdef CPPUTEST_STATIC_REALTIME + LD_LIBRARIES += -lrt +endif + +TARGET_LIB = \ + $(CPPUTEST_LIB_DIR)/lib$(COMPONENT_NAME).a + +ifndef TEST_TARGET + ifndef TARGET_PLATFORM + TEST_TARGET = $(COMPONENT_NAME)_tests + else + TEST_TARGET = $(COMPONENT_NAME)_$(TARGET_PLATFORM)_tests + endif +endif + +#Helper Functions +get_src_from_dir = $(wildcard $1/*.cpp) $(wildcard $1/*.cc) $(wildcard $1/*.c) +get_dirs_from_dirspec = $(wildcard $1) +get_src_from_dir_list = $(foreach dir, $1, $(call get_src_from_dir,$(dir))) +__src_to = $(subst .c,$1, $(subst .cc,$1, $(subst .cpp,$1,$(if $(CPPUTEST_USE_VPATH),$(notdir $2),$2)))) +src_to = $(addprefix $(CPPUTEST_OBJS_DIR)/,$(call __src_to,$1,$2)) +src_to_o = $(call src_to,.o,$1) +src_to_d = $(call src_to,.d,$1) +src_to_gcda = $(call src_to,.gcda,$1) +src_to_gcno = $(call src_to,.gcno,$1) +time = $(shell date +%s) +delta_t = $(eval minus, $1, $2) +debug_print_list = $(foreach word,$1,echo " $(word)";) echo; + +#Derived +STUFF_TO_CLEAN += $(TEST_TARGET) $(TEST_TARGET).exe $(TARGET_LIB) $(TARGET_MAP) + +SRC += $(call get_src_from_dir_list, $(SRC_DIRS)) $(SRC_FILES) +OBJ = $(call src_to_o,$(SRC)) + +STUFF_TO_CLEAN += $(OBJ) + +TEST_SRC += $(call get_src_from_dir_list, $(TEST_SRC_DIRS)) $(TEST_SRC_FILES) +TEST_OBJS = $(call src_to_o,$(TEST_SRC)) +STUFF_TO_CLEAN += $(TEST_OBJS) + + +MOCKS_SRC += $(call get_src_from_dir_list, $(MOCKS_SRC_DIRS)) +MOCKS_OBJS = $(call src_to_o,$(MOCKS_SRC)) +STUFF_TO_CLEAN += $(MOCKS_OBJS) + +ALL_SRC = $(SRC) $(TEST_SRC) $(MOCKS_SRC) + +# If we're using VPATH +ifeq ($(CPPUTEST_USE_VPATH), Y) +# gather all the source directories and add them + VPATH += $(sort $(dir $(ALL_SRC))) +# Add the component name to the objs dir path, to differentiate between same-name objects + CPPUTEST_OBJS_DIR := $(addsuffix /$(COMPONENT_NAME),$(CPPUTEST_OBJS_DIR)) +endif + +#Test coverage with gcov +GCOV_OUTPUT = gcov_output.txt +GCOV_REPORT = gcov_report.txt +GCOV_ERROR = gcov_error.txt +GCOV_GCDA_FILES = $(call src_to_gcda, $(ALL_SRC)) +GCOV_GCNO_FILES = $(call src_to_gcno, $(ALL_SRC)) +TEST_OUTPUT = $(TEST_TARGET).txt +STUFF_TO_CLEAN += \ + $(GCOV_OUTPUT)\ + $(GCOV_REPORT)\ + $(GCOV_REPORT).html\ + $(GCOV_ERROR)\ + $(GCOV_GCDA_FILES)\ + $(GCOV_GCNO_FILES)\ + $(TEST_OUTPUT) + +#The gcda files for gcov need to be deleted before each run +#To avoid annoying messages. +GCOV_CLEAN = $(SILENCE)rm -f $(GCOV_GCDA_FILES) $(GCOV_OUTPUT) $(GCOV_REPORT) $(GCOV_ERROR) +RUN_TEST_TARGET = $(SILENCE) $(GCOV_CLEAN) ; echo "Running $(TEST_TARGET)"; ./$(TEST_TARGET) $(CPPUTEST_EXE_FLAGS) -ojunit + +ifeq ($(CPPUTEST_USE_GCOV), Y) + + ifeq ($(COMPILER_NAME),$(CLANG_STR)) + LD_LIBRARIES += --coverage + else + LD_LIBRARIES += -lgcov + endif +endif + + +INCLUDES_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(INCLUDE_DIRS)) +INCLUDES += $(foreach dir, $(INCLUDES_DIRS_EXPANDED), -I$(dir)) +MOCK_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(MOCKS_SRC_DIRS)) +INCLUDES += $(foreach dir, $(MOCK_DIRS_EXPANDED), -I$(dir)) + +CPPUTEST_CPPFLAGS += $(INCLUDES) $(CPPUTESTFLAGS) + +DEP_FILES = $(call src_to_d, $(ALL_SRC)) +STUFF_TO_CLEAN += $(DEP_FILES) $(PRODUCTION_CODE_START) $(PRODUCTION_CODE_END) +STUFF_TO_CLEAN += $(STDLIB_CODE_START) $(MAP_FILE) cpputest_*.xml junit_run_output + +# We'll use the CPPUTEST_CFLAGS etc so that you can override AND add to the CppUTest flags +CFLAGS = $(CPPUTEST_CFLAGS) $(CPPUTEST_ADDITIONAL_CFLAGS) +CPPFLAGS = $(CPPUTEST_CPPFLAGS) $(CPPUTEST_ADDITIONAL_CPPFLAGS) +CXXFLAGS = $(CPPUTEST_CXXFLAGS) $(CPPUTEST_ADDITIONAL_CXXFLAGS) +LDFLAGS = $(CPPUTEST_LDFLAGS) $(CPPUTEST_ADDITIONAL_LDFLAGS) + +# Don't consider creating the archive a warning condition that does STDERR output +ARFLAGS := $(ARFLAGS)c + +DEP_FLAGS=-MMD -MP + +# Some macros for programs to be overridden. For some reason, these are not in Make defaults +RANLIB = ranlib + +# Targets + +.PHONY: all +all: start $(TEST_TARGET) + $(RUN_TEST_TARGET) + +.PHONY: start +start: $(TEST_TARGET) + $(SILENCE)START_TIME=$(call time) + +.PHONY: all_no_tests +all_no_tests: $(TEST_TARGET) + +.PHONY: flags +flags: + @echo + @echo "OS ${UNAME_OS}" + @echo "Compile C and C++ source with CPPFLAGS:" + @$(call debug_print_list,$(CPPFLAGS)) + @echo "Compile C++ source with CXXFLAGS:" + @$(call debug_print_list,$(CXXFLAGS)) + @echo "Compile C source with CFLAGS:" + @$(call debug_print_list,$(CFLAGS)) + @echo "Link with LDFLAGS:" + @$(call debug_print_list,$(LDFLAGS)) + @echo "Link with LD_LIBRARIES:" + @$(call debug_print_list,$(LD_LIBRARIES)) + @echo "Create libraries with ARFLAGS:" + @$(call debug_print_list,$(ARFLAGS)) + +TEST_DEPS = $(TEST_OBJS) $(MOCKS_OBJS) $(PRODUCTION_CODE_START) $(TARGET_LIB) $(USER_LIBS) $(PRODUCTION_CODE_END) $(CPPUTEST_LIB) $(STDLIB_CODE_START) +test-deps: $(TEST_DEPS) + +$(TEST_TARGET): $(TEST_DEPS) + @echo Linking $@ + $(SILENCE)$(CXX) -o $@ $^ $(LD_LIBRARIES) $(LDFLAGS) + +$(TARGET_LIB): $(OBJ) + @echo Building archive $@ + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(AR) $(ARFLAGS) $@ $^ + $(SILENCE)$(RANLIB) $@ + +test: $(TEST_TARGET) + $(RUN_TEST_TARGET) | tee $(TEST_OUTPUT) + +vtest: $(TEST_TARGET) + $(RUN_TEST_TARGET) -v | tee $(TEST_OUTPUT) + +$(CPPUTEST_OBJS_DIR)/%.o: %.cc + @echo compiling $(notdir $<) + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $< + +$(CPPUTEST_OBJS_DIR)/%.o: %.cpp + @echo compiling $(notdir $<) + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $< + +$(CPPUTEST_OBJS_DIR)/%.o: %.c + @echo compiling $(notdir $<) + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(COMPILE.c) $(DEP_FLAGS) $(OUTPUT_OPTION) $< + +ifneq "$(MAKECMDGOALS)" "clean" +-include $(DEP_FILES) +endif + +.PHONY: clean +clean: + @echo Making clean + $(SILENCE)$(RM) $(STUFF_TO_CLEAN) + $(SILENCE)rm -rf gcov objs #$(CPPUTEST_OBJS_DIR) + $(SILENCE)rm -rf $(CPPUTEST_LIB_DIR) + $(SILENCE)find . -name "*.gcno" | xargs rm -f + $(SILENCE)find . -name "*.gcda" | xargs rm -f + +#realclean gets rid of all gcov, o and d files in the directory tree +#not just the ones made by this makefile +.PHONY: realclean +realclean: clean + $(SILENCE)rm -rf gcov + $(SILENCE)find . -name "*.gdcno" | xargs rm -f + $(SILENCE)find . -name "*.[do]" | xargs rm -f + +gcov: test +ifeq ($(CPPUTEST_USE_VPATH), Y) + $(SILENCE)gcov --object-directory $(CPPUTEST_OBJS_DIR) $(SRC) >> $(GCOV_OUTPUT) 2>> $(GCOV_ERROR) +else + $(SILENCE)for d in $(SRC_DIRS) ; do \ + gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$d $$d/*.c $$d/*.cpp >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \ + done + $(SILENCE)for f in $(SRC_FILES) ; do \ + gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$f $$f >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \ + done +endif +# $(CPPUTEST_HOME)/scripts/filterGcov.sh $(GCOV_OUTPUT) $(GCOV_ERROR) $(GCOV_REPORT) $(TEST_OUTPUT) + /usr/share/cpputest/scripts/filterGcov.sh $(GCOV_OUTPUT) $(GCOV_ERROR) $(GCOV_REPORT) $(TEST_OUTPUT) + $(SILENCE)cat $(GCOV_REPORT) + $(SILENCE)mkdir -p gcov + $(SILENCE)mv *.gcov gcov + $(SILENCE)mv gcov_* gcov + @echo "See gcov directory for details" + +.PHONEY: format +format: + $(CPPUTEST_HOME)/scripts/reformat.sh $(PROJECT_HOME_DIR) + +.PHONEY: debug +debug: + @echo + @echo "Target Source files:" + @$(call debug_print_list,$(SRC)) + @echo "Target Object files:" + @$(call debug_print_list,$(OBJ)) + @echo "Test Source files:" + @$(call debug_print_list,$(TEST_SRC)) + @echo "Test Object files:" + @$(call debug_print_list,$(TEST_OBJS)) + @echo "Mock Source files:" + @$(call debug_print_list,$(MOCKS_SRC)) + @echo "Mock Object files:" + @$(call debug_print_list,$(MOCKS_OBJS)) + @echo "All Input Dependency files:" + @$(call debug_print_list,$(DEP_FILES)) + @echo Stuff to clean: + @$(call debug_print_list,$(STUFF_TO_CLEAN)) + @echo Includes: + @$(call debug_print_list,$(INCLUDES)) + +-include $(OTHER_MAKEFILE_TO_INCLUDE) diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_connection_handler/coap_connection_handlertest.cpp b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_connection_handler/coap_connection_handlertest.cpp new file mode 100644 index 0000000000..383d42b6b8 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_connection_handler/coap_connection_handlertest.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ +#include "CppUTest/TestHarness.h" +#include "test_coap_connection_handler.h" + +TEST_GROUP(coap_connection_handler) +{ + void setup() + { + } + + void teardown() + { + } +}; + +TEST(coap_connection_handler, test_connection_handler_create) +{ + CHECK(test_connection_handler_create()); +} + +TEST(coap_connection_handler, test_connection_handler_destroy) +{ + CHECK(test_connection_handler_destroy()); +} + +TEST(coap_connection_handler, test_coap_connection_handler_open_connection) +{ + CHECK(test_coap_connection_handler_open_connection()); +} + +TEST(coap_connection_handler, test_coap_connection_handler_send_data) +{ + CHECK(test_coap_connection_handler_send_data()); +} + +TEST(coap_connection_handler, test_coap_connection_handler_virtual_recv) +{ + CHECK(test_coap_connection_handler_virtual_recv()); +} + +TEST(coap_connection_handler, test_coap_connection_handler_socket_belongs_to) +{ + CHECK(test_coap_connection_handler_socket_belongs_to()); +} + +TEST(coap_connection_handler, test_timer_callbacks) +{ + CHECK(test_timer_callbacks()); +} + +TEST(coap_connection_handler, test_socket_api_callbacks) +{ + CHECK(test_socket_api_callbacks()); +} + +TEST(coap_connection_handler, test_security_callbacks) +{ + CHECK(test_security_callbacks()); +} + diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_connection_handler/main.cpp b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_connection_handler/main.cpp new file mode 100644 index 0000000000..c04ec8b369 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_connection_handler/main.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ + +#include "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP(coap_connection_handler); + diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_connection_handler/test_coap_connection_handler.c b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_connection_handler/test_coap_connection_handler.c new file mode 100644 index 0000000000..6c26a8db09 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_connection_handler/test_coap_connection_handler.c @@ -0,0 +1,469 @@ +/* + * Copyright (c) 2015-2016 ARM Limited. All Rights Reserved. + */ +#include "test_coap_connection_handler.h" +#include +#include +#include "nsdynmemLIB_stub.h" +#include "mbedtls/platform.h" +#include "mbedtls/ssl.h" +#include "coap_connection_handler.h" +#include "coap_security_handler_stub.h" +#include "ns_timer_stub.h" +#include "socket_api.h" +#include "socket_api_stub.h" +#include "net_interface.h" + +int send_to_sock_cb(int8_t socket_id, uint8_t address, uint16_t port, const unsigned char *a, int b) +{ + return 1; +} + +int receive_from_sock_cb(int8_t socket_id, uint8_t address, uint16_t port, unsigned char *a, int b) +{ + return 1; +} + +int get_passwd_cb(int8_t socket_id, uint8_t address, uint16_t port, uint8_t *pw_ptr, uint8_t *pw_len) +{ + return 0; +} + +void sec_done_cb(int8_t socket_id, uint8_t address[static 16], uint16_t port, uint8_t keyblock[static 40]) +{ + return 1; +} + +bool test_connection_handler_create() +{ + coap_security_handler_stub.counter = -1; + if( NULL != connection_handler_create(NULL, NULL, NULL, NULL) ) + return false; + + if( NULL != connection_handler_create(&receive_from_sock_cb, NULL, NULL, NULL) ) + return false; + + nsdynmemlib_stub.returnCounter = 1; + coap_conn_handler_t *handler = connection_handler_create(&receive_from_sock_cb, NULL, NULL, NULL); + if( NULL == handler ) + return false; + ns_dyn_mem_free(handler); + return true; +} + +bool test_connection_handler_destroy() +{ + coap_security_handler_stub.counter = -1; + nsdynmemlib_stub.returnCounter = 1; + coap_conn_handler_t *handler = connection_handler_create(&receive_from_sock_cb, NULL, NULL, NULL); + + connection_handler_destroy(handler); + return true; +} + +bool test_coap_connection_handler_open_connection() +{ + coap_security_handler_stub.counter = -1; + nsdynmemlib_stub.returnCounter = 1; + coap_conn_handler_t *handler = connection_handler_create(&receive_from_sock_cb, NULL, NULL, NULL); + + if( -1 != coap_connection_handler_open_connection(NULL, 0,false,false,false,false) ) + return false; + + if( -1 != coap_connection_handler_open_connection(handler, 0,false,false,false,false) ) + return false; + + ns_dyn_mem_free(handler); + nsdynmemlib_stub.returnCounter = 1; + handler = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL); + if( -1 != coap_connection_handler_open_connection(handler, 0,true,true,true,false) ) + return false; + + nsdynmemlib_stub.returnCounter = 2; + if( 0 != coap_connection_handler_open_connection(handler, 0,true,true,true,false) ) + return false; + + nsdynmemlib_stub.returnCounter = 2; + if( 0 != coap_connection_handler_open_connection(handler, 22,false,true,true,true) ) + return false; + + //open second one + nsdynmemlib_stub.returnCounter = 1; + coap_conn_handler_t *handler2 = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL); + nsdynmemlib_stub.returnCounter = 2; + if( 0 != coap_connection_handler_open_connection(handler2, 22,false,true,true,true) ) + return false; + + if( 0 != coap_connection_handler_open_connection(handler, 23,false,false,false,false) ) + return false; + + connection_handler_destroy(handler2); + connection_handler_destroy(handler); + return true; +} + +bool test_coap_connection_handler_send_data() +{ + coap_security_handler_stub.counter = -1; + if( -1 != coap_connection_handler_send_data(NULL, NULL, NULL, 0, false)) + return false; + + ns_address_t addr; + memset(addr.address, 1, 16); + addr.identifier = 22; + + nsdynmemlib_stub.returnCounter = 1; + coap_conn_handler_t *handler = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL); + nsdynmemlib_stub.returnCounter = 2; + if( 0 != coap_connection_handler_open_connection(handler, 22,false,true,false,false) ) + return false; + + if( -1 != coap_connection_handler_send_data(handler, &addr, NULL, 0, true)) + return false; + + connection_handler_destroy(handler); + + coap_security_handler_stub.sec_obj = (coap_security_t *)malloc(sizeof(coap_security_t)); + memset(coap_security_handler_stub.sec_obj, 0, sizeof(coap_security_t)); + coap_security_handler_stub.sec_obj->_remote_port = 22; + memset(coap_security_handler_stub.sec_obj->_remote_address, 1, 16 ); + + nsdynmemlib_stub.returnCounter = 1; + handler = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL); + nsdynmemlib_stub.returnCounter = 4; + if( 0 != coap_connection_handler_open_connection(handler, 22,false,true,false,false) ) + return false; + + if( -1 != coap_connection_handler_send_data(handler, &addr, NULL, 0, true)) + return false; + + if( -1 != coap_connection_handler_send_data(handler, &addr, NULL, 0, true)) + return false; + + connection_handler_destroy(handler); + + free(coap_security_handler_stub.sec_obj); + coap_security_handler_stub.sec_obj = NULL; + + //NON SECURE HERE --> + nsdynmemlib_stub.returnCounter = 1; + handler = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL); + nsdynmemlib_stub.returnCounter = 2; + if( 0 != coap_connection_handler_open_connection(handler, 22,false,false,false,false) ) + return false; + + + if( 1 != coap_connection_handler_send_data(handler, &addr, NULL, 0, true)) + return false; + connection_handler_destroy(handler); + + nsdynmemlib_stub.returnCounter = 1; + handler = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL); + nsdynmemlib_stub.returnCounter = 2; + if( 0 != coap_connection_handler_open_connection(handler, 22,false,false,true,false) ) + return false; + + socket_api_stub.int8_value = 7; + if( 7 != coap_connection_handler_send_data(handler, &addr, NULL, 0, true)) + return false; + connection_handler_destroy(handler); + + //<-- NON SECURE HERE + + return true; +} + +bool test_coap_connection_handler_virtual_recv() +{ + coap_security_handler_stub.counter = -1; + uint8_t buf[16]; + memset(&buf, 1, 16); + if( -1 != coap_connection_handler_virtual_recv(NULL,buf, 12, NULL, 0) ) + return false; + + nsdynmemlib_stub.returnCounter = 1; + coap_conn_handler_t *handler = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL); + nsdynmemlib_stub.returnCounter = 2; + if( 0 != coap_connection_handler_open_connection(handler, 22,false,true,true,false) ) + return false; + + if( -1 != coap_connection_handler_virtual_recv(handler,buf, 12, NULL, 0) ) + return false; + + nsdynmemlib_stub.returnCounter = 1; + if( -1 != coap_connection_handler_virtual_recv(handler,buf, 12, NULL, 0) ) + return false; + + ns_timer_stub.int8_value = 0; + nsdynmemlib_stub.returnCounter = 3; + if( -1 != coap_connection_handler_virtual_recv(handler,buf, 12, &buf, 1) ) + return false; + + //handler->socket->data still in memory + coap_security_handler_stub.sec_obj = (coap_security_t *)malloc(sizeof(coap_security_t)); + memset(coap_security_handler_stub.sec_obj, 0, sizeof(coap_security_t)); + coap_security_handler_stub.sec_obj->_remote_port = 55; + memset(coap_security_handler_stub.sec_obj->_remote_address, 4, 16 ); + + ns_timer_stub.int8_value = -1; + nsdynmemlib_stub.returnCounter = 3; + if( -1 != coap_connection_handler_virtual_recv(handler,buf, 12, &buf, 1) ) + return false; + + ns_timer_stub.int8_value = 0; + nsdynmemlib_stub.returnCounter = 3; + if( -1 != coap_connection_handler_virtual_recv(handler,buf, 12, &buf, 1) ) + return false; + + connection_handler_destroy(handler); + + nsdynmemlib_stub.returnCounter = 1; + coap_conn_handler_t *handler2 = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, &get_passwd_cb, &sec_done_cb); + nsdynmemlib_stub.returnCounter = 2; + if( 0 != coap_connection_handler_open_connection(handler2, 24,false,true,true,false) ) + return false; + + nsdynmemlib_stub.returnCounter = 3; + if( 0 != coap_connection_handler_virtual_recv(handler2,buf, 12, &buf, 1) ) + return false; + + nsdynmemlib_stub.returnCounter = 1; + coap_security_handler_stub.int_value = 0; + coap_security_handler_stub.sec_obj->_remote_port = 12; + memset(coap_security_handler_stub.sec_obj->_remote_address, 1, 16 ); + if( 0 != coap_connection_handler_virtual_recv(handler2,buf, 12, &buf, 1) ) + return false; + + nsdynmemlib_stub.returnCounter = 1; + if( 0 != coap_connection_handler_virtual_recv(handler2,buf, 12, &buf, 1) ) + return false; + + nsdynmemlib_stub.returnCounter = 1; + coap_security_handler_stub.int_value = MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY; + if( 0 != coap_connection_handler_virtual_recv(handler2,buf, 12, &buf, 1) ) + return false; + + connection_handler_destroy(handler2); + + free(coap_security_handler_stub.sec_obj); + coap_security_handler_stub.sec_obj = NULL; + + nsdynmemlib_stub.returnCounter = 1; + coap_conn_handler_t *handler3 = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, &get_passwd_cb, &sec_done_cb); + nsdynmemlib_stub.returnCounter = 2; + if( 0 != coap_connection_handler_open_connection(handler3, 26,false,false,true,false) ) + return false; + + nsdynmemlib_stub.returnCounter = 3; + if( 0 != coap_connection_handler_virtual_recv(handler3,buf, 12, &buf, 1) ) + return false; + + connection_handler_destroy(handler3); + + return true; +} + +bool test_coap_connection_handler_socket_belongs_to() +{ + coap_security_handler_stub.counter = -1; + if( false != coap_connection_handler_socket_belongs_to(NULL, 2) ) + return false; + + socket_api_stub.int8_value = 0; + nsdynmemlib_stub.returnCounter = 1; + coap_conn_handler_t *handler = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL); + nsdynmemlib_stub.returnCounter = 2; + if( 0 != coap_connection_handler_open_connection(handler, 22,false,true,true,false) ) + return false; + + if( true != coap_connection_handler_socket_belongs_to(handler, 0) ) + return false; + + if( false != coap_connection_handler_socket_belongs_to(handler, 3) ) + return false; + connection_handler_destroy(handler); + + nsdynmemlib_stub.returnCounter = 0; + return true; +} + +bool test_timer_callbacks() +{ + coap_security_handler_stub.counter = -1; + uint8_t buf[16]; + memset(&buf, 1, 16); + + nsdynmemlib_stub.returnCounter = 1; + coap_conn_handler_t *handler = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL); + nsdynmemlib_stub.returnCounter = 2; + if( 0 != coap_connection_handler_open_connection(handler, 22,false,true,true,false) ) + return false; + + //handler->socket->data still in memory + coap_security_handler_stub.sec_obj = (coap_security_t *)malloc(sizeof(coap_security_t)); + memset(coap_security_handler_stub.sec_obj, 0, sizeof(coap_security_t)); + coap_security_handler_stub.sec_obj->_remote_port = 55; + memset(coap_security_handler_stub.sec_obj->_remote_address, 4, 16 ); + coap_security_handler_stub.sec_obj->_timer_id = 5; + + ns_timer_stub.int8_value = 0; + nsdynmemlib_stub.returnCounter = 3; + ns_timer_stub.int8_value = 5; + if( -1 != coap_connection_handler_virtual_recv(handler,buf, 12, &buf, 1) ) + return false; + + //Note next tests will affect ns_timer test (cycle & cycle_count + if( coap_security_handler_stub.start_timer_cb ){ + coap_security_handler_stub.start_timer_cb(1, 0, 0); + + coap_security_handler_stub.start_timer_cb(1, 1, 2); + } + + if( coap_security_handler_stub.timer_status_cb ){ + if( -1 != coap_security_handler_stub.timer_status_cb(4) ) + return false; + + if( 0 != coap_security_handler_stub.timer_status_cb(1) ) + return false; + } + + if( ns_timer_stub.cb ){ + ns_timer_stub.cb(4, 0); + + ns_timer_stub.cb(5, 0); + + coap_security_handler_stub.int_value = MBEDTLS_ERR_SSL_TIMEOUT; + + ns_timer_stub.cb(5, 0); + coap_security_handler_stub.int_value = 0; + } + + connection_handler_destroy(handler); + free(coap_security_handler_stub.sec_obj); + coap_security_handler_stub.sec_obj = NULL; + return true; +} + +bool test_socket_api_callbacks() +{ + coap_security_handler_stub.counter = -1; + uint8_t buf[16]; + memset(&buf, 1, 16); + + socket_callback_t *sckt_data = (socket_callback_t *)malloc(sizeof(socket_callback_t)); + memset(sckt_data, 0, sizeof(socket_callback_t)); + + coap_security_handler_stub.sec_obj = (coap_security_t *)malloc(sizeof(coap_security_t)); + memset(coap_security_handler_stub.sec_obj, 0, sizeof(coap_security_t)); + + socket_api_stub.int8_value = 0; + nsdynmemlib_stub.returnCounter = 1; + coap_conn_handler_t *handler = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL); + nsdynmemlib_stub.returnCounter = 2; + if( 0 != coap_connection_handler_open_connection(handler, 22,false,false,true,false) ) + return false; + + if( socket_api_stub.recv_cb ){ + sckt_data->event_type = SOCKET_DATA; + sckt_data->d_len = 1; + socket_api_stub.int8_value = -1; + socket_api_stub.recv_cb(sckt_data); + + nsdynmemlib_stub.returnCounter = 1; + socket_api_stub.recv_cb(sckt_data); + + nsdynmemlib_stub.returnCounter = 1; + socket_api_stub.int8_value = 1; + socket_api_stub.recv_cb(sckt_data); + } + + connection_handler_destroy(handler); + + nsdynmemlib_stub.returnCounter = 1; + coap_conn_handler_t *handler2 = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, &get_passwd_cb, &sec_done_cb); + nsdynmemlib_stub.returnCounter = 2; + if( 0 != coap_connection_handler_open_connection(handler2, 22,false,true,true,false) ) + return false; + + if( socket_api_stub.recv_cb ){ + nsdynmemlib_stub.returnCounter = 1; + socket_api_stub.int8_value = 1; + sckt_data->socket_id = 1; + socket_api_stub.recv_cb(sckt_data); + + nsdynmemlib_stub.returnCounter = 2; + socket_api_stub.int8_value = 1; + sckt_data->socket_id = 1; + socket_api_stub.recv_cb(sckt_data); + + nsdynmemlib_stub.returnCounter = 1; + socket_api_stub.int8_value = 1; + sckt_data->socket_id = 1; + socket_api_stub.recv_cb(sckt_data); + + coap_security_handler_stub.int_value = 4; + nsdynmemlib_stub.returnCounter = 1; + socket_api_stub.int8_value = 1; + sckt_data->socket_id = 1; + socket_api_stub.recv_cb(sckt_data); + + coap_security_handler_stub.int_value = MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY; + nsdynmemlib_stub.returnCounter = 1; + socket_api_stub.int8_value = 1; + sckt_data->socket_id = 1; + socket_api_stub.recv_cb(sckt_data); + } + + connection_handler_destroy(handler2); + + free(coap_security_handler_stub.sec_obj); + coap_security_handler_stub.sec_obj = NULL; + + free(sckt_data); + sckt_data = NULL; + return true; +} + +bool test_security_callbacks() +{ + coap_security_handler_stub.counter = -1; + uint8_t buf[16]; + memset(&buf, 1, 16); + + socket_callback_t *sckt_data = (socket_callback_t *)malloc(sizeof(socket_callback_t)); + memset(sckt_data, 0, sizeof(socket_callback_t)); + + coap_security_handler_stub.sec_obj = (coap_security_t *)malloc(sizeof(coap_security_t)); + memset(coap_security_handler_stub.sec_obj, 0, sizeof(coap_security_t)); + + nsdynmemlib_stub.returnCounter = 1; + coap_conn_handler_t *handler = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL); + nsdynmemlib_stub.returnCounter = 2; + if( 0 != coap_connection_handler_open_connection(handler, 22,false,true,true,false) ) + return false; + + if( socket_api_stub.recv_cb ){ + sckt_data->event_type = SOCKET_DATA; + sckt_data->d_len = 1; + nsdynmemlib_stub.returnCounter = 2; + socket_api_stub.int8_value = 1; + sckt_data->socket_id = 0; + socket_api_stub.recv_cb(sckt_data); + } + + if( coap_security_handler_stub.send_cb ){ + coap_security_handler_stub.send_cb(0, buf, 22, &buf, 16); + } + if( coap_security_handler_stub.receive_cb ){ + coap_security_handler_stub.receive_cb(0, &buf, 16); + } + + connection_handler_destroy(handler); + + free(coap_security_handler_stub.sec_obj); + coap_security_handler_stub.sec_obj = NULL; + + free(sckt_data); + sckt_data = NULL; + return true; +} diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_connection_handler/test_coap_connection_handler.h b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_connection_handler/test_coap_connection_handler.h new file mode 100644 index 0000000000..f13725af58 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_connection_handler/test_coap_connection_handler.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 TEST_COAP_CONNECTION_HANDLER_H +#define TEST_COAP_CONNECTION_HANDLER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +bool test_connection_handler_create(); + +bool test_connection_handler_destroy(); + +bool test_coap_connection_handler_open_connection(); + +bool test_coap_connection_handler_send_data(); + +bool test_coap_connection_handler_virtual_recv(); + +bool test_coap_connection_handler_socket_belongs_to(); + +bool test_timer_callbacks(); + +bool test_socket_api_callbacks(); + +bool test_security_callbacks(); + +#ifdef __cplusplus +} +#endif + +#endif // TEST_COAP_CONNECTION_HANDLER_H + diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_message_handler/coap_message_handlertest.cpp b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_message_handler/coap_message_handlertest.cpp new file mode 100644 index 0000000000..e36d92667d --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_message_handler/coap_message_handlertest.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ +#include "CppUTest/TestHarness.h" +#include "test_coap_message_handler.h" + +TEST_GROUP(coap_message_handler) +{ + void setup() + { + } + + void teardown() + { + } +}; + +TEST(coap_message_handler, test_coap_message_handler_init) +{ + CHECK(test_coap_message_handler_init()); +} + +TEST(coap_message_handler, test_coap_message_handler_destroy) +{ + CHECK(test_coap_message_handler_destroy()); +} + +TEST(coap_message_handler, test_coap_message_handler_find_transaction) +{ + CHECK(test_coap_message_handler_find_transaction()); +} + +TEST(coap_message_handler, test_coap_message_handler_coap_msg_process) +{ + CHECK(test_coap_message_handler_coap_msg_process()); +} + +TEST(coap_message_handler, test_coap_message_handler_request_send) +{ + CHECK(test_coap_message_handler_request_send()); +} + +TEST(coap_message_handler, test_coap_message_handler_response_send) +{ + CHECK(test_coap_message_handler_response_send()); +} + +TEST(coap_message_handler, test_coap_message_handler_exec) +{ + CHECK(test_coap_message_handler_exec()); +} + diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_message_handler/main.cpp b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_message_handler/main.cpp new file mode 100644 index 0000000000..f042e6bdeb --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_message_handler/main.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ + +#include "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP(coap_message_handler); + diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_message_handler/test_coap_message_handler.c b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_message_handler/test_coap_message_handler.c new file mode 100644 index 0000000000..9210150458 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_message_handler/test_coap_message_handler.c @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + */ +#include "test_coap_message_handler.h" +#include +#include "coap_message_handler.h" +#include "sn_coap_protocol_stub.h" +#include "nsdynmemLIB_stub.h" +#include "sn_coap_builder_stub.h" +#include "sn_coap_parser_stub.h" + +int retCounter = 0; +int retValue = 0; + +static void *own_alloc(uint16_t size) +{ + if( retCounter > 0 ){ + retCounter--; + return malloc(size); + } + return NULL; +} + +static void own_free(void *ptr) +{ + if (ptr) { + free(ptr); + } +} + +static uint8_t coap_tx_function(uint8_t *data_ptr, uint16_t data_len, sn_nsdl_addr_s *address_ptr, void *param) +{ + return 0; +} + +int resp_recv(int8_t service_id, uint16_t msg_id, sn_coap_hdr_s *response_ptr){ + return retValue; +} + +int16_t process_cb(int8_t a, sn_coap_hdr_s *b, coap_transaction_t *c) +{ + +} + +bool test_coap_message_handler_init() +{ + if( NULL != coap_message_handler_init(NULL, NULL, NULL) ) + return false; + if( NULL != coap_message_handler_init(&own_alloc, NULL, NULL) ) + return false; + if( NULL != coap_message_handler_init(&own_alloc, &own_free, NULL) ) + return false; + if( NULL != coap_message_handler_init(&own_alloc, &own_free, &coap_tx_function) ) + return false; + retCounter = 1; + sn_coap_protocol_stub.expectedCoap = NULL; + if( NULL != coap_message_handler_init(&own_alloc, &own_free, &coap_tx_function) ) + return false; + retCounter = 1; + sn_coap_protocol_stub.expectedCoap = (struct coap_s*)malloc(sizeof(struct coap_s)); + memset(sn_coap_protocol_stub.expectedCoap, 0, sizeof(struct coap_s)); + coap_msg_handler_t *handle = coap_message_handler_init(&own_alloc, &own_free, &coap_tx_function); + if( NULL == handle ) + return false; + free(sn_coap_protocol_stub.expectedCoap); + sn_coap_protocol_stub.expectedCoap = NULL; + free(handle); + return true; +} + +bool test_coap_message_handler_destroy() +{ + if( -1 != coap_message_handler_destroy(NULL) ) + return false; + retCounter = 1; + sn_coap_protocol_stub.expectedCoap = (struct coap_s*)malloc(sizeof(struct coap_s)); + memset(sn_coap_protocol_stub.expectedCoap, 0, sizeof(struct coap_s)); + coap_msg_handler_t *handle = coap_message_handler_init(&own_alloc, &own_free, &coap_tx_function); + + if( 0 != coap_message_handler_destroy(handle) ) + return false; + + free(sn_coap_protocol_stub.expectedCoap); + return true; +} + +bool test_coap_message_handler_find_transaction() +{ + if( NULL != coap_message_handler_find_transaction(NULL, 0)) + return false; + retCounter = 1; + sn_coap_protocol_stub.expectedCoap = (struct coap_s*)malloc(sizeof(struct coap_s)); + memset(sn_coap_protocol_stub.expectedCoap, 0, sizeof(struct coap_s)); + coap_msg_handler_t *handle = coap_message_handler_init(&own_alloc, &own_free, &coap_tx_function); + + uint8_t buf[16]; + memset(&buf, 1, 16); + char uri[3]; + uri[0] = "r"; + uri[1] = "s"; + uri[2] = "\0"; + + sn_coap_builder_stub.expectedUint16 = 1; + nsdynmemlib_stub.returnCounter = 3; + if( 2 != coap_message_handler_request_send(handle, 3, 0, buf, 24, 1, 2, &uri, 4, NULL, 0, &resp_recv)) + return false; + + if( NULL == coap_message_handler_find_transaction(&buf, 24)) + return false; + + free(sn_coap_protocol_stub.expectedCoap); + sn_coap_protocol_stub.expectedCoap = NULL; + coap_message_handler_destroy(handle); + return true; +} + +bool test_coap_message_handler_coap_msg_process() +{ + uint8_t buf[16]; + memset(&buf, 1, 16); + if( -1 != coap_message_handler_coap_msg_process(NULL, 0, buf, 22, NULL, 0, NULL)) + return false; + + retCounter = 1; + sn_coap_protocol_stub.expectedCoap = (struct coap_s*)malloc(sizeof(struct coap_s)); + memset(sn_coap_protocol_stub.expectedCoap, 0, sizeof(struct coap_s)); + coap_msg_handler_t *handle = coap_message_handler_init(&own_alloc, &own_free, &coap_tx_function); + + sn_coap_protocol_stub.expectedHeader = NULL; + if( -1 != coap_message_handler_coap_msg_process(handle, 0, buf, 22, NULL, 0, process_cb)) + return false; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 66; + if( -1 != coap_message_handler_coap_msg_process(handle, 0, buf, 22, NULL, 0, process_cb)) + return false; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = COAP_STATUS_OK; + sn_coap_protocol_stub.expectedHeader->msg_code = 1; + retValue = -1; + if( 0 != coap_message_handler_coap_msg_process(handle, 0, buf, 22, NULL, 0, process_cb)) + return false; + + nsdynmemlib_stub.returnCounter = 1; + if( -1 != coap_message_handler_coap_msg_process(handle, 0, buf, 22, NULL, 0, process_cb)) + return false; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = COAP_STATUS_OK; + sn_coap_protocol_stub.expectedHeader->msg_code = 333; + + if( -1 != coap_message_handler_coap_msg_process(handle, 0, buf, 22, NULL, 0, process_cb)) + return false; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = COAP_STATUS_OK; + sn_coap_protocol_stub.expectedHeader->msg_code = 333; + + char uri[3]; + uri[0] = "r"; + uri[1] = "s"; + uri[2] = "\0"; + + sn_coap_builder_stub.expectedUint16 = 1; + nsdynmemlib_stub.returnCounter = 3; + if( 2 != coap_message_handler_request_send(handle, 3, 0, buf, 24, 1, 2, &uri, 4, NULL, 0, &resp_recv)) + return false; + + sn_coap_protocol_stub.expectedHeader->msg_id = 2; +// sn_coap_protocol_stub.expectedHeader->token_ptr = (uint8_t*)malloc(4); +// memset(sn_coap_protocol_stub.expectedHeader->token_ptr, 1, 4); + if( -1 != coap_message_handler_coap_msg_process(handle, 0, buf, 22, NULL, 0, process_cb)) + return false; + +// free(sn_coap_protocol_stub.expectedHeader->token_ptr); + + free(sn_coap_protocol_stub.expectedCoap); + sn_coap_protocol_stub.expectedCoap = NULL; + coap_message_handler_destroy(handle); + return true; +} + +bool test_coap_message_handler_request_send() +{ + retCounter = 1; + sn_coap_protocol_stub.expectedCoap = (struct coap_s*)malloc(sizeof(struct coap_s)); + memset(sn_coap_protocol_stub.expectedCoap, 0, sizeof(struct coap_s)); + coap_msg_handler_t *handle = coap_message_handler_init(&own_alloc, &own_free, &coap_tx_function); + + uint8_t buf[16]; + memset(&buf, 1, 16); + char uri[3]; + uri[0] = "r"; + uri[1] = "s"; + uri[2] = "\0"; + if( 0 != coap_message_handler_request_send(handle, 3, 0, buf, 24, 1, 2, &uri, 4, NULL, 0, NULL)) + return false; + + sn_coap_builder_stub.expectedUint16 = 1; + nsdynmemlib_stub.returnCounter = 1; + if( 0 != coap_message_handler_request_send(handle, 3, 0, buf, 24, 1, 2, &uri, 4, NULL, 0, NULL)) + return false; + + sn_coap_builder_stub.expectedUint16 = 1; + nsdynmemlib_stub.returnCounter = 3; + if( 0 != coap_message_handler_request_send(handle, 3, 0, buf, 24, 1, 2, &uri, 4, NULL, 0, NULL)) + return false; + + sn_coap_builder_stub.expectedUint16 = 1; + nsdynmemlib_stub.returnCounter = 3; + if( 0 != coap_message_handler_request_send(handle, 3, 0, buf, 24, 1, 2, &uri, 4, NULL, 0, NULL)) + return false; + + sn_coap_builder_stub.expectedUint16 = 1; + nsdynmemlib_stub.returnCounter = 3; + if( 2 != coap_message_handler_request_send(handle, 3, 0, buf, 24, 1, 2, &uri, 4, NULL, 0, &resp_recv)) + return false; + + free(sn_coap_protocol_stub.expectedCoap); + sn_coap_protocol_stub.expectedCoap = NULL; + coap_message_handler_destroy(handle); + return true; +} + +bool test_coap_message_handler_response_send() +{ + if( -1 != coap_message_handler_response_send(NULL, 2, 0, NULL, 1,3,NULL, 0)) + return false; + + retCounter = 1; + sn_coap_protocol_stub.expectedCoap = (struct coap_s*)malloc(sizeof(struct coap_s)); + memset(sn_coap_protocol_stub.expectedCoap, 0, sizeof(struct coap_s)); + coap_msg_handler_t *handle = coap_message_handler_init(&own_alloc, &own_free, &coap_tx_function); + sn_coap_hdr_s *header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(header, 0, sizeof(sn_coap_hdr_s)); + + if( -2 != coap_message_handler_response_send(handle, 2, 0, header, 1,3,NULL, 0)) + return false; + + uint8_t buf[16]; + memset(&buf, 1, 16); + char uri[3]; + uri[0] = "r"; + uri[1] = "s"; + uri[2] = "\0"; + sn_coap_builder_stub.expectedUint16 = 1; + nsdynmemlib_stub.returnCounter = 3; + if( 2 != coap_message_handler_request_send(handle, 3, 0, buf, 24, 1, 2, &uri, 4, NULL, 0, &resp_recv)) + return false; + + header->msg_id = 2; + sn_coap_builder_stub.expectedUint16 = 2; + coap_transaction_t * tx = coap_message_handler_find_transaction(&buf, 24); + if( tx ){ + tx->client_request = false; + } + sn_coap_builder_stub.expectedHeader = NULL; + if( -1 != coap_message_handler_response_send(handle, 2, 0, header, 1,3,NULL, 0)) + return false; + + sn_coap_builder_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_builder_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + nsdynmemlib_stub.returnCounter = 1; + if( -1 != coap_message_handler_response_send(handle, 2, 0, header, 1,3,NULL, 0)) + return false; + + sn_coap_builder_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_builder_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + nsdynmemlib_stub.returnCounter = 2; + if( 0 != coap_message_handler_response_send(handle, 2, 0, header, 1,3,NULL, 0)) + return false; + +// free(header); + free(sn_coap_protocol_stub.expectedCoap); + sn_coap_protocol_stub.expectedCoap = NULL; + coap_message_handler_destroy(handle); + return true; +} + +bool test_coap_message_handler_exec() +{ + if( -1 != coap_message_handler_exec(NULL, 0)) + return false; + retCounter = 1; + sn_coap_protocol_stub.expectedCoap = (struct coap_s*)malloc(sizeof(struct coap_s)); + memset(sn_coap_protocol_stub.expectedCoap, 0, sizeof(struct coap_s)); + coap_msg_handler_t *handle = coap_message_handler_init(&own_alloc, &own_free, &coap_tx_function); + if( 0 != coap_message_handler_exec(handle, 0)) + return false; + + free(sn_coap_protocol_stub.expectedCoap); + sn_coap_protocol_stub.expectedCoap = NULL; + coap_message_handler_destroy(handle); + return true; +} diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_message_handler/test_coap_message_handler.h b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_message_handler/test_coap_message_handler.h new file mode 100644 index 0000000000..93a18f1ccd --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_message_handler/test_coap_message_handler.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 TEST_COAP_MESSAGE_HANDLER_H +#define TEST_COAP_MESSAGE_HANDLER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +bool test_coap_message_handler_init(); +bool test_coap_message_handler_destroy(); +bool test_coap_message_handler_find_transaction(); +bool test_coap_message_handler_coap_msg_process(); +bool test_coap_message_handler_request_send(); +bool test_coap_message_handler_response_send(); +bool test_coap_message_handler_exec(); + +#ifdef __cplusplus +} +#endif + +#endif // TEST_COAP_MESSAGE_HANDLER_H + diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_security_handler/coap_security_handlertest.cpp b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_security_handler/coap_security_handlertest.cpp new file mode 100644 index 0000000000..a649a0fb96 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_security_handler/coap_security_handlertest.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ +#include "CppUTest/TestHarness.h" +#include "test_coap_security_handler.h" +#include "mbedtls_stub.h" +#include "nsdynmemLIB_stub.h" + +TEST_GROUP(coap_security_handler) +{ + void setup() + { + nsdynmemlib_stub.returnCounter = 0; + mbedtls_stub.useCounter = false; + } + + void teardown() + { + } +}; + +TEST(coap_security_handler, test_thread_security_create) +{ + CHECK(test_thread_security_create()); +} + +TEST(coap_security_handler, test_thread_security_destroy) +{ + CHECK(test_thread_security_destroy()); +} + +TEST(coap_security_handler, test_coap_security_handler_connect) +{ + CHECK(test_coap_security_handler_connect()); +} + +TEST(coap_security_handler, test_coap_security_handler_continue_connecting) +{ + CHECK(test_coap_security_handler_continue_connecting()); +} + +TEST(coap_security_handler, test_coap_security_handler_send_message) +{ + CHECK(test_coap_security_handler_send_message()); +} + +TEST(coap_security_handler, test_thread_security_send_close_alert) +{ + CHECK(test_thread_security_send_close_alert()); +} + +TEST(coap_security_handler, test_coap_security_handler_read) +{ + CHECK(test_coap_security_handler_read()); +} diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_security_handler/main.cpp b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_security_handler/main.cpp new file mode 100644 index 0000000000..e657503fd1 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_security_handler/main.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ + +#include "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP(coap_security_handler); + diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_security_handler/test_coap_security_handler.c b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_security_handler/test_coap_security_handler.c new file mode 100644 index 0000000000..6585a9ed4c --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_security_handler/test_coap_security_handler.c @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2015-2016 ARM Limited. All Rights Reserved. + */ +#include "test_coap_security_handler.h" +#include "coap_security_handler.h" +#include +#include "nsdynmemLIB_stub.h" +#include "mbedtls_stub.h" +#include "mbedtls/ssl.h" + +static int send_to_socket(int8_t socket_id, uint8_t *address_ptr, uint16_t port, const unsigned char *buf, size_t len) +{ + +} + +static int receive_from_socket(int8_t socket_id, unsigned char *buf, size_t len) +{ + +} + +static void start_timer_callback(int8_t timer_id, uint32_t int_ms, uint32_t fin_ms) +{ + +} + +static int timer_status_callback(int8_t timer_id) +{ + +} + +bool test_thread_security_create() +{ + uint8_t buf[16]; + if( NULL != coap_security_create(1,2,&buf,12,ECJPAKE,&send_to_socket, &receive_from_socket, &start_timer_callback, NULL) ) + return false; + + if( NULL != coap_security_create(1,2,&buf,12,ECJPAKE,&send_to_socket, &receive_from_socket, &start_timer_callback, &timer_status_callback) ) + return false; + + nsdynmemlib_stub.returnCounter = 1; + mbedtls_stub.expected_int = -1; + if( NULL != coap_security_create(1,2,&buf,12,ECJPAKE,&send_to_socket, &receive_from_socket, &start_timer_callback, &timer_status_callback) ) + return false; + + mbedtls_stub.expected_int = 0; + nsdynmemlib_stub.returnCounter = 2; + mbedtls_stub.crt_expected_int = -1; + if( NULL != coap_security_create(1,2,&buf,12,ECJPAKE,&send_to_socket, &receive_from_socket, &start_timer_callback, &timer_status_callback) ) + return false; + + nsdynmemlib_stub.returnCounter = 2; + mbedtls_stub.crt_expected_int = 0; + coap_security_t *handle = coap_security_create(1,2,&buf,12,ECJPAKE,&send_to_socket, &receive_from_socket, &start_timer_callback, &timer_status_callback); + if( NULL == handle ) + return false; + + coap_security_destroy(handle); + + return true; +} + +bool test_thread_security_destroy() +{ + uint8_t buf[16]; + nsdynmemlib_stub.returnCounter = 2; + mbedtls_stub.crt_expected_int = 0; + coap_security_t *handle = coap_security_create(1,2,&buf,12,ECJPAKE,&send_to_socket, &receive_from_socket, &start_timer_callback, &timer_status_callback); + if( NULL == handle ) + return false; + + coap_security_destroy(handle); + return true; +} + +bool test_coap_security_handler_connect() +{ + uint8_t buf[16]; + nsdynmemlib_stub.returnCounter = 2; + mbedtls_stub.crt_expected_int = 0; + coap_security_t *handle = coap_security_create(1,2,&buf,12,ECJPAKE,&send_to_socket, &receive_from_socket, &start_timer_callback, &timer_status_callback); + if( NULL == handle ) + return false; + + unsigned char pw = "pwd"; + coap_security_keys_t keys; + keys._priv = &pw; + keys._priv_len = 3; + if( -1 != coap_security_handler_connect_non_blocking(NULL, true, DTLS, keys, 0, 1) ) + return false; + mbedtls_stub.useCounter = true; + mbedtls_stub.counter = 0; + mbedtls_stub.retArray[0] = -1; + mbedtls_stub.retArray[1] = -1; + mbedtls_stub.retArray[2] = -1; + mbedtls_stub.retArray[3] = -1; + mbedtls_stub.retArray[4] = -1; + mbedtls_stub.retArray[5] = MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED; + mbedtls_stub.retArray[6] = -1; + mbedtls_stub.retArray[7] = -1; + + if( -1 != coap_security_handler_connect_non_blocking(handle, true, DTLS, keys, 0, 1) ) + return false; + + mbedtls_stub.counter = 0; + mbedtls_stub.retArray[0] = 0; + if( -1 != coap_security_handler_connect_non_blocking(handle, true, DTLS, keys, 0, 1) ) + return false; + + mbedtls_stub.counter = 0; +// mbedtls_stub.retArray[0] = 0; + mbedtls_stub.retArray[1] = 0; + if( -1 != coap_security_handler_connect_non_blocking(handle, true, DTLS, keys, 0, 1) ) + return false; + + simple_cookie_t c; + memset(&c, 0, sizeof(simple_cookie_t)); + mbedtls_stub.cookie_obj = &c; + memset(&mbedtls_stub.cookie_value, 1, 8); + mbedtls_stub.cookie_len = 2; + mbedtls_stub.counter = 0; +// mbedtls_stub.retArray[0] = 0; +// mbedtls_stub.retArray[1] = 0; + mbedtls_stub.retArray[2] = 0; + if( -1 != coap_security_handler_connect_non_blocking(handle, true, DTLS, keys, 0, 1) ) + return false; + + c.len = 8; + memset(&c.value, 1, 8); + mbedtls_stub.cookie_obj = &c; + memset(&mbedtls_stub.cookie_value, 1, 8); + + mbedtls_stub.cookie_len = 8; + mbedtls_stub.counter = 0; +// mbedtls_stub.retArray[0] = 0; +// mbedtls_stub.retArray[1] = 0; +// mbedtls_stub.retArray[2] = 0; + mbedtls_stub.retArray[3] = 0; + if( -1 != coap_security_handler_connect_non_blocking(handle, true, DTLS, keys, 0, 1) ) + return false; + + mbedtls_stub.counter = 0; +// mbedtls_stub.retArray[0] = 0; +// mbedtls_stub.retArray[1] = 0; +// mbedtls_stub.retArray[2] = 0; +// mbedtls_stub.retArray[3] = 0; + mbedtls_stub.retArray[4] = 0; + if( -1 != coap_security_handler_connect_non_blocking(handle, true, DTLS, keys, 0, 1) ) + return false; + + mbedtls_stub.counter = 0; +// mbedtls_stub.retArray[0] = 0; +// mbedtls_stub.retArray[1] = 0; +// mbedtls_stub.retArray[2] = 0; +// mbedtls_stub.retArray[3] = 0; +// mbedtls_stub.retArray[4] = 0; + mbedtls_stub.retArray[6] = 0; + mbedtls_stub.retArray[7] = 0; + if( 1 != coap_security_handler_connect_non_blocking(handle, true, DTLS, keys, 0, 1) ) + return false; + + mbedtls_stub.counter = 0; + mbedtls_stub.retArray[5] = MBEDTLS_ERR_SSL_BAD_HS_FINISHED; + + if( -1 != coap_security_handler_connect_non_blocking(handle, true, DTLS, keys, 0, 1) ) + return false; + + mbedtls_stub.counter = 0; + mbedtls_stub.retArray[5] = HANDSHAKE_FINISHED_VALUE; + + if( 1 != coap_security_handler_connect_non_blocking(handle, true, DTLS, keys, 0, 1) ) + return false; + + coap_security_destroy(handle); + return true; +} + +bool test_coap_security_handler_continue_connecting() +{ + uint8_t buf[16]; + nsdynmemlib_stub.returnCounter = 2; + mbedtls_stub.crt_expected_int = 0; + coap_security_t *handle = coap_security_create(1,2,&buf,12,ECJPAKE,&send_to_socket, &receive_from_socket, &start_timer_callback, &timer_status_callback); + if( NULL == handle ) + return false; + + mbedtls_stub.useCounter = true; + mbedtls_stub.counter = 0; + mbedtls_stub.retArray[0] = MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED; + mbedtls_stub.retArray[1] = -1; + mbedtls_stub.retArray[2] = -1; + + if( -1 != coap_security_handler_continue_connecting(handle) ) + return false; + + mbedtls_stub.counter = 0; + mbedtls_stub.retArray[0] = MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED; + mbedtls_stub.retArray[1] = 0; + mbedtls_stub.retArray[2] = 0; + + if( 1 != coap_security_handler_continue_connecting(handle) ) + return false; + + mbedtls_stub.counter = 0; + mbedtls_stub.retArray[0] = MBEDTLS_ERR_SSL_BAD_HS_FINISHED; + + if( MBEDTLS_ERR_SSL_BAD_HS_FINISHED != coap_security_handler_continue_connecting(handle) ) + return false; + + mbedtls_stub.counter = 0; + mbedtls_stub.retArray[0] = MBEDTLS_ERR_SSL_WANT_READ; + + if( 1 != coap_security_handler_continue_connecting(handle) ) + return false; + + mbedtls_stub.counter = 0; + mbedtls_stub.retArray[0] = HANDSHAKE_FINISHED_VALUE_RETURN_ZERO; + + if( 0 != coap_security_handler_continue_connecting(handle) ) + return false; + + coap_security_destroy(handle); + return true; +} + +bool test_coap_security_handler_send_message() +{ + uint8_t buf[16]; + nsdynmemlib_stub.returnCounter = 2; + mbedtls_stub.crt_expected_int = 0; + coap_security_t *handle = coap_security_create(1,2,&buf,12,ECJPAKE,&send_to_socket, &receive_from_socket, &start_timer_callback, &timer_status_callback); + if( NULL == handle ) + return false; + + if( -1 != coap_security_handler_send_message(NULL, NULL, 0)) + return false; + + mbedtls_stub.expected_int = 6; + unsigned char cbuf[6]; + if( 6 != coap_security_handler_send_message(handle, &cbuf, 6)) + return false; + + coap_security_destroy(handle); + return true; +} + +bool test_thread_security_send_close_alert() +{ + uint8_t buf[16]; + nsdynmemlib_stub.returnCounter = 2; + mbedtls_stub.crt_expected_int = 0; + coap_security_t *handle = coap_security_create(1,2,&buf,12,ECJPAKE,&send_to_socket, &receive_from_socket, &start_timer_callback, &timer_status_callback); + if( NULL == handle ) + return false; + + if( -1 != coap_security_send_close_alert(NULL)) + return false; + + mbedtls_stub.expected_int = 0; + if( 0 != coap_security_send_close_alert(handle)) + return false; + + coap_security_destroy(handle); + return true; +} + +bool test_coap_security_handler_read() +{ + uint8_t buf[16]; + nsdynmemlib_stub.returnCounter = 2; + mbedtls_stub.crt_expected_int = 0; + coap_security_t *handle = coap_security_create(1,2,&buf,12,ECJPAKE,&send_to_socket, &receive_from_socket, &start_timer_callback, &timer_status_callback); + if( NULL == handle ) + return false; + + if( -1 != coap_security_handler_read(NULL, NULL, 0)) + return false; + + mbedtls_stub.expected_int = 6; + unsigned char cbuf[6]; + if( 6 != coap_security_handler_read(handle, &cbuf, 6)) + return false; + + coap_security_destroy(handle); + return true; +} + diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_security_handler/test_coap_security_handler.h b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_security_handler/test_coap_security_handler.h new file mode 100644 index 0000000000..1b06bed343 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_security_handler/test_coap_security_handler.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 TEST_COAP_SECURITY_HANDLER_H +#define TEST_COAP_SECURITY_HANDLER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +bool test_thread_security_create(); + +bool test_thread_security_destroy(); + +bool test_coap_security_handler_connect(); + +bool test_coap_security_handler_continue_connecting(); + +bool test_coap_security_handler_send_message(); + +bool test_thread_security_send_close_alert(); + +bool test_coap_security_handler_read(); + +#ifdef __cplusplus +} +#endif + +#endif // TEST_COAP_SECURITY_HANDLER_H + diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_service_api/coap_service_apitest.cpp b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_service_api/coap_service_apitest.cpp new file mode 100644 index 0000000000..9054de6313 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_service_api/coap_service_apitest.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ +#include "CppUTest/TestHarness.h" +#include "test_coap_service_api.h" + +TEST_GROUP(coap_service_api) +{ + void setup() + { + } + + void teardown() + { + } +}; + +TEST(coap_service_api, test_coap_service_initialize) +{ + CHECK(test_coap_service_initialize()); +} + +TEST(coap_service_api, test_coap_service_delete) +{ + CHECK(test_coap_service_delete()); +} + +TEST(coap_service_api, test_coap_service_virtual_socket_recv) +{ + CHECK(test_coap_service_virtual_socket_recv()); +} + +TEST(coap_service_api, test_coap_service_virtual_socket_set_cb) +{ + CHECK(test_coap_service_virtual_socket_set_cb()); +} + +TEST(coap_service_api, test_coap_service_register_uri) +{ + CHECK(test_coap_service_register_uri()); +} + +TEST(coap_service_api, test_coap_service_unregister_uri) +{ + CHECK(test_coap_service_unregister_uri()); +} + +TEST(coap_service_api, test_coap_service_request_send) +{ + CHECK(test_coap_service_request_send()); +} + +TEST(coap_service_api, test_coap_service_response_send) +{ + CHECK(test_coap_service_response_send()); +} + +TEST(coap_service_api, test_coap_callbacks) +{ + CHECK(test_coap_callbacks()); +} + +TEST(coap_service_api, test_eventOS_callbacks) +{ + CHECK(test_eventOS_callbacks()); +} + +TEST(coap_service_api, test_conn_handler_callbacks) +{ + CHECK(test_conn_handler_callbacks()); +} + diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_service_api/main.cpp b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_service_api/main.cpp new file mode 100644 index 0000000000..e050cec95f --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_service_api/main.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ + +#include "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP(coap_service_api); + diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_service_api/test_coap_service_api.c b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_service_api/test_coap_service_api.c new file mode 100644 index 0000000000..5cc5f380d2 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_service_api/test_coap_service_api.c @@ -0,0 +1,418 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + */ +#include "test_coap_service_api.h" +#include +#include "coap_service_api.h" +#include "nsdynmemLIB_stub.h" +#include "coap_connection_handler_stub.h" +#include "coap_message_handler_stub.h" +#include "eventOS_event_stub.h" +#include "eventOS_event.h" +#include "net_interface.h" + +int sec_done_cb(int8_t service_id, uint8_t address[static 16], uint8_t keyblock[static 40]){ + return 2; +} + +int sec_start_cb(int8_t service_id, uint8_t address[static 16], uint16_t port, uint8_t* pw, uint8_t *pw_len) +{ + return 2; +} + +int request_recv_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *request_ptr) +{ + return 2; +} + +int virtual_sock_send_cb(int8_t service_id, uint8_t destination_addr_ptr[static 16], uint16_t port, const uint8_t *data_ptr, uint16_t data_len) +{ + return 2; +} + +bool test_coap_service_initialize() +{ + if( -1 != coap_service_initialize(1, 2, 0, NULL, NULL )) + return false; + + + nsdynmemlib_stub.returnCounter = 1; + thread_conn_handler_stub.handler_obj = NULL; + if( -1 != coap_service_initialize(1, 2, 0, NULL, NULL )) + return false; + + thread_conn_handler_stub.handler_obj = (coap_conn_handler_t*)malloc(sizeof(coap_conn_handler_t)); + memset(thread_conn_handler_stub.handler_obj, 0, sizeof(coap_conn_handler_t)); + coap_message_handler_stub.coap_ptr = NULL; + + nsdynmemlib_stub.returnCounter = 1; + thread_conn_handler_stub.int_value = -1; + if( -1 != coap_service_initialize(1, 2, 0, NULL, NULL )) + return false; + + thread_conn_handler_stub.handler_obj = (coap_conn_handler_t*)malloc(sizeof(coap_conn_handler_t)); + memset(thread_conn_handler_stub.handler_obj, 0, sizeof(coap_conn_handler_t)); + nsdynmemlib_stub.returnCounter = 1; + thread_conn_handler_stub.int_value = 0; + + if( 1 != coap_service_initialize(1, 2, 0, NULL, NULL )) + return false; + + nsdynmemlib_stub.returnCounter = 1; + if( 2 != coap_service_initialize(3, 4, 0, NULL, NULL )) + return false; + + coap_service_delete(2); + coap_service_delete(1); + + free( thread_conn_handler_stub.handler_obj ); + thread_conn_handler_stub.handler_obj = NULL; + return true; +} + +bool test_coap_service_delete() +{ + coap_service_delete(1); + + thread_conn_handler_stub.handler_obj = (coap_conn_handler_t*)malloc(sizeof(coap_conn_handler_t)); + memset(thread_conn_handler_stub.handler_obj, 0, sizeof(coap_conn_handler_t)); + nsdynmemlib_stub.returnCounter = 1; + coap_message_handler_stub.coap_ptr = NULL; + + if( 1 != coap_service_initialize(1, 2, 0, NULL, NULL )) + return false; + + coap_service_delete(1); + + free( thread_conn_handler_stub.handler_obj ); + thread_conn_handler_stub.handler_obj = NULL; + + return true; +} + +bool test_coap_service_virtual_socket_recv() +{ + uint8_t buf[16]; + if( -1 != coap_service_virtual_socket_recv(1, &buf, 10, NULL, 0) ) + return false; + + thread_conn_handler_stub.handler_obj = (coap_conn_handler_t*)malloc(sizeof(coap_conn_handler_t)); + memset(thread_conn_handler_stub.handler_obj, 0, sizeof(coap_conn_handler_t)); + nsdynmemlib_stub.returnCounter = 1; + coap_message_handler_stub.coap_ptr = NULL; + + if( 1 != coap_service_initialize(1, 2, 0, NULL, NULL )) + return false; + + thread_conn_handler_stub.int_value = 5; + if( 5 != coap_service_virtual_socket_recv(1, &buf, 10, NULL, 0) ) + return false; + + coap_service_delete(1); + + free( thread_conn_handler_stub.handler_obj ); + thread_conn_handler_stub.handler_obj = NULL; + + thread_conn_handler_stub.int_value = 0; + + return true; +} + +bool test_coap_service_virtual_socket_set_cb() +{ + if( -1 != coap_service_virtual_socket_set_cb(1, NULL) ) + return false; + + thread_conn_handler_stub.handler_obj = (coap_conn_handler_t*)malloc(sizeof(coap_conn_handler_t)); + memset(thread_conn_handler_stub.handler_obj, 0, sizeof(coap_conn_handler_t)); + nsdynmemlib_stub.returnCounter = 1; + coap_message_handler_stub.coap_ptr = NULL; + + if( 1 != coap_service_initialize(1, 2, 0, NULL, NULL )) + return false; + + if( 0 != coap_service_virtual_socket_set_cb(1, NULL) ) + return false; + + coap_service_delete(1); + + free( thread_conn_handler_stub.handler_obj ); + thread_conn_handler_stub.handler_obj = NULL; + + return true; +} + +bool test_coap_service_register_uri() +{ + if( -1 != coap_service_register_uri(1, "as", 1, &request_recv_cb)) + return false; + + thread_conn_handler_stub.handler_obj = (coap_conn_handler_t*)malloc(sizeof(coap_conn_handler_t)); + memset(thread_conn_handler_stub.handler_obj, 0, sizeof(coap_conn_handler_t)); + nsdynmemlib_stub.returnCounter = 1; + coap_message_handler_stub.coap_ptr = NULL; + + if( 1 != coap_service_initialize(1, 2, 0, NULL, NULL )) + return false; + + if( -2 != coap_service_register_uri(1, "as", 1, &request_recv_cb) ) + return false; + + nsdynmemlib_stub.returnCounter = 1; + if( -2 != coap_service_register_uri(1, "as", 1, &request_recv_cb) ) + return false; + + nsdynmemlib_stub.returnCounter = 2; + if( 0 != coap_service_register_uri(1, "as", 1, &request_recv_cb) ) + return false; + + coap_service_delete(1); + + free( thread_conn_handler_stub.handler_obj ); + thread_conn_handler_stub.handler_obj = NULL; + + return true; +} + +bool test_coap_service_unregister_uri() +{ + if( -1 != coap_service_unregister_uri(1, "as")) + return false; + + thread_conn_handler_stub.handler_obj = (coap_conn_handler_t*)malloc(sizeof(coap_conn_handler_t)); + memset(thread_conn_handler_stub.handler_obj, 0, sizeof(coap_conn_handler_t)); + nsdynmemlib_stub.returnCounter = 1; + coap_message_handler_stub.coap_ptr = NULL; + thread_conn_handler_stub.int_value = 0; + + if( 1 != coap_service_initialize(1, 2, 0, NULL, NULL )) + return false; + + nsdynmemlib_stub.returnCounter = 2; + if( 0 != coap_service_register_uri(1, "as", 1, &request_recv_cb) ) + return false; + + if( -2 != coap_service_unregister_uri(1, "ts") ) + return false; + + if( 0 != coap_service_unregister_uri(1, "as") ) + return false; + + coap_service_delete(1); + + free( thread_conn_handler_stub.handler_obj ); + thread_conn_handler_stub.handler_obj = NULL; + + return true; +} + +bool test_coap_service_request_send() +{ + uint8_t buf[16]; + coap_message_handler_stub.uint16_value = 6; + if( 6 != coap_service_request_send(0,0,&buf,0,0,0,NULL, 0,NULL,0,NULL)) + return false; + return true; +} + +bool test_coap_service_response_send() +{ + uint8_t buf[16]; + coap_message_handler_stub.int8_value = 6; + if( 6 != coap_service_response_send(0,0,NULL, 65, 0,NULL, 0)) + return false; + return true; +} + +bool test_coap_callbacks() +{ + thread_conn_handler_stub.handler_obj = (coap_conn_handler_t*)malloc(sizeof(coap_conn_handler_t)); + memset(thread_conn_handler_stub.handler_obj, 0, sizeof(coap_conn_handler_t)); + nsdynmemlib_stub.returnCounter = 1; + coap_message_handler_stub.coap_ptr = (coap_msg_handler_t *)malloc(sizeof(coap_msg_handler_t)); + memset(coap_message_handler_stub.coap_ptr, 0, sizeof(coap_msg_handler_t)); + + if( 1 != coap_service_initialize(1, 2, 0, NULL, NULL )) + return false; + + if( 0 != coap_message_handler_stub.coap_ptr->sn_coap_service_malloc(0)) + return false; + + nsdynmemlib_stub.returnCounter = 1; + void *handle = coap_message_handler_stub.coap_ptr->sn_coap_service_malloc(5); + if( 0 == handle ) + return false; + + coap_message_handler_stub.coap_ptr->sn_coap_service_free(handle); + + //coap_tx_function + uint8_t data[14]; + memset(&data, 3, 14); + sn_nsdl_addr_s addr; + addr.addr_len = 2; + addr.port = 4; + addr.addr_ptr = &data; + if( 255 != coap_message_handler_stub.coap_ptr->sn_coap_tx_callback(NULL, 0, &addr, NULL)) + return false; + + coap_transaction_t *tr = (coap_transaction_t *)malloc(sizeof(coap_transaction_t)); + memset(tr, 0, sizeof(coap_transaction_t)); + + if( 255 != coap_message_handler_stub.coap_ptr->sn_coap_tx_callback(&data, 0, &addr, tr)) + return false; + + tr->service_id = 1; + thread_conn_handler_stub.int_value = -2; + if( 255 != coap_message_handler_stub.coap_ptr->sn_coap_tx_callback(&data, 0, &addr, tr)) + return false; + + nsdynmemlib_stub.returnCounter = 1; + if( 255 != coap_message_handler_stub.coap_ptr->sn_coap_tx_callback(&data, 2, &addr, tr)) + return false; + + free(tr->data_ptr); + free(tr); + + coap_service_delete(1); + + free( coap_message_handler_stub.coap_ptr ); + coap_message_handler_stub.coap_ptr = NULL; + + free( thread_conn_handler_stub.handler_obj ); + thread_conn_handler_stub.handler_obj = NULL; + + return true; +} + +#define COAP_TICK_TIMER 0xf1 //MUST BE SAME AS IN coap_service_api.c +bool test_eventOS_callbacks() +{ + thread_conn_handler_stub.handler_obj = (coap_conn_handler_t*)malloc(sizeof(coap_conn_handler_t)); + memset(thread_conn_handler_stub.handler_obj, 0, sizeof(coap_conn_handler_t)); + nsdynmemlib_stub.returnCounter = 1; + if( 1 != coap_service_initialize(1, 2, 0, NULL, NULL )) + return false; + + if( eventOs_event_stub.event_ptr ){ + arm_event_s event; + event.event_type = ARM_LIB_TASKLET_INIT_EVENT; + eventOs_event_stub.event_ptr(&event); + + event.event_type = ARM_LIB_SYSTEM_TIMER_EVENT; + event.event_id = COAP_TICK_TIMER; + eventOs_event_stub.event_ptr(&event); + } + + coap_service_delete(1); + free( thread_conn_handler_stub.handler_obj ); + thread_conn_handler_stub.handler_obj = NULL; + return true; +} + +bool test_conn_handler_callbacks() +{ + uint8_t buf[16]; + thread_conn_handler_stub.handler_obj = (coap_conn_handler_t*)malloc(sizeof(coap_conn_handler_t)); + memset(thread_conn_handler_stub.handler_obj, 0, sizeof(coap_conn_handler_t)); + nsdynmemlib_stub.returnCounter = 1; + if( 1 != coap_service_initialize(1, 2, COAP_SERVICE_OPTIONS_SECURE_BYPASS, &sec_start_cb, &sec_done_cb )) + return false; + + if( thread_conn_handler_stub.send_to_sock_cb ){ + thread_conn_handler_stub.bool_value = true; + coap_service_virtual_socket_set_cb(1, &virtual_sock_send_cb); + if( 2 != thread_conn_handler_stub.send_to_sock_cb(1, buf, 12, NULL, 0)) + return false; + thread_conn_handler_stub.bool_value = false; + if( -1 != thread_conn_handler_stub.send_to_sock_cb(1, buf, 12, NULL, 0)) + return false; + } + + if( thread_conn_handler_stub.receive_from_sock_cb ){ + coap_message_handler_stub.int16_value = 2; + if( -1 != thread_conn_handler_stub.receive_from_sock_cb(1, buf, 12, NULL, 0)) + return false; + + nsdynmemlib_stub.returnCounter = 1; + uint8_t * ptr = ns_dyn_mem_alloc(5); + memset(ptr, 3, 5); + nsdynmemlib_stub.returnCounter = 1; + if( 2 != thread_conn_handler_stub.receive_from_sock_cb(1, buf, 12, ptr, 5)) + return false; + ns_dyn_mem_free(ptr); + coap_message_handler_stub.int16_value = 0; + + //This could be moved to own test function, + //but thread_conn_handler_stub.receive_from_sock_cb must be called successfully + if( coap_message_handler_stub.cb ){ + if( -1 != coap_message_handler_stub.cb(1, NULL, NULL) ) + return false; + + sn_coap_hdr_s * coap = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(coap, 0, sizeof(sn_coap_hdr_s)); + + uint8_t uri[2] = "as"; + coap->uri_path_ptr = &uri; + coap->uri_path_len=2; + + if( -1 != coap_message_handler_stub.cb(1, coap, NULL) ) + return false; + + thread_conn_handler_stub.bool_value = true; + nsdynmemlib_stub.returnCounter = 2; + if( 0 != coap_service_register_uri(1, "as", 1, &request_recv_cb) ) + return false; + + if( -1 != coap_message_handler_stub.cb(1, coap, NULL) ) + return false; + + coap_transaction_t *tr = (coap_transaction_t *)malloc(sizeof(coap_transaction_t)); + memset(tr, 0, sizeof(coap_transaction_t)); + + if( 2 != coap_message_handler_stub.cb(1, coap, tr) ) + return false; + + free(tr); + tr = NULL; + + thread_conn_handler_stub.bool_value = false; + free(coap); + coap = NULL; + } + } + + if(thread_conn_handler_stub.get_passwd_cb){ + thread_conn_handler_stub.bool_value = true; + if( 2 != thread_conn_handler_stub.get_passwd_cb(1, buf, 12, NULL, 0)) + return false; + thread_conn_handler_stub.bool_value = false; + if( -1 != thread_conn_handler_stub.get_passwd_cb(1, buf, 12, NULL, 0)) + return false; + } + + if(thread_conn_handler_stub.sec_done_cb){ + uint8_t block[40]; + thread_conn_handler_stub.bool_value = true; + + coap_transaction_t *tr = (coap_transaction_t *)malloc(sizeof(coap_transaction_t)); + memset(tr, 0, sizeof(coap_transaction_t)); + nsdynmemlib_stub.returnCounter = 1; + tr->data_ptr = ns_dyn_mem_alloc(1); + tr->data_len = 1; + coap_message_handler_stub.coap_tx_ptr = tr; + + thread_conn_handler_stub.sec_done_cb(1, buf, 12, block); + + free(tr); + coap_message_handler_stub.coap_tx_ptr = NULL; + + thread_conn_handler_stub.bool_value = false; + + } + + coap_service_delete(1); + free( thread_conn_handler_stub.handler_obj ); + thread_conn_handler_stub.handler_obj = NULL; + + return true; +} diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_service_api/test_coap_service_api.h b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_service_api/test_coap_service_api.h new file mode 100644 index 0000000000..94916476c3 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/coap_service_api/test_coap_service_api.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 TEST_COAP_SERVICE_API_H +#define TEST_COAP_SERVICE_API_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +bool test_coap_service_initialize(); + +bool test_coap_service_delete(); + +bool test_coap_service_virtual_socket_recv(); + +bool test_coap_service_virtual_socket_set_cb(); + +bool test_coap_service_register_uri(); + +bool test_coap_service_unregister_uri(); + +bool test_coap_service_request_send(); + +bool test_coap_service_response_send(); + +bool test_coap_callbacks(); + +bool test_eventOS_callbacks(); + +bool test_conn_handler_callbacks(); + + +#ifdef __cplusplus +} +#endif + +#endif // TEST_COAP_SERVICE_API_H + diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/makefile_defines.txt b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/makefile_defines.txt new file mode 100755 index 0000000000..9991a6eaaf --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/makefile_defines.txt @@ -0,0 +1,40 @@ +#--- Inputs ----# +CPPUTEST_HOME = /usr +CPPUTEST_USE_EXTENSIONS = Y +CPPUTEST_USE_VPATH = Y +CPPUTEST_USE_GCOV = Y +CPP_PLATFORM = gcc + +INCLUDE_DIRS =\ + .\ + ../stub\ + ../../../../coap-service/\ + ../../../../source/include/\ + ../../../../yotta_modules/mbedtls/ \ + ../../../../yotta_modules/sal-stack-nanostack/nanostack/ \ + ../../../../yotta_modules/nanostack-randlib/mbed-client-randlib/ \ + ../../../../yotta_modules/nanostack-libservice/ \ + ../../../../yotta_modules/nanostack-libservice/mbed-client-libservice/ \ + ../../../../yotta_modules/mbed-client-c/nsdl-c/ \ + ../../../../yotta_modules/mbed-client-c/source/libCoap/src/include/ \ + ../../../../yotta_modules/sal-stack-nanostack-eventloop/nanostack-event-loop/ \ + ../../../../yotta_modules/sal-stack-nanostack-eventloop/source/ \ + ../../../../yotta_modules/mbed-trace/ \ + ../../../../../nanostack/nanostack/\ + ../../../../../libService/libService/\ + ../../../../../nsdl-c/nsdl-c/\ + ../../../../../nsdl-c/source/libCoap/src/include/\ + ../../../../../event-loop/nanostack-event-loop/\ + ../../../../../event-loop/source/ \ + ../../../../../mbedtls/include/ \ + ../../../../../mbedtls/include/mbedtls/ \ + /usr/include\ + $(CPPUTEST_HOME)/include\ + +CPPUTESTFLAGS = -D__thumb2__ -w +CPPUTEST_CFLAGS += -std=gnu99 + +#if you need to use -std=c++11 or c++0x you need to uncomment this +#CPPUTESTFLAGS += -DCPPUTEST_STD_CPP_LIB_DISABLED +#CPPUTEST_CXXFLAGS += -std=gnu++0x + diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/run_tests b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/run_tests new file mode 100755 index 0000000000..ce3fc0c170 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/run_tests @@ -0,0 +1,35 @@ +#!/bin/bash +echo +echo Build Coap-service unit tests +echo + +# Remember to add new test folder to Makefile +make clean +make all + +echo +echo Create results +echo +mkdir results +find ./ -name '*.xml' | xargs cp -t ./results/ + +echo +echo Create coverage document +echo +mkdir coverages +cd coverages + +lcov -q -d ../. -c -o app.info +lcov -q -r app.info "/test*" -o app.info +lcov -q -r app.info "/usr*" -o app.info +lcov -q -r app.info "/libService*" -o app.info +lcov -q -r app.info "/yotta_modules*" -o app.info +genhtml -q --no-branch-coverage app.info +cd .. +echo +echo +echo +echo Have a nice bug hunt! +echo +echo +echo diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_connection_handler_stub.c b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_connection_handler_stub.c new file mode 100644 index 0000000000..83e6ce7828 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_connection_handler_stub.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + */ + +#include +#include "coap_connection_handler.h" +#include "coap_security_handler.h" +#include "ns_list.h" +#include "ns_trace.h" +#include "nsdynmemLIB.h" +#include "socket_api.h" +#include "net_interface.h" +#include "eventOS_callback_timer.h" +#include "coap_connection_handler_stub.h" + +thread_conn_handler_stub_def thread_conn_handler_stub; + +int coap_connection_handler_virtual_recv(coap_conn_handler_t *handler, uint8_t address[static 16], uint16_t port, uint8_t *data_ptr, uint16_t data_len) +{ + return thread_conn_handler_stub.int_value; +} + +coap_conn_handler_t *connection_handler_create(int (*recv_cb)(int8_t socket_id, uint8_t address[static 16], uint16_t port, unsigned char *, int), + int (*send_cb)(int8_t socket_id, uint8_t address[static 16], uint16_t port, const unsigned char *, int), + int (*pw_cb)(int8_t socket_id, uint8_t address[static 16], uint16_t port, uint8_t *pw_ptr, uint8_t *pw_len), + void(*done_cb)(int8_t socket_id, uint8_t address[static 16], uint16_t port, uint8_t keyblock[static KEY_BLOCK_LEN]) ) +{ + thread_conn_handler_stub.send_to_sock_cb = send_cb; + thread_conn_handler_stub.receive_from_sock_cb = recv_cb; + thread_conn_handler_stub.get_passwd_cb = pw_cb; + thread_conn_handler_stub.sec_done_cb = done_cb; + return thread_conn_handler_stub.handler_obj; +} + +void connection_handler_destroy(coap_conn_handler_t *handler) +{ + +} +void connection_handler_close_secure_connection( coap_conn_handler_t *handler, uint8_t destination_addr_ptr[static 16], uint16_t port ) +{ + +} + +int coap_connection_handler_open_connection(coap_conn_handler_t *handler, uint16_t listen_port, bool use_ephemeral_port, bool is_secure, bool is_real_socket, bool bypassSec) +{ + return thread_conn_handler_stub.int_value; +} + +int coap_connection_handler_send_data(coap_conn_handler_t *handler, ns_address_t *dest_addr, uint8_t *data_ptr, uint16_t data_len, bool bypass_link_sec) +{ + return thread_conn_handler_stub.int_value; +} + +bool coap_connection_handler_socket_belongs_to(coap_conn_handler_t *handler, int8_t socket_id) +{ + return thread_conn_handler_stub.bool_value; +} + +int8_t coap_connection_handler_set_timeout(coap_conn_handler_t *handler, uint32_t min, uint32_t max) +{ + return 0; +} + +void coap_connection_handler_exec(uint32_t time) +{ + +} diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_connection_handler_stub.h b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_connection_handler_stub.h new file mode 100644 index 0000000000..5d24c67859 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_connection_handler_stub.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 __COAP_CONNECTION_HANDLER_STUB_H__ +#define __COAP_CONNECTION_HANDLER_STUB_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "coap_connection_handler.h" + +typedef struct { + int int_value; + bool bool_value; + coap_conn_handler_t *handler_obj; + + int (*send_to_sock_cb)(int8_t socket_id, uint8_t address[static 16], uint16_t port, const unsigned char *, int); + int (*receive_from_sock_cb)(int8_t socket_id, uint8_t address[static 16], uint16_t port, unsigned char *, int); + int (*get_passwd_cb)(int8_t socket_id, uint8_t address[static 16], uint16_t port, uint8_t *pw_ptr, uint8_t *pw_len); + void (*sec_done_cb)(int8_t socket_id, uint8_t address[static 16], uint16_t port, uint8_t keyblock[static 40]); + +} thread_conn_handler_stub_def; + +extern thread_conn_handler_stub_def thread_conn_handler_stub; + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_message_handler_stub.c b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_message_handler_stub.c new file mode 100644 index 0000000000..68f2b66912 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_message_handler_stub.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015-2016 ARM Limited. All Rights Reserved. + */ + +#include "coap_message_handler_stub.h" + +coap_message_handler_stub_def coap_message_handler_stub; + +coap_msg_handler_t *coap_message_handler_init(void *(*used_malloc_func_ptr)(uint16_t), void (*used_free_func_ptr)(void *), + uint8_t (*used_tx_callback_ptr)(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *)) +{ + if(coap_message_handler_stub.coap_ptr){ + coap_message_handler_stub.coap_ptr->sn_coap_service_malloc = used_malloc_func_ptr; + coap_message_handler_stub.coap_ptr->sn_coap_service_free = used_free_func_ptr; + coap_message_handler_stub.coap_ptr->sn_coap_tx_callback = used_tx_callback_ptr; + } + return coap_message_handler_stub.coap_ptr; +} + +int8_t coap_message_handler_destroy(coap_msg_handler_t *handle) +{ + return coap_message_handler_stub.int8_value; +} + +coap_transaction_t *coap_message_handler_transaction_valid(coap_transaction_t *tr_ptr) +{ + return coap_message_handler_stub.coap_ptr; +} + +coap_transaction_t *coap_message_handler_find_transaction(uint8_t *address_ptr, uint16_t port) +{ + return coap_message_handler_stub.coap_tx_ptr; +} + +int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t socket_id, uint8_t source_addr_ptr[static 16], uint16_t port, + uint8_t *data_ptr, uint16_t data_len, int16_t (cb)(int8_t, sn_coap_hdr_s *, coap_transaction_t *)) +{ + coap_message_handler_stub.cb = cb; + return coap_message_handler_stub.int16_value; +} + +uint16_t coap_message_handler_request_send(coap_msg_handler_t *handle, int8_t service_id, uint8_t options, + const uint8_t destination_addr[static 16], uint16_t destination_port, sn_coap_msg_type_e msg_type, sn_coap_msg_code_e msg_code, + const char *uri, sn_coap_content_format_e cont_type, const uint8_t *payload_ptr, uint16_t payload_len, coap_message_handler_response_recv *request_response_cb) +{ + return coap_message_handler_stub.uint16_value; +} + +int8_t coap_message_handler_response_send(coap_msg_handler_t *handle, int8_t service_id, uint8_t options, sn_coap_hdr_s *request_ptr, sn_coap_msg_code_e message_code,sn_coap_content_format_e content_type, const uint8_t *payload_ptr, uint16_t payload_len) +{ + return coap_message_handler_stub.int8_value; +} + +int8_t coap_message_handler_exec(coap_msg_handler_t *handle, uint32_t current_time) +{ + return coap_message_handler_stub.int8_value; +} + diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_message_handler_stub.h b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_message_handler_stub.h new file mode 100644 index 0000000000..c8c37d142c --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_message_handler_stub.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 __COAP_MESSAGE_HANDLER_STUB_H__ +#define __COAP_MESSAGE_HANDLER_STUB_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "coap_message_handler.h" + +typedef struct { + int8_t int8_value; + int16_t int16_value; + uint16_t uint16_value; + coap_msg_handler_t *coap_ptr; + coap_transaction_t *coap_tx_ptr; + int16_t (*cb)(int8_t, sn_coap_hdr_s *, coap_transaction_t *); +} coap_message_handler_stub_def; + +extern coap_message_handler_stub_def coap_message_handler_stub; + +#ifdef __cplusplus +} +#endif + +#endif // __COAP_MESSAGE_HANDLER_STUB_H__ diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_security_handler_stub.c b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_security_handler_stub.c new file mode 100644 index 0000000000..1583dc0aa7 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_security_handler_stub.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2015-2016 ARM Limited. All Rights Reserved. + */ + +#include +#include +#include +#include "ns_trace.h" +#include "nsdynmemLIB.h" +#include "coap_connection_handler.h" +#include "coap_security_handler_stub.h" + +thread_sec_def coap_security_handler_stub; + +coap_security_t *coap_security_create(int8_t socket_id, int8_t timer_id, uint8_t *address_ptr, uint16_t port, SecureConnectionMode mode, + int (*send_cb)(int8_t socket_id, uint8_t *address_ptr, uint16_t port, const unsigned char *, size_t), + int (*receive_cb)(int8_t socket_id, unsigned char *, size_t), + void (*start_timer_cb)(int8_t timer_id, uint32_t min, uint32_t fin), + int (*timer_status_cb)(int8_t timer_id)) +{ + coap_security_handler_stub.send_cb = send_cb; + coap_security_handler_stub.receive_cb = receive_cb; + coap_security_handler_stub.start_timer_cb = start_timer_cb; + coap_security_handler_stub.timer_status_cb = timer_status_cb; + return coap_security_handler_stub.sec_obj; +} + +void coap_security_destroy(coap_security_t *sec) +{ + +} + +int coap_security_handler_connect_non_blocking(coap_security_t *sec, bool is_server, SecureSocketMode sock_mode, coap_security_keys_t keys, uint32_t timeout_min, uint32_t timeout_max) +{ + sec->_is_started = true; + if( coap_security_handler_stub.counter >= 0){ + return coap_security_handler_stub.values[coap_security_handler_stub.counter--]; + } + return coap_security_handler_stub.int_value; +} + +int coap_security_handler_continue_connecting(coap_security_t *sec) +{ + if( coap_security_handler_stub.counter >= 0){ + return coap_security_handler_stub.values[coap_security_handler_stub.counter--]; + } + + return coap_security_handler_stub.int_value; +} + + +int coap_security_handler_send_message(coap_security_t *sec, unsigned char *message, size_t len) +{ + if( coap_security_handler_stub.counter >= 0){ + return coap_security_handler_stub.values[coap_security_handler_stub.counter--]; + } + return coap_security_handler_stub.int_value; +} + +int coap_security_send_close_alert(coap_security_t *sec) +{ + if( coap_security_handler_stub.counter >= 0){ + return coap_security_handler_stub.values[coap_security_handler_stub.counter--]; + } + return coap_security_handler_stub.int_value; +} + +int coap_security_handler_read(coap_security_t *sec, unsigned char* buffer, size_t len) +{ + if( coap_security_handler_stub.counter >= 0){ + return coap_security_handler_stub.values[coap_security_handler_stub.counter--]; + } + return coap_security_handler_stub.int_value; +} diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_security_handler_stub.h b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_security_handler_stub.h new file mode 100644 index 0000000000..2316ffff7d --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_security_handler_stub.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015-2016 ARM Limited. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 __COAP_SECURITY_HANDLER_STUB_H__ +#define __COAP_SECURITY_HANDLER_STUB_H__ + +#include +#include "coap_security_handler.h" + +typedef struct tsh{ + coap_security_t *sec_obj; + int int_value; + int counter; + int values[10]; + + int (*send_cb)(int8_t socket_id, uint8_t *address_ptr, uint16_t port, const unsigned char *, size_t); + int (*receive_cb)(int8_t socket_id, unsigned char *, size_t); + void (*start_timer_cb)(int8_t timer_id, uint32_t min, uint32_t fin); + int (*timer_status_cb)(int8_t timer_id); +} thread_sec_def; + +extern thread_sec_def coap_security_handler_stub; + +#endif //__COAP_SECURITY_HANDLER_STUB_H__ diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_service_api_stub.c b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_service_api_stub.c new file mode 100644 index 0000000000..cdd1d2698d --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/coap_service_api_stub.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015-2016 ARM Limited. All Rights Reserved. + */ + +#include + +#include "ns_types.h" +#include "ns_list.h" +#include "ns_trace.h" +#include "nsdynmemLIB.h" +#include "sn_nsdl.h" +#include "sn_coap_header.h" +#include "coap_service_api.h" +#include "coap_message_handler.h" +#include "eventOS_event.h" +#include "eventOS_scheduler.h" +#include "eventOS_event_timer.h" +#include "common_functions.h" +#include "net_interface.h" + +int8_t coap_service_initialize(int8_t interface_id, uint16_t listen_port, uint8_t service_options, + coap_service_security_start_cb *start_ptr, coap_service_security_done_cb *coap_security_done_cb) +{ + return 0; +} + +void coap_service_delete(int8_t service_id) +{ +} + +int16_t coap_service_virtual_socket_recv(int8_t service_id, uint8_t source_addr_ptr[static 16], uint16_t port, uint8_t *data_ptr, uint16_t data_len) +{ + return 0; +} + +int16_t coap_service_virtual_socket_set_cb(int8_t service_id, coap_service_virtual_socket_send_cb *send_method_ptr) +{ + return 0; +} + +int8_t coap_service_register_uri(int8_t service_id, const char *uri, uint8_t allowed_method, coap_service_request_recv_cb *request_recv_cb) +{ + return 0; +} + +int8_t coap_service_unregister_uri(int8_t service_id, const char *uri) +{ + return 0; +} + +uint16_t coap_service_request_send(int8_t service_id, uint8_t options, const uint8_t destination_addr[static 16], uint16_t destination_port, sn_coap_msg_type_e msg_type, sn_coap_msg_code_e msg_code, const char *uri, sn_coap_content_format_e cont_type, const uint8_t *payload_ptr, uint16_t payload_len, coap_service_response_recv *request_response_cb) +{ + return 0; +} + +int8_t coap_service_response_send(int8_t service_id, uint8_t options, sn_coap_hdr_s *request_ptr, sn_coap_msg_code_e message_code, sn_coap_content_format_e content_type, const uint8_t *payload_ptr,uint16_t payload_len) +{ + return 0; +} + +uint32_t coap_service_get_internal_timer_ticks(void) +{ + return 1; +} diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/eventOS_event_stub.c b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/eventOS_event_stub.c new file mode 100644 index 0000000000..b050d35078 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/eventOS_event_stub.c @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + */ + +#include +#include "ns_types.h" +#include "eventOS_event.h" +#include "eventOS_event_stub.h" + +eventOs_event_stub_def eventOs_event_stub; + +int8_t eventOS_event_send(arm_event_s *event) +{ + return eventOs_event_stub.int8_value; +} + +int8_t eventOS_event_handler_create(void (*handler_func_ptr)(arm_event_s *), uint8_t init_event_type) +{ + eventOs_event_stub.event_ptr = handler_func_ptr; + return eventOs_event_stub.int8_value; +} diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/eventOS_event_stub.h b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/eventOS_event_stub.h new file mode 100644 index 0000000000..fb2a9fc83f --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/eventOS_event_stub.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 __EVENTOS_EVENT_STUB_H__ +#define __EVENTOS_EVENT_STUB_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "eventOS_event.h" + +typedef struct { + void (*event_ptr)(arm_event_s *); + int8_t int8_value; +} eventOs_event_stub_def; + +extern eventOs_event_stub_def eventOs_event_stub; + +#ifdef __cplusplus +} +#endif + +#endif // __EVENTOS_EVENT_STUB_H__ diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/mbed_trace_stub.c b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/mbed_trace_stub.c new file mode 100644 index 0000000000..34dae55225 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/mbed_trace_stub.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2014-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 + +#ifndef YOTTA_CFG_MBED_TRACE +#define YOTTA_CFG_MBED_TRACE 1 +#define YOTTA_CFG_MBED_TRACE_FEA_IPV6 1 +#endif + +#include "mbed-trace/mbed_trace.h" +#if YOTTA_CFG_MBED_TRACE_FEA_IPV6 == 1 +#include "mbed-client-libservice/ip6string.h" +#include "mbed-client-libservice/common_functions.h" +#endif + + +int mbed_trace_init(void) +{ + return 0; +} +void mbed_trace_free(void) +{ +} + +void mbed_trace_buffer_sizes(int lineLength, int tmpLength) +{ +} + +void mbed_trace_config_set(uint8_t config) +{ +} + +uint8_t mbed_trace_config_get(void) +{ + return 0; +} + +void mbed_trace_prefix_function_set(char *(*pref_f)(size_t)) +{ +} + +void mbed_trace_suffix_function_set(char *(*suffix_f)(void)) +{ +} + +void mbed_trace_print_function_set(void (*printf)(const char *)) +{ +} + +void mbed_trace_cmdprint_function_set(void (*printf)(const char *)) +{ +} + +void mbed_trace_exclude_filters_set(char *filters) +{ + +} + +const char *mbed_trace_exclude_filters_get(void) +{ + return NULL; +} + +const char *mbed_trace_include_filters_get(void) +{ + return NULL; +} + +void mbed_trace_include_filters_set(char *filters) +{ + +} + +void mbed_tracef(uint8_t dlevel, const char *grp, const char *fmt, ...) +{ +} + +const char *mbed_trace_last(void) +{ + return NULL; +} + +/* Helping functions */ +#define tmp_data_left() m_trace.tmp_data_length-(m_trace.tmp_data_ptr-m_trace.tmp_data) +#if YOTTA_CFG_MBED_TRACE_FEA_IPV6 == 1 +char *mbed_trace_ipv6(const void *addr_ptr) +{ + return NULL; +} + +char *mbed_trace_ipv6_prefix(const uint8_t *prefix, uint8_t prefix_len) +{ + return NULL; +} +#endif //YOTTA_CFG_MBED_TRACE_FEA_IPV6 + +char *mbed_trace_array(const uint8_t *buf, uint16_t len) +{ + return NULL; +} diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c new file mode 100644 index 0000000000..d6d88e6acb --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + */ + +#include "mbedtls_stub.h" + +mbedtls_stub_def mbedtls_stub; + +//From ssl.h +int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ) +{ + if( mbedtls_stub.useCounter ){ + + if( mbedtls_stub.retArray[mbedtls_stub.counter] == HANDSHAKE_FINISHED_VALUE || + mbedtls_stub.retArray[mbedtls_stub.counter] == HANDSHAKE_FINISHED_VALUE_RETURN_ZERO){ + + ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER; + if(mbedtls_stub.retArray[mbedtls_stub.counter] == HANDSHAKE_FINISHED_VALUE_RETURN_ZERO) + return 0; + } + return mbedtls_stub.retArray[mbedtls_stub.counter++]; + } + return mbedtls_stub.expected_int; +} + +int mbedtls_ssl_close_notify( mbedtls_ssl_context *a ) +{ + if( mbedtls_stub.useCounter ){ + return mbedtls_stub.retArray[mbedtls_stub.counter++]; + } + return mbedtls_stub.expected_int; +} + +void mbedtls_ssl_init( mbedtls_ssl_context *a ){ + +} +void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ){ + +} + +void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ){ + +} + +void mbedtls_ssl_config_init( mbedtls_ssl_config *a ){ + +} + +void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *a, uint32_t b, uint32_t c) +{ + +} + +void mbedtls_ssl_free( mbedtls_ssl_context *a ){ + +} + +int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *a, + mbedtls_x509_crt *b, + mbedtls_pk_context *c ){ + if( mbedtls_stub.useCounter ){ + return mbedtls_stub.retArray[mbedtls_stub.counter++]; + } + return mbedtls_stub.expected_int; +} + +void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *a, int c ){ + +} + +void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *a, + mbedtls_x509_crt *b, + mbedtls_x509_crl *c ){ + +} + +int mbedtls_ssl_conf_psk( mbedtls_ssl_config *a, + const unsigned char *b, size_t c, + const unsigned char *d, size_t e ){ + if( mbedtls_stub.useCounter ){ + return mbedtls_stub.retArray[mbedtls_stub.counter++]; + } + return mbedtls_stub.expected_int; +} + +int mbedtls_ssl_config_defaults( mbedtls_ssl_config *a, + int b, int c, int d){ + if( mbedtls_stub.useCounter ){ + return mbedtls_stub.retArray[mbedtls_stub.counter++]; + } + return mbedtls_stub.expected_int; +} + +void mbedtls_ssl_conf_rng( mbedtls_ssl_config *a, + int (*f_rng)(void *, unsigned char *, size_t), + void *b ){ + +} + +void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *a, + const int *b) +{ + +} + +int mbedtls_ssl_setup( mbedtls_ssl_context *a, + const mbedtls_ssl_config *b ){ + if( mbedtls_stub.useCounter ){ + return mbedtls_stub.retArray[mbedtls_stub.counter++]; + } + return mbedtls_stub.expected_int; +} + +void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, + void *p_bio, + int (*f_send)(void *, const unsigned char *, size_t), + int (*f_recv)(void *, unsigned char *, size_t), + int (*f_recv_timeout)(void *, unsigned char *, size_t, uint32_t) ){ + if( p_bio != NULL ){ + if( f_send ) + f_send( p_bio, NULL, 0 ); + if( f_recv ) + f_recv( p_bio, NULL, 0 ); + if( f_recv_timeout ) + f_recv_timeout( p_bio, NULL, 0, 0 ); + } +} + +void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *a, + void *ctx, + void (*f_set_timer)(void *, uint32_t int_ms, uint32_t fin_ms), + int (*f_get_timer)(void *) ){ + f_set_timer(ctx, 1, 2); + f_get_timer(ctx); + if(mbedtls_stub.invalidate_timer){ + f_set_timer(ctx, 0, 0); + } + f_get_timer(ctx); +} + +int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ){ + if( mbedtls_stub.useCounter ){ + return mbedtls_stub.retArray[mbedtls_stub.counter++]; + } + return mbedtls_stub.expected_int; +} + +uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *a ){ + return mbedtls_stub.uint32_value; +} + +int mbedtls_ssl_read( mbedtls_ssl_context *a, unsigned char *b, size_t c){ + if( mbedtls_stub.useCounter ){ + return mbedtls_stub.retArray[mbedtls_stub.counter++]; + } + return mbedtls_stub.expected_int; +} + +int mbedtls_ssl_write( mbedtls_ssl_context *a, const unsigned char *b, size_t c ){ + if( mbedtls_stub.useCounter ){ + return mbedtls_stub.retArray[mbedtls_stub.counter++]; + } + return mbedtls_stub.expected_int; +} + + + +//From crt_drbg.h +int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *a, + int (*f_entropy)(void *, unsigned char *, size_t), + void *b, + const unsigned char *c, + size_t d ){ + return mbedtls_stub.crt_expected_int; +} + +void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *a ){ + +} + +void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *a ){ + +} + +int mbedtls_ctr_drbg_random_with_add( void *a, + unsigned char *b, size_t c, + const unsigned char *d, size_t e ){ + return mbedtls_stub.crt_expected_int; +} + +int mbedtls_ctr_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ){ + return mbedtls_stub.crt_expected_int; +} + +//From x509_crt.h +void mbedtls_x509_crt_init( mbedtls_x509_crt *a ){ + +} + +void mbedtls_x509_crt_free( mbedtls_x509_crt *a ){ + +} + +int mbedtls_x509_crt_parse( mbedtls_x509_crt *a, const unsigned char *b, size_t c ){ + if( mbedtls_stub.useCounter ){ + return mbedtls_stub.retArray[mbedtls_stub.counter++]; + } + return mbedtls_stub.expected_int; +} + +//From entropy.h +void mbedtls_entropy_init( mbedtls_entropy_context *a ){ + +} + +void mbedtls_entropy_free( mbedtls_entropy_context *ctx ){ + +} + +int mbedtls_entropy_func( void *a, unsigned char *b, size_t c ){ + if( mbedtls_stub.useCounter ){ + return mbedtls_stub.retArray[mbedtls_stub.counter++]; + } + return mbedtls_stub.expected_int; +} + +int mbedtls_entropy_add_source( mbedtls_entropy_context *a, + mbedtls_entropy_f_source_ptr f_source, void *b, + size_t c, int d ){ + unsigned char buf[2]; + size_t len; + f_source(NULL, buf, 1, &len); + + if( mbedtls_stub.useCounter ){ + return mbedtls_stub.retArray[mbedtls_stub.counter++]; + } + return mbedtls_stub.expected_int; +} + +//From pk.h +int mbedtls_pk_parse_key( mbedtls_pk_context *a, + const unsigned char *b, size_t c, + const unsigned char *d, size_t e ){ + if( mbedtls_stub.useCounter ){ + return mbedtls_stub.retArray[mbedtls_stub.counter++]; + } + return mbedtls_stub.expected_int; +} + +void mbedtls_pk_init( mbedtls_pk_context *ctx ) +{ + +} + +void mbedtls_pk_free( mbedtls_pk_context *ctx ) +{ + +} + +void mbedtls_ssl_config_free( mbedtls_ssl_config *a) +{ + +} + +int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, + const unsigned char *pw, + size_t pw_len ) +{ + if( mbedtls_stub.useCounter ){ + return mbedtls_stub.retArray[mbedtls_stub.counter++]; + } + return mbedtls_stub.expected_int; +} + +void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie ) +{ + if( mbedtls_stub.cookie_obj && f_cookie_check && mbedtls_stub.cookie_len > 0 ){ + f_cookie_check(mbedtls_stub.cookie_obj, &mbedtls_stub.cookie_value, mbedtls_stub.cookie_len, NULL, 0); + } + if( mbedtls_stub.cookie_obj && f_cookie_write && mbedtls_stub.cookie_len > 0 ){ + unsigned char out[16]; + unsigned char *ptr = &out; + f_cookie_write(mbedtls_stub.cookie_obj, &ptr, ptr+mbedtls_stub.cookie_len, NULL, 0); + } +} + +void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_export_keys_t *f_export_keys, + void *p_export_keys ) +{ + if( f_export_keys && p_export_keys){ + unsigned char value[40]; + memset(&value, 1, 40); + f_export_keys(p_export_keys, &value, "", 0, 0,0); //failure case + + f_export_keys(p_export_keys, &value, "", 0, 20,0); //success case + } +} + +int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ) +{ + if( mbedtls_stub.useCounter ){ + return mbedtls_stub.retArray[mbedtls_stub.counter++]; + } + return mbedtls_stub.expected_int; +} diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/mbedtls_stub.h b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/mbedtls_stub.h new file mode 100644 index 0000000000..52402bd74f --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/mbedtls_stub.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 MBEDTLS_STUB_H +#define MBEDTLS_STUB_H + +#define MBEDTLS_SSL_EXPORT_KEYS + +#include +#include +#include "mbedtls/platform.h" +#include "mbedtls/ssl.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/x509_crt.h" +#include "mbedtls/sha256.h" +#include "mbedtls/entropy.h" +#include "mbedtls/pk.h" + + + +#define HANDSHAKE_FINISHED_VALUE 8888 +#define HANDSHAKE_FINISHED_VALUE_RETURN_ZERO 8889 + +typedef struct { + int crt_expected_int; + bool useCounter; + int counter; + int retArray[20]; + int expected_int; + uint32_t uint32_value; + bool invalidate_timer; + void *cookie_obj; + unsigned char cookie_value[8]; + size_t cookie_len; +} mbedtls_stub_def; + +extern mbedtls_stub_def mbedtls_stub; + +#endif // MBEDTLS_STUB_H diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/ns_list_stub.c b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/ns_list_stub.c new file mode 100644 index 0000000000..2d5e650d96 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/ns_list_stub.c @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + */ + +#define NS_LIST_FN extern + +#include "ns_list.h" + + diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/ns_timer_stub.c b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/ns_timer_stub.c new file mode 100644 index 0000000000..f543d941b0 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/ns_timer_stub.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014-2015 ARM Limited. All Rights Reserved. + */ +#include "ns_types.h" +#include "ns_list.h" +#include "ns_timer.h" +#include "ns_timer_stub.h" +#include "eventOS_callback_timer.h" +#include "platform/arm_hal_interrupt.h" +#include "platform/arm_hal_timer.h" +#include "nsdynmemLIB.h" + +ns_timer_stub_def ns_timer_stub; + +int8_t ns_timer_init(void) +{ + return ns_timer_stub.int8_value; +} + +int8_t eventOS_callback_timer_register(void (*timer_interrupt_handler)(int8_t, uint16_t)) +{ + ns_timer_stub.cb = timer_interrupt_handler; + return ns_timer_stub.int8_value; +} + +int8_t eventOS_callback_timer_unregister(int8_t ns_timer_id) +{ + return ns_timer_stub.int8_value; +} + + +int8_t ns_timer_sleep(void) +{ + return ns_timer_stub.int8_value; +} + +int8_t eventOS_callback_timer_start(int8_t ns_timer_id, uint16_t slots) +{ + return ns_timer_stub.int8_value; +} + +int8_t eventOS_callback_timer_stop(int8_t ns_timer_id) +{ + return ns_timer_stub.int8_value; +} diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/ns_timer_stub.h b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/ns_timer_stub.h new file mode 100644 index 0000000000..5db49ded5b --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/ns_timer_stub.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 __NS_TIMER_STUB_H__ +#define __NS_TIMER_STUB_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + int8_t int8_value; + void (*cb)(int8_t, uint16_t); +} ns_timer_stub_def; + +extern ns_timer_stub_def ns_timer_stub; + +#ifdef __cplusplus +} +#endif + +#endif // __NS_TIMER_STUB_H__ diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/nsdynmemLIB_stub.c b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/nsdynmemLIB_stub.c new file mode 100644 index 0000000000..e3f16f2e6e --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/nsdynmemLIB_stub.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014-2015 ARM Limited. All Rights Reserved. + */ +#include "nsdynmemLIB_stub.h" +#include +#include +#include +#include "platform/arm_hal_interrupt.h" +#include + +nsdynmemlib_stub_data_t nsdynmemlib_stub; + +void ns_dyn_mem_init(uint8_t *heap, uint16_t h_size, void (*passed_fptr)(heap_fail_t), mem_stat_t *info_ptr) +{ +} + +void *ns_dyn_mem_alloc(int16_t alloc_size) +{ + if (nsdynmemlib_stub.returnCounter > 0) + { + nsdynmemlib_stub.returnCounter--; + return malloc(alloc_size); + } + else + { + return(nsdynmemlib_stub.expectedPointer); + } +} + +void *ns_dyn_mem_temporary_alloc(int16_t alloc_size) +{ + if (nsdynmemlib_stub.returnCounter > 0) + { + nsdynmemlib_stub.returnCounter--; + return malloc(alloc_size); + } + else + { + return(nsdynmemlib_stub.expectedPointer); + } +} + +void ns_dyn_mem_free(void *block) +{ + free(block); +} diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/nsdynmemLIB_stub.h b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/nsdynmemLIB_stub.h new file mode 100644 index 0000000000..46e5fc0e43 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/nsdynmemLIB_stub.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 __NSDYNMEMLIB_STUB_H__ +#define __NSDYNMEMLIB_STUB_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stdint.h" + +typedef struct { + uint8_t returnCounter; + void* expectedPointer; +} nsdynmemlib_stub_data_t; + +extern nsdynmemlib_stub_data_t nsdynmemlib_stub; + + +void *ns_dyn_mem_alloc(int16_t alloc_size); +void *ns_dyn_mem_temporary_alloc(int16_t alloc_size); +void ns_dyn_mem_free(void *block); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/randLIB_stub.c b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/randLIB_stub.c new file mode 100644 index 0000000000..2b4ae0acab --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/randLIB_stub.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014-2015 ARM Limited. All Rights Reserved. + */ +#include +#include +#include +#include +#include "randLIB.h" +#include "platform/arm_hal_random.h" + +#if ((RAND_MAX+1) & RAND_MAX) != 0 +#error "RAND_MAX isn't 2^n-1 :(" +#endif + +int counter = 1; + +void randLIB_seed_random(void) +{ +} + +uint8_t randLIB_get_8bit(void) +{ + return 0; +} + +uint16_t randLIB_get_16bit(void) +{ + return 0; +} + +uint32_t randLIB_get_32bit(void) +{ + return 0; +} + +int8_t randLIB_get_n_bytes_random(uint8_t *data_ptr, uint8_t eight_bit_boundary) +{ + if(data_ptr && eight_bit_boundary > 0){ + data_ptr[0] = counter++%255; + } + return 0; +} + +uint16_t randLIB_get_random_in_range(uint16_t min, uint16_t max) +{ + return 0; +} + +uint32_t randLIB_randomise_base(uint32_t base, uint16_t min_factor, uint16_t max_factor) +{ + return 0; +} diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_builder_stub.c b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_builder_stub.c new file mode 100644 index 0000000000..1d30a79cbc --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_builder_stub.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2011-2015 ARM Limited. All Rights Reserved. + */ + +/** + * \file sn_coap_builder.c + * + * \brief CoAP Message builder + * + * Functionality: Builds CoAP message + * + */ + +/* * * * * * * * * * * * * * */ +/* * * * INCLUDE FILES * * * */ +/* * * * * * * * * * * * * * */ + +#include "ns_types.h" +#include "sn_coap_header.h" +#include "sn_coap_builder_stub.h" + +sn_coap_builder_stub_def sn_coap_builder_stub; + +sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code) +{ + return sn_coap_builder_stub.expectedHeader; +} + +int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr) +{ + return sn_coap_builder_stub.expectedInt16; +} + +uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_coap_msg_ptr) +{ + return sn_coap_builder_stub.expectedUint16; +} + +int16_t sn_coap_builder_options_build_add_zero_length_option(uint8_t **dst_packet_data_pptr, uint8_t option_length, uint8_t option_exist, sn_coap_option_numbers_e option_number) +{ + return sn_coap_builder_stub.expectedInt16; +} + diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_builder_stub.h b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_builder_stub.h new file mode 100644 index 0000000000..7ddc9c1944 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_builder_stub.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 __SN_COAP_BUILDER_STUB_H__ +#define __SN_COAP_BUILDER_STUB_H__ + +typedef struct { + int16_t expectedInt16; + uint16_t expectedUint16; + sn_coap_hdr_s *expectedHeader; +} sn_coap_builder_stub_def; + +extern sn_coap_builder_stub_def sn_coap_builder_stub; + +#endif //__SN_COAP_BUILDER_STUB_H__ diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_parser_stub.c b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_parser_stub.c new file mode 100644 index 0000000000..327b74998e --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_parser_stub.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2011-2015 ARM Limited. All Rights Reserved. + */ + +/** + *\file sn_coap_parser.c + * + * \brief CoAP Header parser + * + * Functionality: Parses CoAP Header + * + */ + +#include "ns_types.h" +#include "sn_nsdl.h" +#include "sn_coap_protocol.h" +#include "sn_coap_parser_stub.h" + +sn_coap_parser_def sn_coap_parser_stub; + +sn_coap_hdr_s *sn_coap_parser(struct coap_s *handle, uint16_t packet_data_len, uint8_t *packet_data_ptr, coap_version_e *coap_version_ptr) +{ + return sn_coap_parser_stub.expectedHeader; +} + +void sn_coap_parser_release_allocated_coap_msg_mem(struct coap_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr) +{ + if (freed_coap_msg_ptr != NULL) { + if (freed_coap_msg_ptr->uri_path_ptr != NULL) { + free(freed_coap_msg_ptr->uri_path_ptr); + } + + if (freed_coap_msg_ptr->token_ptr != NULL) { + free(freed_coap_msg_ptr->token_ptr); + } + + if (freed_coap_msg_ptr->content_type_ptr != NULL) { + free(freed_coap_msg_ptr->content_type_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr != NULL) { + if (freed_coap_msg_ptr->options_list_ptr->max_age_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->max_age_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->proxy_uri_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->proxy_uri_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->etag_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->etag_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->uri_host_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->uri_host_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->location_path_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->location_path_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->uri_port_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->uri_port_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->location_query_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->location_query_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->observe_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->observe_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->uri_query_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->uri_query_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->block2_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->block2_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->block1_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->block1_ptr); + } + if (freed_coap_msg_ptr->options_list_ptr->accept_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->accept_ptr); + } + + free(freed_coap_msg_ptr->options_list_ptr); + } + + free(freed_coap_msg_ptr); + freed_coap_msg_ptr = NULL; + } +} diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_parser_stub.h b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_parser_stub.h new file mode 100644 index 0000000000..72be957164 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_parser_stub.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 __SN_COAP_PARSER_STUB_H__ +#define __SN_COAP_PARSER_STUB_H__ + +#include "sn_coap_header.h" + +typedef struct { + sn_coap_hdr_s *expectedHeader; +} sn_coap_parser_def; + +extern sn_coap_parser_def sn_coap_parser_stub; + +#endif //__SN_COAP_PARSER_STUB_H__ diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_protocol_stub.c b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_protocol_stub.c new file mode 100644 index 0000000000..69d0fd4efc --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_protocol_stub.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2011-2015 ARM Limited. All Rights Reserved. + */ + + +#include +#include /* For libary malloc() */ +#include /* For memset() and memcpy() */ +#ifdef __linux__ +#include +#endif + +#include "ns_types.h" +#include "sn_nsdl.h" +#include "sn_coap_protocol.h" +#include "sn_coap_header_internal.h" +#include "sn_coap_protocol_internal.h" +#include "sn_coap_protocol_stub.h" + +uint16_t sn_coap_block_data_size = 0; + +uint8_t sn_coap_resending_queue_msgs = 0; +uint8_t sn_coap_resending_queue_bytes = 0; +uint8_t sn_coap_resending_count = 0; +uint8_t sn_coap_resending_intervall = 0; + +uint8_t sn_coap_duplication_buffer_size = 0; + +sn_coap_protocol_stub_def sn_coap_protocol_stub; + +int8_t sn_coap_protocol_destroy(struct coap_s *handle) +{ + return sn_coap_protocol_stub.expectedInt8; +} + +struct coap_s *sn_coap_protocol_init(void *(*used_malloc_func_ptr)(uint16_t), void (*used_free_func_ptr)(void *), + uint8_t (*used_tx_callback_ptr)(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *), + int8_t (*used_rx_callback_ptr)(sn_coap_hdr_s *, sn_nsdl_addr_s *, void *param)) +{ + if( sn_coap_protocol_stub.expectedCoap ){ + sn_coap_protocol_stub.expectedCoap->sn_coap_protocol_free = used_free_func_ptr; + sn_coap_protocol_stub.expectedCoap->sn_coap_protocol_malloc = used_malloc_func_ptr; + sn_coap_protocol_stub.expectedCoap->sn_coap_rx_callback = used_rx_callback_ptr; + sn_coap_protocol_stub.expectedCoap->sn_coap_tx_callback = used_tx_callback_ptr; + } + return sn_coap_protocol_stub.expectedCoap; +} + +int8_t sn_coap_protocol_set_block_size(struct coap_s *handle, uint16_t block_size) +{ + return sn_coap_protocol_stub.expectedInt8; +} + +int8_t sn_coap_protocol_set_duplicate_buffer_size(struct coap_s *handle, uint8_t size) +{ + return sn_coap_protocol_stub.expectedInt8; +} + +int8_t sn_coap_protocol_set_retransmission_parameters(struct coap_s *handle, uint8_t resending_count, uint8_t resending_intervall) +{ + return sn_coap_protocol_stub.expectedInt8; +} + +int8_t sn_coap_protocol_set_retransmission_buffer(struct coap_s *handle, uint8_t buffer_size_messages, uint16_t buffer_size_bytes) +{ + return sn_coap_protocol_stub.expectedInt8; +} + +void sn_coap_protocol_clear_retransmission_buffer(struct coap_s *handle) +{ +} + + +int16_t sn_coap_protocol_build(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, + uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, void *param) +{ + //TODO: check if needed here + src_coap_msg_ptr->msg_id = 2; + return sn_coap_protocol_stub.expectedInt16; +} + +sn_coap_hdr_s *sn_coap_protocol_parse(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t packet_data_len, uint8_t *packet_data_ptr, void *param) +{ + return sn_coap_protocol_stub.expectedHeader; +} + +int8_t sn_coap_protocol_exec(struct coap_s *handle, uint32_t current_time) +{ + return sn_coap_protocol_stub.expectedInt8; +} + +coap_send_msg_s *sn_coap_protocol_allocate_mem_for_msg(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint16_t packet_data_len) +{ + return sn_coap_protocol_stub.expectedSendMsg; +} + diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_protocol_stub.h b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_protocol_stub.h new file mode 100644 index 0000000000..0f8a67260d --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/sn_coap_protocol_stub.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 __SN_COAP_PROTOCOL_STUB_H__ +#define __SN_COAP_PROTOCOL_STUB_H__ + +#include "sn_coap_header_internal.h" +#include "sn_coap_protocol_internal.h" + +typedef struct { + int8_t expectedInt8; + int16_t expectedInt16; + struct coap_s *expectedCoap; + sn_coap_hdr_s *expectedHeader; + coap_send_msg_s *expectedSendMsg; +} sn_coap_protocol_stub_def; + +extern sn_coap_protocol_stub_def sn_coap_protocol_stub; + +#endif //__SN_COAP_PROTOCOL_STUB_H__ diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/socket_api_stub.c b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/socket_api_stub.c new file mode 100644 index 0000000000..685f27d77f --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/socket_api_stub.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + */ +#include "socket_api.h" +#include "socket_api_stub.h" + +socket_api_stub_data_t socket_api_stub; + +int8_t socket_raw_open(void (*passed_fptr)(void *)) +{ + if( socket_api_stub.counter >= 0){ + return socket_api_stub.values[socket_api_stub.counter--]; + } + + return socket_api_stub.int8_value; +} +int8_t socket_open(uint8_t protocol, uint16_t identifier, void (*passed_fptr)(void *)) +{ + socket_api_stub.recv_cb = passed_fptr; + if( socket_api_stub.counter >= 0){ + return socket_api_stub.values[socket_api_stub.counter--]; + } + + return socket_api_stub.int8_value; +} + +int8_t socket_free(int8_t socket) +{ + if( socket_api_stub.counter >= 0){ + return socket_api_stub.values[socket_api_stub.counter--]; + } + + return socket_api_stub.int8_value; +} +int8_t socket_listen(int8_t socket) +{ + if( socket_api_stub.counter >= 0){ + return socket_api_stub.values[socket_api_stub.counter--]; + } + + return socket_api_stub.int8_value; +} +int8_t socket_connect(int8_t socket, ns_address_t *address, uint8_t randomly_take_src_number) +{ + if( socket_api_stub.counter >= 0){ + return socket_api_stub.values[socket_api_stub.counter--]; + } + + return socket_api_stub.int8_value; +} +int8_t socket_bind(int8_t socket, const ns_address_t *address) +{ + if( socket_api_stub.counter >= 0){ + return socket_api_stub.values[socket_api_stub.counter--]; + } + + return socket_api_stub.int8_value; +} +int8_t socket_close(int8_t socket, ns_address_t *address) +{ + if( socket_api_stub.counter >= 0){ + return socket_api_stub.values[socket_api_stub.counter--]; + } + + return socket_api_stub.int8_value; +} +int8_t socket_send(int8_t socket, uint8_t *buffer, uint16_t length) +{ + if( socket_api_stub.counter >= 0){ + return socket_api_stub.values[socket_api_stub.counter--]; + } + + return socket_api_stub.int8_value; +} +int16_t socket_read(int8_t socket, ns_address_t *address, uint8_t *buffer, uint16_t length) +{ + if( address ){ + memset(&address->address, 0, 16); + address->identifier = 0; + } + if( socket_api_stub.counter >= 0){ + return socket_api_stub.values[socket_api_stub.counter--]; + } + + return socket_api_stub.int8_value; +} +int8_t socket_sendto(int8_t socket, ns_address_t *address, uint8_t *buffer, uint16_t length) +{ + if( socket_api_stub.counter >= 0){ + return socket_api_stub.values[socket_api_stub.counter--]; + } + + return socket_api_stub.int8_value; +} +int8_t socket_read_session_address(int8_t socket, ns_address_t *address) +{ + if( socket_api_stub.counter >= 0){ + return socket_api_stub.values[socket_api_stub.counter--]; + } + + return socket_api_stub.int8_value; +} +int8_t socket_setsockopt(int8_t socket, uint8_t level, uint8_t opt_name, const void *opt_value, uint16_t opt_len) +{ + if( socket_api_stub.counter >= 0){ + return socket_api_stub.values[socket_api_stub.counter--]; + } + + return socket_api_stub.int8_value; +} +int8_t socket_getsockopt(int8_t socket, uint8_t level, uint8_t opt_name, void *opt_value, uint16_t *opt_len) +{ + if( socket_api_stub.counter >= 0){ + return socket_api_stub.values[socket_api_stub.counter--]; + } + + return socket_api_stub.int8_value; +} diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/socket_api_stub.h b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/socket_api_stub.h new file mode 100644 index 0000000000..bc7dacf4a1 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/socket_api_stub.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015 ARM Limited. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 __SOCKET_API_STUB_H__ +#define __SOCKET_API_STUB_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stdint.h" + +typedef struct { + void (*recv_cb)(void *); + int8_t int8_value; + int counter; + int values[10]; +} socket_api_stub_data_t; + +extern socket_api_stub_data_t socket_api_stub; + +#ifdef __cplusplus +} +#endif + +#endif //__SOCKET_API_STUB_H__ + + + + + diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/system_timer_stub.c b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/system_timer_stub.c new file mode 100644 index 0000000000..7de1ab64f9 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/system_timer_stub.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014-2015 ARM Limited. All Rights Reserved. + */ +#include "ns_types.h" +#include "timer_sys.h" +#include "platform/arm_hal_interrupt.h" +#include "ns_timer.h" +#include "nsdynmemLIB.h" +#include "eventOS_event.h" +#include "eventOS_callback_timer.h" + +#ifndef ST_MAX +#define ST_MAX 6 +#endif + +#define TIMER_SYS_TICK_PERIOD 100 + +void timer_sys_init(void) +{ +} + +void timer_sys_disable(void) +{ + +} + +int8_t timer_sys_wakeup(void) +{ + return 0; +} + +uint32_t timer_get_runtime_ticks(void) // only used in dev_stats_internal.c +{ + return 0; +} + + + +int8_t eventOS_event_timer_request(uint8_t snmessage, uint8_t event_type, int8_t tasklet_id, uint32_t time) +{ + return -1; +} + +int8_t eventOS_event_timer_cancel(uint8_t snmessage, int8_t tasklet_id) +{ + return -1; +} + + +uint32_t eventOS_event_timer_shortest_active_timer(void) +{ + return 0; +} + +void system_timer_tick_update(uint32_t ticks) +{ +} + diff --git a/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/timeout_stub.c b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/timeout_stub.c new file mode 100644 index 0000000000..dfda619110 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/test/coap-service/unittest/stub/timeout_stub.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2016 ARM Limited. All Rights Reserved. + */ + + #include "eventOS_event_timer.h" + +// Timeout structure, already typedefed to timeout_t +struct timeout_entry_t { + uint8_t id; +}; + +static timeout_t timeout_stub; + +timeout_t *eventOS_timeout_ms(void (*callback)(void *), uint32_t ms, void *arg) +{ + return &timeout_stub; +} + +void eventOS_timeout_cancel(timeout_t *t) +{ + +} diff --git a/features/FEATURE_CLIENT/coap-service/xsl_script.sh b/features/FEATURE_CLIENT/coap-service/xsl_script.sh new file mode 100755 index 0000000000..d5320b42b8 --- /dev/null +++ b/features/FEATURE_CLIENT/coap-service/xsl_script.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# Copyright (c) 2015 ARM Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# * http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +echo +echo "Creating report" +echo + +echo ' + +' >> lcov/index.xml + +for f in lcov/results/*.xml +do +name=${f##*/} +echo ''>> lcov/index.xml +done + +echo '' >> lcov/index.xml + +echo +echo "Report created to lcov/index.xml (outputs html)" +echo \ No newline at end of file diff --git a/features/FEATURE_CLIENT/mbed-client-c/.gitattributes b/features/FEATURE_CLIENT/mbed-client-c/.gitattributes new file mode 100644 index 0000000000..2ea1cbf6ba --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/.gitattributes @@ -0,0 +1,2 @@ +* text=auto +*.uvproj eol=lf diff --git a/features/FEATURE_CLIENT/mbed-client-c/.gitignore b/features/FEATURE_CLIENT/mbed-client-c/.gitignore new file mode 100644 index 0000000000..0b5c53aa76 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/.gitignore @@ -0,0 +1,36 @@ +*.o +*.a +*.d +*.eww +*.bak +*.dep +*.Scr +*.uvgui.* +build/ +*.dep +*.ewd +*.ewt +Debug +Release +settings +*_release +Obj +*_output +Backup* +*.r43 +*.htm +*.uvgui.* +*.lib +*.crf +*.uvopt +*.out +docs/ +yotta_modules +yotta_targets +test/nsdl-c/unittest/coverages +test/nsdl-c/unittest/results +.yotta.json +coverage/ +lcov/ +upload.tar.gz + diff --git a/features/FEATURE_CLIENT/mbed-client-c/.mbedignore b/features/FEATURE_CLIENT/mbed-client-c/.mbedignore new file mode 100644 index 0000000000..4140aabf01 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/.mbedignore @@ -0,0 +1,2 @@ +test/* +unittest/* diff --git a/features/FEATURE_CLIENT/mbed-client-c/.yotta_ignore b/features/FEATURE_CLIENT/mbed-client-c/.yotta_ignore new file mode 100644 index 0000000000..6cd3f5174f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/.yotta_ignore @@ -0,0 +1,5 @@ +# need unity.h: +unittest/* +test/* +doxygen/* + diff --git a/features/FEATURE_CLIENT/mbed-client-c/LICENSE b/features/FEATURE_CLIENT/mbed-client-c/LICENSE new file mode 100644 index 0000000000..97df0e645d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/LICENSE @@ -0,0 +1,2 @@ +Unless specifically indicated otherwise in a file, files are licensed +under the Apache 2.0 license, as can be found in: apache-2.0.txt \ No newline at end of file diff --git a/features/FEATURE_CLIENT/mbed-client-c/Makefile.test b/features/FEATURE_CLIENT/mbed-client-c/Makefile.test new file mode 100644 index 0000000000..38c19e922b --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/Makefile.test @@ -0,0 +1,51 @@ +# +# Makefile.test for combined NSDL+COAP library unit tests +# + + +# List of subdirectories to build +TEST_FOLDER := ./test/ +# List of unit test directories for libraries +UNITTESTS := $(sort $(dir $(wildcard $(TEST_FOLDER)*/unittest/*))) +TESTDIRS := $(UNITTESTS:%=build-%) +CLEANTESTDIRS := $(UNITTESTS:%=clean-%) +COVERAGEFILE := ./lcov/coverage.info + +.PHONY: test +test: $(TESTDIRS) + @rm -rf ./lcov + @rm -rf ./coverage + @mkdir -p lcov + @mkdir -p lcov/results + @mkdir coverage + @find ./test -name '*.xml' | xargs cp -t ./lcov/results/ + @rm -f lcov/index.xml + @./xsl_script.sh + @cp junit_xsl.xslt lcov/. + @xsltproc -o lcov/testresults.html lcov/junit_xsl.xslt lcov/index.xml + @rm -f lcov/junit_xsl.xslt + @rm -f lcov/index.xml + @find ./ -name '*.gcno' | xargs cp --backup=numbered -t ./coverage/ + @find ./ -name '*.gcda' | xargs cp --backup=numbered -t ./coverage/ + @gcovr --object-directory ./coverage --exclude-unreachable-branches -e '.*/builds/.*' -e '.*/test/.*' -e '.*/yotta_modules/.*' -e '.*/stubs/.*' -e '.*/mbed-client-c/.*' -x -o ./lcov/gcovr.xml + @lcov -d test/. -c -o $(COVERAGEFILE) + @lcov -q -r $(COVERAGEFILE) "/usr*" -o $(COVERAGEFILE) + @lcov -q -r $(COVERAGEFILE) "/test*" -o $(COVERAGEFILE) + @lcov -q -r $(COVERAGEFILE) "/mbed-client-libservice*" -o $(COVERAGEFILE) + @genhtml -q $(COVERAGEFILE) --show-details --output-directory lcov/html + @echo mbed-client-c module unit tests built + +$(TESTDIRS): + @make -C $(@:build-%=%) + +$(CLEANDIRS): + @make -C $(@:clean-%=%) clean + +$(CLEANTESTDIRS): + @make -C $(@:clean-%=%) clean + +# Extend default clean rule +clean: clean-extra + +clean-extra: $(CLEANDIRS) \ + $(CLEANTESTDIRS) diff --git a/features/FEATURE_CLIENT/mbed-client-c/README.txt b/features/FEATURE_CLIENT/mbed-client-c/README.txt new file mode 100644 index 0000000000..f58f925c7d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/README.txt @@ -0,0 +1,2 @@ +The mbed Device C Client Library provides a simple and efficient way to create mbed Device Client in +C. \ No newline at end of file diff --git a/features/FEATURE_CLIENT/mbed-client-c/apache-2.0.txt b/features/FEATURE_CLIENT/mbed-client-c/apache-2.0.txt new file mode 100644 index 0000000000..0e4cf3ee99 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/apache-2.0.txt @@ -0,0 +1,56 @@ + + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + You must give any other recipients of the Work or Derivative Works a copy of this License; and + You must cause any modified files to carry prominent notices stating that You changed the files; and + You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/features/FEATURE_CLIENT/mbed-client-c/doxygen/client-c_doxy b/features/FEATURE_CLIENT/mbed-client-c/doxygen/client-c_doxy new file mode 100644 index 0000000000..6762da802b --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/doxygen/client-c_doxy @@ -0,0 +1,1846 @@ +# 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 = client-c + +# 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 = + +# 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 = "mbed Server c Client library" + +# 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 = 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, 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 = NO + +# 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 = NO + +# 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 = YES + +# 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 = YES + +# 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 = YES + +# 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 = YES + +# 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 = YES + +# 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 = 18 + +# 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 = + +# 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 = ../nsdl-c + +# 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 + +# 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 = YES + +# 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 = + +# 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 = + +# 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 = NO + +# 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 = YES + +# 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 = YES + +# 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 = 44 + +# 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/features/FEATURE_CLIENT/mbed-client-c/junit_xsl.xslt b/features/FEATURE_CLIENT/mbed-client-c/junit_xsl.xslt new file mode 100644 index 0000000000..7376b27f26 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/junit_xsl.xslt @@ -0,0 +1,101 @@ + + + + + + + + + +

+ Unittest report +

+ +

+ + Total tests run + , failures: + + + + + +

+
+ + +

+ +

+ + + + + + + + + + + +
Tests runTests failedOther errors
+
+ + + + + + + + +
Tests namePASS/FAILFailing caseReason
+
+ + + + + + + + + + + PASS + + + + + + + FAIL + + + + + + + + + + + + + + + + FAIL + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/features/FEATURE_CLIENT/mbed-client-c/module.json b/features/FEATURE_CLIENT/mbed-client-c/module.json new file mode 100644 index 0000000000..9f6ddcfffc --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/module.json @@ -0,0 +1,20 @@ +{ + "name": "mbed-client-c", + "version": "2.7.7", + "description": "Nanostack NSDL and COAP library", + "keywords": [ + "coap", + "nanostack" + ], + "license": "Apache-2.0", + "extraIncludes": [ + "nsdl-c", + "source/libNsdl/src/include", + "source/libCoap/src/include" + ], + "dependencies": { + "nanostack-libservice": "^3.0.0", + "mbed-trace": ">=0.2.0,<2.0.0" + }, + "targetDependencies": {} +} diff --git a/features/FEATURE_CLIENT/mbed-client-c/nsdl-c/sn_coap_header.h b/features/FEATURE_CLIENT/mbed-client-c/nsdl-c/sn_coap_header.h new file mode 100644 index 0000000000..24ba34dadf --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/nsdl-c/sn_coap_header.h @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2011-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 sn_coap_header.h + * + * \brief CoAP C-library User header interface header file + */ + +#ifndef SN_COAP_HEADER_H_ +#define SN_COAP_HEADER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Handle structure */ +struct coap_s; + +/* * * * * * * * * * * * * * */ +/* * * * ENUMERATIONS * * * */ +/* * * * * * * * * * * * * * */ + +/** + * \brief Enumeration for CoAP Version + */ +typedef enum coap_version_ { + COAP_VERSION_1 = 0x40, + COAP_VERSION_UNKNOWN = 0xFF +} coap_version_e; + +/** + * \brief Enumeration for CoAP Message type, used in CoAP Header + */ +typedef enum sn_coap_msg_type_ { + COAP_MSG_TYPE_CONFIRMABLE = 0x00, /**< Reliable Request messages */ + COAP_MSG_TYPE_NON_CONFIRMABLE = 0x10, /**< Non-reliable Request and Response messages */ + COAP_MSG_TYPE_ACKNOWLEDGEMENT = 0x20, /**< Response to a Confirmable Request */ + COAP_MSG_TYPE_RESET = 0x30 /**< Answer a Bad Request */ +} sn_coap_msg_type_e; + +/** + * \brief Enumeration for CoAP Message code, used in CoAP Header + */ +typedef enum sn_coap_msg_code_ { + COAP_MSG_CODE_EMPTY = 0, + COAP_MSG_CODE_REQUEST_GET = 1, + COAP_MSG_CODE_REQUEST_POST = 2, + COAP_MSG_CODE_REQUEST_PUT = 3, + COAP_MSG_CODE_REQUEST_DELETE = 4, + + COAP_MSG_CODE_RESPONSE_CREATED = 65, + COAP_MSG_CODE_RESPONSE_DELETED = 66, + COAP_MSG_CODE_RESPONSE_VALID = 67, + COAP_MSG_CODE_RESPONSE_CHANGED = 68, + COAP_MSG_CODE_RESPONSE_CONTENT = 69, + COAP_MSG_CODE_RESPONSE_CONTINUE = 95, + COAP_MSG_CODE_RESPONSE_BAD_REQUEST = 128, + COAP_MSG_CODE_RESPONSE_UNAUTHORIZED = 129, + COAP_MSG_CODE_RESPONSE_BAD_OPTION = 130, + COAP_MSG_CODE_RESPONSE_FORBIDDEN = 131, + COAP_MSG_CODE_RESPONSE_NOT_FOUND = 132, + COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED = 133, + COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE = 134, + COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE = 136, + COAP_MSG_CODE_RESPONSE_PRECONDITION_FAILED = 140, + COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE = 141, + COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT = 143, + COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR = 160, + COAP_MSG_CODE_RESPONSE_NOT_IMPLEMENTED = 161, + COAP_MSG_CODE_RESPONSE_BAD_GATEWAY = 162, + COAP_MSG_CODE_RESPONSE_SERVICE_UNAVAILABLE = 163, + COAP_MSG_CODE_RESPONSE_GATEWAY_TIMEOUT = 164, + COAP_MSG_CODE_RESPONSE_PROXYING_NOT_SUPPORTED = 165 +} sn_coap_msg_code_e; + +/** + * \brief Enumeration for CoAP Option number, used in CoAP Header + */ +typedef enum sn_coap_option_numbers_ { + COAP_OPTION_IF_MATCH = 1, + COAP_OPTION_URI_HOST = 3, + COAP_OPTION_ETAG = 4, + COAP_OPTION_IF_NONE_MATCH = 5, + COAP_OPTION_OBSERVE = 6, + COAP_OPTION_URI_PORT = 7, + COAP_OPTION_LOCATION_PATH = 8, + COAP_OPTION_URI_PATH = 11, + COAP_OPTION_CONTENT_FORMAT = 12, + COAP_OPTION_MAX_AGE = 14, + COAP_OPTION_URI_QUERY = 15, + COAP_OPTION_ACCEPT = 17, + COAP_OPTION_LOCATION_QUERY = 20, + COAP_OPTION_BLOCK2 = 23, + COAP_OPTION_BLOCK1 = 27, + COAP_OPTION_SIZE2 = 28, + COAP_OPTION_PROXY_URI = 35, + COAP_OPTION_PROXY_SCHEME = 39, + COAP_OPTION_SIZE1 = 60 +// 128 = (Reserved) +// 132 = (Reserved) +// 136 = (Reserved) +} sn_coap_option_numbers_e; + +/** + * \brief Enumeration for CoAP Content Format codes + */ +typedef enum sn_coap_content_format_ { + COAP_CT_NONE = -1, + COAP_CT_TEXT_PLAIN = 0, + COAP_CT_LINK_FORMAT = 40, + COAP_CT_XML = 41, + COAP_CT_OCTET_STREAM = 42, + COAP_CT_EXI = 47, + COAP_CT_JSON = 50 +} sn_coap_content_format_e; + +/** + * \brief Enumeration for CoAP status, used in CoAP Header + */ +typedef enum sn_coap_status_ { + COAP_STATUS_OK = 0, /**< Default value is OK */ + COAP_STATUS_PARSER_ERROR_IN_HEADER = 1, /**< CoAP will send Reset message to invalid message sender */ + COAP_STATUS_PARSER_DUPLICATED_MSG = 2, /**< CoAP will send Acknowledgement message to duplicated message sender */ + COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING = 3, /**< User will get whole message after all message blocks received. + User must release messages with this status. */ + COAP_STATUS_PARSER_BLOCKWISE_ACK = 4, /**< Acknowledgement for sent Blockwise message received */ + COAP_STATUS_PARSER_BLOCKWISE_MSG_REJECTED = 5, /**< Blockwise message received but not supported by compiling switch */ + COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED = 6, /**< Blockwise message fully received and returned to app. + User must take care of releasing whole payload of the blockwise messages */ + COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED = 7 /**< When re-transmissions have been done and ACK not received, CoAP library calls + RX callback with this status */ +} sn_coap_status_e; + + +/* * * * * * * * * * * * * */ +/* * * * STRUCTURES * * * */ +/* * * * * * * * * * * * * */ + +/** + * \brief Structure for CoAP Options + */ +typedef struct sn_coap_options_list_ { + + uint8_t max_age_len; /**< 0-4 bytes. */ + uint8_t *max_age_ptr; /**< Must be set to NULL if not used */ + + uint16_t proxy_uri_len; /**< 1-1034 bytes. */ + uint8_t *proxy_uri_ptr; /**< Must be set to NULL if not used */ + + uint8_t etag_len; /**< 1-8 bytes. Repeatable */ + uint8_t *etag_ptr; /**< Must be set to NULL if not used */ + + uint16_t uri_host_len; /**< 1-255 bytes. */ + uint8_t *uri_host_ptr; /**< Must be set to NULL if not used */ + + uint16_t location_path_len; /**< 0-255 bytes. Repeatable */ + uint8_t *location_path_ptr; /**< Must be set to NULL if not used */ + + uint8_t uri_port_len; /**< 0-2 bytes. */ + uint8_t *uri_port_ptr; /**< Must be set to NULL if not used */ + + uint16_t location_query_len; /**< 0-255 bytes. Repeatable */ + uint8_t *location_query_ptr; /**< Must be set to NULL if not used */ + + uint8_t observe; + uint8_t observe_len; /**< 0-2 bytes. */ + uint8_t *observe_ptr; /**< Must be set to NULL if not used */ + + uint8_t accept_len; /**< 0-2 bytes. Repeatable */ + uint8_t *accept_ptr; /**< Must be set to NULL if not used */ + + uint16_t uri_query_len; /**< 1-255 bytes. Repeatable */ + uint8_t *uri_query_ptr; /**< Must be set to NULL if not used */ + + uint8_t block1_len; /**< 0-3 bytes. */ + uint8_t *block1_ptr; /**< Not for User */ + + uint8_t block2_len; /**< 0-3 bytes. */ + uint8_t *block2_ptr; /**< Not for User */ + + uint8_t size1_len; /**< 0-4 bytes. */ + uint8_t *size1_ptr; /**< Not for User */ + + uint8_t size2_len; /**< 0-4 bytes. */ + uint8_t *size2_ptr; /**< Not for User */ +} sn_coap_options_list_s; + + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ +/* !!! Main CoAP message struct !!! */ +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +/** + * \brief Main CoAP message struct + */ +typedef struct sn_coap_hdr_ { + sn_coap_status_e coap_status; /**< Used for telling to User special cases when parsing message */ + + /* * * * * * * * * * * */ + /* * * * Header * * * */ + /* * * * * * * * * * * */ + + sn_coap_msg_type_e msg_type; /**< Confirmable, Non-Confirmable, Acknowledgement or Reset */ + sn_coap_msg_code_e msg_code; /**< Empty: 0; Requests: 1-31; Responses: 64-191 */ + uint16_t msg_id; /**< Message ID. Parser sets parsed message ID, builder sets message ID of built coap message */ + + /* * * * * * * * * * * */ + /* * * * Options * * * */ + /* * * * * * * * * * * */ + + /* Here are most often used Options */ + + uint16_t uri_path_len; /**< 0-255 bytes. Repeatable. */ + uint8_t *uri_path_ptr; /**< Must be set to NULL if not used. E.g: temp1/temp2 */ + + uint8_t token_len; /**< 1-8 bytes. */ + uint8_t *token_ptr; /**< Must be set to NULL if not used */ + + uint8_t content_type_len; /**< 0-2 bytes. */ + uint8_t *content_type_ptr; /**< Must be set to NULL if not used */ + + /* Here are not so often used Options */ + sn_coap_options_list_s *options_list_ptr; /**< Must be set to NULL if not used */ + + /* * * * * * * * * * * */ + /* * * * Payload * * * */ + /* * * * * * * * * * * */ + + uint16_t payload_len; /**< Must be set to zero if not used */ + uint8_t *payload_ptr; /**< Must be set to NULL if not used */ +} sn_coap_hdr_s; + +/* * * * * * * * * * * * * * * * * * * * * * */ +/* * * * EXTERNAL FUNCTION PROTOTYPES * * * */ +/* * * * * * * * * * * * * * * * * * * * * * */ +/** + * \fn sn_coap_hdr_s *sn_coap_parser(struct coap_s *handle, uint16_t packet_data_len, uint8_t *packet_data_ptr, coap_version_e *coap_version_ptr) + * + * \brief Parses CoAP message from given Packet data + * + * \param *handle Pointer to CoAP library handle + * + * \param packet_data_len is length of given Packet data to be parsed to CoAP message + * + * \param *packet_data_ptr is source for Packet data to be parsed to CoAP message + * + * \param *coap_version_ptr is destination for parsed CoAP specification version + * + * \return Return value is pointer to parsed CoAP message.\n + * In following failure cases NULL is returned:\n + * -Failure in given pointer (= NULL)\n + * -Failure in memory allocation (malloc() returns NULL) + */ +extern sn_coap_hdr_s *sn_coap_parser(struct coap_s *handle, uint16_t packet_data_len, uint8_t *packet_data_ptr, coap_version_e *coap_version_ptr); + +/** + * \fn void sn_coap_parser_release_allocated_coap_msg_mem(struct coap_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr) + * + * \brief Releases memory of given CoAP message + * + * Note!!! Does not release Payload part + * + * \param *handle Pointer to CoAP library handle + * + * \param *freed_coap_msg_ptr is pointer to released CoAP message + */ +extern void sn_coap_parser_release_allocated_coap_msg_mem(struct coap_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr); + +/** + * \fn int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr) + * + * \brief Builds an outgoing message buffer from a CoAP header structure. + * + * \param *dst_packet_data_ptr is pointer to allocated destination to built CoAP packet + * + * \param *src_coap_msg_ptr is pointer to source structure for building Packet data + * + * \return Return value is byte count of built Packet data. In failure cases:\n + * -1 = Failure in given CoAP header structure\n + * -2 = Failure in given pointer (= NULL) + */ +extern int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr); + +/** + * \fn uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_coap_msg_ptr) + * + * \brief Calculates needed Packet data memory size for given CoAP message + * + * \param *src_coap_msg_ptr is pointer to data which needed Packet + * data length is calculated + * + * \return Return value is count of needed memory as bytes for build Packet data + * Null if failed + */ +extern uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_coap_msg_ptr); + +/** + * \fn int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_size) + * + * \brief Builds an outgoing message buffer from a CoAP header structure. + * + * \param *dst_packet_data_ptr is pointer to allocated destination to built CoAP packet + * + * \param *src_coap_msg_ptr is pointer to source structure for building Packet data + * + * \param blockwise_payload_size Blockwise message maximum payload size + * + * \return Return value is byte count of built Packet data. In failure cases:\n + * -1 = Failure in given CoAP header structure\n + * -2 = Failure in given pointer (= NULL) + */ +extern int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size); + +/** + * \fn uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size) + * + * \brief Calculates needed Packet data memory size for given CoAP message + * + * \param *src_coap_msg_ptr is pointer to data which needed Packet + * data length is calculated + * \param blockwise_payload_size Blockwise message maximum payload size + * + * \return Return value is count of needed memory as bytes for build Packet data + * Null if failed + */ +extern uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size); + +/** + * \fn sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code) + * + * \brief Prepares generic response packet from a request packet. This function allocates memory for the resulting sn_coap_hdr_s + * + * \param *handle Pointer to CoAP library handle + * \param *coap_packet_ptr The request packet pointer + * \param msg_code response messages code + * + * \return *coap_packet_ptr The allocated and pre-filled response packet pointer + * NULL Error in parsing the request + * + */ +extern sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code); + +/** + * \brief Initialise a message structure to empty + * + * \param *coap_msg_ptr is pointer to CoAP message to initialise + * + * \return Return value is pointer passed in + */ +extern sn_coap_hdr_s *sn_coap_parser_init_message(sn_coap_hdr_s *coap_msg_ptr); + +/** + * \brief Allocate an empty message structure + * + * \param *handle Pointer to CoAP library handle + * + * \return Return value is pointer to an empty CoAP message.\n + * In following failure cases NULL is returned:\n + * -Failure in given pointer (= NULL)\n + * -Failure in memory allocation (malloc() returns NULL) + */ +extern sn_coap_hdr_s *sn_coap_parser_alloc_message(struct coap_s *handle); + +/** + * \brief Allocate an empty options structure + * + * \param *handle Pointer to CoAP library handle + * \param *coap_msg_ptr is pointer to CoAP message that will contain the options + * + * If the message already has a pointer to an option structure, that pointer + * is returned, rather than a new structure being allocated. + * + * \return Return value is pointer to the CoAP options structure.\n + * In following failure cases NULL is returned:\n + * -Failure in given pointer (= NULL)\n + * -Failure in memory allocation (malloc() returns NULL) + */ +extern sn_coap_options_list_s *sn_coap_parser_alloc_options(struct coap_s *handle, sn_coap_hdr_s *coap_msg_ptr); + +#ifdef __cplusplus +} +#endif + +#endif /* SN_COAP_HEADER_H_ */ diff --git a/features/FEATURE_CLIENT/mbed-client-c/nsdl-c/sn_coap_protocol.h b/features/FEATURE_CLIENT/mbed-client-c/nsdl-c/sn_coap_protocol.h new file mode 100644 index 0000000000..f3959f453d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/nsdl-c/sn_coap_protocol.h @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2011-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 sn_coap_protocol.h + * + * \brief CoAP C-library User protocol interface header file + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef SN_COAP_PROTOCOL_H_ +#define SN_COAP_PROTOCOL_H_ + +#include "sn_coap_header.h" + +/** + * \fn struct coap_s *sn_coap_protocol_init(void* (*used_malloc_func_ptr)(uint16_t), void (*used_free_func_ptr)(void*), + uint8_t (*used_tx_callback_ptr)(sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *), + int8_t (*used_rx_callback_ptr)(sn_coap_hdr_s *, sn_nsdl_addr_s *) + * + * \brief Initializes CoAP Protocol part. When using libNsdl, sn_nsdl_init() calls this function. + * + * \param *used_malloc_func_ptr is function pointer for used memory allocation function. + * + * \param *used_free_func_ptr is function pointer for used memory free function. + * + * \param *used_tx_callback_ptr function callback pointer to tx function for sending coap messages + * + * \param *used_rx_callback_ptr used to return CoAP header struct with status COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED + * when re-sendings exceeded. If set to NULL, no error message is returned. + * + * \return Pointer to handle when success + * Null if failed + */ + +extern struct coap_s *sn_coap_protocol_init(void *(*used_malloc_func_ptr)(uint16_t), void (*used_free_func_ptr)(void *), + uint8_t (*used_tx_callback_ptr)(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *), + int8_t (*used_rx_callback_ptr)(sn_coap_hdr_s *, sn_nsdl_addr_s *, void *)); + +/** + * \fn int8_t sn_coap_protocol_destroy(void) + * + * \brief Frees all memory from CoAP protocol part + * + * \param *handle Pointer to CoAP library handle + * + * \return Return value is always 0 + */ +extern int8_t sn_coap_protocol_destroy(struct coap_s *handle); + +/** + * \fn int16_t sn_coap_protocol_build(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr) + * + * \brief Builds Packet data from given CoAP header structure to be sent + * + * \param *dst_addr_ptr is pointer to destination address where CoAP message + * will be sent (CoAP builder needs that information for message resending purposes) + * + * \param *dst_packet_data_ptr is pointer to destination of built Packet data + * + * \param *src_coap_msg_ptr is pointer to source of built Packet data + * + * \param param void pointer that will be passed to tx/rx function callback when those are called. + * + * \return Return value is byte count of built Packet data.\n + * Note: If message is blockwised, all payload is not sent at the same time\n + * In failure cases:\n + * -1 = Failure in CoAP header structure\n + * -2 = Failure in given pointer (= NULL)\n + * -3 = Failure in Reset message\ŋ + * If there is not enough memory (or User given limit exceeded) for storing + * resending messages, situation is ignored. + */ +extern int16_t sn_coap_protocol_build(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, void *param); + +/** + * \fn sn_coap_hdr_s *sn_coap_protocol_parse(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t packet_data_len, uint8_t *packet_data_ptr) + * + * \brief Parses received CoAP message from given Packet data + * + * \param *src_addr_ptr is pointer to source address of received CoAP message + * (CoAP parser needs that information for Message acknowledgement) + * + * \param *handle Pointer to CoAP library handle + * + * \param packet_data_len is length of given Packet data to be parsed to CoAP message + * + * \param *packet_data_ptr is pointer to source of Packet data to be parsed to CoAP message + * + * \param param void pointer that will be passed to tx/rx function callback when those are called. + * + * \return Return value is pointer to parsed CoAP message structure. This structure includes also coap_status field.\n + * In following failure cases NULL is returned:\n + * -Given NULL pointer\n + * -Failure in parsed header of non-confirmable message\ŋ + * -Out of memory (malloc() returns NULL) + */ +extern sn_coap_hdr_s *sn_coap_protocol_parse(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t packet_data_len, uint8_t *packet_data_ptr, void *); + +/** + * \fn int8_t sn_coap_protocol_exec(struct coap_s *handle, uint32_t current_time) + * + * \brief Sends CoAP messages from re-sending queue, if there is any. + * Cleans also old messages from the duplication list and from block receiving list + * + * This function can be called e.g. once in a second but also more frequently. + * + * \param *handle Pointer to CoAP library handle + * + * \param current_time is System time in seconds. This time is + * used for message re-sending timing and to identify old saved data. + * + * \return 0 if success + * -1 if failed + */ + +extern int8_t sn_coap_protocol_exec(struct coap_s *handle, uint32_t current_time); + +/** + * \fn int8_t sn_coap_protocol_set_block_size(uint16_t block_size) + * + * \brief If block transfer is enabled, this function changes the block size. + * + * \param uint16_t block_size maximum size of CoAP payload. Valid sizes are 16, 32, 64, 128, 256, 512 and 1024 bytes + * \return 0 = success + * -1 = failure + */ +extern int8_t sn_coap_protocol_set_block_size(struct coap_s *handle, uint16_t block_size); + +/** + * \fn int8_t sn_coap_protocol_set_duplicate_buffer_size(uint8_t message_count) + * + * \brief If dublicate message detection is enabled, this function changes buffer size. + * + * \param uint8_t message_count max number of messages saved for duplicate control + * \return 0 = success + * -1 = failure + */ +extern int8_t sn_coap_protocol_set_duplicate_buffer_size(struct coap_s *handle, uint8_t message_count); + +/** + * \fn int8_t sn_coap_protocol_set_retransmission_parameters(uint8_t resending_count, uint8_t resending_intervall) + * + * \brief If re-transmissions are enabled, this function changes resending count and interval. + * + * \param uint8_t resending_count max number of resendings for message + * \param uint8_t resending_intervall message resending intervall in seconds + * \return 0 = success, -1 = failure + */ +extern int8_t sn_coap_protocol_set_retransmission_parameters(struct coap_s *handle, + uint8_t resending_count, uint8_t resending_interval); + +/** + * \fn int8_t sn_coap_protocol_set_retransmission_buffer(uint8_t buffer_size_messages, uint16_t buffer_size_bytes) + * + * \brief If re-transmissions are enabled, this function changes message retransmission queue size. + * Set size to '0' to disable feature. If both are set to '0', then re-sendings are disabled. + * + * \param uint8_t buffer_size_messages queue size - maximum number of messages to be saved to queue + * \param uint8_t buffer_size_bytes queue size - maximum size of messages saved to queue + * \return 0 = success, -1 = failure + */ +extern int8_t sn_coap_protocol_set_retransmission_buffer(struct coap_s *handle, + uint8_t buffer_size_messages, uint16_t buffer_size_bytes); + +/** + * \fn void sn_coap_protocol_clear_retransmission_buffer(struct coap_s *handle) + * + * \param *handle Pointer to CoAP library handle + * + * \brief If re-transmissions are enabled, this function removes all messages from the retransmission queue. + */ +extern void sn_coap_protocol_clear_retransmission_buffer(struct coap_s *handle); + +#endif /* SN_COAP_PROTOCOL_H_ */ + +#ifdef __cplusplus +} +#endif diff --git a/features/FEATURE_CLIENT/mbed-client-c/nsdl-c/sn_nsdl.h b/features/FEATURE_CLIENT/mbed-client-c/nsdl-c/sn_nsdl.h new file mode 100644 index 0000000000..993660cb98 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/nsdl-c/sn_nsdl.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2011-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 sn_nsdl.h +* +* \brief libNsdl generic header file +* +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef SN_NSDL_H_ +#define SN_NSDL_H_ + +/* * * Common * * */ + +#define SN_NSDL_SUCCESS 0 +#define SN_NSDL_FAILURE (-1) + +/* * * * * * * * * * * * * * */ +/* * * * ENUMERATIONS * * * */ +/* * * * * * * * * * * * * * */ + + +/** + * \brief Used protocol + */ +typedef enum sn_nsdl_capab_ { + SN_NSDL_PROTOCOL_HTTP = 0x01, /**< Unsupported */ + SN_NSDL_PROTOCOL_HTTPS = 0x02, /**< Unsupported */ + SN_NSDL_PROTOCOL_COAP = 0x04 /**< Supported */ +} sn_nsdl_capab_e; + +/** + * \brief Address type of given address + */ +typedef enum sn_nsdl_addr_type_ { + SN_NSDL_ADDRESS_TYPE_IPV6 = 0x01, /**< Supported */ + SN_NSDL_ADDRESS_TYPE_IPV4 = 0x02, /**< Supported */ + SN_NSDL_ADDRESS_TYPE_HOSTNAME = 0x03, /**< Unsupported */ + SN_NSDL_ADDRESS_TYPE_NONE = 0xFF +} sn_nsdl_addr_type_e; + + +#define SN_NDSL_RESOURCE_NOT_REGISTERED 0 +#define SN_NDSL_RESOURCE_REGISTERING 1 +#define SN_NDSL_RESOURCE_REGISTERED 2 + + +/* * * * * * * * * * * * * */ +/* * * * STRUCTURES * * * */ +/* * * * * * * * * * * * * */ + +/** + * \brief Address structure of Packet data + */ +typedef struct sn_nsdl_addr_ { + sn_nsdl_addr_type_e type; + + uint8_t addr_len; + uint8_t *addr_ptr; + + uint16_t port; + +} sn_nsdl_addr_s; + +/** + * \brief Used for creating manually registration message with sn_coap_register() + */ +typedef struct registration_info_ { + uint8_t *endpoint_ptr; /**< Endpoint name */ + uint8_t endpoint_len; + + uint8_t *endpoint_type_ptr; /**< Endpoint type */ + uint8_t endpoint_type_len; + + uint8_t *links_ptr; /**< Resource registration string */ + uint16_t links_len; + +} registration_info_t; + +#endif /* SN_NSDL_H_ */ + +#ifdef __cplusplus +} +#endif diff --git a/features/FEATURE_CLIENT/mbed-client-c/nsdl-c/sn_nsdl_lib.h b/features/FEATURE_CLIENT/mbed-client-c/nsdl-c/sn_nsdl_lib.h new file mode 100755 index 0000000000..c6ee7ff5e0 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/nsdl-c/sn_nsdl_lib.h @@ -0,0 +1,684 @@ +/* + * Copyright (c) 2011-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 sn_nsdl_lib.h +* +* \brief NanoService Devices Library header file +* +* +*/ + +#ifndef SN_NSDL_LIB_H_ +#define SN_NSDL_LIB_H_ + +#include "ns_list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SN_NSDL_ENDPOINT_NOT_REGISTERED 0 +#define SN_NSDL_ENDPOINT_IS_REGISTERED 1 + +/* Handle structure */ +struct nsdl_s; + +/** + * \brief Received device server security + */ +typedef enum omalw_server_security_ { + SEC_NOT_SET = -1, + PSK = 0, + RPK = 1, + CERTIFICATE = 2, + NO_SEC = 3 +} omalw_server_security_t; + +/** + * \brief Endpoint binding and mode + */ +typedef enum sn_nsdl_oma_binding_and_mode_ { + BINDING_MODE_NOT_SET = 0, + BINDING_MODE_U = 0x01, + BINDING_MODE_Q = 0x02, + BINDING_MODE_S = 0x04 +} sn_nsdl_oma_binding_and_mode_t; + +/** + * \brief Endpoint registration mode. + * If REGISTER_WITH_RESOURCES, endpoint sends list of all resources during registration. + * If REGISTER_WITH_TEMPLATE, endpoint sends registration without resource list. Device server must have + * correctly configured template. + */ +typedef enum sn_nsdl_registration_mode_ { + REGISTER_WITH_RESOURCES = 0, + REGISTER_WITH_TEMPLATE +} sn_nsdl_registration_mode_t; + + +typedef struct omalw_certificate_list_ { + uint8_t certificate_chain_len; + uint8_t *certificate_ptr[2]; + uint16_t certificate_len[2]; + uint8_t *own_private_key_ptr; + uint16_t own_private_key_len; +} omalw_certificate_list_t; + +/** + * \brief Endpoint registration parameters + */ +typedef struct sn_nsdl_ep_parameters_ { + uint8_t *endpoint_name_ptr; /**< Endpoint name */ + uint8_t endpoint_name_len; + + uint8_t *domain_name_ptr; /**< Domain to register. If null, NSP uses default domain */ + uint8_t domain_name_len; + + uint8_t *type_ptr; /**< Endpoint type */ + uint8_t type_len; + + uint8_t *lifetime_ptr; /**< Endpoint lifetime in seconds. eg. "1200" = 1200 seconds */ + uint8_t lifetime_len; + + sn_nsdl_registration_mode_t ds_register_mode; /**< Defines registration mode */ + sn_nsdl_oma_binding_and_mode_t binding_and_mode; /**< Defines endpoints binding and mode */ + + uint8_t *location_ptr; /**< Endpoint location in server, optional parameter,default is NULL */ + uint8_t location_len; + +} sn_nsdl_ep_parameters_s; + +/** + * \brief For internal use + */ +typedef struct sn_nsdl_sent_messages_ { + uint16_t msg_id_number; + uint8_t message_type; + ns_list_link_t link; +} sn_nsdl_sent_messages_s; + +/** + * \brief Includes resource path + */ +typedef struct sn_grs_resource_ { + uint8_t pathlen; + uint8_t *path; +} sn_grs_resource_s; + +/** + * \brief Table of created resources + */ +typedef struct sn_grs_resource_list_ { + uint8_t res_count; /**< Number of resources */ + sn_grs_resource_s *res; +} sn_grs_resource_list_s; + +/** + * \brief Resource access rights + */ +typedef enum sn_grs_resource_acl_ { + SN_GRS_GET_ALLOWED = 0x01 , + SN_GRS_PUT_ALLOWED = 0x02, + SN_GRS_POST_ALLOWED = 0x04, + SN_GRS_DELETE_ALLOWED = 0x08 +} sn_grs_resource_acl_e; + + +typedef enum sn_nsdl_oma_device_error_ { + NO_ERROR = 0, + LOW_BATTERY_POWER = 1, + EXTERNAL_POWER_SUPPLY_OFF = 2, + GPS_MODULE_FAILURE = 3, + LOW_RECEIVED_SIGNAL_STRENGTH = 4, + OUT_OF_MEMORY = 5, + SMS_FAILURE = 6, + IP_CONN_FAILURE = 7, + PERIPHERAL_MALFUNCTION = 8 +} sn_nsdl_oma_device_error_t; + +/** + * \brief Defines the resource mode + */ +typedef enum sn_nsdl_resource_mode_ { + SN_GRS_STATIC, /**< Static resources have some value that doesn't change */ + SN_GRS_DYNAMIC, /**< Dynamic resources are handled in application. Therefore one must give function callback pointer to them */ + SN_GRS_DIRECTORY /**< Directory resources are unused and unsupported */ +} sn_nsdl_resource_mode_e; + +/** + * \brief Resource registration parameters + */ +typedef struct sn_nsdl_resource_parameters_ { + uint8_t *resource_type_ptr; + uint16_t resource_type_len; + + uint8_t *interface_description_ptr; + uint16_t interface_description_len; + + uint8_t coap_content_type; + + uint8_t mime_content_type; + + uint8_t observable; + + uint8_t registered; + +} sn_nsdl_resource_parameters_s; + +/** + * \brief Defines parameters for the resource. + */ +typedef struct sn_nsdl_resource_info_ { + sn_nsdl_resource_parameters_s *resource_parameters_ptr; + + sn_nsdl_resource_mode_e mode; /**< STATIC etc.. */ + + uint16_t pathlen; /**< Address */ + uint8_t *path; + + uint16_t resourcelen; /**< 0 if dynamic resource, resource information in static resource */ + uint8_t *resource; /**< NULL if dynamic resource */ + + sn_grs_resource_acl_e access; + + uint8_t (*sn_grs_dyn_res_callback)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *, sn_nsdl_capab_e); + + ns_list_link_t link; + + uint8_t publish_uri; + +} sn_nsdl_resource_info_s; + +/** + * \brief Defines OMA device object parameters. + */ +typedef struct sn_nsdl_oma_device_ { + sn_nsdl_oma_device_error_t error_code; /**< Error code. Mandatory. Can be more than one */ + uint8_t (*sn_oma_device_boot_callback)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *, sn_nsdl_capab_e); /**< Device boot callback function. If defined, this is called when reset request is received */ + +} sn_nsdl_oma_device_t; + +/** + * \brief Defines OMAlw server information + */ +typedef struct sn_nsdl_oma_server_info_ { + sn_nsdl_addr_s *omalw_address_ptr; + omalw_server_security_t omalw_server_security; + +} sn_nsdl_oma_server_info_t; + +/** + * \brief Defines endpoint parameters to OMA bootstrap. + */ +typedef struct sn_nsdl_bs_ep_info_ { + void (*oma_bs_status_cb)(sn_nsdl_oma_server_info_t *); /**< Callback for OMA bootstrap status */ + sn_nsdl_oma_device_t *device_object; /**< OMA LWM2M mandatory device resources */ + void (*oma_bs_status_cb_handle)(sn_nsdl_oma_server_info_t *, + struct nsdl_s *); /**< Callback for OMA bootstrap status with nsdl handle */ +} sn_nsdl_bs_ep_info_t; + + + + +/** + * \fn struct nsdl_s *sn_nsdl_init (uint8_t (*sn_nsdl_tx_cb)(sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *), + * uint8_t (*sn_nsdl_rx_cb)(sn_coap_hdr_s *, sn_nsdl_addr_s *), + * sn_nsdl_mem_s *sn_memory) + * + * \brief Initialization function for NSDL library. Initializes NSDL, GRS, HTTP and CoAP. + * + * \param *sn_nsdl_tx_callback A callback function for sending messages. + * + * \param *sn_nsdl_rx_callback A callback function for parsed messages. If received message is not CoAP protocol message (eg. ACK), message for GRS (GET, PUT, POST, DELETE) or + * reply for some DS messages (register message etc.), rx callback will be called. + * + * \param *sn_memory Memory structure which includes function pointers to the allocation and free functions. + * + * \return pointer to created handle structure. NULL if failed + */ +struct nsdl_s *sn_nsdl_init(uint8_t (*sn_nsdl_tx_cb)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *), + uint8_t (*sn_nsdl_rx_cb)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *), + void *(*sn_nsdl_alloc)(uint16_t), void (*sn_nsdl_free)(void *)); + +/** + * \fn extern uint16_t sn_nsdl_register_endpoint(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr); + * + * \brief Registers endpoint to mbed Device Server. + * \param *handle Pointer to nsdl-library handle + * \param *endpoint_info_ptr Contains endpoint information. + * + * \return registration message ID, 0 if failed + */ +extern uint16_t sn_nsdl_register_endpoint(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr); + +/** + * \fn extern uint16_t sn_nsdl_unregister_endpoint(struct nsdl_s *handle) + * + * \brief Sends unregister-message to mbed Device Server. + * + * \param *handle Pointer to nsdl-library handle + * + * \return unregistration message ID, 0 if failed + */ +extern uint16_t sn_nsdl_unregister_endpoint(struct nsdl_s *handle); + +/** + * \fn extern uint16_t sn_nsdl_update_registration(struct nsdl_s *handle, uint8_t *lt_ptr, uint8_t lt_len); + * + * \brief Update the registration with mbed Device Server. + * + * \param *handle Pointer to nsdl-library handle + * \param *lt_ptr Pointer to lifetime value string in ascii form, eg. "1200" + * \param lt_len Length of the lifetime string + * + * \return registration update message ID, 0 if failed + */ +extern uint16_t sn_nsdl_update_registration(struct nsdl_s *handle, uint8_t *lt_ptr, uint8_t lt_len); + +/** + * \fn extern int8_t sn_nsdl_set_endpoint_location(struct nsdl_s *handle, uint8_t *location_ptr, uint8_t location_len); + * + * \brief Sets the location receievd from Device Server. + * + * \param *handle Pointer to nsdl-library handle + * \param *lt_ptr Pointer to location value string , eg. "s322j4k" + * \param lt_len Length of the location string + * + * \return success, 0 if failed -1 + */ +extern int8_t sn_nsdl_set_endpoint_location(struct nsdl_s *handle, uint8_t *location_ptr, uint8_t location_len); + + +/** + * \fn extern int8_t sn_nsdl_is_ep_registered(struct nsdl_s *handle) + * + * \brief Checks if endpoint is registered. + * + * \param *handle Pointer to nsdl-library handle + * + * \return 1 Endpoint registration is done successfully + * \return 0 Endpoint is not registered + */ +extern int8_t sn_nsdl_is_ep_registered(struct nsdl_s *handle); + +/** + * \fn extern void sn_nsdl_nsp_lost(struct nsdl_s *handle); + * + * \brief A function to inform mbed Device C client library if application detects a fault in mbed Device Server registration. + * + * \param *handle Pointer to nsdl-library handle + * + * After calling this function sn_nsdl_is_ep_registered() will return "not registered". + */ +extern void sn_nsdl_nsp_lost(struct nsdl_s *handle); + +/** + * \fn extern uint16_t sn_nsdl_send_observation_notification(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len, + * uint8_t *payload_ptr, uint16_t payload_len, + * uint8_t *observe_ptr, uint8_t observe_len, + * sn_coap_msg_type_e message_type, uint8_t content_type) + * + * + * \brief Sends observation message to mbed Device Server + * + * \param *handle Pointer to nsdl-library handle + * \param *token_ptr Pointer to token to be used + * \param token_len Token length + * \param *payload_ptr Pointer to payload to be sent + * \param payload_len Payload length + * \param *observe_ptr Pointer to observe number to be sent + * \param observe_len Observe number len + * \param message_type Observation message type (confirmable or non-confirmable) + * \param content_type Observation message payload contetnt type + * + * \return !0 Success, observation messages message ID + * \return 0 Failure + */ +extern uint16_t sn_nsdl_send_observation_notification(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len, + uint8_t *payload_ptr, uint16_t payload_len, + uint8_t *observe_ptr, uint8_t observe_len, + sn_coap_msg_type_e message_type, + uint8_t content_type); + +/** + * \fn extern uint16_t sn_nsdl_send_observation_notification_with_uri_path(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len, + * uint8_t *payload_ptr, uint16_t payload_len, + * uint8_t *observe_ptr, uint8_t observe_len, + * sn_coap_msg_type_e message_type, uint8_t content_type, + * uint8_t *uri_path_ptr, + * uint16_t uri_path_len) + * + * + * \brief Sends observation message to mbed Device Server with uri path + * + * \param *handle Pointer to nsdl-library handle + * \param *token_ptr Pointer to token to be used + * \param token_len Token length + * \param *payload_ptr Pointer to payload to be sent + * \param payload_len Payload length + * \param *observe_ptr Pointer to observe number to be sent + * \param observe_len Observe number len + * \param message_type Observation message type (confirmable or non-confirmable) + * \param content_type Observation message payload contetnt type + * \param uri_path_ptr Pointer to uri path to be sent + * \param uri_path_len Uri path len + * + * \return !0 Success, observation messages message ID + * \return 0 Failure + */ +extern uint16_t sn_nsdl_send_observation_notification_with_uri_path(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len, + uint8_t *payload_ptr, uint16_t payload_len, + uint8_t *observe_ptr, uint8_t observe_len, + sn_coap_msg_type_e message_type, + uint8_t content_type, + uint8_t *uri_path_ptr, + uint16_t uri_path_len); + +/** + * \fn extern uint32_t sn_nsdl_get_version(void) + * + * \brief Version query function. + * + * Used to retrieve the version information from the mbed Device C Client library. + * + * \return Pointer to library version string +*/ +extern char *sn_nsdl_get_version(void); + +/** + * \fn extern int8_t sn_nsdl_process_coap(struct nsdl_s *handle, uint8_t *packet, uint16_t packet_len, sn_nsdl_addr_s *src) + * + * \brief To push CoAP packet to mbed Device C Client library + * + * Used to push an CoAP packet to mbed Device C Client library for processing. + * + * \param *handle Pointer to nsdl-library handle + * + * \param *packet Pointer to a uint8_t array containing the packet (including the CoAP headers). + * After successful execution this array may contain the response packet. + * + * \param *packet_len Pointer to length of the packet. After successful execution this array may contain the length + * of the response packet. + * + * \param *src Pointer to packet source address information. After successful execution this array may contain + * the destination address of the response packet. + * + * \return 0 Success + * \return -1 Failure + */ +extern int8_t sn_nsdl_process_coap(struct nsdl_s *handle, uint8_t *packet, uint16_t packet_len, sn_nsdl_addr_s *src); + +/** + * \fn extern int8_t sn_nsdl_exec(struct nsdl_s *handle, uint32_t time); + * + * \brief CoAP retransmission function. + * + * Used to give execution time for the mbed Device C Client library for retransmissions. + * + * \param *handle Pointer to nsdl-library handle + * + * \param time Time in seconds. + * + * \return 0 Success + * \return -1 Failure + */ +extern int8_t sn_nsdl_exec(struct nsdl_s *handle, uint32_t time); + +/** + * \fn extern int8_t sn_nsdl_create_resource(struct nsdl_s *handle, sn_nsdl_resource_info_s *res); + * + * \brief Resource creating function. + * + * Used to create a static or dynamic CoAP resource. + * + * \param *res Pointer to a structure of type sn_nsdl_resource_info_t that contains the information + * about the resource. + * + * \return 0 Success + * \return -1 Failure + * \return -2 Resource already exists + * \return -3 Invalid path + * \return -4 List adding failure + */ +extern int8_t sn_nsdl_create_resource(struct nsdl_s *handle, sn_nsdl_resource_info_s *res); + +/** + * \fn extern int8_t sn_nsdl_update_resource(sn_nsdl_resource_info_s *res) + * + * \brief Resource updating function. + * + * Used to update the direct value of a static resource, the callback function pointer of a dynamic resource + * and access rights of the recource. + * + * \param *handle Pointer to nsdl-library handle + * \param *res Pointer to a structure of type sn_nsdl_resource_info_t that contains the information + * about the resource. Only the pathlen and path elements are evaluated along with + * either resourcelen and resource or the function pointer. + * + * \return 0 Success + * \return -1 Failure + */ +extern int8_t sn_nsdl_update_resource(struct nsdl_s *handle, sn_nsdl_resource_info_s *res); + +/** + * \fn extern int8_t sn_nsdl_delete_resource(struct nsdl_s *handle, uint8_t pathlen, uint8_t *path) + * + * \brief Resource delete function. + * + * Used to delete a resource. If resource has a subresources, these all must also be removed. + * + * \param *handle Pointer to nsdl-library handle + * \param pathlen Contains the length of the path that is to be deleted (excluding possible trailing "\0"). + * \param *path_ptr A pointer to an array containing the path. + * + * \return 0 Success + * \return -1 Failure (No such resource) + */ +extern int8_t sn_nsdl_delete_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path); + +/** + * \fn extern sn_nsdl_resource_info_s *sn_nsdl_get_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path) + * + * \brief Resource get function. + * + * Used to get a resource. + * + * \param *handle Pointer to nsdl-library handle + * \param pathlen Contains the length of the path that is to be returned (excluding possible trailing '\0'). + * \param *path A pointer to an array containing the path. + * + * \return !NULL Success, pointer to a sn_nsdl_resource_info_s that contains the resource information\n + * \return NULL Failure + */ +extern sn_nsdl_resource_info_s *sn_nsdl_get_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path); + +/** + * \fn extern sn_grs_resource_list_s *sn_nsdl_list_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path) + * + * \brief Resource list function. + * + * \param *handle Pointer to nsdl-library handle + * \param pathlen Contains the length of the target path (excluding possible trailing '\0'). + * The length value is not examined if the path itself is a NULL pointer. + * \param *path A pointer to an array containing the path or a NULL pointer. + * + * \return !NULL A pointer to a sn_grs_resource_list_s structure containing the resource listing. + * \return NULL Failure with an unspecified error + */ +sn_grs_resource_list_s *sn_nsdl_list_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path); + +/** + * \fn extern void sn_nsdl_free_resource_list(struct nsdl_s *handle, sn_grs_resource_list_s *list) + * + * \brief Free a resource list obtained from sn_nsdl_list_resource() + * + * \param list The list to free, or NULL. + */ +void sn_nsdl_free_resource_list(struct nsdl_s *handle, sn_grs_resource_list_s *list); + +/** + * \fn extern int8_t sn_nsdl_send_coap_message(struct nsdl_s *handle, sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr); + * + * \brief Send an outgoing CoAP request. + * + * \param *handle Pointer to nsdl-library handle + * \param *address_ptr Pointer to source address struct + * \param *coap_hdr_ptr Pointer to CoAP message to be sent + * + * \return 0 Success + * \return -1 Failure + */ +extern int8_t sn_nsdl_send_coap_message(struct nsdl_s *handle, sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr); + +/** + * \fn extern int8_t set_NSP_address(struct nsdl_s *handle, uint8_t *NSP_address, uint16_t port, sn_nsdl_addr_type_e address_type); + * + * \brief This function is used to set the mbed Device Server address given by an application. + * + * \param *handle Pointer to nsdl-library handle + * \return 0 Success + * \return -1 Failed to indicate that internal address pointer is not allocated (call nsdl_init() first). + */ +extern int8_t set_NSP_address(struct nsdl_s *handle, uint8_t *NSP_address, uint16_t port, sn_nsdl_addr_type_e address_type); + +/** + * \fn extern int8_t sn_nsdl_destroy(struct nsdl_s *handle); + * + * \param *handle Pointer to nsdl-library handle + * \brief This function releases all allocated memory in mbed Device C Client library. + */ +extern int8_t sn_nsdl_destroy(struct nsdl_s *handle); + +/** + * \fn extern uint16_t sn_nsdl_oma_bootstrap(struct nsdl_s *handle, sn_nsdl_addr_s *bootstrap_address_ptr, sn_nsdl_ep_parameters_s *endpoint_info_ptr, sn_nsdl_bs_ep_info_t *bootstrap_endpoint_info_ptr); + * + * \brief Starts OMA bootstrap process + * + * \param *handle Pointer to nsdl-library handle + * + * \return bootstrap message ID, 0 if failed + */ +extern uint16_t sn_nsdl_oma_bootstrap(struct nsdl_s *handle, sn_nsdl_addr_s *bootstrap_address_ptr, sn_nsdl_ep_parameters_s *endpoint_info_ptr, sn_nsdl_bs_ep_info_t *bootstrap_endpoint_info_ptr); + +/** + * \fn extern omalw_certificate_list_t *sn_nsdl_get_certificates(struct nsdl_s *handle); + * + * \brief Get pointer to received device server certificates + * + * \param *handle Pointer to nsdl-library handle + */ +extern omalw_certificate_list_t *sn_nsdl_get_certificates(struct nsdl_s *handle); + +/** + * \fn extern int8_t sn_nsdl_update_certificates(struct nsdl_s *handle, omalw_certificate_list_t* certificate_ptr, uint8_t certificate_chain); + * + * \brief Updates certificate pointers to resource server. + * + * \param *handle Pointer to nsdl-library handle + */ +extern int8_t sn_nsdl_update_certificates(struct nsdl_s *handle, omalw_certificate_list_t *certificate_ptr, uint8_t certificate_chain); + +/** + * \fn extern int8_t sn_nsdl_create_oma_device_object(struct nsdl_s *handle, sn_nsdl_oma_device_t *device_object_ptr); + * + * \brief Creates new device object resource + * + * \param *handle Pointer to nsdl-library handle + */ +extern int8_t sn_nsdl_create_oma_device_object(struct nsdl_s *handle, sn_nsdl_oma_device_t *device_object_ptr); + +/** + * \fn sn_coap_hdr_s *sn_nsdl_build_response(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code) + * + * \brief Prepares generic response packet from a request packet. This function allocates memory for the resulting sn_coap_hdr_s + * + * \param *handle Pointer to library handle + * \param *coap_packet_ptr The request packet pointer + * \param msg_code response messages code + * + * \return *coap_packet_ptr The allocated and pre-filled response packet pointer + * NULL Error in parsing the request + * + */ +extern sn_coap_hdr_s *sn_nsdl_build_response(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code); + +/** + * \fn void sn_nsdl_release_allocated_coap_msg_mem(struct nsdl_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr) + * + * \brief Releases memory of given CoAP message + * + * Note!!! Does not release Payload part + * + * \param *handle Pointer to CoAP library handle + * + * \param *freed_coap_msg_ptr is pointer to released CoAP message + */ +extern void sn_nsdl_release_allocated_coap_msg_mem(struct nsdl_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr); + +/** + * \fn int8_t sn_nsdl_set_retransmission_parameters(struct nsdl_s *handle, uint8_t resending_count, uint8_t resending_intervall) + * + * \brief If re-transmissions are enabled, this function changes resending count and interval. + * + * \param *handle Pointer to library handle + * \param uint8_t resending_count max number of resendings for message + * \param uint8_t resending_intervall message resending intervall in seconds + * \return 0 = success, -1 = failure + */ +extern int8_t sn_nsdl_set_retransmission_parameters(struct nsdl_s *handle, uint8_t resending_count, uint8_t resending_interval); + +/** + * \fn int8_t sn_nsdl_set_retransmission_buffer(struct nsdl_s *handle, uint8_t buffer_size_messages, uint16_t buffer_size_bytes) + * + * \brief If re-transmissions are enabled, this function changes message retransmission queue size. + * Set size to '0' to disable feature. If both are set to '0', then re-sendings are disabled. + * + * \param *handle Pointer to library handle + * \param uint8_t buffer_size_messages queue size - maximum number of messages to be saved to queue + * \param uint8_t buffer_size_bytes queue size - maximum size of messages saved to queue + * \return 0 = success, -1 = failure + */ +extern int8_t sn_nsdl_set_retransmission_buffer(struct nsdl_s *handle, + uint8_t buffer_size_messages, uint16_t buffer_size_bytes); + +/** + * \fn int8_t sn_nsdl_set_block_size(struct nsdl_s *handle, uint16_t block_size) + * + * \brief If block transfer is enabled, this function changes the block size. + * + * \param *handle Pointer to library handle + * \param uint16_t block_size maximum size of CoAP payload. Valid sizes are 16, 32, 64, 128, 256, 512 and 1024 bytes + * \return 0 = success, -1 = failure + */ +extern int8_t sn_nsdl_set_block_size(struct nsdl_s *handle, uint16_t block_size); + +/** + * \fn int8_t sn_nsdl_set_duplicate_buffer_size(struct nsdl_s *handle,uint8_t message_count) + * + * \brief If dublicate message detection is enabled, this function changes buffer size. + * + * \param *handle Pointer to library handle + * \param uint8_t message_count max number of messages saved for duplicate control + * \return 0 = success, -1 = failure + */ +extern int8_t sn_nsdl_set_duplicate_buffer_size(struct nsdl_s *handle, uint8_t message_count); + +#ifdef __cplusplus +} +#endif + +#endif /* SN_NSDL_LIB_H_ */ diff --git a/features/FEATURE_CLIENT/mbed-client-c/run_unit_tests.sh b/features/FEATURE_CLIENT/mbed-client-c/run_unit_tests.sh new file mode 100755 index 0000000000..e503c34e04 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/run_unit_tests.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Copyright (c) 2015 ARM Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# * http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +echo +echo "Build mbed Client C unit tests" +echo + +yt target x86-linux-native +yt up +make -f Makefile.test test +#make -f Makefile.test test clean diff --git a/features/FEATURE_CLIENT/mbed-client-c/run_unit_tests_with_valgrind.sh b/features/FEATURE_CLIENT/mbed-client-c/run_unit_tests_with_valgrind.sh new file mode 100755 index 0000000000..f02fd71470 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/run_unit_tests_with_valgrind.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# Execute script with root path where to find binaries. +# For example ./run_unit_tests_with_valgrind.sh ./build/x86-linux-native-coverage/test/mbedclient/ + +input="binaries.txt" +valgrind_logs="valgrind_logs" +rm -rf $valgrind_logs +mkdir $valgrind_logs +find $1 -type f -executable -exec sh -c "file -i '{}' | grep -q 'x-executable; charset=binary'" \; -print > $input +while file= read -r binary +do + valgrind --track-origins=yes --xml=yes --xml-file="${valgrind_logs}/valgrind_$(basename $binary).xml" "$binary" + +done < "$input" diff --git a/features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/include/sn_coap_header_internal.h b/features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/include/sn_coap_header_internal.h new file mode 100644 index 0000000000..0a6d5936cb --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/include/sn_coap_header_internal.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2011-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 sn_coap_header_internal.h + * + * \brief Header file for CoAP Header part + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef SN_COAP_HEADER_INTERNAL_H_ +#define SN_COAP_HEADER_INTERNAL_H_ + + +/* * * * * * * * * * * */ +/* * * * DEFINES * * * */ +/* * * * * * * * * * * */ + +#define COAP_VERSION COAP_VERSION_1 /* Tells which IETF CoAP specification version the CoAP message supports. */ +/* This value is written to CoAP message header part. */ + +/* CoAP Header defines */ +#define COAP_HEADER_LENGTH 4 /* Fixed Header length of CoAP message as bytes */ +#define COAP_HEADER_VERSION_MASK 0xC0 +#define COAP_HEADER_MSG_TYPE_MASK 0x30 +#define COAP_HEADER_TOKEN_LENGTH_MASK 0x0F +#define COAP_HEADER_MSG_ID_MSB_SHIFT 8 + +/* CoAP Options defines */ +#define COAP_OPTIONS_OPTION_NUMBER_SHIFT 4 + +/* * * * * * * * * * * * * * */ +/* * * * ENUMERATIONS * * * */ +/* * * * * * * * * * * * * * */ + +/* * * * * * * * * * * * * */ +/* * * * STRUCTURES * * * */ +/* * * * * * * * * * * * * */ + +/** + * \brief This structure is returned by sn_coap_exec() for sending + */ +typedef struct sn_nsdl_transmit_ { + sn_nsdl_addr_s *dst_addr_ptr; + + sn_nsdl_capab_e protocol; + + uint16_t packet_len; + uint8_t *packet_ptr; + uint8_t *uri_path_ptr; + uint8_t uri_path_len; +} sn_nsdl_transmit_s; + +/* * * * * * * * * * * * * * * * * * * * * * */ +/* * * * EXTERNAL FUNCTION PROTOTYPES * * * */ +/* * * * * * * * * * * * * * * * * * * * * * */ +extern int8_t sn_coap_header_validity_check(sn_coap_hdr_s *src_coap_msg_ptr, coap_version_e coap_version); + +#endif /* SN_COAP_HEADER_INTERNAL_H_ */ + +#ifdef __cplusplus +} +#endif diff --git a/features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/include/sn_coap_protocol_internal.h b/features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/include/sn_coap_protocol_internal.h new file mode 100644 index 0000000000..bb536e1cf9 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/include/sn_coap_protocol_internal.h @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2011-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 sn_coap_protocol_internal.h + * + * \brief Header file for CoAP Protocol part + * + */ + +#ifndef SN_COAP_PROTOCOL_INTERNAL_H_ +#define SN_COAP_PROTOCOL_INTERNAL_H_ + +#include "ns_list.h" +#include "sn_coap_header_internal.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* * * * * * * * * * * */ +/* * * * DEFINES * * * */ +/* * * * * * * * * * * */ + +/* * For Message resending * */ +#define ENABLE_RESENDINGS 1 /**< Enable / Disable resending from library in building */ + +#define SN_COAP_RESENDING_MAX_COUNT 3 /**< Default number of re-sendings */ +#define SN_COAP_RESENDING_QUEUE_SIZE_MSGS 2 /**< Default re-sending queue size - defines how many messages can be stored. Setting this to 0 disables feature */ +#define SN_COAP_RESENDING_QUEUE_SIZE_BYTES 0 /**< Default re-sending queue size - defines size of the re-sending buffer. Setting this to 0 disables feature */ +#define DEFAULT_RESPONSE_TIMEOUT 10 /**< Default re-sending timeout as seconds */ + +/* These parameters sets maximum values application can set with API */ +#define SN_COAP_MAX_ALLOWED_RESENDING_COUNT 6 /**< Maximum allowed count of re-sending */ +#define SN_COAP_MAX_ALLOWED_RESENDING_BUFF_SIZE_MSGS 6 /**< Maximum allowed number of saved re-sending messages */ +#define SN_COAP_MAX_ALLOWED_RESENDING_BUFF_SIZE_BYTES 512 /**< Maximum allowed size of re-sending buffer */ +#define SN_COAP_MAX_ALLOWED_RESPONSE_TIMEOUT 40 /**< Maximum allowed re-sending timeout */ + +#define RESPONSE_RANDOM_FACTOR 1 /**< Resending random factor, value is specified in IETF CoAP specification */ + +/* * For Message duplication detecting * */ + +/* Init value for the maximum count of messages to be stored for duplication detection */ +/* Setting of this value to 0 will disable duplication check, also reduce use of ROM memory */ + +// Keep the old flag to maintain backward compatibility +#ifndef SN_COAP_DUPLICATION_MAX_MSGS_COUNT +#define SN_COAP_DUPLICATION_MAX_MSGS_COUNT 0 +#endif + +#ifdef YOTTA_CFG_COAP_DUPLICATION_MAX_MSGS_COUNT +#define SN_COAP_DUPLICATION_MAX_MSGS_COUNT YOTTA_CFG_COAP_DUPLICATION_MAX_MSGS_COUNT +#elif defined MBED_CONF_MBED_CLIENT_SN_COAP_DUPLICATION_MAX_MSGS_COUNT +#define SN_COAP_DUPLICATION_MAX_MSGS_COUNT MBED_CONF_MBED_CLIENT_SN_COAP_DUPLICATION_MAX_MSGS_COUNT +#endif + + + +/* Maximum allowed number of saved messages for duplicate searching */ +#define SN_COAP_MAX_ALLOWED_DUPLICATION_MESSAGE_COUNT 6 + +/* Maximum time in seconds of messages to be stored for duplication detection */ +#define SN_COAP_DUPLICATION_MAX_TIME_MSGS_STORED 60 /* RESPONSE_TIMEOUT * RESPONSE_RANDOM_FACTOR * (2 ^ MAX_RETRANSMIT - 1) + the expected maximum round trip time */ + +/* * For Message blockwising * */ + +/* Init value for the maximum payload size to be sent and received at one blockwise message */ +/* Setting of this value to 0 will disable this feature, and also reduce use of ROM memory */ +/* Note: Current Coap implementation supports Blockwise transfers specification version draft-ietf-core-block-03 */ +/* Note: This define is common for both received and sent Blockwise messages */ + +#ifdef YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE +#define SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE +#elif defined MBED_CONF_MBED_CLIENT_SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE +#define SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE MBED_CONF_MBED_CLIENT_SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE +#endif + +#ifndef SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE +#define SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE 0 /**< Must be 2^x and x is at least 4. Suitable values: 0, 16, 32, 64, 128, 256, 512 and 1024 */ +#endif + + +#ifndef SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED +#define SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED 10 /**< Maximum time in seconds of data (messages and payload) to be stored for blockwising */ +#endif + + + +/* * * * * * * * * * * * * * */ +/* * * * ENUMERATIONS * * * */ +/* * * * * * * * * * * * * * */ + +/* * * * * * * * * * * * * */ +/* * * * STRUCTURES * * * */ +/* * * * * * * * * * * * * */ + + + + +/* Structure which is stored to Linked list for message sending purposes */ +typedef struct coap_send_msg_ { + uint8_t resending_counter; /* Tells how many times message is still tried to resend */ + uint32_t resending_time; /* Tells next resending time */ + + sn_nsdl_transmit_s *send_msg_ptr; + + struct coap_s *coap; /* CoAP library handle */ + void *param; /* Extra parameter that will be passed to TX/RX callback functions */ + + ns_list_link_t link; +} coap_send_msg_s; + +typedef NS_LIST_HEAD(coap_send_msg_s, link) coap_send_msg_list_t; + +/* Structure which is stored to Linked list for message duplication detection purposes */ +typedef struct coap_duplication_info_ { + uint32_t timestamp; /* Tells when duplication information is stored to Linked list */ + + uint8_t addr_len; + uint8_t *addr_ptr; + uint16_t port; + + uint16_t msg_id; + + struct coap_s *coap; /* CoAP library handle */ + + ns_list_link_t link; +} coap_duplication_info_s; + +typedef NS_LIST_HEAD(coap_duplication_info_s, link) coap_duplication_info_list_t; + +/* Structure which is stored to Linked list for blockwise messages sending purposes */ +typedef struct coap_blockwise_msg_ { + uint32_t timestamp; /* Tells when Blockwise message is stored to Linked list */ + + sn_coap_hdr_s *coap_msg_ptr; + struct coap_s *coap; /* CoAP library handle */ + + ns_list_link_t link; +} coap_blockwise_msg_s; + +typedef NS_LIST_HEAD(coap_blockwise_msg_s, link) coap_blockwise_msg_list_t; + +/* Structure which is stored to Linked list for blockwise messages receiving purposes */ +typedef struct coap_blockwise_payload_ { + uint32_t timestamp; /* Tells when Payload is stored to Linked list */ + + uint8_t addr_len; + uint8_t *addr_ptr; + uint16_t port; + + uint16_t payload_len; + uint8_t *payload_ptr; + struct coap_s *coap; /* CoAP library handle */ + + ns_list_link_t link; +} coap_blockwise_payload_s; + +typedef NS_LIST_HEAD(coap_blockwise_payload_s, link) coap_blockwise_payload_list_t; + +struct coap_s { + void *(*sn_coap_protocol_malloc)(uint16_t); + void (*sn_coap_protocol_free)(void *); + + uint8_t (*sn_coap_tx_callback)(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *); + int8_t (*sn_coap_rx_callback)(sn_coap_hdr_s *, sn_nsdl_addr_s *, void *); + + #if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ + coap_send_msg_list_t linked_list_resent_msgs; /* Active resending messages are stored to this Linked list */ + uint16_t count_resent_msgs; + #endif + + #if SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */ + coap_duplication_info_list_t linked_list_duplication_msgs; /* Messages for duplicated messages detection is stored to this Linked list */ + uint16_t count_duplication_msgs; + #endif + + #if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwise is not used at all, this part of code will not be compiled */ + coap_blockwise_msg_list_t linked_list_blockwise_sent_msgs; /* Blockwise message to to be sent is stored to this Linked list */ + coap_blockwise_payload_list_t linked_list_blockwise_received_payloads; /* Blockwise payload to to be received is stored to this Linked list */ + #endif + + uint32_t system_time; /* System time seconds */ + uint16_t sn_coap_block_data_size; + uint8_t sn_coap_resending_queue_msgs; + uint8_t sn_coap_resending_queue_bytes; + uint8_t sn_coap_resending_count; + uint8_t sn_coap_resending_intervall; + uint8_t sn_coap_duplication_buffer_size; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* SN_COAP_PROTOCOL_INTERNAL_H_ */ + diff --git a/features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/sn_coap_builder.c b/features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/sn_coap_builder.c new file mode 100644 index 0000000000..80ab24da0e --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/sn_coap_builder.c @@ -0,0 +1,1180 @@ +/* + * Copyright (c) 2011-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 sn_coap_builder.c + * + * \brief CoAP Message builder + * + * Functionality: Builds CoAP message + * + */ + +/* * * * * * * * * * * * * * */ +/* * * * INCLUDE FILES * * * */ +/* * * * * * * * * * * * * * */ + +#include /* For memset() and memcpy() */ + +#include "ns_types.h" +#include "sn_nsdl.h" +#include "sn_coap_header.h" +#include "sn_coap_header_internal.h" +#include "sn_coap_protocol_internal.h" +#include "mbed-trace/mbed_trace.h" + +#define TRACE_GROUP "coap" +/* * * * LOCAL FUNCTION PROTOTYPES * * * */ +static int8_t sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr); +static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr); +static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option); +static int16_t sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet_data_pptr, uint16_t option_len, uint8_t *option_ptr, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number); +static int16_t sn_coap_builder_options_build_add_zero_length_option(uint8_t **dst_packet_data_pptr, uint8_t option_length, uint8_t option_exist, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number); +static int16_t sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, uint8_t **src_pptr, uint16_t *src_len_ptr, sn_coap_option_numbers_e option, uint16_t *previous_option_number); +static uint8_t sn_coap_builder_options_get_option_part_count(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option); +static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option_string(uint16_t query_len, uint8_t *query_ptr, uint8_t query_index, sn_coap_option_numbers_e option); +static int16_t sn_coap_builder_options_get_option_part_position(uint16_t query_len, uint8_t *query_ptr, uint8_t query_index, sn_coap_option_numbers_e option); +static void sn_coap_builder_payload_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr); +static uint8_t sn_coap_builder_options_calculate_jump_need(sn_coap_hdr_s *src_coap_msg_ptr, uint8_t block_option); + +sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code) +{ + sn_coap_hdr_s *coap_res_ptr; + + if (!coap_packet_ptr || !handle) { + return NULL; + } + + coap_res_ptr = sn_coap_parser_alloc_message(handle); + if (!coap_res_ptr) { + return NULL; + } + + if (coap_packet_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) { + coap_res_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + coap_res_ptr->msg_code = (sn_coap_msg_code_e)msg_code; + coap_res_ptr->msg_id = coap_packet_ptr->msg_id; + } + + else if (coap_packet_ptr->msg_type == COAP_MSG_TYPE_NON_CONFIRMABLE) { + coap_res_ptr->msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE; + coap_res_ptr->msg_code = (sn_coap_msg_code_e)msg_code; + /* msg_id needs to be set by the caller in this case */ + } + + else { + handle->sn_coap_protocol_free( coap_res_ptr ); + return NULL; + } + + if (coap_packet_ptr->token_ptr) { + coap_res_ptr->token_len = coap_packet_ptr->token_len; + coap_res_ptr->token_ptr = handle->sn_coap_protocol_malloc(coap_res_ptr->token_len); + if (!coap_res_ptr->token_ptr) { + handle->sn_coap_protocol_free(coap_res_ptr); + return NULL; + } + memcpy(coap_res_ptr->token_ptr, coap_packet_ptr->token_ptr, coap_res_ptr->token_len); + } + return coap_res_ptr; +} + +int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr) +{ + return sn_coap_builder_2(dst_packet_data_ptr, src_coap_msg_ptr, SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE); +} + +int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size) +{ + tr_debug("sn_coap_builder_2"); + uint8_t *base_packet_data_ptr = NULL; + + /* * * * Check given pointers * * * */ + if (dst_packet_data_ptr == NULL || src_coap_msg_ptr == NULL) { + return -2; + } + + /* Initialize given Packet data memory area with zero values */ + uint16_t dst_byte_count_to_be_built = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_msg_ptr, blockwise_payload_size); + tr_debug("sn_coap_builder_2 - message len: [%d]", dst_byte_count_to_be_built); + if (!dst_byte_count_to_be_built) { + return -1; + } + + memset(dst_packet_data_ptr, 0, dst_byte_count_to_be_built); + + /* * * * Store base (= original) destination Packet data pointer for later usage * * * */ + base_packet_data_ptr = dst_packet_data_ptr; + + /* * * * * * * * * * * * * * * * * * */ + /* * * * Header part building * * * */ + /* * * * * * * * * * * * * * * * * * */ + if (sn_coap_builder_header_build(&dst_packet_data_ptr, src_coap_msg_ptr) != 0) { + /* Header building failed */ + return -1; + } + + /* If else than Reset message because Reset message must be empty */ + if (src_coap_msg_ptr->msg_type != COAP_MSG_TYPE_RESET) { + /* * * * * * * * * * * * * * * * * * */ + /* * * * Options part building * * * */ + /* * * * * * * * * * * * * * * * * * */ + sn_coap_builder_options_build(&dst_packet_data_ptr, src_coap_msg_ptr); + + /* * * * * * * * * * * * * * * * * * */ + /* * * * Payload part building * * * */ + /* * * * * * * * * * * * * * * * * * */ + sn_coap_builder_payload_build(&dst_packet_data_ptr, src_coap_msg_ptr); + } + /* * * * Return built Packet data length * * * */ + return (dst_packet_data_ptr - base_packet_data_ptr); +} +uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_coap_msg_ptr) +{ + return sn_coap_builder_calc_needed_packet_data_size_2(src_coap_msg_ptr, SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE); +} + +uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size) +{ + tr_debug("sn_coap_builder_calc_needed_packet_data_size_2"); + uint16_t returned_byte_count = 0; + + if (!src_coap_msg_ptr) { + return 0; + } + /* * * * * HEADER * * * * */ + + /* Header size is fixed */ + returned_byte_count = COAP_HEADER_LENGTH; + + /* * * * * OPTIONS * * * * */ + + /* If else than Reset message because Reset message must be empty */ + if (src_coap_msg_ptr->msg_type != COAP_MSG_TYPE_RESET) { + uint16_t repeatable_option_size = 0; +#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + bool is_blockwise_needed = false; + if ((src_coap_msg_ptr->payload_len > blockwise_payload_size) && (blockwise_payload_size > 0)) { + is_blockwise_needed = true; + } +#endif + /* TOKEN - Length is 1-8 bytes */ + if (src_coap_msg_ptr->token_ptr != NULL) { + if (src_coap_msg_ptr->token_len > 8 || src_coap_msg_ptr->token_len < 1) { /* Check that option is not longer than defined */ + return 0; + } + + returned_byte_count += src_coap_msg_ptr->token_len; + } + /* URI PATH - Repeatable option. Length of one option is 0-255 */ + /* Do not add uri-path for notification message. + * Uri-path is needed for cancelling observation with RESET message */ + if (!src_coap_msg_ptr->options_list_ptr || + (src_coap_msg_ptr->options_list_ptr && !src_coap_msg_ptr->options_list_ptr->observe_len && !src_coap_msg_ptr->options_list_ptr->observe_ptr)) { + if (src_coap_msg_ptr->uri_path_ptr != NULL) { + repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->uri_path_len, + src_coap_msg_ptr->uri_path_ptr, COAP_OPTION_URI_PATH); + if (repeatable_option_size) { + returned_byte_count += repeatable_option_size; + } else { + return 0; + } + } + } + /* CONTENT TYPE - Length of this option is 0-2 bytes */ + if (src_coap_msg_ptr->content_type_ptr != NULL) { + returned_byte_count++; + if (src_coap_msg_ptr->content_type_len > 2) { + return 0; + } + + returned_byte_count += src_coap_msg_ptr->content_type_len; + } + /* If options list pointer exists */ + if (src_coap_msg_ptr->options_list_ptr != NULL) { + /* ACCEPT - Repeatable option. Length of this option is 0-2 bytes */ + if (src_coap_msg_ptr->options_list_ptr->accept_ptr != NULL) { + repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->accept_len, + src_coap_msg_ptr->options_list_ptr->accept_ptr, COAP_OPTION_ACCEPT); + if (repeatable_option_size) { + returned_byte_count += repeatable_option_size; + } else { + return 0; + } + } + /* MAX AGE - Length of this option is 0-4 bytes */ + if (src_coap_msg_ptr->options_list_ptr->max_age_ptr != NULL) { + returned_byte_count++; + if (src_coap_msg_ptr->options_list_ptr->max_age_len > 4) { + return 0; + } + + returned_byte_count += src_coap_msg_ptr->options_list_ptr->max_age_len; + } + /* PROXY URI - Length of this option is 1-1034 bytes */ + if (src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr != NULL) { + if (src_coap_msg_ptr->options_list_ptr->proxy_uri_len >= 1 && src_coap_msg_ptr->options_list_ptr->proxy_uri_len <= 12) { /* Add option header byte(s) - depending of option length */ + returned_byte_count++; + } + + else if (src_coap_msg_ptr->options_list_ptr->proxy_uri_len >= 13 && src_coap_msg_ptr->options_list_ptr->proxy_uri_len <= 269) { + returned_byte_count += 2; + } + + else if (src_coap_msg_ptr->options_list_ptr->proxy_uri_len >= 270 && src_coap_msg_ptr->options_list_ptr->proxy_uri_len <= 1034) { + returned_byte_count += 3; + } + + else { + return 0; + } + + /* Add needed memory for Option value */ + returned_byte_count += src_coap_msg_ptr->options_list_ptr->proxy_uri_len; + } + /* ETAG - Repeatable option. Length of this option is 1-8 bytes*/ + if (src_coap_msg_ptr->options_list_ptr->etag_ptr != NULL) { + repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->etag_len, + src_coap_msg_ptr->options_list_ptr->etag_ptr, COAP_OPTION_ETAG); + if (repeatable_option_size) { + returned_byte_count += repeatable_option_size; + } else { + return 0; + } + } + /* URI HOST - Length of this option is 1-255 bytes */ + if (src_coap_msg_ptr->options_list_ptr->uri_host_ptr != NULL) { + if (src_coap_msg_ptr->options_list_ptr->uri_host_len > 0 && src_coap_msg_ptr->options_list_ptr->uri_host_len <= 12) { + returned_byte_count++; + } + + else if (src_coap_msg_ptr->options_list_ptr->uri_host_len >= 13 && src_coap_msg_ptr->options_list_ptr->uri_host_len <= 255) { + returned_byte_count += 2; + } + + else { + return 0; + } + + returned_byte_count += src_coap_msg_ptr->options_list_ptr->uri_host_len; + } + /* LOCATION PATH - Repeatable option. Length of this option is 0-255 bytes*/ + if (src_coap_msg_ptr->options_list_ptr->location_path_ptr != NULL) { + repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->location_path_len, + src_coap_msg_ptr->options_list_ptr->location_path_ptr, COAP_OPTION_LOCATION_PATH); + if (repeatable_option_size) { + returned_byte_count += repeatable_option_size; + } else { + return 0; + } + } + /* URI PORT - Length of this option is 0-2 bytes */ + if (src_coap_msg_ptr->options_list_ptr->uri_port_ptr != NULL) { + returned_byte_count++; + if (src_coap_msg_ptr->options_list_ptr->uri_port_len > 2) { + return 0; + } + + returned_byte_count += src_coap_msg_ptr->options_list_ptr->uri_port_len; + } + /* lOCATION QUERY - Repeatable option. Length of this option is 0-255 bytes */ + if (src_coap_msg_ptr->options_list_ptr->location_query_ptr != NULL) { + repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->location_query_len, + src_coap_msg_ptr->options_list_ptr->location_query_ptr, COAP_OPTION_LOCATION_QUERY); + if (repeatable_option_size) { + returned_byte_count += repeatable_option_size; + } else { + return 0; + } + } + /* OBSERVE - Length of this option is 0-3 bytes */ + if (src_coap_msg_ptr->options_list_ptr->observe_ptr != NULL) { + returned_byte_count++; + if (src_coap_msg_ptr->options_list_ptr->observe_len > 3) { + return 0; + } + + returned_byte_count += src_coap_msg_ptr->options_list_ptr->observe_len; + } else if (src_coap_msg_ptr->options_list_ptr->observe) { + returned_byte_count++; + } + /* URI QUERY - Repeatable option. Length of this option is 1-255 */ + if (src_coap_msg_ptr->options_list_ptr->uri_query_ptr != NULL) { + repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->uri_query_len, + src_coap_msg_ptr->options_list_ptr->uri_query_ptr, COAP_OPTION_URI_QUERY); + if (repeatable_option_size) { + returned_byte_count += repeatable_option_size; + } else { + return 0; + } + } + + /* BLOCK 1 - Length of this option is 1-3 bytes*/ + if (src_coap_msg_ptr->options_list_ptr->block1_ptr != NULL) { + returned_byte_count++; + if (src_coap_msg_ptr->options_list_ptr->block1_len > 3 || src_coap_msg_ptr->options_list_ptr->block1_len < 1) { + return 0; + } + + returned_byte_count += src_coap_msg_ptr->options_list_ptr->block1_len; + } +#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + else if (is_blockwise_needed && src_coap_msg_ptr->msg_code < COAP_MSG_CODE_RESPONSE_CREATED) { + returned_byte_count += 2; + } +#endif + /* SIZE1 - Length of this option is 0-4 bytes */ + if (src_coap_msg_ptr->options_list_ptr->size1_ptr != NULL) { + returned_byte_count++; + if (src_coap_msg_ptr->options_list_ptr->size1_len > 4) { + return 0; + } + returned_byte_count += src_coap_msg_ptr->options_list_ptr->size1_len; + } +#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + else if (is_blockwise_needed && src_coap_msg_ptr->msg_code < COAP_MSG_CODE_RESPONSE_CREATED){ + returned_byte_count++; + if(src_coap_msg_ptr->payload_len < 0xFF) { + returned_byte_count++; + } else { + returned_byte_count += 2; + } + } +#endif + /* BLOCK 2 - Length of this option is 1-3 bytes*/ + if (src_coap_msg_ptr->options_list_ptr->block2_ptr != NULL) { + returned_byte_count++; + if (src_coap_msg_ptr->options_list_ptr->block2_len > 3 || src_coap_msg_ptr->options_list_ptr->block2_len < 1) { + return 0; + } + + returned_byte_count += src_coap_msg_ptr->options_list_ptr->block2_len; + } +#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + else if (is_blockwise_needed && src_coap_msg_ptr->msg_code >= COAP_MSG_CODE_RESPONSE_CREATED) { + returned_byte_count += 2; + } +#endif + /* SIZE2 - Length of this option is 0-4 bytes */ + if (src_coap_msg_ptr->options_list_ptr->size2_ptr != NULL) { + returned_byte_count++; + if (src_coap_msg_ptr->options_list_ptr->size2_len > 4) { + return 0; + } + + returned_byte_count += src_coap_msg_ptr->options_list_ptr->size2_len; + } +#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + else if (is_blockwise_needed && src_coap_msg_ptr->msg_code >= COAP_MSG_CODE_RESPONSE_CREATED){ + returned_byte_count++; + if(src_coap_msg_ptr->payload_len < 0xFF) { + returned_byte_count++; + } else { + returned_byte_count += 2; + } + } +#endif + } +#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + /* * * * * PAYLOAD * * * * */ + if (is_blockwise_needed) { + /* Two bytes for Block option */ + if (src_coap_msg_ptr->msg_code < COAP_MSG_CODE_RESPONSE_CREATED) { + returned_byte_count += sn_coap_builder_options_calculate_jump_need(src_coap_msg_ptr, 1); + + } else { /* Response message */ + returned_byte_count += sn_coap_builder_options_calculate_jump_need(src_coap_msg_ptr, 2); + } + + /* Add maximum payload at one Blockwise message */ + returned_byte_count += blockwise_payload_size; + returned_byte_count ++; /* For payload marker */ + } else { + returned_byte_count += sn_coap_builder_options_calculate_jump_need(src_coap_msg_ptr, 0); + /* Add wanted payload */ + + returned_byte_count += src_coap_msg_ptr->payload_len; + + if (src_coap_msg_ptr->payload_len) { + returned_byte_count ++; /* For payload marker */ + } + } +#else + returned_byte_count += src_coap_msg_ptr->payload_len; + if (src_coap_msg_ptr->payload_len) { + returned_byte_count ++; /* For payload marker */ + } + returned_byte_count += sn_coap_builder_options_calculate_jump_need(src_coap_msg_ptr, 0); +#endif + } + return returned_byte_count; +} +/** + * \fn static uint8_t sn_coap_builder_options_calculate_jump_need(sn_coap_hdr_s *src_coap_msg_ptr, uint8_t block_option) + * + * \brief Checks if there is need for option jump + * + * \param *src_coap_msg_ptr is source of checked CoAP message + * + * \param block option marks if block option is to be added to message later. 0 = no block option, 1 = block1 and 2 = block2 + * + * \return Returns bytes needed for jumping + */ + +static uint8_t sn_coap_builder_options_calculate_jump_need(sn_coap_hdr_s *src_coap_msg_ptr, uint8_t block_option) +{ + uint8_t previous_option_number = 0; + uint8_t needed_space = 0; + + if (src_coap_msg_ptr->options_list_ptr != NULL) { + /* If option numbers greater than 12 is not used, then jumping is not needed */ + if (!src_coap_msg_ptr->options_list_ptr->uri_query_ptr && + !src_coap_msg_ptr->options_list_ptr->accept_ptr && + !src_coap_msg_ptr->options_list_ptr->location_query_ptr && + !src_coap_msg_ptr->options_list_ptr->block2_ptr && + !src_coap_msg_ptr->options_list_ptr->block1_ptr && + !src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr && + !block_option && + !src_coap_msg_ptr->options_list_ptr->max_age_ptr && + !src_coap_msg_ptr->options_list_ptr->size1_ptr && + !src_coap_msg_ptr->options_list_ptr->size2_ptr) { + return 0; + } + + if (src_coap_msg_ptr->options_list_ptr->uri_host_ptr != NULL) { + previous_option_number = (COAP_OPTION_URI_HOST); + } + + if (src_coap_msg_ptr->options_list_ptr->etag_ptr != NULL) { + previous_option_number = (COAP_OPTION_ETAG); + } + + if ((src_coap_msg_ptr->options_list_ptr->observe_ptr != NULL) || (src_coap_msg_ptr->options_list_ptr->observe)) { + previous_option_number = (COAP_OPTION_OBSERVE); + } + + if (src_coap_msg_ptr->options_list_ptr->uri_port_ptr != NULL) { + previous_option_number = (COAP_OPTION_URI_PORT); + } + + if (src_coap_msg_ptr->options_list_ptr->location_path_ptr != NULL) { + previous_option_number = (COAP_OPTION_LOCATION_PATH); + } + + if (src_coap_msg_ptr->uri_path_ptr != NULL) { + previous_option_number = (COAP_OPTION_URI_PATH); + } + if (src_coap_msg_ptr->content_type_ptr != NULL) { + previous_option_number = (COAP_OPTION_CONTENT_FORMAT); + } + if (src_coap_msg_ptr->options_list_ptr->max_age_ptr != NULL) { + if ((COAP_OPTION_MAX_AGE - previous_option_number) > 12) { + needed_space += 1; + } + previous_option_number = (COAP_OPTION_MAX_AGE); + } + + if (src_coap_msg_ptr->options_list_ptr->uri_query_ptr != NULL) { + if ((COAP_OPTION_URI_QUERY - previous_option_number) > 12) { + needed_space += 1; + } + previous_option_number = (COAP_OPTION_URI_QUERY); + } + if (src_coap_msg_ptr->options_list_ptr->accept_ptr != NULL) { + if ((COAP_OPTION_ACCEPT - previous_option_number) > 12) { + needed_space += 1; + } + previous_option_number = (COAP_OPTION_ACCEPT); + } + if (src_coap_msg_ptr->options_list_ptr->location_query_ptr != NULL) { + if ((COAP_OPTION_LOCATION_QUERY - previous_option_number) > 12) { + needed_space += 1; + } + previous_option_number = (COAP_OPTION_LOCATION_QUERY); + } + if (src_coap_msg_ptr->options_list_ptr->block2_ptr != NULL) { + if ((COAP_OPTION_BLOCK2 - previous_option_number) > 12 || + (block_option == 2 && (COAP_OPTION_BLOCK2 - previous_option_number) > 12)) { + needed_space += 1; + } + previous_option_number = (COAP_OPTION_BLOCK2); + } + if (src_coap_msg_ptr->options_list_ptr->block1_ptr != NULL) { + if ((COAP_OPTION_BLOCK1 - previous_option_number) > 12 || + (block_option == 1 && (COAP_OPTION_BLOCK1 - previous_option_number) > 12)) { + needed_space += 1; + } + previous_option_number = (COAP_OPTION_BLOCK1); + } + if (src_coap_msg_ptr->options_list_ptr->size2_ptr != NULL) { + if ((COAP_OPTION_SIZE2 - previous_option_number) > 12) { + needed_space += 1; + } + previous_option_number = (COAP_OPTION_SIZE2); + } + if (src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr != NULL) { + if ((COAP_OPTION_PROXY_URI - previous_option_number) > 12) { + needed_space += 1; + } + if ((COAP_OPTION_PROXY_URI - previous_option_number) > 269) { //Can not happen + needed_space += 1; + } + previous_option_number = (COAP_OPTION_PROXY_URI); + } + if (src_coap_msg_ptr->options_list_ptr->size1_ptr != NULL || + (block_option == 1 && (COAP_OPTION_SIZE1 - previous_option_number) > 12)) { + if ((COAP_OPTION_SIZE1 - previous_option_number) > 12) { + needed_space += 1; + } + previous_option_number = (COAP_OPTION_SIZE1); + } + } + + else { + if (src_coap_msg_ptr->uri_path_ptr != 0) { + previous_option_number = (COAP_OPTION_URI_PATH); + } + + if (src_coap_msg_ptr->content_type_ptr != 0) { + previous_option_number = (COAP_OPTION_CONTENT_FORMAT); + } + +#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE //block_option 1 & 2 only used if this maro is defined + if (block_option == 2) { + if ((COAP_OPTION_BLOCK2 - previous_option_number) > 12) { + needed_space += 1; + } + previous_option_number = (COAP_OPTION_BLOCK2); + } + if (block_option == 1) { + if ((COAP_OPTION_BLOCK1 - previous_option_number) > 12) { + needed_space += 1; + } + previous_option_number = (COAP_OPTION_BLOCK1); + } + +#endif + } + return needed_space; +} + +/** + * \fn static int8_t sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr) + * + * \brief Builds Header part of Packet data + * + * \param **dst_packet_data_pptr is destination for built Packet data + * + * \param *src_coap_msg_ptr is source for building Packet data + * + * \return Return value is 0 in ok case and -1 in failure case + **************************************************************************** */ +static int8_t sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr) +{ + /* * * * Check validity of Header values * * * */ + if (sn_coap_header_validity_check(src_coap_msg_ptr, COAP_VERSION) != 0) { + return -1; + } + + /* * * Add CoAP Version * * */ + **dst_packet_data_pptr += COAP_VERSION; + + /* * * Add Message type * * */ + **dst_packet_data_pptr += src_coap_msg_ptr->msg_type; + + /* * * Add Token length * * */ + **dst_packet_data_pptr += (src_coap_msg_ptr->token_len); + + (*dst_packet_data_pptr) ++; + /* * * Add Message code * * */ + **dst_packet_data_pptr = src_coap_msg_ptr->msg_code; + (*dst_packet_data_pptr) ++; + + /* * * Add Message ID * * */ + **dst_packet_data_pptr = (uint8_t)(src_coap_msg_ptr->msg_id >> COAP_HEADER_MSG_ID_MSB_SHIFT); /* MSB part */ + (*dst_packet_data_pptr) ++; + **dst_packet_data_pptr = (uint8_t)src_coap_msg_ptr->msg_id; /* LSB part */ + (*dst_packet_data_pptr) ++; + + /* Success */ + return 0; +} + +/** + * \fn static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr) + * + * \brief Builds Options part of Packet data + * + * \param **dst_packet_data_pptr is destination for built Packet data + * + * \param *src_coap_msg_ptr is source for building Packet data + * + * \return Return value is 0 in every case + */ +static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr) +{ + int16_t ret_status = 0; + + /* * * * Check if Options are used at all * * * */ + if (src_coap_msg_ptr->uri_path_ptr == NULL && src_coap_msg_ptr->token_ptr == NULL && + src_coap_msg_ptr->content_type_ptr == NULL && src_coap_msg_ptr->options_list_ptr == NULL) { + return 0; + } + + /* * * * First add Token option * * * */ + if (src_coap_msg_ptr->token_len && src_coap_msg_ptr->token_ptr) { + memcpy(*dst_packet_data_pptr, src_coap_msg_ptr->token_ptr, src_coap_msg_ptr->token_len); + } + (*dst_packet_data_pptr) += src_coap_msg_ptr->token_len; + + /* Then build rest of the options */ + + /* * * * Initialize previous Option number for new built message * * * */ + uint16_t previous_option_number = 0; + + //missing: COAP_OPTION_IF_MATCH, COAP_OPTION_IF_NONE_MATCH, COAP_OPTION_SIZE + + /* Check if less used options are used at all */ + if (src_coap_msg_ptr->options_list_ptr != NULL) { + /* * * * Build Uri-Host option * * * */ + sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->uri_host_len, + src_coap_msg_ptr->options_list_ptr->uri_host_ptr, COAP_OPTION_URI_HOST, &previous_option_number); + + /* * * * Build ETag option * * * */ + sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->etag_ptr, + (uint16_t *)&src_coap_msg_ptr->options_list_ptr->etag_len, COAP_OPTION_ETAG, &previous_option_number); + + /* * * * Build Observe option * * * * */ + ret_status = sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->observe_len, + src_coap_msg_ptr->options_list_ptr->observe_ptr, COAP_OPTION_OBSERVE, &previous_option_number); + if (ret_status == 0) { + sn_coap_builder_options_build_add_zero_length_option(dst_packet_data_pptr, + src_coap_msg_ptr->options_list_ptr->observe_len, + src_coap_msg_ptr->options_list_ptr->observe, + COAP_OPTION_OBSERVE, + &previous_option_number); + } + + /* * * * Build Uri-Port option * * * */ + sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->uri_port_len, + src_coap_msg_ptr->options_list_ptr->uri_port_ptr, COAP_OPTION_URI_PORT, &previous_option_number); + + /* * * * Build Location-Path option * * * */ + sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->location_path_ptr, + &src_coap_msg_ptr->options_list_ptr->location_path_len, COAP_OPTION_LOCATION_PATH, &previous_option_number); + } + /* * * * Build Uri-Path option * * * */ + /* Do not add uri-path for notification message. + * Uri-path is needed for cancelling observation with RESET message */ + if (!src_coap_msg_ptr->options_list_ptr || + (src_coap_msg_ptr->options_list_ptr && !src_coap_msg_ptr->options_list_ptr->observe_len && !src_coap_msg_ptr->options_list_ptr->observe_ptr)) + sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->uri_path_ptr, + &src_coap_msg_ptr->uri_path_len, COAP_OPTION_URI_PATH, &previous_option_number); + + /* * * * Build Content-Type option * * * */ + sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->content_type_len, + src_coap_msg_ptr->content_type_ptr, COAP_OPTION_CONTENT_FORMAT, &previous_option_number); + + if (src_coap_msg_ptr->options_list_ptr != NULL) { + /* * * * Build Max-Age option * * * */ + sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->max_age_len, + src_coap_msg_ptr->options_list_ptr->max_age_ptr, COAP_OPTION_MAX_AGE, &previous_option_number); + + /* * * * Build Uri-Query option * * * * */ + sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->uri_query_ptr, + &src_coap_msg_ptr->options_list_ptr->uri_query_len, COAP_OPTION_URI_QUERY, &previous_option_number); + + /* * * * Build Accept option * * * * */ + sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->accept_ptr, + (uint16_t *)&src_coap_msg_ptr->options_list_ptr->accept_len, COAP_OPTION_ACCEPT, &previous_option_number); + } + + if (src_coap_msg_ptr->options_list_ptr != NULL) { + /* * * * Build Location-Query option * * * */ + sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->location_query_ptr, + &src_coap_msg_ptr->options_list_ptr->location_query_len, COAP_OPTION_LOCATION_QUERY, &previous_option_number); + + /* * * * Build Block2 option * * * * */ + sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->block2_len, + src_coap_msg_ptr->options_list_ptr->block2_ptr, COAP_OPTION_BLOCK2, &previous_option_number); + + /* * * * Build Block1 option * * * * */ + sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->block1_len, + src_coap_msg_ptr->options_list_ptr->block1_ptr, COAP_OPTION_BLOCK1, &previous_option_number); + + /* * * * Build Size2 option * * * */ + sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->size2_len, + src_coap_msg_ptr->options_list_ptr->size2_ptr, COAP_OPTION_SIZE2, &previous_option_number); + + /* * * * Build Proxy-Uri option * * * */ + sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->proxy_uri_len, + src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr, COAP_OPTION_PROXY_URI, &previous_option_number); + + + /* * * * Build Size1 option * * * */ + sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->size1_len, + src_coap_msg_ptr->options_list_ptr->size1_ptr, COAP_OPTION_SIZE1, &previous_option_number); + } + + /* Success */ + return 0; +} + +/** + * \fn static int16_t sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet_data_pptr, uint16_t option_value_len, uint8_t *option_value_ptr, sn_coap_option_numbers_e option_number) + * + * \brief Adds Options part of Packet data + * + * \param **dst_packet_data_pptr is destination for built Packet data + * + * \param option_value_len is Option value length to be added + * + * \param *option_value_ptr is pointer to Option value data to be added + * + * \param option_number is Option number to be added + * + * \return Return value is 0 if option was not added, 1 if added + */ +static int16_t sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet_data_pptr, uint16_t option_len, + uint8_t *option_ptr, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number) +{ + /* Check if there is option at all */ + if (option_ptr != NULL) { + uint16_t option_delta; + + option_delta = (option_number - *previous_option_number); + + /* * * Build option header * * */ + + /* First option length without extended part */ + if (option_len <= 12) { + **dst_packet_data_pptr = option_len; + } + + else if (option_len > 12 && option_len < 269) { + **dst_packet_data_pptr = 0x0D; + } + + else if (option_len >= 269) { + **dst_packet_data_pptr = 0x0E; + } + + /* Then option delta with extensions, and move pointer */ + if (option_delta <= 12) { + **dst_packet_data_pptr += (option_delta << 4); + *dst_packet_data_pptr += 1; + } + + else if (option_delta > 12 && option_delta < 269) { + **dst_packet_data_pptr += 0xD0; + option_delta -= 13; + + *(*dst_packet_data_pptr + 1) = (uint8_t)option_delta; + *dst_packet_data_pptr += 2; + } + //This is currently dead code (but possibly needed in future) + else if (option_delta >= 269) { + **dst_packet_data_pptr += 0xE0; + option_delta -= 269; + + *(*dst_packet_data_pptr + 2) = (uint8_t)option_delta; + *(*dst_packet_data_pptr + 1) = (option_delta >> 8); + *dst_packet_data_pptr += 3; + } + + /* Now option length extensions, if needed */ + if (option_len > 12 && option_len < 269) { + **dst_packet_data_pptr = (uint8_t)(option_len - 13); + *dst_packet_data_pptr += 1; + } + + else if (option_len >= 269) { + *(*dst_packet_data_pptr + 1) = (uint8_t)(option_len - 269); + **dst_packet_data_pptr = ((option_len - 269) >> 8); + *dst_packet_data_pptr += 2; + } + + *previous_option_number = option_number; + + /* Write Option value */ + memcpy(*dst_packet_data_pptr, option_ptr, option_len); + + /* Increase destination Packet data pointer */ + (*dst_packet_data_pptr) += option_len; + + return 1; + } + + /* Success */ + return 0; +} + +/* + * @return 1 if was added 0 otherwise +*/ +int16_t sn_coap_builder_options_build_add_zero_length_option(uint8_t **dst_packet_data_pptr, + uint8_t option_length, + uint8_t option_exist, + sn_coap_option_numbers_e option_number, + uint16_t *previous_option_number) +{ + if ((option_exist != 0) && (option_length == 0)) { + uint16_t option_delta; + + option_delta = (option_number - *previous_option_number); + + /* * * Build option header * * */ + + /* First option length without extended part */ + **dst_packet_data_pptr = 0; + + /* Then option delta with extensions, and move pointer */ + if (option_delta <= 12) { + **dst_packet_data_pptr += (option_delta << 4); + *dst_packet_data_pptr += 1; + } + //Cannot happen currently --> + else if (option_delta > 12 && option_delta < 269) { + **dst_packet_data_pptr += 0xD0; + option_delta -= 13; + + *(*dst_packet_data_pptr + 1) = (uint8_t)option_delta; + *dst_packet_data_pptr += 2; + } + + else if (option_delta >= 269) { + **dst_packet_data_pptr += 0xE0; + option_delta -= 269; + + *(*dst_packet_data_pptr + 2) = (uint8_t)option_delta; + *(*dst_packet_data_pptr + 1) = (option_delta >> 8); + *dst_packet_data_pptr += 3; + } + //<-- Cannot happen currently + + *previous_option_number = option_number; + + return 1; + } + return 0; +} + +/** + * \fn static int16_t sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, uint8_t **src_pptr, uint16_t *src_len_ptr, sn_coap_option_numbers_e option) + * + * \brief Builds Option Uri-Query from given CoAP Header structure to Packet data + * + * \param **dst_packet_data_pptr is destination for built Packet data + * + * \param uint8_t **src_pptr + * + * \param uint16_t *src_len_ptr + * + * \paramsn_coap_option_numbers_e option option to be added + * + * \return Return value is 0 always + */ +static int16_t sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, uint8_t **src_pptr, uint16_t *src_len_ptr, sn_coap_option_numbers_e option, uint16_t *previous_option_number) +{ + /* Check if there is option at all */ + if (*src_pptr != NULL) { + uint8_t *query_ptr = *src_pptr; + uint8_t query_part_count = 0; + uint16_t query_len = *src_len_ptr; + uint8_t i = 0; + uint16_t query_part_offset = 0; + + /* Get query part count */ + query_part_count = sn_coap_builder_options_get_option_part_count(query_len, query_ptr, option); + + /* * * * Options by adding all parts to option * * * */ + for (i = 0; i < query_part_count; i++) { + /* Get length of query part */ + uint16_t one_query_part_len = sn_coap_builder_options_get_option_part_length_from_whole_option_string(query_len, query_ptr, i, option); + + /* Get position of query part */ + query_part_offset = sn_coap_builder_options_get_option_part_position(query_len, query_ptr, i, option); + + /* Add Uri-query's one part to Options */ + sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, one_query_part_len, *src_pptr + query_part_offset, option, previous_option_number); + } + } + /* Success */ + return 0; +} + + +/** + * \fn static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option) + * + * \brief Calculates needed Packet data memory size for option + * + * \param path_len is length of calculated strting(s) + * + * \param *path_ptr is pointer to calculated options + * + * \return Return value is count of needed memory as bytes for Uri-query option + */ +static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option) +{ + uint8_t query_part_count = sn_coap_builder_options_get_option_part_count(query_len, query_ptr, option); + uint8_t i = 0; + uint16_t ret_value = 0; + + /* * * * * * * * * * * * * * * * * * * * * * * * */ + /* * * * Calculate Uri-query options length * * */ + /* * * * * * * * * * * * * * * * * * * * * * * * */ + for (i = 0; i < query_part_count; i++) { + /* * * Length of Option number and Option value length * * */ + + /* Get length of Query part */ + uint16_t one_query_part_len = sn_coap_builder_options_get_option_part_length_from_whole_option_string(query_len, query_ptr, i, option); + + /* Check option length */ + switch (option) { + case (COAP_OPTION_ETAG): /* Length 1-8 */ + if (one_query_part_len < 1 || one_query_part_len > 8) { + return 0; + } + break; + case (COAP_OPTION_LOCATION_PATH): /* Length 0-255 */ + case (COAP_OPTION_URI_PATH): /* Length 0-255 */ + case (COAP_OPTION_LOCATION_QUERY): /* Length 0-255 */ + if (one_query_part_len > 255) { + return 0; + } + break; + case (COAP_OPTION_URI_QUERY): /* Length 1-255 */ + if (one_query_part_len < 1 || one_query_part_len > 255) { + return 0; + } + break; + case (COAP_OPTION_ACCEPT): /* Length 0-2 */ + if (one_query_part_len > 2) { + return 0; + } + break; + default: + break; //impossible scenario currently + } + + /* Check if 4 bits are enough for writing Option value length */ + if (one_query_part_len <= 12) { + /* 4 bits are enough for Option value length */ + ret_value++; + } else if (one_query_part_len >= 13 && one_query_part_len < 269) { + /* Extra byte for Option value length is needed */ + ret_value += 2; + } + //This can only happen if we are in default case above, currently is not happening + else if (one_query_part_len >= 270 && one_query_part_len < 1034) { + /* Extra bytes for Option value length is needed */ + ret_value += 3; + } + + + /* * * Length of Option value * * */ + + /* Increase options length */ + ret_value += one_query_part_len; + } + + /* Success */ + return ret_value; +} + + + +/** + * \fn static uint8_t sn_coap_builder_options_get_option_part_count(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option) + * + * \brief Gets query part count from whole option string + * + * \param query_len is length of whole Path + * + * \param *query_ptr is pointer to the start of whole Path + * + * \return Return value is count of query parts + */ +static uint8_t sn_coap_builder_options_get_option_part_count(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option) +{ + uint8_t returned_query_count = 0; + uint16_t query_len_index = 0; + uint8_t char_to_search = '&'; + + if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) { + char_to_search = '/'; + } + + /* Loop whole query and search '\0' characters (not first and last char) */ + for (query_len_index = 1; query_len_index < query_len - 1; query_len_index++) { + /* If new query part starts */ + if (*(query_ptr + query_len_index) == char_to_search) { /* If match */ + returned_query_count++; + } + } + + returned_query_count++; + + return returned_query_count; +} + +/** + * \fn static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option_string(uint16_t query_len, + uint8_t *query_ptr, + uint8_t query_index, sn_coap_option_numbers_e option) + * + * \brief Gets one's query part length from whole query string + * + * \param query_len is length of whole string + * + * \param *query_ptr is pointer to the start of whole string + * + * \param query_index is query part index to be found + * + * \param sn_coap_option_numbers_e option is option number of the option + * + * \return Return value is length of query part + */ +static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option_string(uint16_t query_len, uint8_t *query_ptr, + uint8_t query_index, sn_coap_option_numbers_e option) +{ + uint16_t returned_query_part_len = 0; + uint8_t temp_query_index = 0; + uint16_t query_len_index = 0; + uint8_t char_to_search = '&'; + + if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) { + char_to_search = '/'; + } + + /* Loop whole query and search '\0' characters */ + for (query_len_index = 0; query_len_index < query_len; query_len_index++) { + /* Store character to temp_char for helping debugging */ + uint8_t temp_char = *query_ptr; + + /* If new query part starts */ + if (temp_char == char_to_search && returned_query_part_len > 0) { /* returned_query_part_len > 0 is for querys which start with "\0" */ + /* If query part index is wanted */ + if (temp_query_index == query_index) { + /* Return length of query part */ + return returned_query_part_len; + } else { + /* Reset length of query part because wanted query part finding continues*/ + returned_query_part_len = 0; + } + + /* Next query part is looped */ + temp_query_index++; + } else if (temp_char != char_to_search) { /* Else if query part continues */ + /* Increase query part length */ + returned_query_part_len++; + } + + query_ptr++; + } + + /* Return length of query part in cases that query part does not finish to '\0' character (last query part can be like that) */ + return returned_query_part_len; +} + +/** + * \fn static uint16_t sn_coap_builder_options_get_option_part_position(uint16_t query_len, + uint8_t *query_ptr, + uint8_t query_index, sn_coap_option_numbers_e option) + * + * \brief Gets query part position in whole query + * + * \param query_len is length of whole query + * + * \param *query_ptr is pointer to the start of whole query + * + * \param query_index is query part index to be found + * + * \return Return value is position (= offset) of query part in whole query. In + * fail cases -1 is returned. + */ +static int16_t sn_coap_builder_options_get_option_part_position(uint16_t query_len, uint8_t *query_ptr, + uint8_t query_index, sn_coap_option_numbers_e option) +{ + uint16_t returned_query_part_offset = 0; + uint8_t temp_query_index = 0; + uint16_t query_len_index = 0; + uint8_t char_to_search = '&'; + + if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) { + char_to_search = '/'; + } + + if (query_index == 0) { + if (*query_ptr == 0 || *query_ptr == char_to_search) { + return 1; + } else { + return 0; + } + } + + /* Loop whole query and search separator characters */ + for (query_len_index = 0; query_len_index < query_len; query_len_index++) { + /* Store character to temp_char for helping debugging */ + uint8_t temp_char = *query_ptr; + + /* If new query part starts */ + if (temp_char == char_to_search && returned_query_part_offset > 0) { /* returned_query_part_offset > 0 is for querys which start with searched char */ + /* If query part index is wanted */ + if (temp_query_index == (query_index - 1)) { + /* Return offset of query part */ + return (returned_query_part_offset + 1); /* Plus one is for passing separator */ + } + + /* Next query part is looped */ + temp_query_index++; + } + + returned_query_part_offset++; + + query_ptr++; + } + + return -1; //Dead code? +} + + +/** + * \fn static void sn_coap_builder_payload_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr) + * + * \brief Builds Options part of Packet data + * + * \param **dst_packet_data_pptr is destination for built Packet data + * + * \param *src_coap_msg_ptr is source for building Packet data + */ +static void sn_coap_builder_payload_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr) +{ + /* Check if Payload is used at all */ + if (src_coap_msg_ptr->payload_len && src_coap_msg_ptr->payload_ptr != NULL) { + /* Write Payload marker */ + + **dst_packet_data_pptr = 0xff; + (*dst_packet_data_pptr)++; + + /* Write Payload */ + memcpy(*dst_packet_data_pptr, src_coap_msg_ptr->payload_ptr, src_coap_msg_ptr->payload_len); + + /* Increase destination Packet data pointer */ + (*dst_packet_data_pptr) += src_coap_msg_ptr->payload_len; + } +} diff --git a/features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/sn_coap_header_check.c b/features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/sn_coap_header_check.c new file mode 100644 index 0000000000..cf0ae768ff --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/sn_coap_header_check.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2011-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 sn_coap_header_check.c + * + * \brief CoAP Header validity checker + * + * Functionality: Checks validity of CoAP Header + * + */ + +/* * * * INCLUDE FILES * * * */ +#include "ns_types.h" +#include "sn_nsdl.h" +#include "sn_coap_header.h" +#include "sn_coap_protocol.h" +#include "sn_coap_header_internal.h" +#include "sn_coap_protocol_internal.h" + +/** + * \fn int8_t sn_coap_header_validity_check(sn_coap_hdr_s *src_coap_msg_ptr, coap_version_e coap_version) + * + * \brief Checks validity of given Header + * + * \param *src_coap_msg_ptr is source for building Packet data + * \param coap_version is version of used CoAP specification + * + * \return Return value is status of validity check. In ok cases 0 and in + * failure cases -1 + */ +int8_t sn_coap_header_validity_check(sn_coap_hdr_s *src_coap_msg_ptr, coap_version_e coap_version) +{ + /* * Check validity of CoAP Version * */ + if (coap_version != COAP_VERSION_1) { + return -1; + } + + /* * Check validity of Message type * */ + switch (src_coap_msg_ptr->msg_type) { + case COAP_MSG_TYPE_CONFIRMABLE: + case COAP_MSG_TYPE_NON_CONFIRMABLE: + case COAP_MSG_TYPE_ACKNOWLEDGEMENT: + case COAP_MSG_TYPE_RESET: + break; /* Ok cases */ + default: + return -1; /* Failed case */ + } + + /* * Check validity of Message code * */ + switch (src_coap_msg_ptr->msg_code) { + case COAP_MSG_CODE_EMPTY: + case COAP_MSG_CODE_REQUEST_GET: + case COAP_MSG_CODE_REQUEST_POST: + case COAP_MSG_CODE_REQUEST_PUT: + case COAP_MSG_CODE_REQUEST_DELETE: + case COAP_MSG_CODE_RESPONSE_CREATED: + case COAP_MSG_CODE_RESPONSE_DELETED: + case COAP_MSG_CODE_RESPONSE_VALID: + case COAP_MSG_CODE_RESPONSE_CHANGED: + case COAP_MSG_CODE_RESPONSE_CONTENT: + case COAP_MSG_CODE_RESPONSE_BAD_REQUEST: + case COAP_MSG_CODE_RESPONSE_UNAUTHORIZED: + case COAP_MSG_CODE_RESPONSE_BAD_OPTION: + case COAP_MSG_CODE_RESPONSE_FORBIDDEN: + case COAP_MSG_CODE_RESPONSE_NOT_FOUND: + case COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED: + case COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE: + case COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE: + case COAP_MSG_CODE_RESPONSE_PRECONDITION_FAILED: + case COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE: + case COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT: + case COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR: + case COAP_MSG_CODE_RESPONSE_NOT_IMPLEMENTED: + case COAP_MSG_CODE_RESPONSE_BAD_GATEWAY: + case COAP_MSG_CODE_RESPONSE_SERVICE_UNAVAILABLE: + case COAP_MSG_CODE_RESPONSE_GATEWAY_TIMEOUT: + case COAP_MSG_CODE_RESPONSE_PROXYING_NOT_SUPPORTED: + case COAP_MSG_CODE_RESPONSE_CONTINUE: + break; /* Ok cases */ + default: + return -1; /* Failed case */ + } + + /* Success */ + return 0; +} diff --git a/features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/sn_coap_parser.c b/features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/sn_coap_parser.c new file mode 100644 index 0000000000..0ac83e9f86 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/sn_coap_parser.c @@ -0,0 +1,843 @@ +/* + * Copyright (c) 2011-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 sn_coap_parser.c + * + * \brief CoAP Header parser + * + * Functionality: Parses CoAP Header + * + */ + +/* * * * * * * * * * * * * * */ +/* * * * INCLUDE FILES * * * */ +/* * * * * * * * * * * * * * */ + +#include +#include /* For memset() and memcpy() */ + +#include "ns_types.h" +#include "sn_nsdl.h" +#include "sn_coap_header.h" +#include "sn_coap_protocol.h" +#include "sn_coap_header_internal.h" +#include "sn_coap_protocol_internal.h" + +/* * * * * * * * * * * * * * * * * * * * */ +/* * * * LOCAL FUNCTION PROTOTYPES * * * */ +/* * * * * * * * * * * * * * * * * * * * */ + +static void sn_coap_parser_header_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, coap_version_e *coap_version_ptr); +static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, uint8_t *packet_data_start_ptr, uint16_t packet_len); +static int8_t sn_coap_parser_options_parse_multiple_options(struct coap_s *handle, uint8_t **packet_data_pptr, uint16_t packet_left_len, uint8_t **dst_pptr, uint16_t *dst_len_ptr, sn_coap_option_numbers_e option, uint16_t option_number_len); +static int16_t sn_coap_parser_options_count_needed_memory_multiple_option(uint8_t *packet_data_ptr, uint16_t packet_left_len, sn_coap_option_numbers_e option, uint16_t option_number_len); +static int8_t sn_coap_parser_payload_parse(uint16_t packet_data_len, uint8_t *packet_data_start_ptr, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr); + +sn_coap_hdr_s *sn_coap_parser_init_message(sn_coap_hdr_s *coap_msg_ptr) +{ + /* * * * Check given pointer * * * */ + if (coap_msg_ptr == NULL) { + return NULL; + } + + /* XXX not technically legal to memset pointers to 0 */ + memset(coap_msg_ptr, 0x00, sizeof(sn_coap_hdr_s)); + + return coap_msg_ptr; +} + +sn_coap_hdr_s *sn_coap_parser_alloc_message(struct coap_s *handle) +{ + sn_coap_hdr_s *returned_coap_msg_ptr; + + /* * * * Check given pointer * * * */ + if (handle == NULL) { + return NULL; + } + + /* * * * Allocate memory for returned CoAP message and initialize allocated memory with with default values * * * */ + returned_coap_msg_ptr = handle->sn_coap_protocol_malloc(sizeof(sn_coap_hdr_s)); + + return sn_coap_parser_init_message(returned_coap_msg_ptr); +} + +sn_coap_options_list_s *sn_coap_parser_alloc_options(struct coap_s *handle, sn_coap_hdr_s *coap_msg_ptr) +{ + /* * * * Check given pointers * * * */ + if (handle == NULL || coap_msg_ptr == NULL) { + return NULL; + } + + /* * * * If the message already has options, return them * * * */ + if (coap_msg_ptr->options_list_ptr) { + return coap_msg_ptr->options_list_ptr; + } + + /* * * * Allocate memory for options and initialize allocated memory with with default values * * * */ + coap_msg_ptr->options_list_ptr = handle->sn_coap_protocol_malloc(sizeof(sn_coap_options_list_s)); + + if (coap_msg_ptr->options_list_ptr == NULL) { + return NULL; + } + + /* XXX not technically legal to memset pointers to 0 */ + memset(coap_msg_ptr->options_list_ptr, 0x00, sizeof(sn_coap_options_list_s)); + + return coap_msg_ptr->options_list_ptr; +} + +sn_coap_hdr_s *sn_coap_parser(struct coap_s *handle, uint16_t packet_data_len, uint8_t *packet_data_ptr, coap_version_e *coap_version_ptr) +{ + uint8_t *data_temp_ptr = packet_data_ptr; + sn_coap_hdr_s *parsed_and_returned_coap_msg_ptr = NULL; + + /* * * * Check given pointer * * * */ + if (packet_data_ptr == NULL || packet_data_len < 4 || handle == NULL) { + return NULL; + } + + /* * * * Allocate and initialize CoAP message * * * */ + parsed_and_returned_coap_msg_ptr = sn_coap_parser_alloc_message(handle); + + if (parsed_and_returned_coap_msg_ptr == NULL) { + return NULL; + } + + /* * * * Header parsing, move pointer over the header... * * * */ + sn_coap_parser_header_parse(&data_temp_ptr, parsed_and_returned_coap_msg_ptr, coap_version_ptr); + + /* * * * Options parsing, move pointer over the options... * * * */ + if (sn_coap_parser_options_parse(handle, &data_temp_ptr, parsed_and_returned_coap_msg_ptr, packet_data_ptr, packet_data_len) != 0) { + parsed_and_returned_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_ERROR_IN_HEADER; + return parsed_and_returned_coap_msg_ptr; + } + + /* * * * Payload parsing * * * */ + if (sn_coap_parser_payload_parse(packet_data_len, packet_data_ptr, &data_temp_ptr, parsed_and_returned_coap_msg_ptr) == -1) { + parsed_and_returned_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_ERROR_IN_HEADER; + return parsed_and_returned_coap_msg_ptr; + } + + /* * * * Return parsed CoAP message * * * * */ + return parsed_and_returned_coap_msg_ptr; +} + +void sn_coap_parser_release_allocated_coap_msg_mem(struct coap_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr) +{ + if (handle == NULL) { + return; + } + + if (freed_coap_msg_ptr != NULL) { + if (freed_coap_msg_ptr->uri_path_ptr != NULL) { + handle->sn_coap_protocol_free(freed_coap_msg_ptr->uri_path_ptr); + } + + if (freed_coap_msg_ptr->token_ptr != NULL) { + handle->sn_coap_protocol_free(freed_coap_msg_ptr->token_ptr); + } + + if (freed_coap_msg_ptr->content_type_ptr != NULL) { + handle->sn_coap_protocol_free(freed_coap_msg_ptr->content_type_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr != NULL) { + if (freed_coap_msg_ptr->options_list_ptr->max_age_ptr != NULL) { + handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->max_age_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->proxy_uri_ptr != NULL) { + handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->proxy_uri_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->etag_ptr != NULL) { + handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->etag_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->uri_host_ptr != NULL) { + handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->uri_host_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->location_path_ptr != NULL) { + handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->location_path_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->uri_port_ptr != NULL) { + handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->uri_port_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->location_query_ptr != NULL) { + handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->location_query_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->observe_ptr != NULL) { + handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->observe_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->uri_query_ptr != NULL) { + handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->uri_query_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->block2_ptr != NULL) { + handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->block2_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->block1_ptr != NULL) { + handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->block1_ptr); + } + if (freed_coap_msg_ptr->options_list_ptr->accept_ptr != NULL) { + handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->accept_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->size1_ptr != NULL) { + handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->size1_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->size2_ptr != NULL) { + handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->size2_ptr); + } + + handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr); + } + + handle->sn_coap_protocol_free(freed_coap_msg_ptr); + } +} + +/** + * \fn static void sn_coap_parser_header_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, coap_version_e *coap_version_ptr) + * + * \brief Parses CoAP message's Header part from given Packet data + * + * \param **packet_data_ptr is source for Packet data to be parsed to CoAP message + * + * \param *dst_coap_msg_ptr is destination for parsed CoAP message + * + * \param *coap_version_ptr is destination for parsed CoAP specification version + */ +static void sn_coap_parser_header_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, coap_version_e *coap_version_ptr) +{ + /* Parse CoAP Version and message type*/ + *coap_version_ptr = (coap_version_e)(**packet_data_pptr & COAP_HEADER_VERSION_MASK); + dst_coap_msg_ptr->msg_type = (sn_coap_msg_type_e)(**packet_data_pptr & COAP_HEADER_MSG_TYPE_MASK); + (*packet_data_pptr) += 1; + + /* Parse Message code */ + dst_coap_msg_ptr->msg_code = (sn_coap_msg_code_e) **packet_data_pptr; + (*packet_data_pptr) += 1; + + /* Parse Message ID */ + dst_coap_msg_ptr->msg_id = *(*packet_data_pptr + 1); + dst_coap_msg_ptr->msg_id += **packet_data_pptr << COAP_HEADER_MSG_ID_MSB_SHIFT; + (*packet_data_pptr) += 2; + +} + +/** + * \fn static uint8_t sn_coap_parser_options_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr) + * + * \brief Parses CoAP message's Options part from given Packet data + * + * \param **packet_data_pptr is source of Packet data to be parsed to CoAP message + * \param *dst_coap_msg_ptr is destination for parsed CoAP message + * + * \return Return value is 0 in ok case and -1 in failure case + */ +static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, uint8_t *packet_data_start_ptr, uint16_t packet_len) +{ + uint8_t previous_option_number = 0; + uint8_t i = 0; + int8_t ret_status = 0; + uint16_t message_left = 0; + + /* Parse token, if exists */ + dst_coap_msg_ptr->token_len = *packet_data_start_ptr & COAP_HEADER_TOKEN_LENGTH_MASK; + + if (dst_coap_msg_ptr->token_len) { + if ((dst_coap_msg_ptr->token_len > 8) || dst_coap_msg_ptr->token_ptr) { + return -1; + } + + dst_coap_msg_ptr->token_ptr = handle->sn_coap_protocol_malloc(dst_coap_msg_ptr->token_len); + + if (dst_coap_msg_ptr->token_ptr == NULL) { + return -1; + } + + memcpy(dst_coap_msg_ptr->token_ptr, *packet_data_pptr, dst_coap_msg_ptr->token_len); + (*packet_data_pptr) += dst_coap_msg_ptr->token_len; + } + + message_left = packet_len - ((*packet_data_pptr) - packet_data_start_ptr); + + /* Loop all Options */ + while (message_left && (**packet_data_pptr != 0xff)) { + + /* Get option length WITHOUT extensions */ + uint16_t option_len = (**packet_data_pptr & 0x0F); + + /* Option number length 15 is reserved for the future use - ERROR */ + if (option_len == 15) { + return -1; + } + + /* Resolve option delta */ + uint16_t option_number = (**packet_data_pptr >> COAP_OPTIONS_OPTION_NUMBER_SHIFT); + + if (option_number == 13) { + option_number = *(*packet_data_pptr + 1) + 13; + (*packet_data_pptr)++; + } else if (option_number == 14) { + option_number = *(*packet_data_pptr + 2); + option_number += (*(*packet_data_pptr + 1) << 8) + 269; + (*packet_data_pptr) += 2; + } + /* Option number 15 reserved for payload marker. This is handled as a error! */ + else if (option_number == 15) { + return -1; + } + + /* Add previous option to option delta and get option number */ + option_number += previous_option_number; + + /* Add possible option length extension to resolve full length of the option */ + if (option_len == 13) { + option_len = *(*packet_data_pptr + 1) + 13; + (*packet_data_pptr)++; + } else if (option_len == 14) { + option_len = *(*packet_data_pptr + 2); + option_len += (*(*packet_data_pptr + 1) << 8) + 269; + (*packet_data_pptr) += 2; + } + + + /* * * Parse option itself * * */ + /* Some options are handled independently in own functions */ + previous_option_number = option_number; + /* Allocate options_list_ptr if needed */ + switch (option_number) { + case COAP_OPTION_MAX_AGE: + case COAP_OPTION_PROXY_URI: + case COAP_OPTION_ETAG: + case COAP_OPTION_URI_HOST: + case COAP_OPTION_LOCATION_PATH: + case COAP_OPTION_URI_PORT: + case COAP_OPTION_LOCATION_QUERY: + case COAP_OPTION_OBSERVE: + case COAP_OPTION_URI_QUERY: + case COAP_OPTION_BLOCK2: + case COAP_OPTION_BLOCK1: + case COAP_OPTION_ACCEPT: + case COAP_OPTION_SIZE1: + case COAP_OPTION_SIZE2: + if (sn_coap_parser_alloc_options(handle, dst_coap_msg_ptr) == NULL) { + return -1; + } + break; + } + + /* Parse option */ + switch (option_number) { + case COAP_OPTION_CONTENT_FORMAT: + if ((option_len > 2) || (dst_coap_msg_ptr->content_type_ptr)) { + return -1; + } + dst_coap_msg_ptr->content_type_len = option_len; + (*packet_data_pptr)++; + + if (option_len) { + dst_coap_msg_ptr->content_type_ptr = handle->sn_coap_protocol_malloc(option_len); + + if (dst_coap_msg_ptr->content_type_ptr == NULL) { + return -1; + } + + memcpy(dst_coap_msg_ptr->content_type_ptr, *packet_data_pptr, option_len); + (*packet_data_pptr) += option_len; + } + break; + + case COAP_OPTION_MAX_AGE: + if ((option_len > 4) || dst_coap_msg_ptr->options_list_ptr->max_age_ptr) { + return -1; + } + dst_coap_msg_ptr->options_list_ptr->max_age_len = option_len; + (*packet_data_pptr)++; + + if (option_len) { + dst_coap_msg_ptr->options_list_ptr->max_age_ptr = handle->sn_coap_protocol_malloc(option_len); + + if (dst_coap_msg_ptr->options_list_ptr->max_age_ptr == NULL) { + return -1; + } + + memcpy(dst_coap_msg_ptr->options_list_ptr->max_age_ptr, *packet_data_pptr, option_len); + (*packet_data_pptr) += option_len; + } + break; + + case COAP_OPTION_PROXY_URI: + if ((option_len > 1034) || (option_len < 1) || dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr) { + return -1; + } + dst_coap_msg_ptr->options_list_ptr->proxy_uri_len = option_len; + (*packet_data_pptr)++; + + dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr = handle->sn_coap_protocol_malloc(option_len); + + if (dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr == NULL) { + return -1; + } + memcpy(dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr, *packet_data_pptr, option_len); + (*packet_data_pptr) += option_len; + + break; + + case COAP_OPTION_ETAG: + /* This is managed independently because User gives this option in one character table */ + + ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, + message_left, + &dst_coap_msg_ptr->options_list_ptr->etag_ptr, + (uint16_t *)&dst_coap_msg_ptr->options_list_ptr->etag_len, + COAP_OPTION_ETAG, option_len); + if (ret_status >= 0) { + i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */ + } else { + return -1; + } + break; + + case COAP_OPTION_URI_HOST: + if ((option_len > 255) || (option_len < 1) || dst_coap_msg_ptr->options_list_ptr->uri_host_ptr) { + return -1; + } + dst_coap_msg_ptr->options_list_ptr->uri_host_len = option_len; + (*packet_data_pptr)++; + + dst_coap_msg_ptr->options_list_ptr->uri_host_ptr = handle->sn_coap_protocol_malloc(option_len); + + if (dst_coap_msg_ptr->options_list_ptr->uri_host_ptr == NULL) { + return -1; + } + memcpy(dst_coap_msg_ptr->options_list_ptr->uri_host_ptr, *packet_data_pptr, option_len); + (*packet_data_pptr) += option_len; + + break; + + case COAP_OPTION_LOCATION_PATH: + if (dst_coap_msg_ptr->options_list_ptr->location_path_ptr) { + return -1; + } + /* This is managed independently because User gives this option in one character table */ + ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left, + &dst_coap_msg_ptr->options_list_ptr->location_path_ptr, &dst_coap_msg_ptr->options_list_ptr->location_path_len, + COAP_OPTION_LOCATION_PATH, option_len); + if (ret_status >= 0) { + i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */ + } else { + return -1; + } + + break; + + + case COAP_OPTION_URI_PORT: + if ((option_len > 2) || dst_coap_msg_ptr->options_list_ptr->uri_port_ptr) { + return -1; + } + dst_coap_msg_ptr->options_list_ptr->uri_port_len = option_len; + (*packet_data_pptr)++; + + if (option_len) { + dst_coap_msg_ptr->options_list_ptr->uri_port_ptr = handle->sn_coap_protocol_malloc(option_len); + + if (dst_coap_msg_ptr->options_list_ptr->uri_port_ptr == NULL) { + return -1; + } + memcpy(dst_coap_msg_ptr->options_list_ptr->uri_port_ptr, *packet_data_pptr, option_len); + (*packet_data_pptr) += option_len; + } + break; + + case COAP_OPTION_LOCATION_QUERY: + ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left, + &dst_coap_msg_ptr->options_list_ptr->location_query_ptr, &dst_coap_msg_ptr->options_list_ptr->location_query_len, + COAP_OPTION_LOCATION_QUERY, option_len); + if (ret_status >= 0) { + i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */ + } else { + return -1; + } + + break; + + case COAP_OPTION_URI_PATH: + ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left, + &dst_coap_msg_ptr->uri_path_ptr, &dst_coap_msg_ptr->uri_path_len, + COAP_OPTION_URI_PATH, option_len); + if (ret_status >= 0) { + i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */ + } else { + return -1; + } + + break; + + case COAP_OPTION_OBSERVE: + if ((option_len > 2) || dst_coap_msg_ptr->options_list_ptr->observe_ptr) { + return -1; + } + + dst_coap_msg_ptr->options_list_ptr->observe = 1; + (*packet_data_pptr)++; + + if (option_len) { + + dst_coap_msg_ptr->options_list_ptr->observe_len = option_len; + + dst_coap_msg_ptr->options_list_ptr->observe_ptr = handle->sn_coap_protocol_malloc(option_len); + + if (dst_coap_msg_ptr->options_list_ptr->observe_ptr == NULL) { + return -1; + } + + memcpy(dst_coap_msg_ptr->options_list_ptr->observe_ptr, *packet_data_pptr, option_len); + (*packet_data_pptr) += option_len; + } + + break; + + case COAP_OPTION_URI_QUERY: + ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left, + &dst_coap_msg_ptr->options_list_ptr->uri_query_ptr, &dst_coap_msg_ptr->options_list_ptr->uri_query_len, + COAP_OPTION_URI_QUERY, option_len); + if (ret_status >= 0) { + i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */ + } else { + return -1; + } + + break; + + case COAP_OPTION_BLOCK2: + if ((option_len > 4) || dst_coap_msg_ptr->options_list_ptr->block2_ptr) { + return -1; + } + dst_coap_msg_ptr->options_list_ptr->block2_len = option_len; + (*packet_data_pptr)++; + + dst_coap_msg_ptr->options_list_ptr->block2_ptr = handle->sn_coap_protocol_malloc(option_len); + + if (dst_coap_msg_ptr->options_list_ptr->block2_ptr == NULL) { + return -1; + } + + memcpy(dst_coap_msg_ptr->options_list_ptr->block2_ptr, *packet_data_pptr, option_len); + (*packet_data_pptr) += option_len; + + break; + + case COAP_OPTION_BLOCK1: + if ((option_len > 4) || dst_coap_msg_ptr->options_list_ptr->block1_ptr) { + return -1; + } + dst_coap_msg_ptr->options_list_ptr->block1_len = option_len; + (*packet_data_pptr)++; + + dst_coap_msg_ptr->options_list_ptr->block1_ptr = handle->sn_coap_protocol_malloc(option_len); + + if (dst_coap_msg_ptr->options_list_ptr->block1_ptr == NULL) { + return -1; + } + + memcpy(dst_coap_msg_ptr->options_list_ptr->block1_ptr, *packet_data_pptr, option_len); + (*packet_data_pptr) += option_len; + + break; + + case COAP_OPTION_ACCEPT: + ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left, + &dst_coap_msg_ptr->options_list_ptr->accept_ptr, (uint16_t *)&dst_coap_msg_ptr->options_list_ptr->accept_len, + COAP_OPTION_ACCEPT, option_len); + if (ret_status >= 0) { + i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */ + } else { + return -1; + } + + break; + + case COAP_OPTION_SIZE1: + if ((option_len > 4) || dst_coap_msg_ptr->options_list_ptr->size1_ptr) { + return -1; + } + dst_coap_msg_ptr->options_list_ptr->size1_len = option_len; + (*packet_data_pptr)++; + + if (option_len) { + dst_coap_msg_ptr->options_list_ptr->size1_ptr = handle->sn_coap_protocol_malloc(option_len); + + if (dst_coap_msg_ptr->options_list_ptr->size1_ptr == NULL) { + return -1; + } + + memcpy(dst_coap_msg_ptr->options_list_ptr->size1_ptr, *packet_data_pptr, option_len); + (*packet_data_pptr) += option_len; + } + break; + + case COAP_OPTION_SIZE2: + if ((option_len > 4) || dst_coap_msg_ptr->options_list_ptr->size2_ptr) { + return -1; + } + dst_coap_msg_ptr->options_list_ptr->size2_len = option_len; + (*packet_data_pptr)++; + + if (option_len) { + dst_coap_msg_ptr->options_list_ptr->size2_ptr = handle->sn_coap_protocol_malloc(option_len); + + if (dst_coap_msg_ptr->options_list_ptr->size2_ptr == NULL) { + return -1; + } + + memcpy(dst_coap_msg_ptr->options_list_ptr->size2_ptr, *packet_data_pptr, option_len); + (*packet_data_pptr) += option_len; + } + break; + + default: + return -1; + } + + /* Check for overflow */ + if ((*packet_data_pptr - packet_data_start_ptr) > packet_len) { + return -1; + } + + message_left = packet_len - (*packet_data_pptr - packet_data_start_ptr); + + + } + + return 0; +} + + +/** + * \fn static int8_t sn_coap_parser_options_parse_multiple_options(uint8_t **packet_data_pptr, uint8_t options_count_left, uint8_t *previous_option_number_ptr, uint8_t **dst_pptr, + * uint16_t *dst_len_ptr, sn_coap_option_numbers_e option, uint16_t option_number_len) + * + * \brief Parses CoAP message's Uri-query options + * + * \param **packet_data_pptr is source for Packet data to be parsed to CoAP message + * + * \param *dst_coap_msg_ptr is destination for parsed CoAP message + * + * \param options_count_left tells how many options are unhandled in Packet data + * + * \param *previous_option_number_ptr is pointer to used and returned previous Option number + * + * \return Return value is count of Uri-query optios parsed. In failure case -1 is returned. +*/ +static int8_t sn_coap_parser_options_parse_multiple_options(struct coap_s *handle, uint8_t **packet_data_pptr, uint16_t packet_left_len, uint8_t **dst_pptr, uint16_t *dst_len_ptr, sn_coap_option_numbers_e option, uint16_t option_number_len) +{ + int16_t uri_query_needed_heap = sn_coap_parser_options_count_needed_memory_multiple_option(*packet_data_pptr, packet_left_len, option, option_number_len); + uint8_t *temp_parsed_uri_query_ptr = NULL; + uint8_t returned_option_counter = 0; + + if (uri_query_needed_heap == -1) { + return -1; + } + + if (uri_query_needed_heap) { + *dst_pptr = (uint8_t *) handle->sn_coap_protocol_malloc(uri_query_needed_heap); + + if (*dst_pptr == NULL) { + return -1; + } + } + + *dst_len_ptr = uri_query_needed_heap; + + temp_parsed_uri_query_ptr = *dst_pptr; + + /* Loop all Uri-Query options */ + while ((temp_parsed_uri_query_ptr - *dst_pptr) < uri_query_needed_heap) { + /* Check if this is first Uri-Query option */ + if (returned_option_counter > 0) { + /* Uri-Query is modified to following format: temp1'\0'temp2'\0'temp3 i.e. */ + /* Uri-Path is modified to following format: temp1\temp2\temp3 i.e. */ + if (option == COAP_OPTION_URI_QUERY || option == COAP_OPTION_LOCATION_QUERY || option == COAP_OPTION_ETAG || option == COAP_OPTION_ACCEPT) { + memset(temp_parsed_uri_query_ptr, '&', 1); + } else if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) { + memset(temp_parsed_uri_query_ptr, '/', 1); + } + + temp_parsed_uri_query_ptr++; + } + + returned_option_counter++; + + (*packet_data_pptr)++; + + if (((temp_parsed_uri_query_ptr - *dst_pptr) + option_number_len) > uri_query_needed_heap) { + return -1; + } + + memcpy(temp_parsed_uri_query_ptr, *packet_data_pptr, option_number_len); + + (*packet_data_pptr) += option_number_len; + temp_parsed_uri_query_ptr += option_number_len; + + if ((temp_parsed_uri_query_ptr - *dst_pptr) >= uri_query_needed_heap || ((**packet_data_pptr >> COAP_OPTIONS_OPTION_NUMBER_SHIFT) != 0)) { + return returned_option_counter; + } + + option_number_len = (**packet_data_pptr & 0x0F); + if (option_number_len == 13) { + option_number_len = *(*packet_data_pptr + 1) + 13; + (*packet_data_pptr)++; + } else if (option_number_len == 14) { + option_number_len = *(*packet_data_pptr + 2); + option_number_len += (*(*packet_data_pptr + 1) << 8) + 269; + (*packet_data_pptr) += 2; + } + } + + return returned_option_counter; +} + + + + +/** + * \fn static uint16_t sn_coap_parser_options_count_needed_memory_multiple_option(uint8_t *packet_data_ptr, uint8_t options_count_left, uint8_t previous_option_number, sn_coap_option_numbers_e option, uint16_t option_number_len) + * + * \brief Counts needed memory for uri query option + * + * \param *packet_data_ptr is start of source for Packet data to be parsed to CoAP message + * + * \param options_count_left tells how many options are unhandled in Packet data + * + * \param previous_option_number is previous Option number + * + * \param sn_coap_option_numbers_e option option number to be calculated + * + * \param uint16_t option_number_len length of the first option part + */ +static int16_t sn_coap_parser_options_count_needed_memory_multiple_option(uint8_t *packet_data_ptr, uint16_t packet_left_len, sn_coap_option_numbers_e option, uint16_t option_number_len) +{ + uint16_t ret_value = 0; + uint16_t i = 1; + + /* Loop all Uri-Query options */ + while (i < packet_left_len) { + if (option == COAP_OPTION_LOCATION_PATH && option_number_len > 255) { + return -1; + } + if (option == COAP_OPTION_URI_PATH && option_number_len > 255) { + return -1; + } + if (option == COAP_OPTION_URI_QUERY && option_number_len > 255) { + return -1; + } + if (option == COAP_OPTION_LOCATION_QUERY && option_number_len > 255) { + return -1; + } + if (option == COAP_OPTION_ACCEPT && option_number_len > 2) { + return -1; + } + if (option == COAP_OPTION_ETAG && option_number_len > 8) { + return -1; + } + + i += option_number_len; + ret_value += option_number_len + 1; /* + 1 is for separator */ + if(ret_value >= packet_left_len) + break; + + if(ret_value >= packet_left_len) + break; + + if( i == packet_left_len ) + break; + + if ((*(packet_data_ptr + i) >> COAP_OPTIONS_OPTION_NUMBER_SHIFT) != 0) { + return (ret_value - 1); /* -1 because last Part path does not include separator */ + } + + option_number_len = (*(packet_data_ptr + i) & 0x0F); + + if (option_number_len == 13) { + i++; + option_number_len = *(packet_data_ptr + i) + 13; + } else if (option_number_len == 14) { + option_number_len = *(packet_data_ptr + i + 2); + option_number_len += (*(packet_data_ptr + i + 1) << 8) + 269; + i += 2; + } else if (option_number_len == 15) { + return -1; + } + i++; + + } + + if (ret_value != 0) { + return (ret_value - 1); /* -1 because last Part path does not include separator */ + } else { + return 0; + } +} + +/** + * \fn static void sn_coap_parser_payload_parse(uint16_t packet_data_len, uint8_t *packet_data_ptr, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr) + * + * \brief Parses CoAP message's Payload part from given Packet data + * + * \param packet_data_len is length of given Packet data to be parsed to CoAP message + * + * \param *packet_data_ptr is start of source for Packet data to be parsed to CoAP message + * + * \param **packet_data_pptr is source for Packet data to be parsed to CoAP message + * + * \param *dst_coap_msg_ptr is destination for parsed CoAP message + *****************************************************************************/ +static int8_t sn_coap_parser_payload_parse(uint16_t packet_data_len, uint8_t *packet_data_start_ptr, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr) +{ + /* If there is payload */ + if ((*packet_data_pptr - packet_data_start_ptr) < packet_data_len) { + if (**packet_data_pptr == 0xff) { + (*packet_data_pptr)++; + /* Parse Payload length */ + dst_coap_msg_ptr->payload_len = packet_data_len - (*packet_data_pptr - packet_data_start_ptr); + + /* The presence of a marker followed by a zero-length payload MUST be processed as a message format error */ + if (dst_coap_msg_ptr->payload_len == 0) { + return -1; + } + + /* Parse Payload by setting CoAP message's payload_ptr to point Payload in Packet data */ + dst_coap_msg_ptr->payload_ptr = *packet_data_pptr; + } + /* No payload marker.. */ + else { + return -1; + } + } + return 0; +} diff --git a/features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/sn_coap_protocol.c b/features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/sn_coap_protocol.c new file mode 100644 index 0000000000..ada7e66cdf --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/source/libCoap/src/sn_coap_protocol.c @@ -0,0 +1,2362 @@ +/* + * Copyright (c) 2011-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 sn_coap_protocol.c + * + * \brief CoAP Protocol implementation + * + * Functionality: CoAP Protocol + * + */ + + +/* * * * * * * * * * * * * * */ +/* * * * INCLUDE FILES * * * */ +/* * * * * * * * * * * * * * */ + +#include +#include /* For libary malloc() */ +#include /* For memset() and memcpy() */ +#if defined __linux__ || defined TARGET_LIKE_MBED +#include +#endif + +#include "ns_types.h" +#include "sn_nsdl.h" +#include "sn_coap_protocol.h" +#include "sn_coap_header_internal.h" +#include "sn_coap_protocol_internal.h" +#include "mbed-trace/mbed_trace.h" +#define TRACE_GROUP "coap" +/* * * * * * * * * * * * * * * * * * * * */ +/* * * * LOCAL FUNCTION PROTOTYPES * * * */ +/* * * * * * * * * * * * * * * * * * * * */ + +static void sn_coap_protocol_send_rst(struct coap_s *handle, uint16_t msg_id, sn_nsdl_addr_s *addr_ptr, void *param); +#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT/* If Message duplication detection is not used at all, this part of code will not be compiled */ +static void sn_coap_protocol_linked_list_duplication_info_store(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id); +static int8_t sn_coap_protocol_linked_list_duplication_info_search(struct coap_s *handle, sn_nsdl_addr_s *scr_addr_ptr, uint16_t msg_id); +static void sn_coap_protocol_linked_list_duplication_info_remove(struct coap_s *handle, uint8_t *scr_addr_ptr, uint16_t port, uint16_t msg_id); +static void sn_coap_protocol_linked_list_duplication_info_remove_old_ones(struct coap_s *handle); +#endif +#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ +static void sn_coap_protocol_linked_list_blockwise_msg_remove(struct coap_s *handle, coap_blockwise_msg_s *removed_msg_ptr); +static void sn_coap_protocol_linked_list_blockwise_payload_store(struct coap_s *handle, sn_nsdl_addr_s *addr_ptr, uint16_t stored_payload_len, uint8_t *stored_payload_ptr); +static uint8_t *sn_coap_protocol_linked_list_blockwise_payload_search(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t *payload_length); +static void sn_coap_protocol_linked_list_blockwise_payload_remove(struct coap_s *handle, coap_blockwise_payload_s *removed_payload_ptr); +static void sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(struct coap_s *handle); +static uint32_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr); +static void sn_coap_protocol_linked_list_blockwise_remove_old_data(struct coap_s *handle); +static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, sn_coap_hdr_s *received_coap_msg_ptr, void *param); +static int8_t sn_coap_convert_block_size(uint16_t block_size); +static sn_coap_hdr_s *sn_coap_protocol_copy_header(struct coap_s *handle, sn_coap_hdr_s *source_header_ptr); +#endif +#if ENABLE_RESENDINGS +static void sn_coap_protocol_linked_list_send_msg_store(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint16_t send_packet_data_len, uint8_t *send_packet_data_ptr, uint32_t sending_time, void *param, uint8_t *uri_path_ptr, uint8_t uri_path_len); +static sn_nsdl_transmit_s *sn_coap_protocol_linked_list_send_msg_search(struct coap_s *handle,sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id); +static void sn_coap_protocol_linked_list_send_msg_remove(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id); +static coap_send_msg_s *sn_coap_protocol_allocate_mem_for_msg(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint16_t packet_data_len); +static void sn_coap_protocol_release_allocated_send_msg_mem(struct coap_s *handle, coap_send_msg_s *freed_send_msg_ptr); +static uint16_t sn_coap_count_linked_list_size(const coap_send_msg_list_t *linked_list_ptr); +#endif + +/* * * * * * * * * * * * * * * * * */ +/* * * * GLOBAL DECLARATIONS * * * */ +/* * * * * * * * * * * * * * * * * */ +static uint16_t message_id; + +int8_t sn_coap_protocol_destroy(struct coap_s *handle) +{ + if (handle == NULL) { + return -1; + } +#if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ + + sn_coap_protocol_clear_retransmission_buffer(handle); + +#endif + +#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */ + ns_list_foreach_safe(coap_duplication_info_s, tmp, &handle->linked_list_duplication_msgs) { + if (tmp->coap == handle) { + if (tmp->addr_ptr) { + handle->sn_coap_protocol_free(tmp->addr_ptr); + tmp->addr_ptr = 0; + } + ns_list_remove(&handle->linked_list_duplication_msgs, tmp); + handle->count_duplication_msgs--; + handle->sn_coap_protocol_free(tmp); + tmp = 0; + } + } +#endif + +#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwise is not used at all, this part of code will not be compiled */ + ns_list_foreach_safe(coap_blockwise_msg_s, tmp, &handle->linked_list_blockwise_sent_msgs) { + if (tmp->coap == handle) { + if (tmp->coap_msg_ptr) { + if (tmp->coap_msg_ptr->payload_ptr) { + handle->sn_coap_protocol_free(tmp->coap_msg_ptr->payload_ptr); + tmp->coap_msg_ptr->payload_ptr = 0; + } + sn_coap_parser_release_allocated_coap_msg_mem(tmp->coap, tmp->coap_msg_ptr); + } + ns_list_remove(&handle->linked_list_blockwise_sent_msgs, tmp); + handle->sn_coap_protocol_free(tmp); + tmp = 0; + } + } + ns_list_foreach_safe(coap_blockwise_payload_s, tmp, &handle->linked_list_blockwise_received_payloads) { + if (tmp->coap == handle) { + if (tmp->addr_ptr) { + handle->sn_coap_protocol_free(tmp->addr_ptr); + tmp->addr_ptr = 0; + } + if (tmp->payload_ptr) { + handle->sn_coap_protocol_free(tmp->payload_ptr); + tmp->payload_ptr = 0; + } + ns_list_remove(&handle->linked_list_blockwise_received_payloads, tmp); + handle->sn_coap_protocol_free(tmp); + tmp = 0; + } + } +#endif + + handle->sn_coap_protocol_free(handle); + handle = 0; + return 0; +} + +struct coap_s *sn_coap_protocol_init(void *(*used_malloc_func_ptr)(uint16_t), void (*used_free_func_ptr)(void *), + uint8_t (*used_tx_callback_ptr)(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *), + int8_t (*used_rx_callback_ptr)(sn_coap_hdr_s *, sn_nsdl_addr_s *, void *param)) +{ + /* Check paramters */ + if ((used_malloc_func_ptr == NULL) || (used_free_func_ptr == NULL) || (used_tx_callback_ptr == NULL)) { + return NULL; + } + + struct coap_s *handle; + handle = used_malloc_func_ptr(sizeof(struct coap_s)); + if (handle == NULL) { + return NULL; + } + + memset(handle, 0, sizeof(struct coap_s)); + + /* * * Handle tx callback * * */ + handle->sn_coap_tx_callback = used_tx_callback_ptr; + + handle->sn_coap_protocol_free = used_free_func_ptr; + handle->sn_coap_protocol_malloc = used_malloc_func_ptr; + + /* * * Handle rx callback * * */ + /* If pointer = 0, then re-sending does not return error when failed */ + handle->sn_coap_rx_callback = used_rx_callback_ptr; + + + +#if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ + + /* * * * Create Linked list for storing active resending messages * * * */ + ns_list_init(&handle->linked_list_resent_msgs); + handle->sn_coap_resending_queue_msgs = SN_COAP_RESENDING_QUEUE_SIZE_MSGS; + handle->sn_coap_resending_queue_bytes = SN_COAP_RESENDING_QUEUE_SIZE_BYTES; + handle->sn_coap_resending_intervall = DEFAULT_RESPONSE_TIMEOUT; + handle->sn_coap_resending_count = SN_COAP_RESENDING_MAX_COUNT; + + +#endif /* ENABLE_RESENDINGS */ + +#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */ + /* * * * Create Linked list for storing Duplication info * * * */ + ns_list_init(&handle->linked_list_duplication_msgs); + handle->sn_coap_duplication_buffer_size = SN_COAP_DUPLICATION_MAX_MSGS_COUNT; +#endif + +#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ + + ns_list_init(&handle->linked_list_blockwise_sent_msgs); + ns_list_init(&handle->linked_list_blockwise_received_payloads); + handle->sn_coap_block_data_size = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE; + +#endif /* ENABLE_RESENDINGS */ + + /* Randomize global message ID */ +#if defined __linux__ || defined TARGET_LIKE_MBED + srand(rand()^time(NULL)); + message_id = rand() % 400 + 100; +#else + message_id = 100; +#endif + + return handle; +} + +int8_t sn_coap_protocol_set_block_size(struct coap_s *handle, uint16_t block_size) +{ + (void) handle; + (void) block_size; +#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + if (handle == NULL) { + return -1; + } + switch (block_size) { + case 0: + case 16: + case 32: + case 64: + case 128: + case 256: + case 512: + case 1024: + handle->sn_coap_block_data_size = block_size; + return 0; + default: + break; + } +#endif + return -1; + +} + +int8_t sn_coap_protocol_set_duplicate_buffer_size(struct coap_s *handle, uint8_t message_count) +{ + (void) handle; + (void) message_count; +#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT + if (handle == NULL) { + return -1; + } + if (message_count <= SN_COAP_MAX_ALLOWED_DUPLICATION_MESSAGE_COUNT) { + handle->sn_coap_duplication_buffer_size = message_count; + return 0; + } +#endif + return -1; +} + +int8_t sn_coap_protocol_set_retransmission_parameters(struct coap_s *handle, + uint8_t resending_count, uint8_t resending_intervall) +{ +#if ENABLE_RESENDINGS + if (handle == NULL) { + return -1; + } + if (resending_count <= SN_COAP_MAX_ALLOWED_RESENDING_COUNT && + resending_intervall <= SN_COAP_MAX_ALLOWED_RESPONSE_TIMEOUT) { + handle->sn_coap_resending_count = resending_count; + + if (resending_intervall == 0) { + handle->sn_coap_resending_intervall = 1; + } else { + handle->sn_coap_resending_intervall = resending_intervall; + } + return 0; + } +#endif + return -1; +} + +int8_t sn_coap_protocol_set_retransmission_buffer(struct coap_s *handle, + uint8_t buffer_size_messages, uint16_t buffer_size_bytes) +{ +#if ENABLE_RESENDINGS + if (handle == NULL) { + return -1; + } + if (buffer_size_bytes <= SN_COAP_MAX_ALLOWED_RESENDING_BUFF_SIZE_BYTES && + buffer_size_messages <= SN_COAP_MAX_ALLOWED_RESENDING_BUFF_SIZE_MSGS ) { + handle->sn_coap_resending_queue_bytes = buffer_size_bytes; + handle->sn_coap_resending_queue_msgs = buffer_size_messages; + return 0; + } + +#endif + return -1; + +} + +void sn_coap_protocol_clear_retransmission_buffer(struct coap_s *handle) +{ +#if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ + if (handle == NULL) { + return; + } + ns_list_foreach_safe(coap_send_msg_s, tmp, &handle->linked_list_resent_msgs) { + if (tmp->send_msg_ptr) { + if (tmp->send_msg_ptr->dst_addr_ptr) { + if (tmp->send_msg_ptr->dst_addr_ptr->addr_ptr) { + handle->sn_coap_protocol_free(tmp->send_msg_ptr->dst_addr_ptr->addr_ptr); + tmp->send_msg_ptr->dst_addr_ptr->addr_ptr = 0; + } + handle->sn_coap_protocol_free(tmp->send_msg_ptr->dst_addr_ptr); + tmp->send_msg_ptr->dst_addr_ptr = 0; + } + if (tmp->send_msg_ptr->packet_ptr) { + handle->sn_coap_protocol_free(tmp->send_msg_ptr->packet_ptr); + tmp->send_msg_ptr->packet_ptr = 0; + } + if (tmp->send_msg_ptr->uri_path_ptr) { + handle->sn_coap_protocol_free(tmp->send_msg_ptr->uri_path_ptr); + tmp->send_msg_ptr->uri_path_ptr = 0; + } + handle->sn_coap_protocol_free(tmp->send_msg_ptr); + tmp->send_msg_ptr = 0; + } + ns_list_remove(&handle->linked_list_resent_msgs, tmp); + --handle->count_resent_msgs; + handle->sn_coap_protocol_free(tmp); + tmp = 0; + } +#endif +} + + +int16_t sn_coap_protocol_build(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, + uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, void *param) +{ + tr_debug("sn_coap_protocol_build - payload len %d", src_coap_msg_ptr->payload_len); + int16_t byte_count_built = 0; +#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ + uint16_t original_payload_len = 0; +#endif + /* * * * Check given pointers * * * */ + if ((dst_addr_ptr == NULL) || (dst_packet_data_ptr == NULL) || (src_coap_msg_ptr == NULL) || handle == NULL) { + return -2; + } + + if (dst_addr_ptr->addr_ptr == NULL) { + return -2; + } + + /* Check if built Message type is else than Acknowledgement or Reset i.e. message type is Confirmable or Non-confirmable */ + /* (for Acknowledgement and Reset messages is written same Message ID than was in the Request message) */ + if (src_coap_msg_ptr->msg_type != COAP_MSG_TYPE_ACKNOWLEDGEMENT && + src_coap_msg_ptr->msg_type != COAP_MSG_TYPE_RESET && + src_coap_msg_ptr->msg_id == 0) { + /* * * * Generate new Message ID and increase it by one * * * */ + src_coap_msg_ptr->msg_id = message_id; + message_id++; + if (message_id == 0) { + message_id = 1; + } + } + +#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ + + /* If blockwising needed */ + if ((src_coap_msg_ptr->payload_len > handle->sn_coap_block_data_size) && (handle->sn_coap_block_data_size > 0)) { + /* * * * Add Blockwise option to send CoAP message * * */ + + /* Allocate memory for less used options */ + if (sn_coap_parser_alloc_options(handle, src_coap_msg_ptr) == NULL) { + return -2; + } + + + /* Check if Request message */ + if (src_coap_msg_ptr->msg_code < COAP_MSG_CODE_RESPONSE_CREATED) { + tr_debug("sn_coap_protocol_build - block1 request"); + /* Add Blockwise option, use Block1 because Request payload */ + src_coap_msg_ptr->options_list_ptr->block1_len = 1; + if( src_coap_msg_ptr->options_list_ptr->block1_ptr ){ + handle->sn_coap_protocol_free(src_coap_msg_ptr->options_list_ptr->block1_ptr); + src_coap_msg_ptr->options_list_ptr->block1_ptr = 0; + } + src_coap_msg_ptr->options_list_ptr->block1_ptr = handle->sn_coap_protocol_malloc(1); + + if (src_coap_msg_ptr->options_list_ptr->block1_ptr == NULL) { + handle->sn_coap_protocol_free(src_coap_msg_ptr->options_list_ptr); + src_coap_msg_ptr->options_list_ptr = 0; + return -2; + } + + /* Add size1 parameter */ + tr_debug("sn_coap_protocol_build block1 request - payload len %d", src_coap_msg_ptr->payload_len); + if(src_coap_msg_ptr->payload_len < 0xFF) { + src_coap_msg_ptr->options_list_ptr->size1_len = 1; + } else { + src_coap_msg_ptr->options_list_ptr->size1_len = 2; + } + + if( src_coap_msg_ptr->options_list_ptr->size1_ptr ){ + handle->sn_coap_protocol_free(src_coap_msg_ptr->options_list_ptr->size1_ptr); + src_coap_msg_ptr->options_list_ptr->size1_ptr = 0; + } + src_coap_msg_ptr->options_list_ptr->size1_ptr = + handle->sn_coap_protocol_malloc(src_coap_msg_ptr->options_list_ptr->size1_len); + if (src_coap_msg_ptr->options_list_ptr->size1_ptr) { + for (int i = 0; i < src_coap_msg_ptr->options_list_ptr->size1_len; i++) { + src_coap_msg_ptr->options_list_ptr->size1_ptr[i] = + (src_coap_msg_ptr->payload_len >> ((src_coap_msg_ptr->options_list_ptr->size1_len - i - 1) * 8)); + } + } + + *(src_coap_msg_ptr->options_list_ptr->block1_ptr) = 0x08; /* First block (BLOCK NUMBER, 4 MSB bits) + More to come (MORE, 1 bit) */ + *(src_coap_msg_ptr->options_list_ptr->block1_ptr) |= sn_coap_convert_block_size(handle->sn_coap_block_data_size); + + + } else { /* Response message */ + tr_debug("sn_coap_protocol_build - block2 response"); + /* Add Blockwise option, use Block2 because Response payload */ + src_coap_msg_ptr->options_list_ptr->block2_len = 1; + if( src_coap_msg_ptr->options_list_ptr->block2_ptr ){ + handle->sn_coap_protocol_free(src_coap_msg_ptr->options_list_ptr->block2_ptr); + src_coap_msg_ptr->options_list_ptr->block2_ptr = 0; + } + + src_coap_msg_ptr->options_list_ptr->block2_ptr = handle->sn_coap_protocol_malloc(1); + + if (src_coap_msg_ptr->options_list_ptr->block2_ptr == NULL) { + handle->sn_coap_protocol_free(src_coap_msg_ptr->options_list_ptr); + src_coap_msg_ptr->options_list_ptr = 0; + return -2; + } + + if(src_coap_msg_ptr->payload_len < 0xFF) { + src_coap_msg_ptr->options_list_ptr->size2_len = 1; + } else { + src_coap_msg_ptr->options_list_ptr->size2_len = 2; + } + + if( src_coap_msg_ptr->options_list_ptr->size2_ptr ){ + handle->sn_coap_protocol_free(src_coap_msg_ptr->options_list_ptr->size2_ptr); + src_coap_msg_ptr->options_list_ptr->size2_ptr = 0; + } + src_coap_msg_ptr->options_list_ptr->size2_ptr = + handle->sn_coap_protocol_malloc(src_coap_msg_ptr->options_list_ptr->size2_len); + if (src_coap_msg_ptr->options_list_ptr->size2_ptr) { + for (int i = 0; i < src_coap_msg_ptr->options_list_ptr->size2_len; i++) { + src_coap_msg_ptr->options_list_ptr->size2_ptr[i] = + (src_coap_msg_ptr->payload_len >> ((src_coap_msg_ptr->options_list_ptr->size2_len - i - 1) * 8)); + } + } + + *(src_coap_msg_ptr->options_list_ptr->block2_ptr) = 0x08; /* First block (BLOCK NUMBER, 4 MSB bits) + More to come (MORE, 1 bit) */ + *(src_coap_msg_ptr->options_list_ptr->block2_ptr) |= sn_coap_convert_block_size(handle->sn_coap_block_data_size); + } + + /* Store original Payload length */ + original_payload_len = src_coap_msg_ptr->payload_len; + /* Change Payload length of send message because Payload is blockwised */ + src_coap_msg_ptr->payload_len = handle->sn_coap_block_data_size; + } + +#endif + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + /* * * * Build Packet data from CoAP message by using CoAP Header builder * * * */ + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + byte_count_built = sn_coap_builder_2(dst_packet_data_ptr, src_coap_msg_ptr, handle->sn_coap_block_data_size); + + if (byte_count_built < 0) { + return byte_count_built; + } + +#if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ + + /* Check if built Message type was confirmable, only these messages are resent */ + if (src_coap_msg_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) { + /* Store message to Linked list for resending purposes */ + sn_coap_protocol_linked_list_send_msg_store(handle, dst_addr_ptr, byte_count_built, dst_packet_data_ptr, + handle->system_time + (uint32_t)(handle->sn_coap_resending_intervall * RESPONSE_RANDOM_FACTOR), + param, src_coap_msg_ptr->uri_path_ptr, src_coap_msg_ptr->uri_path_len); + } + +#endif /* ENABLE_RESENDINGS */ + +#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ + + /* If blockwising needed */ + if ((original_payload_len > handle->sn_coap_block_data_size) && (handle->sn_coap_block_data_size > 0)) { + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + /* * * * Manage rest blockwise messages sending by storing them to Linked list * * * */ + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + coap_blockwise_msg_s *stored_blockwise_msg_ptr; + + stored_blockwise_msg_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_blockwise_msg_s)); + if (!stored_blockwise_msg_ptr) { + //block paylaod save failed, only first block can be build. Perhaps we should return error. + return byte_count_built; + } + memset(stored_blockwise_msg_ptr, 0, sizeof(coap_blockwise_msg_s)); + + /* Fill struct */ + stored_blockwise_msg_ptr->timestamp = handle->system_time; + + stored_blockwise_msg_ptr->coap_msg_ptr = sn_coap_protocol_copy_header(handle, src_coap_msg_ptr); + if( stored_blockwise_msg_ptr->coap_msg_ptr == NULL ){ + handle->sn_coap_protocol_free(stored_blockwise_msg_ptr); + stored_blockwise_msg_ptr = 0; + return -2; + } + + stored_blockwise_msg_ptr->coap_msg_ptr->payload_len = original_payload_len; + stored_blockwise_msg_ptr->coap_msg_ptr->payload_ptr = handle->sn_coap_protocol_malloc(stored_blockwise_msg_ptr->coap_msg_ptr->payload_len); + + if (!stored_blockwise_msg_ptr->coap_msg_ptr->payload_ptr) { + //block payload save failed, only first block can be build. Perhaps we should return error. + sn_coap_parser_release_allocated_coap_msg_mem(handle, stored_blockwise_msg_ptr->coap_msg_ptr); + handle->sn_coap_protocol_free(stored_blockwise_msg_ptr); + stored_blockwise_msg_ptr = 0; + return byte_count_built; + } + memcpy(stored_blockwise_msg_ptr->coap_msg_ptr->payload_ptr, src_coap_msg_ptr->payload_ptr, stored_blockwise_msg_ptr->coap_msg_ptr->payload_len); + + stored_blockwise_msg_ptr->coap = handle; + + ns_list_add_to_end(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr); + } + + else if (src_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_GET) { + /* Add message to linked list - response can be in blocks and we need header to build response.. */ + coap_blockwise_msg_s *stored_blockwise_msg_ptr; + + stored_blockwise_msg_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_blockwise_msg_s)); + if (!stored_blockwise_msg_ptr) { + return byte_count_built; + } + memset(stored_blockwise_msg_ptr, 0, sizeof(coap_blockwise_msg_s)); + + /* Fill struct */ + stored_blockwise_msg_ptr->timestamp = handle->system_time; + + stored_blockwise_msg_ptr->coap_msg_ptr = sn_coap_protocol_copy_header(handle, src_coap_msg_ptr); + if( stored_blockwise_msg_ptr->coap_msg_ptr == NULL ){ + handle->sn_coap_protocol_free(stored_blockwise_msg_ptr); + stored_blockwise_msg_ptr = 0; + return -2; + } + + stored_blockwise_msg_ptr->coap = handle; + + ns_list_add_to_end(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr); + } + +#endif /* SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE */ + + tr_debug("sn_coap_protocol_build - msg id: [%d], bytes: [%d]", src_coap_msg_ptr->msg_id, byte_count_built); + + /* * * * Return built CoAP message Packet data length * * * */ + return byte_count_built; +} + +sn_coap_hdr_s *sn_coap_protocol_parse(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t packet_data_len, uint8_t *packet_data_ptr, void *param) +{ + tr_debug("sn_coap_protocol_parse"); + sn_coap_hdr_s *returned_dst_coap_msg_ptr = NULL; + coap_version_e coap_version = COAP_VERSION_UNKNOWN; + + /* * * * Check given pointer * * * */ + if (src_addr_ptr == NULL || src_addr_ptr->addr_ptr == NULL || + packet_data_ptr == NULL || handle == NULL) { + return NULL; + } + + /* * * * Parse Packet data to CoAP message by using CoAP Header parser * * * */ + returned_dst_coap_msg_ptr = sn_coap_parser(handle, packet_data_len, packet_data_ptr, &coap_version); + + /* Check status of returned pointer */ + if (returned_dst_coap_msg_ptr == NULL) { + /* Memory allocation error in parser */ + return NULL; + } + /* * * * Send bad request response if parsing fails * * * */ + if (returned_dst_coap_msg_ptr->coap_status == COAP_STATUS_PARSER_ERROR_IN_HEADER) { + sn_coap_protocol_send_rst(handle, returned_dst_coap_msg_ptr->msg_id, src_addr_ptr, param); + sn_coap_parser_release_allocated_coap_msg_mem(handle, returned_dst_coap_msg_ptr); + return NULL; + } + + /* * * * Check validity of parsed Header values * * * */ + if (sn_coap_header_validity_check(returned_dst_coap_msg_ptr, coap_version) != 0) { + /* If message code is in a reserved class (1, 6 or 7), send reset. Message code class is 3 MSB of the message code byte */ + if (((returned_dst_coap_msg_ptr->msg_code >> 5) == 1) || // if class == 1 + ((returned_dst_coap_msg_ptr->msg_code >> 5) == 6) || // if class == 6 + ((returned_dst_coap_msg_ptr->msg_code >> 5) == 7)) { // if class == 7 + sn_coap_protocol_send_rst(handle, returned_dst_coap_msg_ptr->msg_id, src_addr_ptr, param); + } + + /* Release memory of CoAP message */ + sn_coap_parser_release_allocated_coap_msg_mem(handle, returned_dst_coap_msg_ptr); + + /* Return NULL because Header validity check failed */ + return NULL; + } + + /* Check if we need to send reset message */ + /* A recipient MUST acknowledge a Confirmable message with an Acknowledgement + message or, if it lacks context to process the message properly + (including the case where the message is Empty, uses a code with a + reserved class (1, 6 or 7), or has a message format error), MUST + reject it; rejecting a Confirmable message is effected by sending a + matching Reset message and otherwise ignoring it. */ + if (returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) { + /* CoAP ping */ + if (returned_dst_coap_msg_ptr->msg_code == COAP_MSG_CODE_EMPTY) { + sn_coap_protocol_send_rst(handle, returned_dst_coap_msg_ptr->msg_id, src_addr_ptr, param); + + /* Release memory of CoAP message */ + sn_coap_parser_release_allocated_coap_msg_mem(handle, returned_dst_coap_msg_ptr); + + /* Return NULL because Header validity check failed */ + return NULL; + } + } + + +#if !SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is used, this part of code will not be compiled */ + /* If blockwising used in received message */ + if (returned_dst_coap_msg_ptr->options_list_ptr != NULL && + (returned_dst_coap_msg_ptr->options_list_ptr->block1_ptr != NULL || + returned_dst_coap_msg_ptr->options_list_ptr->block2_ptr != NULL)) { + /* Set returned status to User */ + returned_dst_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_REJECTED; + //todo: send response -> not implemented + return returned_dst_coap_msg_ptr; + } +#endif /* !SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE */ + +#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT/* If Message duplication is used, this part of code will not be compiled */ + + /* * * * Manage received CoAP message duplicate detection * * * */ + + /* If no message duplication detected */ + if (sn_coap_protocol_linked_list_duplication_info_search(handle, src_addr_ptr, returned_dst_coap_msg_ptr->msg_id) == -1) { + /* * * No Message duplication: Store received message for detecting later duplication * * */ + + /* Get count of stored duplication messages */ + uint16_t stored_duplication_msgs_count = handle->count_duplication_msgs; + + /* Check if there is no room to store message for duplication detection purposes */ + if (stored_duplication_msgs_count >= handle->sn_coap_duplication_buffer_size) { + /* Get oldest stored duplication message */ + coap_duplication_info_s *stored_duplication_info_ptr = ns_list_get_first(&handle->linked_list_duplication_msgs); + + /* Remove oldest stored duplication message for getting room for new duplication message */ + sn_coap_protocol_linked_list_duplication_info_remove(handle, stored_duplication_info_ptr->addr_ptr, stored_duplication_info_ptr->port, stored_duplication_info_ptr->msg_id); + } + + /* Store Duplication info to Linked list */ + sn_coap_protocol_linked_list_duplication_info_store(handle, src_addr_ptr, returned_dst_coap_msg_ptr->msg_id); + } else { /* * * Message duplication detected * * */ + /* Set returned status to User */ + returned_dst_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_DUPLICATED_MSG; + + /* Because duplicate message, return with coap_status set */ + return returned_dst_coap_msg_ptr; + } +#endif + + /*** And here we check if message was block message ***/ + /*** If so, we call own block handling function and ***/ + /*** return to caller. ***/ +#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + + if (returned_dst_coap_msg_ptr->options_list_ptr != NULL && + (returned_dst_coap_msg_ptr->options_list_ptr->block1_ptr != NULL || + returned_dst_coap_msg_ptr->options_list_ptr->block2_ptr != NULL)) { + returned_dst_coap_msg_ptr = sn_coap_handle_blockwise_message(handle, src_addr_ptr, returned_dst_coap_msg_ptr, param); + } else { + /* Get ... */ + coap_blockwise_msg_s *stored_blockwise_msg_temp_ptr = NULL; + + ns_list_foreach(coap_blockwise_msg_s, msg, &handle->linked_list_blockwise_sent_msgs) { + if (returned_dst_coap_msg_ptr->msg_id == msg->coap_msg_ptr->msg_id) { + stored_blockwise_msg_temp_ptr = msg; + break; + } + } + + if (stored_blockwise_msg_temp_ptr) { + tr_debug("sn_coap_protocol_parse - remove block message %d", stored_blockwise_msg_temp_ptr->coap_msg_ptr->msg_id); + ns_list_remove(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_temp_ptr); + + if (stored_blockwise_msg_temp_ptr->coap_msg_ptr) { + if(stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr){ + handle->sn_coap_protocol_free(stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr); + stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr = 0; + } + sn_coap_parser_release_allocated_coap_msg_mem(stored_blockwise_msg_temp_ptr->coap, stored_blockwise_msg_temp_ptr->coap_msg_ptr); + } + + handle->sn_coap_protocol_free(stored_blockwise_msg_temp_ptr); + stored_blockwise_msg_temp_ptr = 0; + } + } + + if (!returned_dst_coap_msg_ptr) { + return NULL; + } + +#endif + + +#if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ + + /* Check if received Message type was acknowledgement */ + if ((returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_ACKNOWLEDGEMENT) || (returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_RESET)) { + /* * * * Manage CoAP message resending by removing active resending message from Linked list * * */ + + /* Get node count i.e. count of active resending messages */ + uint16_t stored_resending_msgs_count = handle->count_resent_msgs; + + /* Check if there is ongoing active message resendings */ + if (stored_resending_msgs_count > 0) { + sn_nsdl_transmit_s *removed_msg_ptr = NULL; + + /* Check if received message was confirmation for some active resending message */ + removed_msg_ptr = sn_coap_protocol_linked_list_send_msg_search(handle, src_addr_ptr, returned_dst_coap_msg_ptr->msg_id); + + if (removed_msg_ptr != NULL) { + if (returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_RESET) { + if(removed_msg_ptr->uri_path_len) { + returned_dst_coap_msg_ptr->uri_path_ptr = handle->sn_coap_protocol_malloc(removed_msg_ptr->uri_path_len); + if (returned_dst_coap_msg_ptr->uri_path_ptr != NULL) { + memcpy(returned_dst_coap_msg_ptr->uri_path_ptr, removed_msg_ptr->uri_path_ptr, removed_msg_ptr->uri_path_len); + returned_dst_coap_msg_ptr->uri_path_len = removed_msg_ptr->uri_path_len; + } + } + } + /* Remove resending message from active message resending Linked list */ + sn_coap_protocol_linked_list_send_msg_remove(handle, src_addr_ptr, returned_dst_coap_msg_ptr->msg_id); + } + } + } +#endif /* ENABLE_RESENDINGS */ + + /* * * * Return parsed CoAP message * * * */ + return returned_dst_coap_msg_ptr; +} + + +int8_t sn_coap_protocol_exec(struct coap_s *handle, uint32_t current_time) +{ + if( !handle ){ + return -1; + } + + /* * * * Store current System time * * * */ + handle->system_time = current_time; + +#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + /* * * * Remove old blocwise data * * * */ + sn_coap_protocol_linked_list_blockwise_remove_old_data(handle); +#endif + + +#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT + /* * * * Remove old duplication messages * * * */ + sn_coap_protocol_linked_list_duplication_info_remove_old_ones(handle); +#endif + +#if ENABLE_RESENDINGS + /* Check if there is ongoing active message sendings */ + ns_list_foreach_safe(coap_send_msg_s, stored_msg_ptr, &handle->linked_list_resent_msgs) { + // First check that msg belongs to handle + if( stored_msg_ptr->coap == handle ){ + /* Check if it is time to send this message */ + if (current_time >= stored_msg_ptr->resending_time) { + /* * * Increase Resending counter * * */ + stored_msg_ptr->resending_counter++; + + /* Check if all re-sendings have been done */ + if (stored_msg_ptr->resending_counter > handle->sn_coap_resending_count) { + coap_version_e coap_version = COAP_VERSION_UNKNOWN; + + /* Get message ID from stored sending message */ + uint16_t temp_msg_id = (stored_msg_ptr->send_msg_ptr->packet_ptr[2] << 8); + temp_msg_id += (uint16_t)stored_msg_ptr->send_msg_ptr->packet_ptr[3]; + + /* If RX callback have been defined.. */ + if (stored_msg_ptr->coap->sn_coap_rx_callback != 0) { + sn_coap_hdr_s *tmp_coap_hdr_ptr; + /* Parse CoAP message, set status and call RX callback */ + tmp_coap_hdr_ptr = sn_coap_parser(stored_msg_ptr->coap, stored_msg_ptr->send_msg_ptr->packet_len, stored_msg_ptr->send_msg_ptr->packet_ptr, &coap_version); + + if (tmp_coap_hdr_ptr != 0) { + tmp_coap_hdr_ptr->coap_status = COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED; + + stored_msg_ptr->coap->sn_coap_rx_callback(tmp_coap_hdr_ptr, stored_msg_ptr->send_msg_ptr->dst_addr_ptr, stored_msg_ptr->param); + + sn_coap_parser_release_allocated_coap_msg_mem(stored_msg_ptr->coap, tmp_coap_hdr_ptr); + } + } + /* Remove message from Linked list */ + sn_coap_protocol_linked_list_send_msg_remove(handle, stored_msg_ptr->send_msg_ptr->dst_addr_ptr, temp_msg_id); + } else { + /* Send message */ + stored_msg_ptr->coap->sn_coap_tx_callback(stored_msg_ptr->send_msg_ptr->packet_ptr, + stored_msg_ptr->send_msg_ptr->packet_len, stored_msg_ptr->send_msg_ptr->dst_addr_ptr, stored_msg_ptr->param); + + /* * * Count new Resending time * * */ + stored_msg_ptr->resending_time = current_time + (((uint32_t)(handle->sn_coap_resending_intervall * RESPONSE_RANDOM_FACTOR)) << + stored_msg_ptr->resending_counter); + } + + } + } + } + +#endif /* ENABLE_RESENDINGS */ + + return 0; +} + +#if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ + +/**************************************************************************//** + * \fn static void sn_coap_protocol_linked_list_send_msg_store(sn_nsdl_addr_s *dst_addr_ptr, uint16_t send_packet_data_len, uint8_t *send_packet_data_ptr, uint32_t sending_time) + * + * \brief Stores message to Linked list for sending purposes. + + * \param *dst_addr_ptr is pointer to destination address where CoAP message will be sent + * + * \param send_packet_data_len is length of Packet data to be stored + * + * \param *send_packet_data_ptr is Packet data to be stored + * + * \param sending_time is stored sending time + *****************************************************************************/ + +static void sn_coap_protocol_linked_list_send_msg_store(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint16_t send_packet_data_len, + uint8_t *send_packet_data_ptr, uint32_t sending_time, void *param, uint8_t *uri_path_ptr, uint8_t uri_path_len) +{ + + coap_send_msg_s *stored_msg_ptr = NULL; + + /* If both queue parameters are "0" or resending count is "0", then re-sending is disabled */ + if (((handle->sn_coap_resending_queue_msgs == 0) && (handle->sn_coap_resending_queue_bytes == 0)) || (handle->sn_coap_resending_count == 0)) { + return; + } + + if (handle->sn_coap_resending_queue_msgs > 0) { + if (handle->count_resent_msgs >= handle->sn_coap_resending_queue_msgs) { + return; + } + } + + /* Count resending queue size, if buffer size is defined */ + if (handle->sn_coap_resending_queue_bytes > 0) { + if ((sn_coap_count_linked_list_size(&handle->linked_list_resent_msgs) + send_packet_data_len) > handle->sn_coap_resending_queue_bytes) { + return; + } + } + + /* Allocating memory for stored message */ + stored_msg_ptr = sn_coap_protocol_allocate_mem_for_msg(handle, dst_addr_ptr, send_packet_data_len); + + if (stored_msg_ptr == 0) { + return; + } + + /* Filling of coap_send_msg_s with initialization values */ + stored_msg_ptr->resending_counter = 0; + stored_msg_ptr->resending_time = sending_time; + + /* Filling of sn_nsdl_transmit_s */ + stored_msg_ptr->send_msg_ptr->protocol = SN_NSDL_PROTOCOL_COAP; + stored_msg_ptr->send_msg_ptr->packet_len = send_packet_data_len; + memcpy(stored_msg_ptr->send_msg_ptr->packet_ptr, send_packet_data_ptr, send_packet_data_len); + + /* Filling of sn_nsdl_addr_s */ + stored_msg_ptr->send_msg_ptr->dst_addr_ptr->type = dst_addr_ptr->type; + stored_msg_ptr->send_msg_ptr->dst_addr_ptr->addr_len = dst_addr_ptr->addr_len; + memcpy(stored_msg_ptr->send_msg_ptr->dst_addr_ptr->addr_ptr, dst_addr_ptr->addr_ptr, dst_addr_ptr->addr_len); + stored_msg_ptr->send_msg_ptr->dst_addr_ptr->port = dst_addr_ptr->port; + + stored_msg_ptr->coap = handle; + stored_msg_ptr->param = param; + + if (uri_path_len) { + stored_msg_ptr->send_msg_ptr->uri_path_ptr = handle->sn_coap_protocol_malloc(uri_path_len); + if (stored_msg_ptr->send_msg_ptr->uri_path_ptr == NULL){ + return; + } + stored_msg_ptr->send_msg_ptr->uri_path_len = uri_path_len; + memcpy(stored_msg_ptr->send_msg_ptr->uri_path_ptr, uri_path_ptr, uri_path_len); + } + + + /* Storing Resending message to Linked list */ + ns_list_add_to_end(&handle->linked_list_resent_msgs, stored_msg_ptr); + ++handle->count_resent_msgs; +} + +/**************************************************************************//** + * \fn static sn_nsdl_transmit_s *sn_coap_protocol_linked_list_send_msg_search(sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id) + * + * \brief Searches stored resending message from Linked list + * + * \param *src_addr_ptr is searching key for searched message + * + * \param msg_id is searching key for searched message + * + * \return Return value is pointer to found stored resending message in Linked + * list or NULL if message not found + *****************************************************************************/ + +static sn_nsdl_transmit_s *sn_coap_protocol_linked_list_send_msg_search(struct coap_s *handle, + sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id) +{ + /* Loop all stored resending messages Linked list */ + ns_list_foreach(coap_send_msg_s, stored_msg_ptr, &handle->linked_list_resent_msgs) { + /* Get message ID from stored resending message */ + uint16_t temp_msg_id = (stored_msg_ptr->send_msg_ptr->packet_ptr[2] << 8); + temp_msg_id += (uint16_t)stored_msg_ptr->send_msg_ptr->packet_ptr[3]; + + /* If message's Message ID is same than is searched */ + if (temp_msg_id == msg_id) { + /* If message's Source address is same than is searched */ + if (0 == memcmp(src_addr_ptr->addr_ptr, stored_msg_ptr->send_msg_ptr->dst_addr_ptr->addr_ptr, src_addr_ptr->addr_len)) { + /* If message's Source address port is same than is searched */ + if (stored_msg_ptr->send_msg_ptr->dst_addr_ptr->port == src_addr_ptr->port) { + /* * * Message found, return pointer to that stored resending message * * * */ + return stored_msg_ptr->send_msg_ptr; + } + } + } + } + + /* Message not found */ + return NULL; +} +/**************************************************************************//** + * \fn static void sn_coap_protocol_linked_list_send_msg_remove(sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id) + * + * \brief Removes stored resending message from Linked list + * + * \param *src_addr_ptr is searching key for searched message + * \param msg_id is searching key for removed message + *****************************************************************************/ + +static void sn_coap_protocol_linked_list_send_msg_remove(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id) +{ + /* Loop all stored resending messages in Linked list */ + ns_list_foreach(coap_send_msg_s, stored_msg_ptr, &handle->linked_list_resent_msgs) { + /* Get message ID from stored resending message */ + uint16_t temp_msg_id = (stored_msg_ptr->send_msg_ptr->packet_ptr[2] << 8); + temp_msg_id += (uint16_t)stored_msg_ptr->send_msg_ptr->packet_ptr[3]; + + /* If message's Message ID is same than is searched */ + if (temp_msg_id == msg_id) { + /* If message's Source address is same than is searched */ + if (0 == memcmp(src_addr_ptr->addr_ptr, stored_msg_ptr->send_msg_ptr->dst_addr_ptr->addr_ptr, src_addr_ptr->addr_len)) { + /* If message's Source address port is same than is searched */ + if (stored_msg_ptr->send_msg_ptr->dst_addr_ptr->port == src_addr_ptr->port) { + /* * * Message found * * */ + + /* Remove message from Linked list */ + ns_list_remove(&handle->linked_list_resent_msgs, stored_msg_ptr); + --handle->count_resent_msgs; + + /* Free memory of stored message */ + sn_coap_protocol_release_allocated_send_msg_mem(handle, stored_msg_ptr); + + return; + } + } + } + } +} +#endif /* ENABLE_RESENDINGS */ + + +static void sn_coap_protocol_send_rst(struct coap_s *handle, uint16_t msg_id, sn_nsdl_addr_s *addr_ptr, void *param) +{ + uint8_t packet_ptr[4]; + + /* Add CoAP version and message type */ + packet_ptr[0] = COAP_VERSION_1; + packet_ptr[0] |= COAP_MSG_TYPE_RESET; + + /* Add message code */ + packet_ptr[1] = COAP_MSG_CODE_EMPTY; + + /* Add message ID */ + packet_ptr[2] = msg_id >> 8; + packet_ptr[3] = (uint8_t)msg_id; + + /* Send RST */ + handle->sn_coap_tx_callback(packet_ptr, 4, addr_ptr, param); + +} +#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */ + +/**************************************************************************//** + * \fn static void sn_coap_protocol_linked_list_duplication_info_store(sn_nsdl_addr_s *addr_ptr, uint16_t msg_id) + * + * \brief Stores Duplication info to Linked list + * + * \param msg_id is Message ID to be stored + * \param *addr_ptr is pointer to Address information to be stored + *****************************************************************************/ + +static void sn_coap_protocol_linked_list_duplication_info_store(struct coap_s *handle, sn_nsdl_addr_s *addr_ptr, + uint16_t msg_id) +{ + coap_duplication_info_s *stored_duplication_info_ptr = NULL; + + /* * * * Allocating memory for stored Duplication info * * * */ + + /* Allocate memory for stored Duplication info's structure */ + stored_duplication_info_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_duplication_info_s)); + + if (stored_duplication_info_ptr == NULL) { + return; + } + + /* Allocate memory for stored Duplication info's address */ + stored_duplication_info_ptr->addr_ptr = handle->sn_coap_protocol_malloc(addr_ptr->addr_len); + + if (stored_duplication_info_ptr->addr_ptr == NULL) { + handle->sn_coap_protocol_free(stored_duplication_info_ptr); + stored_duplication_info_ptr = 0; + return; + } + + /* * * * Filling fields of stored Duplication info * * * */ + + stored_duplication_info_ptr->timestamp = handle->system_time; + stored_duplication_info_ptr->addr_len = addr_ptr->addr_len; + memcpy(stored_duplication_info_ptr->addr_ptr, addr_ptr->addr_ptr, addr_ptr->addr_len); + stored_duplication_info_ptr->port = addr_ptr->port; + stored_duplication_info_ptr->msg_id = msg_id; + + stored_duplication_info_ptr->coap = handle; + + /* * * * Storing Duplication info to Linked list * * * */ + + ns_list_add_to_end(&handle->linked_list_duplication_msgs, stored_duplication_info_ptr); + ++handle->count_duplication_msgs; +} + +/**************************************************************************//** + * \fn static int8_t sn_coap_protocol_linked_list_duplication_info_search(sn_nsdl_addr_s *addr_ptr, uint16_t msg_id) + * + * \brief Searches stored message from Linked list (Address and Message ID as key) + * + * \param *addr_ptr is pointer to Address key to be searched + * \param msg_id is Message ID key to be searched + * + * \return Return value is 0 when message found and -1 if not found + *****************************************************************************/ + +static int8_t sn_coap_protocol_linked_list_duplication_info_search(struct coap_s *handle, + sn_nsdl_addr_s *addr_ptr, uint16_t msg_id) +{ + /* Loop all nodes in Linked list for searching Message ID */ + ns_list_foreach(coap_duplication_info_s, stored_duplication_info_ptr, &handle->linked_list_duplication_msgs) { + /* If message's Message ID is same than is searched */ + if (stored_duplication_info_ptr->msg_id == msg_id) { + /* If message's Source address is same than is searched */ + if (0 == memcmp(addr_ptr->addr_ptr, stored_duplication_info_ptr->addr_ptr, addr_ptr->addr_len)) { + /* If message's Source address port is same than is searched */ + if (stored_duplication_info_ptr->port == addr_ptr->port) { + /* * * Correct Duplication info found * * * */ + return 0; + } + } + } + } + + return -1; +} + +/**************************************************************************//** + * \fn static void sn_coap_protocol_linked_list_duplication_info_remove(struct coap_s *handle, uint8_t *addr_ptr, uint16_t port, uint16_t msg_id) + * + * \brief Removes stored Duplication info from Linked list + * + * \param *addr_ptr is pointer to Address key to be removed + * + * \param port is Port key to be removed + * + * \param msg_id is Message ID key to be removed + *****************************************************************************/ + +static void sn_coap_protocol_linked_list_duplication_info_remove(struct coap_s *handle, uint8_t *addr_ptr, uint16_t port, uint16_t msg_id) +{ + /* Loop all stored duplication messages in Linked list */ + ns_list_foreach(coap_duplication_info_s, removed_duplication_info_ptr, &handle->linked_list_duplication_msgs) { + /* If message's Address is same than is searched */ + if (handle == removed_duplication_info_ptr->coap && 0 == memcmp(addr_ptr, removed_duplication_info_ptr->addr_ptr, removed_duplication_info_ptr->addr_len)) { + /* If message's Address prt is same than is searched */ + if (removed_duplication_info_ptr->port == port) { + /* If Message ID is same than is searched */ + if (removed_duplication_info_ptr->msg_id == msg_id) { + /* * * * Correct Duplication info found, remove it from Linked list * * * */ + ns_list_remove(&handle->linked_list_duplication_msgs, removed_duplication_info_ptr); + --handle->count_duplication_msgs; + + /* Free memory of stored Duplication info */ + handle->sn_coap_protocol_free(removed_duplication_info_ptr->addr_ptr); + removed_duplication_info_ptr->addr_ptr = 0; + handle->sn_coap_protocol_free(removed_duplication_info_ptr); + removed_duplication_info_ptr = 0; + + return; + } + } + } + } +} + +/**************************************************************************//** + * \fn static void sn_coap_protocol_linked_list_duplication_info_remove_old_ones(struct coap_s *handle) + * + * \brief Removes old stored Duplication detection infos from Linked list + *****************************************************************************/ + +static void sn_coap_protocol_linked_list_duplication_info_remove_old_ones(struct coap_s *handle) +{ + /* Loop all stored duplication messages in Linked list */ + ns_list_foreach_safe(coap_duplication_info_s, removed_duplication_info_ptr, &handle->linked_list_duplication_msgs) { + if ((handle->system_time - removed_duplication_info_ptr->timestamp) > SN_COAP_DUPLICATION_MAX_TIME_MSGS_STORED) { + /* * * * Old Duplication info found, remove it from Linked list * * * */ + ns_list_remove(&handle->linked_list_duplication_msgs, removed_duplication_info_ptr); + --handle->count_duplication_msgs; + + /* Free memory of stored Duplication info */ + handle->sn_coap_protocol_free(removed_duplication_info_ptr->addr_ptr); + removed_duplication_info_ptr->addr_ptr = 0; + handle->sn_coap_protocol_free(removed_duplication_info_ptr); + removed_duplication_info_ptr = 0; + } + } +} + +#endif /* SN_COAP_DUPLICATION_MAX_MSGS_COUNT */ + +#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE +/**************************************************************************//** + * \fn static void sn_coap_protocol_linked_list_blockwise_msg_remove(struct coap_s *handle, coap_blockwise_msg_s *removed_msg_ptr) + * + * \brief Removes stored blockwise message from Linked list + * + * \param removed_msg_ptr is message to be removed + *****************************************************************************/ + +static void sn_coap_protocol_linked_list_blockwise_msg_remove(struct coap_s *handle, coap_blockwise_msg_s *removed_msg_ptr) +{ + if( removed_msg_ptr->coap == handle ){ + ns_list_remove(&handle->linked_list_blockwise_sent_msgs, removed_msg_ptr); + + if( removed_msg_ptr->coap_msg_ptr ){ + if (removed_msg_ptr->coap_msg_ptr->payload_ptr) { + handle->sn_coap_protocol_free(removed_msg_ptr->coap_msg_ptr->payload_ptr); + removed_msg_ptr->coap_msg_ptr->payload_ptr = 0; + } + + sn_coap_parser_release_allocated_coap_msg_mem(handle, removed_msg_ptr->coap_msg_ptr); + } + + handle->sn_coap_protocol_free(removed_msg_ptr); + removed_msg_ptr = 0; + } +} + +/**************************************************************************//** + * \fn static void sn_coap_protocol_linked_list_blockwise_payload_store(sn_nsdl_addr_s *addr_ptr, uint16_t stored_payload_len, uint8_t *stored_payload_ptr) + * + * \brief Stores blockwise payload to Linked list + * + * \param *addr_ptr is pointer to Address information to be stored + * \param stored_payload_len is length of stored Payload + * \param *stored_payload_ptr is pointer to stored Payload + *****************************************************************************/ + +static void sn_coap_protocol_linked_list_blockwise_payload_store(struct coap_s *handle, sn_nsdl_addr_s *addr_ptr, + uint16_t stored_payload_len, + uint8_t *stored_payload_ptr) +{ + if (!addr_ptr || !stored_payload_len || !stored_payload_ptr) { + return; + } + + coap_blockwise_payload_s *stored_blockwise_payload_ptr = NULL; + + /* * * * Allocating memory for stored Payload * * * */ + + /* Allocate memory for stored Payload's structure */ + stored_blockwise_payload_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_blockwise_payload_s)); + + if (stored_blockwise_payload_ptr == NULL) { + return; + } + + /* Allocate memory for stored Payload's data */ + stored_blockwise_payload_ptr->payload_ptr = handle->sn_coap_protocol_malloc(stored_payload_len); + + if (stored_blockwise_payload_ptr->payload_ptr == NULL) { + handle->sn_coap_protocol_free(stored_blockwise_payload_ptr); + stored_blockwise_payload_ptr = 0; + return; + } + + /* Allocate memory for stored Payload's address */ + stored_blockwise_payload_ptr->addr_ptr = handle->sn_coap_protocol_malloc(addr_ptr->addr_len); + + if (stored_blockwise_payload_ptr->addr_ptr == NULL) { + handle->sn_coap_protocol_free(stored_blockwise_payload_ptr->payload_ptr); + stored_blockwise_payload_ptr->payload_ptr = 0; + handle->sn_coap_protocol_free(stored_blockwise_payload_ptr); + stored_blockwise_payload_ptr = 0; + + return; + } + + /* * * * Filling fields of stored Payload * * * */ + + stored_blockwise_payload_ptr->timestamp = handle->system_time; + + memcpy(stored_blockwise_payload_ptr->addr_ptr, addr_ptr->addr_ptr, addr_ptr->addr_len); + stored_blockwise_payload_ptr->port = addr_ptr->port; + memcpy(stored_blockwise_payload_ptr->payload_ptr, stored_payload_ptr, stored_payload_len); + stored_blockwise_payload_ptr->payload_len = stored_payload_len; + + stored_blockwise_payload_ptr->coap = handle; + + /* * * * Storing Payload to Linked list * * * */ + + ns_list_add_to_end(&handle->linked_list_blockwise_received_payloads, stored_blockwise_payload_ptr); +} + +/**************************************************************************//** + * \fn static uint8_t *sn_coap_protocol_linked_list_blockwise_payload_search(sn_nsdl_addr_s *src_addr_ptr, uint16_t *payload_length) + * + * \brief Searches stored blockwise payload from Linked list (Address as key) + * + * \param *addr_ptr is pointer to Address key to be searched + * \param *payload_length is pointer to returned Payload length + * + * \return Return value is pointer to found stored blockwise payload in Linked + * list or NULL if payload not found + *****************************************************************************/ + +static uint8_t *sn_coap_protocol_linked_list_blockwise_payload_search(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t *payload_length) +{ + /* Loop all stored blockwise payloads in Linked list */ + ns_list_foreach(coap_blockwise_payload_s, stored_payload_info_ptr, &handle->linked_list_blockwise_received_payloads) { + /* If payload's Source address is same than is searched */ + if (0 == memcmp(src_addr_ptr->addr_ptr, stored_payload_info_ptr->addr_ptr, src_addr_ptr->addr_len)) { + /* If payload's Source address port is same than is searched */ + if (stored_payload_info_ptr->port == src_addr_ptr->port) { + /* * * Correct Payload found * * * */ + *payload_length = stored_payload_info_ptr->payload_len; + + return stored_payload_info_ptr->payload_ptr; + } + } + } + + return NULL; +} + +/**************************************************************************//** + * \fn static void sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(struct coap_s *handle) + * + * \brief Removes current stored blockwise paylod from Linked list + *****************************************************************************/ + +static void sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(struct coap_s *handle) +{ + coap_blockwise_payload_s *removed_payload_ptr; + + /* Remove oldest node in Linked list*/ + removed_payload_ptr = ns_list_get_first(&handle->linked_list_blockwise_received_payloads); + + if (removed_payload_ptr != NULL) { + sn_coap_protocol_linked_list_blockwise_payload_remove(handle, removed_payload_ptr); + } +} + +/**************************************************************************//** + * \fn static void sn_coap_protocol_linked_list_blockwise_payload_remove(struct coap_s *handle, + * coap_blockwise_msg_s *removed_msg_ptr) + * + * \brief Removes stored blockwise payload from Linked list + * + * \param removed_payload_ptr is payload to be removed + *****************************************************************************/ + +static void sn_coap_protocol_linked_list_blockwise_payload_remove(struct coap_s *handle, + coap_blockwise_payload_s *removed_payload_ptr) +{ + ns_list_remove(&handle->linked_list_blockwise_received_payloads, removed_payload_ptr); + + /* Free memory of stored payload */ + if (removed_payload_ptr->addr_ptr != NULL) { + handle->sn_coap_protocol_free(removed_payload_ptr->addr_ptr); + removed_payload_ptr->addr_ptr = 0; + } + + if (removed_payload_ptr->payload_ptr != NULL) { + handle->sn_coap_protocol_free(removed_payload_ptr->payload_ptr); + removed_payload_ptr->payload_ptr = 0; + } + + handle->sn_coap_protocol_free(removed_payload_ptr); + removed_payload_ptr = 0; +} + +/**************************************************************************//** + * \fn static uint32_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(sn_nsdl_addr_s *src_addr_ptr) + * + * \brief Counts length of Payloads in Linked list (Address as key) + * + * \param *addr_ptr is pointer to Address key + * + * \return Return value is length of Payloads as bytes + *****************************************************************************/ + +static uint32_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr) +{ + uint32_t ret_whole_payload_len = 0; + /* Loop all stored blockwise payloads in Linked list */ + ns_list_foreach(coap_blockwise_payload_s, searched_payload_info_ptr, &handle->linked_list_blockwise_received_payloads) { + /* If payload's Source address is same than is searched */ + if (0 == memcmp(src_addr_ptr->addr_ptr, searched_payload_info_ptr->addr_ptr, src_addr_ptr->addr_len)) { + /* If payload's Source address port is same than is searched */ + if (searched_payload_info_ptr->port == src_addr_ptr->port) { + /* * * Correct Payload found * * * */ + ret_whole_payload_len += searched_payload_info_ptr->payload_len; + } + } + } + + return ret_whole_payload_len; +} + +/**************************************************************************//** + * \fn static void sn_coap_protocol_linked_list_blockwise_remove_old_data(struct coap_s *handle) + * + * \brief Removes old stored Blockwise messages and payloads from Linked list + *****************************************************************************/ + +static void sn_coap_protocol_linked_list_blockwise_remove_old_data(struct coap_s *handle) +{ + /* Loop all stored Blockwise messages in Linked list */ + ns_list_foreach_safe(coap_blockwise_msg_s, removed_blocwise_msg_ptr, &handle->linked_list_blockwise_sent_msgs) { + if ((handle->system_time - removed_blocwise_msg_ptr->timestamp) > SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED) { + //TODO: Check do we need to check handle == removed_blocwise_msg_ptr->coap here? + + /* * * * Old Blockise message found, remove it from Linked list * * * */ + if( removed_blocwise_msg_ptr->coap_msg_ptr ){ + if(removed_blocwise_msg_ptr->coap_msg_ptr->payload_ptr){ + handle->sn_coap_protocol_free(removed_blocwise_msg_ptr->coap_msg_ptr->payload_ptr); + removed_blocwise_msg_ptr->coap_msg_ptr->payload_ptr = 0; + } + sn_coap_parser_release_allocated_coap_msg_mem(handle, removed_blocwise_msg_ptr->coap_msg_ptr); + removed_blocwise_msg_ptr->coap_msg_ptr = 0; + } + sn_coap_protocol_linked_list_blockwise_msg_remove(handle, removed_blocwise_msg_ptr); + } + } + + /* Loop all stored Blockwise payloads in Linked list */ + ns_list_foreach_safe(coap_blockwise_payload_s, removed_blocwise_payload_ptr, &handle->linked_list_blockwise_received_payloads) { + if ((handle->system_time - removed_blocwise_payload_ptr->timestamp) > SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED) { + /* * * * Old Blockise payload found, remove it from Linked list * * * */ + sn_coap_protocol_linked_list_blockwise_payload_remove(handle, removed_blocwise_payload_ptr); + } + } +} + +#endif /* SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE */ + + +#if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */ +/***************************************************************************//** + * \fn int8_t sn_coap_protocol_allocate_mem_for_msg(sn_nsdl_addr_s *dst_addr_ptr, uint16_t packet_data_len, coap_send_msg_s *msg_ptr) + * + * \brief Allocates memory for given message (send or blockwise message) + * + * \param *dst_addr_ptr is pointer to destination address where message will be sent + * \param packet_data_len is length of allocated Packet data + * + * \return pointer to allocated struct + *****************************************************************************/ + +coap_send_msg_s *sn_coap_protocol_allocate_mem_for_msg(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint16_t packet_data_len) +{ + + coap_send_msg_s *msg_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_send_msg_s)); + + if (msg_ptr == NULL) { + return 0; + } + + memset(msg_ptr, 0, sizeof(coap_send_msg_s)); + + msg_ptr->send_msg_ptr = handle->sn_coap_protocol_malloc(sizeof(sn_nsdl_transmit_s)); + + if (msg_ptr->send_msg_ptr == NULL) { + sn_coap_protocol_release_allocated_send_msg_mem(handle, msg_ptr); + return 0; + } + + memset(msg_ptr->send_msg_ptr, 0 , sizeof(sn_nsdl_transmit_s)); + + msg_ptr->send_msg_ptr->dst_addr_ptr = handle->sn_coap_protocol_malloc(sizeof(sn_nsdl_addr_s)); + + if (msg_ptr->send_msg_ptr->dst_addr_ptr == NULL) { + sn_coap_protocol_release_allocated_send_msg_mem(handle, msg_ptr); + return 0; + } + + memset(msg_ptr->send_msg_ptr->dst_addr_ptr, 0, sizeof(sn_nsdl_addr_s)); + + msg_ptr->send_msg_ptr->packet_ptr = handle->sn_coap_protocol_malloc(packet_data_len); + + if (msg_ptr->send_msg_ptr->packet_ptr == NULL) { + sn_coap_protocol_release_allocated_send_msg_mem(handle, msg_ptr); + return 0; + } + + msg_ptr->send_msg_ptr->dst_addr_ptr->addr_ptr = handle->sn_coap_protocol_malloc(dst_addr_ptr->addr_len); + + if (msg_ptr->send_msg_ptr->dst_addr_ptr->addr_ptr == NULL) { + sn_coap_protocol_release_allocated_send_msg_mem(handle, msg_ptr); + return 0; + } + + memset(msg_ptr->send_msg_ptr->dst_addr_ptr->addr_ptr, 0, dst_addr_ptr->addr_len); + + return msg_ptr; +} + + +/**************************************************************************//** + * \fn static void sn_coap_protocol_release_allocated_send_msg_mem(struct coap_s *handle, coap_send_msg_s *freed_send_msg_ptr) + * + * \brief Releases memory of given Sending message (coap_send_msg_s) + * + * \param *freed_send_msg_ptr is pointer to released Sending message + *****************************************************************************/ + +static void sn_coap_protocol_release_allocated_send_msg_mem(struct coap_s *handle, coap_send_msg_s *freed_send_msg_ptr) +{ + if (freed_send_msg_ptr != NULL) { + if (freed_send_msg_ptr->send_msg_ptr != NULL) { + if (freed_send_msg_ptr->send_msg_ptr->dst_addr_ptr != NULL) { + if (freed_send_msg_ptr->send_msg_ptr->dst_addr_ptr->addr_ptr != NULL) { + handle->sn_coap_protocol_free(freed_send_msg_ptr->send_msg_ptr->dst_addr_ptr->addr_ptr); + freed_send_msg_ptr->send_msg_ptr->dst_addr_ptr->addr_ptr = 0; + } + + handle->sn_coap_protocol_free(freed_send_msg_ptr->send_msg_ptr->dst_addr_ptr); + freed_send_msg_ptr->send_msg_ptr->dst_addr_ptr = 0; + } + + if (freed_send_msg_ptr->send_msg_ptr->packet_ptr != NULL) { + handle->sn_coap_protocol_free(freed_send_msg_ptr->send_msg_ptr->packet_ptr); + freed_send_msg_ptr->send_msg_ptr->packet_ptr = 0; + } + + if (freed_send_msg_ptr->send_msg_ptr->uri_path_ptr != NULL) { + handle->sn_coap_protocol_free(freed_send_msg_ptr->send_msg_ptr->uri_path_ptr); + freed_send_msg_ptr->send_msg_ptr->uri_path_ptr = 0; + } + + handle->sn_coap_protocol_free(freed_send_msg_ptr->send_msg_ptr); + freed_send_msg_ptr->send_msg_ptr = 0; + } + + handle->sn_coap_protocol_free(freed_send_msg_ptr); + freed_send_msg_ptr = 0; + } +} + +/**************************************************************************//** + * \fn static uint16_t sn_coap_count_linked_list_size(const coap_send_msg_list_t *linked_list_ptr) + * + * \brief Counts total message size of all messages in linked list + * + * \param const coap_send_msg_list_t *linked_list_ptr pointer to linked list + *****************************************************************************/ +static uint16_t sn_coap_count_linked_list_size(const coap_send_msg_list_t *linked_list_ptr) +{ + uint16_t total_size = 0; + + ns_list_foreach(coap_send_msg_s, stored_msg_ptr, linked_list_ptr) { + if (stored_msg_ptr->send_msg_ptr) { + total_size += stored_msg_ptr->send_msg_ptr->packet_len; + } + } + + return total_size; +} + +#endif + +#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */ + +/**************************************************************************//** + * \fn static int8_t sn_coap_handle_blockwise_message(void) + * + * \brief Handles all received blockwise messages + * + * \param *src_addr_ptr pointer to source address information struct + * \param *received_coap_msg_ptr pointer to parsed CoAP message structure + *****************************************************************************/ + +static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, sn_coap_hdr_s *received_coap_msg_ptr, void *param) +{ + tr_debug("sn_coap_handle_blockwise_message"); + sn_coap_hdr_s *src_coap_blockwise_ack_msg_ptr = NULL; + uint16_t dst_packed_data_needed_mem = 0; + uint8_t *dst_ack_packet_data_ptr = NULL; + uint8_t block_temp = 0; + + uint16_t original_payload_len = 0; + uint8_t *original_payload_ptr = NULL; + + /* Block1 Option in a request (e.g., PUT or POST) */ + // Blocked request sending, received ACK, sending next block.. + if (received_coap_msg_ptr->options_list_ptr->block1_ptr) { + tr_debug("sn_coap_handle_blockwise_message - block1, message code: [%d]", received_coap_msg_ptr->msg_code); + if (received_coap_msg_ptr->msg_code > COAP_MSG_CODE_REQUEST_DELETE) { + tr_debug("sn_coap_handle_blockwise_message - send block1 request"); + if (*(received_coap_msg_ptr->options_list_ptr->block1_ptr + (received_coap_msg_ptr->options_list_ptr->block1_len - 1)) & 0x08) { + coap_blockwise_msg_s *stored_blockwise_msg_temp_ptr = NULL; + + /* Get */ + ns_list_foreach(coap_blockwise_msg_s, msg, &handle->linked_list_blockwise_sent_msgs) { + if (msg->coap_msg_ptr && received_coap_msg_ptr->msg_id == msg->coap_msg_ptr->msg_id) { + stored_blockwise_msg_temp_ptr = msg; + break; + } + } + + if (stored_blockwise_msg_temp_ptr) { + /* Build response message */ + + uint16_t block_size = 1; + uint32_t block_number = 0; + + /* Get block option parameters from received message */ + if (received_coap_msg_ptr->options_list_ptr->block1_len == 3) { + block_number = *(received_coap_msg_ptr->options_list_ptr->block1_ptr) << 12; + block_number |= *(received_coap_msg_ptr->options_list_ptr->block1_ptr + 1) << 4; + block_number |= (*(received_coap_msg_ptr->options_list_ptr->block1_ptr + 2)) >> 4; + } + + else if (received_coap_msg_ptr->options_list_ptr->block1_len == 2) { + block_number = *(received_coap_msg_ptr->options_list_ptr->block1_ptr) << 4; + block_number |= (*(received_coap_msg_ptr->options_list_ptr->block1_ptr + 1)) >> 4; + } else if (received_coap_msg_ptr->options_list_ptr->block1_len == 1) { + block_number = (*received_coap_msg_ptr->options_list_ptr->block1_ptr) >> 4; + } + + block_temp = *(received_coap_msg_ptr->options_list_ptr->block1_ptr + (received_coap_msg_ptr->options_list_ptr->block1_len - 1)) & 0x07; + block_size = block_size << (block_temp + 4); + + /* Build next block message */ + src_coap_blockwise_ack_msg_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr; + + if (src_coap_blockwise_ack_msg_ptr->options_list_ptr) { + if (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr) { + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr); + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr = 0; + + } + if (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr) { + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr); + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr = 0; + } + } else { + if (!sn_coap_parser_alloc_options(handle, src_coap_blockwise_ack_msg_ptr)) { + sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr); + return 0; + } + } + + block_number++; + tr_debug("sn_coap_handle_blockwise_message - block1 request, next block number: [%d]", block_number); + if (block_number <= 0x0f) { + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_len = 1; + } else if (block_number <= 0x0fff) { + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_len = 2; + } else if (block_number <= 0x0fffff) { + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_len = 3; + } + + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr = handle->sn_coap_protocol_malloc(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_len); + + if (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr == 0) { + sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr); + return 0; + } + + *(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr + (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_len - 1)) = block_temp; + if (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_len == 3) { + *(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr + 2) = block_number << 4; + *(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr + 1) |= block_number >> 4; + *src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr |= block_number >> 12; + } else if (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_len == 2) { + *(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr + 1) |= block_number << 4; + *src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr |= block_number >> 4; + } else { + *src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr |= block_number << 4; + } + + original_payload_len = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len; + original_payload_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr; + + if ((block_size * (block_number + 1)) > stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len) { + src_coap_blockwise_ack_msg_ptr->payload_len = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len - (block_size * (block_number)); + src_coap_blockwise_ack_msg_ptr->payload_ptr = src_coap_blockwise_ack_msg_ptr->payload_ptr + (block_size * block_number); + } + + /* Not last block */ + else { + /* set more - bit */ + *(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr + (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_len - 1)) |= 0x08; + src_coap_blockwise_ack_msg_ptr->payload_len = block_size; + src_coap_blockwise_ack_msg_ptr->payload_ptr = src_coap_blockwise_ack_msg_ptr->payload_ptr + (block_size * block_number); + } + /* Build and send block message */ + dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size); + + dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem); + if (!dst_ack_packet_data_ptr) { + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr); + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr = 0; + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr); + src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0; + handle->sn_coap_protocol_free(original_payload_ptr); + original_payload_ptr = 0; + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr); + src_coap_blockwise_ack_msg_ptr = 0; + stored_blockwise_msg_temp_ptr->coap_msg_ptr = NULL; + sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr); + return NULL; + } + src_coap_blockwise_ack_msg_ptr->msg_id = message_id++; + if (message_id == 0) { + message_id = 1; + } + + sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size); + tr_debug("sn_coap_handle_blockwise_message - block1 request, send block msg id: [%d]", src_coap_blockwise_ack_msg_ptr->msg_id); + handle->sn_coap_tx_callback(dst_ack_packet_data_ptr, dst_packed_data_needed_mem, src_addr_ptr, param); + + handle->sn_coap_protocol_free(dst_ack_packet_data_ptr); + dst_ack_packet_data_ptr = 0; + + stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len = original_payload_len; + stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr = original_payload_ptr; + + received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_ACK; + } + } else { + // XXX what was this trying to free? + tr_debug("sn_coap_handle_blockwise_message - block1 request - last block sent"); + received_coap_msg_ptr->coap_status = COAP_STATUS_OK; + + } + } + + // Blocked request receiving + else { + tr_debug("sn_coap_handle_blockwise_message - block1 received"); + if (received_coap_msg_ptr->payload_len > handle->sn_coap_block_data_size) { + received_coap_msg_ptr->payload_len = handle->sn_coap_block_data_size; + } + + sn_coap_protocol_linked_list_blockwise_payload_store(handle, src_addr_ptr, received_coap_msg_ptr->payload_len, received_coap_msg_ptr->payload_ptr); + /* If not last block (more value is set) */ + /* Block option length can be 1-3 bytes. First 4-20 bits are for block number. Last 4 bits are ALWAYS more bit + block size. */ + if (*(received_coap_msg_ptr->options_list_ptr->block1_ptr + (received_coap_msg_ptr->options_list_ptr->block1_len - 1)) & 0x08) { + tr_debug("sn_coap_handle_blockwise_message - block1 received, send ack"); + src_coap_blockwise_ack_msg_ptr = sn_coap_parser_alloc_message(handle); + if (src_coap_blockwise_ack_msg_ptr == NULL) { + sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr); + return NULL; + } + + if (sn_coap_parser_alloc_options(handle, src_coap_blockwise_ack_msg_ptr) == NULL) { + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr); + src_coap_blockwise_ack_msg_ptr = 0; + sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr); + return NULL; + } + + // Response with COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE if the payload size is more than we can handle + uint32_t total_message_size = 0; + for(int i=0;i < received_coap_msg_ptr->options_list_ptr->size1_len; i++) { + total_message_size += (*(received_coap_msg_ptr->options_list_ptr->size1_ptr + i) & 0xff) << + 8*(received_coap_msg_ptr->options_list_ptr->size1_len- 1 - i); + } + + tr_debug("sn_coap_handle_blockwise_message - block1 received - incoming size: [%d]", total_message_size); + if (total_message_size > UINT16_MAX) { + src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE; + src_coap_blockwise_ack_msg_ptr->options_list_ptr->size1_ptr = handle->sn_coap_protocol_malloc(2); + if (src_coap_blockwise_ack_msg_ptr->options_list_ptr->size1_ptr) { + src_coap_blockwise_ack_msg_ptr->options_list_ptr->size1_ptr[0] = 0xff; + src_coap_blockwise_ack_msg_ptr->options_list_ptr->size1_ptr[1] = 0xff; + src_coap_blockwise_ack_msg_ptr->options_list_ptr->size1_len = 2; + } + } else if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_GET) { + src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT; + } else if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_POST) { + src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTINUE; + } else if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_PUT) { + src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTINUE; + } else if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_DELETE) { + src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_DELETED; + } + + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_len = received_coap_msg_ptr->options_list_ptr->block1_len; + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr = handle->sn_coap_protocol_malloc(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_len); + if (!src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr) { + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr); + src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0; + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr); + src_coap_blockwise_ack_msg_ptr = NULL; + return NULL; + } + + src_coap_blockwise_ack_msg_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + + memcpy(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr, received_coap_msg_ptr->options_list_ptr->block1_ptr, received_coap_msg_ptr->options_list_ptr->block1_len); + + /* Check block size */ + block_temp = (*(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr + (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_len - 1)) & 0x07); + if (block_temp > sn_coap_convert_block_size(handle->sn_coap_block_data_size)) { + *(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr + (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_len - 1)) &= 0xF8; + *(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr + (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_len - 1)) |= sn_coap_convert_block_size(handle->sn_coap_block_data_size); + } + + src_coap_blockwise_ack_msg_ptr->msg_id = received_coap_msg_ptr->msg_id; + + dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size); + + dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem); + if (!dst_ack_packet_data_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr); + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr); + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr = 0; + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr); + src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0; + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr); + src_coap_blockwise_ack_msg_ptr = 0; + return NULL; + } + + sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size); + tr_debug("sn_coap_handle_blockwise_message - block1 received - send msg id [%d]", src_coap_blockwise_ack_msg_ptr->msg_id); + handle->sn_coap_tx_callback(dst_ack_packet_data_ptr, dst_packed_data_needed_mem, src_addr_ptr, param); + + sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr); + handle->sn_coap_protocol_free(dst_ack_packet_data_ptr); + dst_ack_packet_data_ptr = 0; + + received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING; + + } else { + tr_debug("sn_coap_handle_blockwise_message - block1 received, last block received"); + /* * * This is the last block when whole Blockwise payload from received * * */ + /* * * blockwise messages is gathered and returned to User * * */ + + /* Store last Blockwise payload to Linked list */ + uint16_t payload_len = 0; + uint8_t *payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len); + uint32_t whole_payload_len = sn_coap_protocol_linked_list_blockwise_payloads_get_len(handle, src_addr_ptr); + uint8_t *temp_whole_payload_ptr = NULL; + + tr_debug("sn_coap_handle_blockwise_message - block1 received, whole_payload_len %d", whole_payload_len); + temp_whole_payload_ptr = handle->sn_coap_protocol_malloc(whole_payload_len); + if (temp_whole_payload_ptr == NULL || whole_payload_len > UINT16_MAX) { + tr_debug("sn_coap_handle_blockwise_message - block1 received, last block received alloc fails"); + sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr); + handle->sn_coap_protocol_free(temp_whole_payload_ptr); + return 0; + } + + // In block message case, payload_ptr freeing must be done in application level + received_coap_msg_ptr->payload_ptr = temp_whole_payload_ptr; + received_coap_msg_ptr->payload_len = whole_payload_len; + + /* Copy stored Blockwise payloads to returned whole Blockwise payload pointer */ + while (payload_ptr != NULL) { + memcpy(temp_whole_payload_ptr, payload_ptr, payload_len); + temp_whole_payload_ptr += payload_len; + sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(handle); + payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len); + } + received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + } + } + } + + + /* Block2 Option in a response (e.g., a 2.05 response for GET) */ + /* Message ID must be same than in received message */ + else { + tr_debug("sn_coap_handle_blockwise_message - block2 - message code: [%d]", received_coap_msg_ptr->msg_code); + //This is response to request we made + if (received_coap_msg_ptr->msg_code > COAP_MSG_CODE_REQUEST_DELETE) { + tr_debug("sn_coap_handle_blockwise_message - send block2 request"); + uint32_t block_number = 0; + + /* Store blockwise payload to Linked list */ + //todo: add block number to stored values - just to make sure all packets are in order + sn_coap_protocol_linked_list_blockwise_payload_store(handle, src_addr_ptr, received_coap_msg_ptr->payload_len, received_coap_msg_ptr->payload_ptr); + + /* If not last block (more value is set) */ + if (*(received_coap_msg_ptr->options_list_ptr->block2_ptr + (received_coap_msg_ptr->options_list_ptr->block2_len - 1)) & 0x08) { + coap_blockwise_msg_s *previous_blockwise_msg_ptr = NULL; + //build and send ack + received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING; + + ns_list_foreach(coap_blockwise_msg_s, msg, &handle->linked_list_blockwise_sent_msgs) { + if (received_coap_msg_ptr->msg_id == msg->coap_msg_ptr->msg_id) { + previous_blockwise_msg_ptr = msg; + break; + } + } + + if (!previous_blockwise_msg_ptr || !previous_blockwise_msg_ptr->coap_msg_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr); + return 0; + } + + src_coap_blockwise_ack_msg_ptr = sn_coap_parser_alloc_message(handle); + if (src_coap_blockwise_ack_msg_ptr == NULL) { + return 0; + } + + ns_list_remove(&handle->linked_list_blockwise_sent_msgs, previous_blockwise_msg_ptr); + if( previous_blockwise_msg_ptr->coap_msg_ptr ){ + if(previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr){ + handle->sn_coap_protocol_free(previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr); + previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr = 0; + } + sn_coap_parser_release_allocated_coap_msg_mem(handle, previous_blockwise_msg_ptr->coap_msg_ptr); + previous_blockwise_msg_ptr->coap_msg_ptr = 0; + } + handle->sn_coap_protocol_free(previous_blockwise_msg_ptr); + previous_blockwise_msg_ptr = 0; + +// if (src_coap_blockwise_ack_msg_ptr->payload_ptr) { + +// src_coap_blockwise_ack_msg_ptr->payload_ptr = 0; +// src_coap_blockwise_ack_msg_ptr->payload_len = 0; +// } + + /* * * Then build CoAP Acknowledgement message * * */ + + if (sn_coap_parser_alloc_options(handle, src_coap_blockwise_ack_msg_ptr) == NULL) { + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr); + src_coap_blockwise_ack_msg_ptr = 0; + sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr); + return NULL; + } + + src_coap_blockwise_ack_msg_ptr->msg_id = message_id++; + if (message_id == 0) { + message_id = 1; + } + +// if (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr) { +// handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr); +// src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr = 0; +// } + + /* Update block option */ + block_temp = *(received_coap_msg_ptr->options_list_ptr->block2_ptr + (received_coap_msg_ptr->options_list_ptr->block2_len - 1)) & 0x07; + + if (received_coap_msg_ptr->options_list_ptr->block2_len == 3) { + block_number = *(received_coap_msg_ptr->options_list_ptr->block2_ptr) << 12; + block_number |= *(received_coap_msg_ptr->options_list_ptr->block2_ptr + 1) << 4; + block_number |= (*(received_coap_msg_ptr->options_list_ptr->block2_ptr + 2)) >> 4; + } + + else if (received_coap_msg_ptr->options_list_ptr->block2_len == 2) { + block_number = *(received_coap_msg_ptr->options_list_ptr->block2_ptr) << 4; + block_number |= (*(received_coap_msg_ptr->options_list_ptr->block2_ptr + 1)) >> 4; + } else if (received_coap_msg_ptr->options_list_ptr->block2_len == 1) { + block_number = (*received_coap_msg_ptr->options_list_ptr->block2_ptr) >> 4; + } + + block_number ++; + + if (block_number <= 0x0f) { + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_len = 1; + } else if (block_number <= 0x0fff) { + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_len = 2; + } else if (block_number <= 0x0fffff) { + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_len = 3; + } + + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr = handle->sn_coap_protocol_malloc(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_len); + + if (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr == 0) { + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr); + src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0; + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr); + src_coap_blockwise_ack_msg_ptr = 0; + sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr); + return 0; + } + + *(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr + (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_len - 1)) = block_temp; + + if (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_len == 3) { + *(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr + 2) = block_number << 4; + *(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr + 1) |= block_number >> 4; + *src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr |= block_number >> 12; + } else if (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_len == 2) { + *(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr + 1) = block_number << 4; + *src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr |= block_number >> 4; + } else { + *src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr |= block_number << 4; + } + + /* Then get needed memory count for Packet data */ + dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_blockwise_ack_msg_ptr ,handle->sn_coap_block_data_size); + + /* Then allocate memory for Packet data */ + dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem); + + if (dst_ack_packet_data_ptr == NULL) { + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr); + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr = 0; + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr); + src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0; + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr); + src_coap_blockwise_ack_msg_ptr = 0; + sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr); + return NULL; + } + memset(dst_ack_packet_data_ptr, 0, dst_packed_data_needed_mem); + + /* * * Then build Acknowledgement message to Packed data * * */ + if ((sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size)) < 0) { + handle->sn_coap_protocol_free(dst_ack_packet_data_ptr); + dst_ack_packet_data_ptr = 0; + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr); + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr = 0; + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr); + src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0; + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr); + src_coap_blockwise_ack_msg_ptr = 0; + sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr); + return NULL; + } + + /* * * Save to linked list * * */ + coap_blockwise_msg_s *stored_blockwise_msg_ptr; + + stored_blockwise_msg_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_blockwise_msg_s)); + if (!stored_blockwise_msg_ptr) { + handle->sn_coap_protocol_free(dst_ack_packet_data_ptr); + dst_ack_packet_data_ptr = 0; + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr); + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr = 0; + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr); + src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0; + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr); + src_coap_blockwise_ack_msg_ptr = 0; + sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr); + return 0; + } + memset(stored_blockwise_msg_ptr, 0, sizeof(coap_blockwise_msg_s)); + + stored_blockwise_msg_ptr->timestamp = handle->system_time; + + stored_blockwise_msg_ptr->coap_msg_ptr = src_coap_blockwise_ack_msg_ptr; + stored_blockwise_msg_ptr->coap = handle; + + ns_list_add_to_end(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr); + + /* * * Then release memory of CoAP Acknowledgement message * * */ + handle->sn_coap_tx_callback(dst_ack_packet_data_ptr, + dst_packed_data_needed_mem, src_addr_ptr, param); + +#if ENABLE_RESENDINGS + sn_coap_protocol_linked_list_send_msg_store(handle, src_addr_ptr, + dst_packed_data_needed_mem, + dst_ack_packet_data_ptr, + handle->system_time + (uint32_t)(handle->sn_coap_resending_intervall * RESPONSE_RANDOM_FACTOR), param, NULL, 0); +#endif + handle->sn_coap_protocol_free(dst_ack_packet_data_ptr); + dst_ack_packet_data_ptr = 0; + } + + //Last block received + else { + /* * * This is the last block when whole Blockwise payload from received * * */ + /* * * blockwise messages is gathered and returned to User * * */ + + /* Store last Blockwise payload to Linked list */ + uint16_t payload_len = 0; + uint8_t *payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len); + uint16_t whole_payload_len = sn_coap_protocol_linked_list_blockwise_payloads_get_len(handle, src_addr_ptr); + uint8_t *temp_whole_payload_ptr = NULL; + + temp_whole_payload_ptr = handle->sn_coap_protocol_malloc(whole_payload_len); + if (!temp_whole_payload_ptr) { + return 0; + } + + received_coap_msg_ptr->payload_ptr = temp_whole_payload_ptr; + received_coap_msg_ptr->payload_len = whole_payload_len; + + /* Copy stored Blockwise payloads to returned whole Blockwise payload pointer */ + while (payload_ptr != NULL) { + memcpy(temp_whole_payload_ptr, payload_ptr, payload_len); + + temp_whole_payload_ptr += payload_len; + + sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(handle); + payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len); + } + received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + + //todo: remove previous msg from list + } + + } + + //Now we send data to request + else { + tr_debug("sn_coap_handle_blockwise_message - block2 received"); + //Get message by using block number + //NOTE: Getting the first from list might not be correct one + coap_blockwise_msg_s *stored_blockwise_msg_temp_ptr = ns_list_get_first(&handle->linked_list_blockwise_sent_msgs); + if (stored_blockwise_msg_temp_ptr) { + uint16_t block_size = 1; + uint32_t block_number = 0; + + /* Resolve block parameters */ + if (received_coap_msg_ptr->options_list_ptr->block2_len == 3) { + block_number = *(received_coap_msg_ptr->options_list_ptr->block2_ptr) << 12; + block_number |= *(received_coap_msg_ptr->options_list_ptr->block2_ptr + 1) << 4; + block_number |= (*(received_coap_msg_ptr->options_list_ptr->block2_ptr + 2)) >> 4; + } + + else if (received_coap_msg_ptr->options_list_ptr->block2_len == 2) { + block_number = *(received_coap_msg_ptr->options_list_ptr->block2_ptr) << 4; + block_number |= (*(received_coap_msg_ptr->options_list_ptr->block2_ptr + 1)) >> 4; + } else if (received_coap_msg_ptr->options_list_ptr->block2_len == 1) { + block_number = (*received_coap_msg_ptr->options_list_ptr->block2_ptr) >> 4; + } + + block_temp = *(received_coap_msg_ptr->options_list_ptr->block2_ptr + (received_coap_msg_ptr->options_list_ptr->block2_len - 1)) & 0x07; + block_size = block_size << (block_temp + 4); + + /* Build response message */ + src_coap_blockwise_ack_msg_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr; + + if (src_coap_blockwise_ack_msg_ptr->options_list_ptr) { + if (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr) { + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr); + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1_ptr = 0; + + } + if (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr) { + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr); + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr = 0; + } + } else { + if (sn_coap_parser_alloc_options(handle, src_coap_blockwise_ack_msg_ptr) == NULL) { + return 0; + } + } + + src_coap_blockwise_ack_msg_ptr->msg_id = received_coap_msg_ptr->msg_id; + + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_len = received_coap_msg_ptr->options_list_ptr->block2_len; + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr = handle->sn_coap_protocol_malloc(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_len); + + if (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr == NULL) { + if(src_coap_blockwise_ack_msg_ptr->payload_ptr){ + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->payload_ptr); + } + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr); + src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0; + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr); + stored_blockwise_msg_temp_ptr->coap_msg_ptr = NULL; + src_coap_blockwise_ack_msg_ptr = 0; + return NULL; + } + memcpy(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr, received_coap_msg_ptr->options_list_ptr->block2_ptr, src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_len); + + /* * Payload part * */ + + /* Check if last block */ + + original_payload_len = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len; + original_payload_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr; + + if ((block_size * (block_number + 1)) > stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len) { + src_coap_blockwise_ack_msg_ptr->payload_len = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len - (block_size * block_number); + src_coap_blockwise_ack_msg_ptr->payload_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr + (block_size * block_number); + } + /* Not last block */ + else { + /* set more - bit */ + *(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr + (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_len - 1)) |= 0x08; + src_coap_blockwise_ack_msg_ptr->payload_len = block_size; + src_coap_blockwise_ack_msg_ptr->payload_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr + (block_size * block_number); + } + + /* Build and send block message */ + dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size); + + dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem); + if (!dst_ack_packet_data_ptr) { + if(original_payload_ptr){ + handle->sn_coap_protocol_free(original_payload_ptr); + original_payload_ptr = NULL; + } + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr); + src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2_ptr = 0; + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr); + src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0; + handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr); + stored_blockwise_msg_temp_ptr->coap_msg_ptr = NULL; + return NULL; + } + + sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size); + tr_debug("sn_coap_handle_blockwise_message - block2 received, send message: [%d]", src_coap_blockwise_ack_msg_ptr->msg_id); + handle->sn_coap_tx_callback(dst_ack_packet_data_ptr, dst_packed_data_needed_mem, src_addr_ptr, param); + + handle->sn_coap_protocol_free(dst_ack_packet_data_ptr); + dst_ack_packet_data_ptr = 0; + + stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len = original_payload_len; + stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr = original_payload_ptr; + + if ((block_size * (block_number + 1)) > stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len) { + sn_coap_protocol_linked_list_blockwise_msg_remove(handle, stored_blockwise_msg_temp_ptr); + } + + received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_ACK; + } + } + } + return received_coap_msg_ptr; +} + +static int8_t sn_coap_convert_block_size(uint16_t block_size) +{ + if (block_size == 16) { + return 0; + } else if (block_size == 32) { + return 1; + } else if (block_size == 64) { + return 2; + } else if (block_size == 128) { + return 3; + } else if (block_size == 256) { + return 4; + } else if (block_size == 512) { + return 5; + } else if (block_size == 1024) { + return 6; + } + + return 0; +} + +static sn_coap_hdr_s *sn_coap_protocol_copy_header(struct coap_s *handle, sn_coap_hdr_s *source_header_ptr) +{ + sn_coap_hdr_s *destination_header_ptr; + + destination_header_ptr = sn_coap_parser_alloc_message(handle); + if (!destination_header_ptr) { + return 0; + } + + destination_header_ptr->coap_status = source_header_ptr->coap_status; + destination_header_ptr->msg_type = source_header_ptr->msg_type; + destination_header_ptr->msg_code = source_header_ptr->msg_code; + destination_header_ptr->msg_id = source_header_ptr->msg_id; + + if (source_header_ptr->uri_path_ptr) { + destination_header_ptr->uri_path_len = source_header_ptr->uri_path_len; + destination_header_ptr->uri_path_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->uri_path_len); + if (!destination_header_ptr->uri_path_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); + return 0; + } + memcpy(destination_header_ptr->uri_path_ptr, source_header_ptr->uri_path_ptr, source_header_ptr->uri_path_len); + } + + if (source_header_ptr->token_ptr) { + destination_header_ptr->token_len = source_header_ptr->token_len; + destination_header_ptr->token_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->token_len); + if (!destination_header_ptr->token_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); + return 0; + } + memcpy(destination_header_ptr->token_ptr, source_header_ptr->token_ptr, source_header_ptr->token_len); + } + + if (source_header_ptr->content_type_ptr) { + destination_header_ptr->content_type_len = source_header_ptr->content_type_len; + destination_header_ptr->content_type_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->content_type_len); + if (!destination_header_ptr->content_type_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); + return 0; + } + memcpy(destination_header_ptr->content_type_ptr, source_header_ptr->content_type_ptr, source_header_ptr->content_type_len); + } + + /* Options list */ + if (source_header_ptr->options_list_ptr) { + if (sn_coap_parser_alloc_options(handle, destination_header_ptr) == NULL) { + sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); + return 0; + } + + if (source_header_ptr->options_list_ptr->max_age_ptr) { + destination_header_ptr->options_list_ptr->max_age_len = source_header_ptr->options_list_ptr->max_age_len; + destination_header_ptr->options_list_ptr->max_age_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->max_age_len); + if (!destination_header_ptr->options_list_ptr->max_age_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); + return 0; + } + memcpy(destination_header_ptr->options_list_ptr->max_age_ptr, source_header_ptr->options_list_ptr->max_age_ptr, source_header_ptr->options_list_ptr->max_age_len); + } + + if (source_header_ptr->options_list_ptr->proxy_uri_ptr) { + destination_header_ptr->options_list_ptr->proxy_uri_len = source_header_ptr->options_list_ptr->proxy_uri_len; + destination_header_ptr->options_list_ptr->proxy_uri_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->proxy_uri_len); + if (!destination_header_ptr->options_list_ptr->proxy_uri_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); + return 0; + } + memcpy(destination_header_ptr->options_list_ptr->proxy_uri_ptr, source_header_ptr->options_list_ptr->proxy_uri_ptr, source_header_ptr->options_list_ptr->proxy_uri_len); + } + + if (source_header_ptr->options_list_ptr->etag_ptr) { + destination_header_ptr->options_list_ptr->etag_len = source_header_ptr->options_list_ptr->etag_len; + destination_header_ptr->options_list_ptr->etag_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->etag_len); + if (!destination_header_ptr->options_list_ptr->etag_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); + return 0; + } + memcpy(destination_header_ptr->options_list_ptr->etag_ptr, source_header_ptr->options_list_ptr->etag_ptr, source_header_ptr->options_list_ptr->etag_len); + } + + if (source_header_ptr->options_list_ptr->uri_host_ptr) { + destination_header_ptr->options_list_ptr->uri_host_len = source_header_ptr->options_list_ptr->uri_host_len; + destination_header_ptr->options_list_ptr->uri_host_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->uri_host_len); + if (!destination_header_ptr->options_list_ptr->uri_host_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); + return 0; + } + memcpy(destination_header_ptr->options_list_ptr->uri_host_ptr, source_header_ptr->options_list_ptr->uri_host_ptr, source_header_ptr->options_list_ptr->uri_host_len); + } + + if (source_header_ptr->options_list_ptr->location_path_ptr) { + destination_header_ptr->options_list_ptr->location_path_len = source_header_ptr->options_list_ptr->location_path_len; + destination_header_ptr->options_list_ptr->location_path_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->location_path_len); + if (!destination_header_ptr->options_list_ptr->location_path_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); + return 0; + } + memcpy(destination_header_ptr->options_list_ptr->location_path_ptr, source_header_ptr->options_list_ptr->location_path_ptr, source_header_ptr->options_list_ptr->location_path_len); + } + + if (source_header_ptr->options_list_ptr->uri_port_ptr) { + destination_header_ptr->options_list_ptr->uri_port_len = source_header_ptr->options_list_ptr->uri_port_len; + destination_header_ptr->options_list_ptr->uri_port_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->uri_port_len); + if (!destination_header_ptr->options_list_ptr->uri_port_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); + return 0; + } + memcpy(destination_header_ptr->options_list_ptr->uri_port_ptr, source_header_ptr->options_list_ptr->uri_port_ptr, source_header_ptr->options_list_ptr->uri_port_len); + } + + if (source_header_ptr->options_list_ptr->location_query_ptr) { + destination_header_ptr->options_list_ptr->location_query_len = source_header_ptr->options_list_ptr->location_query_len; + destination_header_ptr->options_list_ptr->location_query_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->location_query_len); + if (!destination_header_ptr->options_list_ptr->location_query_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); + return 0; + } + memcpy(destination_header_ptr->options_list_ptr->location_query_ptr, source_header_ptr->options_list_ptr->location_query_ptr, source_header_ptr->options_list_ptr->location_query_len); + } + + destination_header_ptr->options_list_ptr->observe = source_header_ptr->options_list_ptr->observe; + + if (source_header_ptr->options_list_ptr->observe_ptr) { + destination_header_ptr->options_list_ptr->observe_len = source_header_ptr->options_list_ptr->observe_len; + destination_header_ptr->options_list_ptr->observe_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->observe_len); + if (!destination_header_ptr->options_list_ptr->observe_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); + return 0; + } + memcpy(destination_header_ptr->options_list_ptr->observe_ptr, source_header_ptr->options_list_ptr->observe_ptr, source_header_ptr->options_list_ptr->observe_len); + } + + if (source_header_ptr->options_list_ptr->accept_ptr) { + destination_header_ptr->options_list_ptr->accept_len = source_header_ptr->options_list_ptr->accept_len; + destination_header_ptr->options_list_ptr->accept_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->accept_len); + if (!destination_header_ptr->options_list_ptr->accept_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); + return 0; + } + memcpy(destination_header_ptr->options_list_ptr->accept_ptr, source_header_ptr->options_list_ptr->accept_ptr, source_header_ptr->options_list_ptr->accept_len); + } + + if (source_header_ptr->options_list_ptr->uri_query_ptr) { + destination_header_ptr->options_list_ptr->uri_query_len = source_header_ptr->options_list_ptr->uri_query_len; + destination_header_ptr->options_list_ptr->uri_query_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->uri_query_len); + if (!destination_header_ptr->options_list_ptr->uri_query_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); + return 0; + } + memcpy(destination_header_ptr->options_list_ptr->uri_query_ptr, source_header_ptr->options_list_ptr->uri_query_ptr, source_header_ptr->options_list_ptr->uri_query_len); + } + + if (source_header_ptr->options_list_ptr->block1_ptr) { + destination_header_ptr->options_list_ptr->block1_len = source_header_ptr->options_list_ptr->block1_len; + destination_header_ptr->options_list_ptr->block1_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->block1_len); + if (!destination_header_ptr->options_list_ptr->block1_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); + return 0; + } + memcpy(destination_header_ptr->options_list_ptr->block1_ptr, source_header_ptr->options_list_ptr->block1_ptr, source_header_ptr->options_list_ptr->block1_len); + } + + if (source_header_ptr->options_list_ptr->block2_ptr) { + destination_header_ptr->options_list_ptr->block2_len = source_header_ptr->options_list_ptr->block2_len; + destination_header_ptr->options_list_ptr->block2_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->block2_len); + if (!destination_header_ptr->options_list_ptr->block2_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr); + return 0; + } + memcpy(destination_header_ptr->options_list_ptr->block2_ptr, source_header_ptr->options_list_ptr->block2_ptr, source_header_ptr->options_list_ptr->block2_len); + } + } + + return destination_header_ptr; +} +#endif diff --git a/features/FEATURE_CLIENT/mbed-client-c/source/libNsdl/src/include/sn_grs.h b/features/FEATURE_CLIENT/mbed-client-c/source/libNsdl/src/include/sn_grs.h new file mode 100755 index 0000000000..dd7e508179 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/source/libNsdl/src/include/sn_grs.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2011-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 GRS_H_ +#define GRS_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define SN_GRS_RESOURCE_ALREADY_EXISTS -2 +#define SN_GRS_INVALID_PATH -3 +#define SN_GRS_LIST_ADDING_FAILURE -4 +#define SN_GRS_RESOURCE_UPDATED -5 + +#define ACCESS_DENIED -6 + +#define SN_GRS_DELETE_METHOD 0 +#define SN_GRS_SEARCH_METHOD 1 + +#define SN_GRS_DEFAULT_ACCESS 0x0F + +#define SN_NDSL_RESOURCE_NOT_REGISTERED 0 +#define SN_NDSL_RESOURCE_REGISTERING 1 +#define SN_NDSL_RESOURCE_REGISTERED 2 + +/***** Structs *****/ + +typedef struct sn_grs_version_ { + uint8_t major_version; + uint8_t minor_version; + uint8_t build; +} sn_grs_version_s; + +typedef NS_LIST_HEAD(sn_nsdl_resource_info_s, link) resource_list_t; + +struct grs_s { + struct coap_s *coap; + + uint16_t resource_root_count; + resource_list_t resource_root_list; + + void *(*sn_grs_alloc)(uint16_t); + void (*sn_grs_free)(void *); + uint8_t (*sn_grs_tx_callback)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *); + int8_t (*sn_grs_rx_callback)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *); +}; + + +struct nsdl_s { + struct grs_s *grs; + + uint8_t *oma_bs_address_ptr; /* Bootstrap address pointer. If null, no bootstrap in use */ + uint8_t oma_bs_address_len; /* Bootstrap address length */ + uint16_t oma_bs_port; /* Bootstrap port */ + void (*sn_nsdl_oma_bs_done_cb)(sn_nsdl_oma_server_info_t *server_info_ptr); /* Callback to inform application when bootstrap is done */ + sn_nsdl_ep_parameters_s *ep_information_ptr; // Endpoint parameters, Name, Domain etc.. + sn_nsdl_oma_server_info_t *nsp_address_ptr; // NSP server address information + uint8_t sn_nsdl_endpoint_registered; + + uint16_t register_msg_id; + uint16_t unregister_msg_id; + + void *(*sn_nsdl_alloc)(uint16_t); + void (*sn_nsdl_free)(void *); + uint8_t (*sn_nsdl_tx_callback)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *); + uint8_t (*sn_nsdl_rx_callback)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *); + void (*sn_nsdl_oma_bs_done_cb_handle)(sn_nsdl_oma_server_info_t *server_info_ptr, + struct nsdl_s *handle); /* Callback to inform application when bootstrap is done with nsdl handle */ + uint16_t update_register_msg_id; + uint16_t register_msg_len; + uint16_t update_register_msg_len; + uint16_t bootstrap_msg_id; + bool handle_bootstrap_msg; +}; + +/***** Function prototypes *****/ +/** + * \fn extern grs_s *sn_grs_init (uint8_t (*sn_grs_tx_callback_ptr)(sn_nsdl_capab_e , uint8_t *, uint16_t, + * sn_nsdl_addr_s *), uint8_t (*sn_grs_rx_callback_ptr)(sn_coap_hdr_s *, sn_nsdl_addr_s *), + * sn_grs_mem_s *sn_memory) + * + * \brief GRS library initialize function. + * + * This function initializes GRS and CoAP. + * + * \param sn_grs_tx_callback A function pointer to a transmit callback function. Should return 1 when succeed, 0 when failed + * \param *sn_grs_rx_callback_ptr A function pointer to a receiving callback function. If received packet is not for GRS, it will be passed to + * upper level (NSDL) to be proceed. + * \param sn_memory A pointer to a structure containing the platform specific functions for memory allocation and free. + * + * \return success pointer to handle, failure = NULL + * +*/ +extern struct grs_s *sn_grs_init(uint8_t (*sn_grs_tx_callback_ptr)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, + sn_nsdl_addr_s *), int8_t (*sn_grs_rx_callback_ptr)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *), void *(*sn_grs_alloc)(uint16_t), void (*sn_grs_free)(void *)); + +extern const sn_nsdl_resource_info_s *sn_grs_get_first_resource(struct grs_s *handle); +extern const sn_nsdl_resource_info_s *sn_grs_get_next_resource(struct grs_s *handle, const sn_nsdl_resource_info_s *sn_grs_current_resource); +extern int8_t sn_grs_process_coap(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *src); +extern sn_nsdl_resource_info_s *sn_grs_search_resource(struct grs_s *handle, uint16_t pathlen, uint8_t *path, uint8_t search_method); +extern int8_t sn_grs_destroy(struct grs_s *handle); +extern sn_grs_resource_list_s *sn_grs_list_resource(struct grs_s *handle, uint16_t pathlen, uint8_t *path); +extern void sn_grs_free_resource_list(struct grs_s *handle, sn_grs_resource_list_s *list); +extern int8_t sn_grs_update_resource(struct grs_s *handle, sn_nsdl_resource_info_s *res); +extern int8_t sn_grs_send_coap_message(struct nsdl_s *handle, sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr); +extern int8_t sn_grs_create_resource(struct grs_s *handle, sn_nsdl_resource_info_s *res); +extern int8_t sn_grs_delete_resource(struct grs_s *handle, uint16_t pathlen, uint8_t *path); +extern void sn_grs_mark_resources_as_registered(struct nsdl_s *handle); + +#ifdef __cplusplus +} +#endif + + + + +#endif /* GRS_H_ */ diff --git a/features/FEATURE_CLIENT/mbed-client-c/source/libNsdl/src/sn_grs.c b/features/FEATURE_CLIENT/mbed-client-c/source/libNsdl/src/sn_grs.c new file mode 100755 index 0000000000..7c868b2e40 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/source/libNsdl/src/sn_grs.c @@ -0,0 +1,1027 @@ +/* + * Copyright (c) 2011-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 sn_grs.c + * + * \brief General resource server. + * + */ +#include +#include + +#include "ns_list.h" +#include "ns_types.h" +#include "sn_nsdl.h" +#include "sn_coap_header.h" +#include "sn_coap_protocol.h" +#include "sn_coap_protocol_internal.h" +#include "sn_nsdl_lib.h" +#include "sn_grs.h" +#include "mbed-trace/mbed_trace.h" + +/* Defines */ +#define TRACE_GROUP "coap" +#define WELLKNOWN_PATH_LEN 16 +#define WELLKNOWN_PATH (".well-known/core") + +/* Local static function prototypes */ +static int8_t sn_grs_resource_info_free(struct grs_s *handle, sn_nsdl_resource_info_s *resource_ptr); +static uint8_t *sn_grs_convert_uri(uint16_t *uri_len, uint8_t *uri_ptr); +static int8_t sn_grs_add_resource_to_list(struct grs_s *handle, sn_nsdl_resource_info_s *resource_ptr); +static int8_t sn_grs_core_request(struct nsdl_s *handle, sn_nsdl_addr_s *src_addr_ptr, sn_coap_hdr_s *coap_packet_ptr); +static uint8_t coap_tx_callback(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *); +static int8_t coap_rx_callback(sn_coap_hdr_s *coap_ptr, sn_nsdl_addr_s *address_ptr, void *param); + +/* Extern function prototypes */ +extern int8_t sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration); + +/** + * \fn int8_t sn_grs_destroy(void) + * \brief This function may be used to flush GRS related stuff when a program exits. + * @return always 0. + */ +extern int8_t sn_grs_destroy(struct grs_s *handle) +{ + if( handle == NULL ){ + return 0; + } + ns_list_foreach_safe(sn_nsdl_resource_info_s, tmp, &handle->resource_root_list) { + ns_list_remove(&handle->resource_root_list, tmp); + --handle->resource_root_count; + sn_grs_resource_info_free(handle, tmp); + } + handle->sn_grs_free(handle); + + return 0; +} + +static uint8_t coap_tx_callback(uint8_t *data_ptr, uint16_t data_len, sn_nsdl_addr_s *address_ptr, void *param) +{ + struct nsdl_s *handle = (struct nsdl_s *)param; + + if (handle == NULL) { + return 0; + } + + return handle->grs->sn_grs_tx_callback(handle, SN_NSDL_PROTOCOL_COAP, data_ptr, data_len, address_ptr); +} + +static int8_t coap_rx_callback(sn_coap_hdr_s *coap_ptr, sn_nsdl_addr_s *address_ptr, void *param) +{ + struct nsdl_s *handle = (struct nsdl_s *)param; + + if (handle == NULL) { + return 0; + } + + return handle->sn_nsdl_rx_callback(handle, coap_ptr, address_ptr); +} + +/** + * \fn int8_t sn_grs_init (uint8_t (*sn_grs_tx_callback_ptr)(sn_nsdl_capab_e , uint8_t *, uint16_t, + * sn_nsdl_addr_s *), int8_t (*sn_grs_rx_callback_ptr)(sn_coap_hdr_s *, sn_nsdl_addr_s *), sn_nsdl_mem_s *sn_memory) + * + * \brief GRS library initialize function. + * + * This function initializes GRS and CoAP libraries. + * + * \param sn_grs_tx_callback A function pointer to a transmit callback function. + * \param *sn_grs_rx_callback_ptr A function pointer to a receiving callback function. If received packet is not for GRS, it will be passed to + * upper level (NSDL) to be proceed. + * \param sn_memory A pointer to a structure containing the platform specific functions for memory allocation and free. + * + * \return success = 0, failure = -1 + * +*/ +extern struct grs_s *sn_grs_init(uint8_t (*sn_grs_tx_callback_ptr)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, + sn_nsdl_addr_s *), int8_t (*sn_grs_rx_callback_ptr)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *), + void *(*sn_grs_alloc)(uint16_t), void (*sn_grs_free)(void *)) +{ + + struct grs_s *handle_ptr = NULL; + + /* Check parameters */ + if (sn_grs_alloc == NULL || sn_grs_free == NULL || + sn_grs_tx_callback_ptr == NULL || sn_grs_rx_callback_ptr == NULL) { + return NULL; + } + + handle_ptr = sn_grs_alloc(sizeof(struct grs_s)); + + if (handle_ptr == NULL) { + return NULL; + } + + memset(handle_ptr, 0, sizeof(struct grs_s)); + + /* Allocation and free - function pointers */ + handle_ptr->sn_grs_alloc = sn_grs_alloc; + handle_ptr->sn_grs_free = sn_grs_free; + + /* TX callback function pointer */ + handle_ptr->sn_grs_tx_callback = sn_grs_tx_callback_ptr; + handle_ptr->sn_grs_rx_callback = sn_grs_rx_callback_ptr; + + /* Initialize CoAP protocol library */ + handle_ptr->coap = sn_coap_protocol_init(sn_grs_alloc, sn_grs_free, coap_tx_callback, coap_rx_callback); + + return handle_ptr; +} + + +extern sn_grs_resource_list_s *sn_grs_list_resource(struct grs_s *handle, uint16_t pathlen, uint8_t *path) +{ + (void) pathlen; + sn_grs_resource_list_s *grs_resource_list_ptr = NULL; + + if( handle == NULL || path == NULL){ + return NULL; + } + + /* Allocate memory for the resource list to be filled */ + grs_resource_list_ptr = handle->sn_grs_alloc(sizeof(sn_grs_resource_list_s)); + if (!grs_resource_list_ptr) { + goto fail; + } + + /* Count resources to the resource list struct */ + grs_resource_list_ptr->res_count = handle->resource_root_count; + grs_resource_list_ptr->res = NULL; + + /**************************************/ + /* Fill resource structs to the table */ + /**************************************/ + + /* If resources in list */ + if (grs_resource_list_ptr->res_count) { + int i; + + /* Allocate memory for resources */ + grs_resource_list_ptr->res = handle->sn_grs_alloc(grs_resource_list_ptr->res_count * sizeof(sn_grs_resource_s)); + if (!grs_resource_list_ptr->res) { + goto fail; + } + + /* Initialise the pointers to NULL to permit easy cleanup */ + for (i = 0; i < grs_resource_list_ptr->res_count; i++) { + grs_resource_list_ptr->res[i].path = NULL; + grs_resource_list_ptr->res[i].pathlen = 0; + } + + i = 0; + ns_list_foreach(sn_nsdl_resource_info_s, grs_resource_ptr, &handle->resource_root_list) { + /* Copy pathlen to resource list */ + grs_resource_list_ptr->res[i].pathlen = grs_resource_ptr->pathlen; + + /* Allocate memory for path string */ + grs_resource_list_ptr->res[i].path = handle->sn_grs_alloc(grs_resource_list_ptr->res[i].pathlen); + if (!grs_resource_list_ptr->res[i].path) { + goto fail; + } + + /* Copy pathstring to resource list */ + memcpy(grs_resource_list_ptr->res[i].path, grs_resource_ptr->path, grs_resource_ptr->pathlen); + + i++; + } + } + return grs_resource_list_ptr; + +fail: + sn_grs_free_resource_list(handle, grs_resource_list_ptr); + return NULL; +} + +extern void sn_grs_free_resource_list(struct grs_s *handle, sn_grs_resource_list_s *list) +{ + if (!list || !handle) { + return; + } + + if (list->res) { + for (int i = 0; i < list->res_count; i++) { + if (list->res[i].path) { + handle->sn_grs_free(list->res[i].path); + list->res[i].path = NULL; + } + } + handle->sn_grs_free(list->res); + list->res = NULL; + } + + handle->sn_grs_free(list); +} + +extern const sn_nsdl_resource_info_s *sn_grs_get_first_resource(struct grs_s *handle) +{ + if( !handle ){ + return NULL; + } + return ns_list_get_first(&handle->resource_root_list); +} + +extern const sn_nsdl_resource_info_s *sn_grs_get_next_resource(struct grs_s *handle, const sn_nsdl_resource_info_s *sn_grs_current_resource) +{ + if( !handle || !sn_grs_current_resource ){ + return NULL; + } + return ns_list_get_next(&handle->resource_root_list, sn_grs_current_resource); +} + +extern int8_t sn_grs_delete_resource(struct grs_s *handle, uint16_t pathlen, uint8_t *path) +{ + /* Local variables */ + sn_nsdl_resource_info_s *resource_temp = NULL; + + /* Search if resource found */ + resource_temp = sn_grs_search_resource(handle, pathlen, path, SN_GRS_SEARCH_METHOD); + + /* If not found */ + if (resource_temp == NULL) { + return SN_NSDL_FAILURE; + } + + /* If found, delete it and delete also subresources, if there is any */ + do { + /* Remove from list */ + ns_list_remove(&handle->resource_root_list, resource_temp); + --handle->resource_root_count; + + /* Free */ + sn_grs_resource_info_free(handle, resource_temp); + + /* Search for subresources */ + resource_temp = sn_grs_search_resource(handle, pathlen, path, SN_GRS_DELETE_METHOD); + } while (resource_temp != NULL); + + return SN_NSDL_SUCCESS; +} + +extern int8_t sn_grs_update_resource(struct grs_s *handle, sn_nsdl_resource_info_s *res) +{ + /* Local variables */ + sn_nsdl_resource_info_s *resource_temp = NULL; + + if( !res || !handle ){ + return SN_NSDL_FAILURE; + } + + /* Search resource */ + resource_temp = sn_grs_search_resource(handle, res->pathlen, res->path, SN_GRS_SEARCH_METHOD); + if (!resource_temp) { + return SN_NSDL_FAILURE; + } + + /* If there is payload on resource, free it */ + if (resource_temp->resource != NULL) { + handle->sn_grs_free(resource_temp->resource); + resource_temp->resource = 0; + } + /* Update resource len */ + resource_temp->resourcelen = res->resourcelen; + + /* If resource len >0, allocate memory and copy payload */ + if (res->resourcelen) { + resource_temp->resource = handle->sn_grs_alloc(res->resourcelen); + if (resource_temp->resource == NULL) { + + resource_temp->resourcelen = 0; + return SN_NSDL_FAILURE; + + } + + memcpy(resource_temp->resource, res->resource, resource_temp->resourcelen); + } + + /* Update access rights and callback address */ + resource_temp->access = res->access; + resource_temp->sn_grs_dyn_res_callback = res->sn_grs_dyn_res_callback; + + /* TODO: resource_parameters_ptr not copied */ + + return SN_NSDL_SUCCESS; +} + +extern int8_t sn_grs_create_resource(struct grs_s *handle, sn_nsdl_resource_info_s *res) +{ + if (!res || !handle) { + return SN_NSDL_FAILURE; + } + + /* Check path validity */ + if (!res->pathlen || !res->path) { + return SN_GRS_INVALID_PATH; + } + + /* Check if resource already exists */ + if (sn_grs_search_resource(handle, res->pathlen, res->path, SN_GRS_SEARCH_METHOD) != (sn_nsdl_resource_info_s *)NULL) { + return SN_GRS_RESOURCE_ALREADY_EXISTS; + } + + if (res->resource_parameters_ptr) { + res->resource_parameters_ptr->registered = SN_NDSL_RESOURCE_NOT_REGISTERED; + } + + /* Create resource */ + if (sn_grs_add_resource_to_list(handle, res) == SN_NSDL_SUCCESS) { + return SN_NSDL_SUCCESS; + } + return SN_GRS_LIST_ADDING_FAILURE; +} + + + +/** + * \fn extern int8_t sn_grs_process_coap(uint8_t *packet, uint16_t *packet_len, sn_nsdl_addr_s *src) + * + * \brief To push CoAP packet to GRS library + * + * Used to push an CoAP packet to GRS library for processing. + * + * \param *packet Pointer to a uint8_t array containing the packet (including the CoAP headers). + * After successful execution this array may contain the response packet. + * + * \param *packet_len Pointer to length of the packet. After successful execution this array may contain the length + * of the response packet. + * + * \param *src Pointer to packet source address information. After successful execution this array may contain + * the destination address of the response packet. + * + * \return 0 = success, -1 = failure +*/ +extern int8_t sn_grs_process_coap(struct nsdl_s *nsdl_handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *src_addr_ptr) +{ + if( !coap_packet_ptr || !nsdl_handle){ + return SN_NSDL_FAILURE; + } + + sn_nsdl_resource_info_s *resource_temp_ptr = NULL; + sn_coap_msg_code_e status = COAP_MSG_CODE_EMPTY; + sn_coap_hdr_s *response_message_hdr_ptr = NULL; + struct grs_s *handle = nsdl_handle->grs; + bool static_get_request = false; + + if (coap_packet_ptr->msg_code <= COAP_MSG_CODE_REQUEST_DELETE) { + /* Check if .well-known/core */ + if (coap_packet_ptr->uri_path_len == WELLKNOWN_PATH_LEN && memcmp(coap_packet_ptr->uri_path_ptr, WELLKNOWN_PATH, WELLKNOWN_PATH_LEN) == 0) { + return sn_grs_core_request(nsdl_handle, src_addr_ptr, coap_packet_ptr); + } + + /* Get resource */ + resource_temp_ptr = sn_grs_search_resource(handle, coap_packet_ptr->uri_path_len, coap_packet_ptr->uri_path_ptr, SN_GRS_SEARCH_METHOD); + + /* * * * * * * * * * * */ + /* If resource exists */ + /* * * * * * * * * * * */ + if (resource_temp_ptr) { + /* If dynamic resource, go to callback */ + if (resource_temp_ptr->mode == SN_GRS_DYNAMIC) { + /* Check accesses */ + if (((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_GET) && !(resource_temp_ptr->access & SN_GRS_GET_ALLOWED)) || + ((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_POST) && !(resource_temp_ptr->access & SN_GRS_POST_ALLOWED)) || + ((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_PUT) && !(resource_temp_ptr->access & SN_GRS_PUT_ALLOWED)) || + ((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_DELETE) && !(resource_temp_ptr->access & SN_GRS_DELETE_ALLOWED))) { + + status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } else { + /* Do not call null pointer.. */ + if (resource_temp_ptr->sn_grs_dyn_res_callback != NULL) { + resource_temp_ptr->sn_grs_dyn_res_callback(nsdl_handle, coap_packet_ptr, src_addr_ptr, SN_NSDL_PROTOCOL_COAP); + } + + if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) { + handle->sn_grs_free(coap_packet_ptr->payload_ptr); + coap_packet_ptr->payload_ptr = 0; + } + sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr); + return SN_NSDL_SUCCESS; + } + } else { + /* Static resource handling */ + switch (coap_packet_ptr->msg_code) { + case (COAP_MSG_CODE_REQUEST_GET): + if (resource_temp_ptr->access & SN_GRS_GET_ALLOWED) { + status = COAP_MSG_CODE_RESPONSE_CONTENT; + static_get_request = true; + } else { + status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + break; + case (COAP_MSG_CODE_REQUEST_POST): + if (resource_temp_ptr->access & SN_GRS_POST_ALLOWED) { + resource_temp_ptr->resourcelen = coap_packet_ptr->payload_len; + handle->sn_grs_free(resource_temp_ptr->resource); + resource_temp_ptr->resource = 0; + if (resource_temp_ptr->resourcelen) { + resource_temp_ptr->resource = handle->sn_grs_alloc(resource_temp_ptr->resourcelen); + if (!resource_temp_ptr->resource) { + status = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; + break; + } + memcpy(resource_temp_ptr->resource, coap_packet_ptr->payload_ptr, resource_temp_ptr->resourcelen); + } + if (coap_packet_ptr->content_type_ptr) { + if (resource_temp_ptr->resource_parameters_ptr) { + resource_temp_ptr->resource_parameters_ptr->coap_content_type = *coap_packet_ptr->content_type_ptr; + } + } + status = COAP_MSG_CODE_RESPONSE_CHANGED; + } else { + status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + break; + case (COAP_MSG_CODE_REQUEST_PUT): + if (resource_temp_ptr->access & SN_GRS_PUT_ALLOWED) { + resource_temp_ptr->resourcelen = coap_packet_ptr->payload_len; + handle->sn_grs_free(resource_temp_ptr->resource); + resource_temp_ptr->resource = 0; + if (resource_temp_ptr->resourcelen) { + resource_temp_ptr->resource = handle->sn_grs_alloc(resource_temp_ptr->resourcelen); + if (!resource_temp_ptr->resource) { + status = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; + break; + } + memcpy(resource_temp_ptr->resource, coap_packet_ptr->payload_ptr, resource_temp_ptr->resourcelen); + } + if (coap_packet_ptr->content_type_ptr) { + if (resource_temp_ptr->resource_parameters_ptr) { + resource_temp_ptr->resource_parameters_ptr->coap_content_type = *coap_packet_ptr->content_type_ptr; + } + } + status = COAP_MSG_CODE_RESPONSE_CHANGED; + } else { + status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + break; + + case (COAP_MSG_CODE_REQUEST_DELETE): + if (resource_temp_ptr->access & SN_GRS_DELETE_ALLOWED) { + if (sn_grs_delete_resource(handle, coap_packet_ptr->uri_path_len, coap_packet_ptr->uri_path_ptr) == SN_NSDL_SUCCESS) { + status = COAP_MSG_CODE_RESPONSE_DELETED; + } else { + //This is dead code (Currently only time delete fails is when resource is not found + //and sn_grs_search_resource is used with same arguments above!) + status = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; + } + } else { + status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + break; + + default: + status = COAP_MSG_CODE_RESPONSE_FORBIDDEN; + break; + } + } + } + + /* * * * * * * * * * * * * * */ + /* If resource was not found */ + /* * * * * * * * * * * * * * */ + + else { + if (coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_POST) { + handle->sn_grs_rx_callback(nsdl_handle, coap_packet_ptr, src_addr_ptr); + + if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) { + handle->sn_grs_free(coap_packet_ptr->payload_ptr); + coap_packet_ptr->payload_ptr = 0; + } + + sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr); + return SN_NSDL_SUCCESS; + } else { + status = COAP_MSG_CODE_RESPONSE_NOT_FOUND; + } + } + + } + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + /* If received packed was other than reset, create response */ + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + if (coap_packet_ptr->msg_type != COAP_MSG_TYPE_RESET && coap_packet_ptr->msg_type != COAP_MSG_TYPE_ACKNOWLEDGEMENT) { + + /* Allocate resopnse message */ + response_message_hdr_ptr = sn_coap_parser_alloc_message(handle->coap); + if (!response_message_hdr_ptr) { + if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) { + handle->sn_grs_free(coap_packet_ptr->payload_ptr); + coap_packet_ptr->payload_ptr = 0; + } + sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr); + return SN_NSDL_FAILURE; + } + + /* If status has not been defined, response internal server error */ + if (status == COAP_MSG_CODE_EMPTY) { + status = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; + } + + /* Fill header */ + response_message_hdr_ptr->msg_code = status; + + if (coap_packet_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) { + response_message_hdr_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + } else { + response_message_hdr_ptr->msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE; + } + + response_message_hdr_ptr->msg_id = coap_packet_ptr->msg_id; + + if (coap_packet_ptr->token_ptr) { + response_message_hdr_ptr->token_len = coap_packet_ptr->token_len; + response_message_hdr_ptr->token_ptr = handle->sn_grs_alloc(response_message_hdr_ptr->token_len); + if (!response_message_hdr_ptr->token_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response_message_hdr_ptr); + + if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) { + handle->sn_grs_free(coap_packet_ptr->payload_ptr); + coap_packet_ptr->payload_ptr = 0; + } + + sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr); + return SN_NSDL_FAILURE; + } + memcpy(response_message_hdr_ptr->token_ptr, coap_packet_ptr->token_ptr, response_message_hdr_ptr->token_len); + } + + if (status == COAP_MSG_CODE_RESPONSE_CONTENT) { + /* Add content type if other than default */ + if (resource_temp_ptr->resource_parameters_ptr) { + if (resource_temp_ptr->resource_parameters_ptr->coap_content_type != 0) { + response_message_hdr_ptr->content_type_len = 1; + response_message_hdr_ptr->content_type_ptr = handle->sn_grs_alloc(response_message_hdr_ptr->content_type_len); + if (!response_message_hdr_ptr->content_type_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response_message_hdr_ptr); + + if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) { + handle->sn_grs_free(coap_packet_ptr->payload_ptr); + coap_packet_ptr->payload_ptr = 0; + } + + sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr); + return SN_NSDL_FAILURE; + } + memcpy(response_message_hdr_ptr->content_type_ptr, &resource_temp_ptr->resource_parameters_ptr->coap_content_type, response_message_hdr_ptr->content_type_len); + } + } + + /* Add payload */ + if (resource_temp_ptr->resourcelen != 0) { + response_message_hdr_ptr->payload_len = resource_temp_ptr->resourcelen; + response_message_hdr_ptr->payload_ptr = handle->sn_grs_alloc(response_message_hdr_ptr->payload_len); + + if (!response_message_hdr_ptr->payload_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response_message_hdr_ptr); + + if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) { + handle->sn_grs_free(coap_packet_ptr->payload_ptr); + coap_packet_ptr->payload_ptr = 0; + } + + sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr); + return SN_NSDL_FAILURE; + } + + memcpy(response_message_hdr_ptr->payload_ptr, resource_temp_ptr->resource, response_message_hdr_ptr->payload_len); + } + // Add max-age attribute for static resources. + // Not a mandatory parameter, no need to return in case of memory allocation fails. + if (static_get_request) { + if (sn_coap_parser_alloc_options(handle->coap, response_message_hdr_ptr)) { + response_message_hdr_ptr->options_list_ptr->max_age_ptr = handle->sn_grs_alloc(1); + if (response_message_hdr_ptr->options_list_ptr->max_age_ptr) { + response_message_hdr_ptr->options_list_ptr->max_age_ptr[0] = 0; + response_message_hdr_ptr->options_list_ptr->max_age_len = 1; + } + } + } + } + sn_grs_send_coap_message(nsdl_handle, src_addr_ptr, response_message_hdr_ptr); + + if (response_message_hdr_ptr->payload_ptr) { + handle->sn_grs_free(response_message_hdr_ptr->payload_ptr); + response_message_hdr_ptr->payload_ptr = 0; + } + sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response_message_hdr_ptr); + } + + /* Free parsed CoAP message */ + if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) { + handle->sn_grs_free(coap_packet_ptr->payload_ptr); + coap_packet_ptr->payload_ptr = 0; + } + sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr); + + + return SN_NSDL_SUCCESS; +} + +extern int8_t sn_grs_send_coap_message(struct nsdl_s *handle, sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr) +{ + tr_debug("sn_grs_send_coap_message"); + uint8_t *message_ptr = NULL; + uint16_t message_len = 0; + uint8_t ret_val = 0; + + if( !handle ){ + return SN_NSDL_FAILURE; + } + + /* Calculate message length */ + message_len = sn_coap_builder_calc_needed_packet_data_size_2(coap_hdr_ptr, handle->grs->coap->sn_coap_block_data_size); + tr_debug("sn_grs_send_coap_message - msg len after calc: [%d]", message_len); + tr_debug("sn_grs_send_coap_message - msg id: [%d]", coap_hdr_ptr->msg_id); + + /* Allocate memory for message and check was allocating successfully */ + message_ptr = handle->grs->sn_grs_alloc(message_len); + if (message_ptr == NULL) { + return SN_NSDL_FAILURE; + } + + /* Build CoAP message */ + if (sn_coap_protocol_build(handle->grs->coap, address_ptr, message_ptr, coap_hdr_ptr, (void *)handle) < 0) { + handle->grs->sn_grs_free(message_ptr); + message_ptr = 0; + return SN_NSDL_FAILURE; + } + + /* Call tx callback function to send message */ + ret_val = handle->grs->sn_grs_tx_callback(handle, SN_NSDL_PROTOCOL_COAP, message_ptr, message_len, address_ptr); + + /* Free allocated memory */ + handle->grs->sn_grs_free(message_ptr); + message_ptr = 0; + + if (ret_val == 0) { + return SN_NSDL_FAILURE; + } else { + return SN_NSDL_SUCCESS; + } +} + +static int8_t sn_grs_core_request(struct nsdl_s *handle, sn_nsdl_addr_s *src_addr_ptr, sn_coap_hdr_s *coap_packet_ptr) +{ + sn_coap_hdr_s *response_message_hdr_ptr = NULL; + sn_coap_content_format_e wellknown_content_format = COAP_CT_LINK_FORMAT; + + /* Allocate response message */ + response_message_hdr_ptr = sn_coap_parser_alloc_message(handle->grs->coap); + if (response_message_hdr_ptr == NULL) { + if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) { + handle->grs->sn_grs_free(coap_packet_ptr->payload_ptr); + coap_packet_ptr->payload_ptr = 0; + } + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + return SN_NSDL_FAILURE; + } + + /* Build response */ + response_message_hdr_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT; + response_message_hdr_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + response_message_hdr_ptr->msg_id = coap_packet_ptr->msg_id; + response_message_hdr_ptr->content_type_len = 1; + response_message_hdr_ptr->content_type_ptr = handle->grs->sn_grs_alloc(1); + if (!response_message_hdr_ptr->content_type_ptr) { + if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) { + handle->grs->sn_grs_free(coap_packet_ptr->payload_ptr); + coap_packet_ptr->payload_ptr = 0; + } + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + handle->grs->sn_grs_free(response_message_hdr_ptr); + return SN_NSDL_FAILURE; + } + + *response_message_hdr_ptr->content_type_ptr = wellknown_content_format; + + sn_nsdl_build_registration_body(handle, response_message_hdr_ptr, 0); + + /* Send and free */ + sn_grs_send_coap_message(handle, src_addr_ptr, response_message_hdr_ptr); + + if (response_message_hdr_ptr->payload_ptr) { + handle->grs->sn_grs_free(response_message_hdr_ptr->payload_ptr); + response_message_hdr_ptr->payload_ptr = 0; + } + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, response_message_hdr_ptr); + + /* Free parsed CoAP message */ + if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) { + handle->grs->sn_grs_free(coap_packet_ptr->payload_ptr); + coap_packet_ptr->payload_ptr = 0; + } + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + + return SN_NSDL_SUCCESS; +} + +/** + * \fn static sn_grs_resource_info_s *sn_grs_search_resource(uint16_t pathlen, uint8_t *path, uint8_t search_method) + * + * \brief Searches given resource from linked list + * + * Search either precise path, or subresources, eg. dr/x -> returns dr/x/1, dr/x/2 etc... + * + * \param pathlen Length of the path to be search + * + * \param *path Pointer to the path string to be search + * + * \param search_method Search method, SEARCH or DELETE + * + * \return Pointer to the resource. If resource not found, return value is NULL + * +*/ + +sn_nsdl_resource_info_s *sn_grs_search_resource(struct grs_s *handle, uint16_t pathlen, uint8_t *path, uint8_t search_method) +{ + + /* Local variables */ + uint8_t *path_temp_ptr = NULL; + /* Check parameters */ + if (!handle || !pathlen || !path) { + return NULL; + } + + /* Remove '/' - marks from the end and beginning */ + path_temp_ptr = sn_grs_convert_uri(&pathlen, path); + + /* Searchs exact path */ + if (search_method == SN_GRS_SEARCH_METHOD) { + /* Scan all nodes on list */ + ns_list_foreach(sn_nsdl_resource_info_s, resource_search_temp, &handle->resource_root_list) { + /* If length equals.. */ + if (resource_search_temp->pathlen == pathlen) { + /* Compare paths, If same return node pointer*/ + if (0 == memcmp(resource_search_temp->path, path_temp_ptr, pathlen)) { + return resource_search_temp; + } + } + } + } + /* Search also subresources, eg. dr/x -> returns dr/x/1, dr/x/2 etc... */ + else if (search_method == SN_GRS_DELETE_METHOD) { + /* Scan all nodes on list */ + ns_list_foreach(sn_nsdl_resource_info_s, resource_search_temp, &handle->resource_root_list) { + uint8_t *temp_path = resource_search_temp->path; + if (resource_search_temp->pathlen > pathlen && + (*(temp_path + (uint8_t)pathlen) == '/') && + 0 == memcmp(resource_search_temp->path, path_temp_ptr, pathlen)) { + return resource_search_temp; + } + } + } + + /* If there was not nodes we wanted, return NULL */ + return NULL; +} + + +/** + * \fn static int8_t sn_grs_add_resource_to_list(sn_grs_resource_info_s *resource_ptr) + * + * \brief Adds given resource to resource list + * + * \param *resource_ptr Pointer to the path string to be search + * + * \return 0 = SN_NSDL_SUCCESS, -1 = SN_NSDL_FAILURE + * +*/ +static int8_t sn_grs_add_resource_to_list(struct grs_s *handle, sn_nsdl_resource_info_s *resource_ptr) +{ + /* Local variables */ + uint8_t *path_start_ptr = NULL; + uint16_t path_len = 0; + sn_nsdl_resource_info_s *resource_copy_ptr = NULL; + + /* Allocate memory for the resource info copy */ + if (!resource_ptr->pathlen) { //Dead code + return SN_NSDL_FAILURE; + } + resource_copy_ptr = handle->sn_grs_alloc(sizeof(sn_nsdl_resource_info_s)); + if (resource_copy_ptr == NULL) { + return SN_NSDL_FAILURE; + } + + /* Set everything to zero */ + memset(resource_copy_ptr, 0, sizeof(sn_nsdl_resource_info_s)); + + resource_copy_ptr->mode = resource_ptr->mode; + resource_copy_ptr->resourcelen = resource_ptr->resourcelen; + resource_copy_ptr->sn_grs_dyn_res_callback = resource_ptr->sn_grs_dyn_res_callback; + resource_copy_ptr->access = resource_ptr->access; + resource_copy_ptr->publish_uri = resource_ptr->publish_uri; + + /* Remove '/' - chars from the beginning and from the end */ + + path_len = resource_ptr->pathlen; + path_start_ptr = sn_grs_convert_uri(&path_len, resource_ptr->path); + + /* Allocate memory for the path */ + resource_copy_ptr->path = handle->sn_grs_alloc(path_len); + if (!resource_copy_ptr->path) { + sn_grs_resource_info_free(handle, resource_copy_ptr); + return SN_NSDL_FAILURE; + } + + /* Update pathlen */ + resource_copy_ptr->pathlen = path_len; + + /* Copy path string to the copy */ + memcpy(resource_copy_ptr->path, path_start_ptr, resource_copy_ptr->pathlen); + + /* Allocate memory for the resource, and copy it to copy */ + if (resource_ptr->resource) { + resource_copy_ptr->resource = handle->sn_grs_alloc(resource_ptr->resourcelen); + if (!resource_copy_ptr->resource) { + sn_grs_resource_info_free(handle, resource_copy_ptr); + return SN_NSDL_FAILURE; + } + memcpy(resource_copy_ptr->resource, resource_ptr->resource, resource_ptr->resourcelen); + } + + + + /* If resource parameters exists, copy them */ + if (resource_ptr->resource_parameters_ptr) { + resource_copy_ptr->resource_parameters_ptr = handle->sn_grs_alloc(sizeof(sn_nsdl_resource_parameters_s)); + if (!resource_copy_ptr->resource_parameters_ptr) { + sn_grs_resource_info_free(handle, resource_copy_ptr); + return SN_NSDL_FAILURE; + } + + memset(resource_copy_ptr->resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s)); + + + resource_copy_ptr->resource_parameters_ptr->resource_type_len = resource_ptr->resource_parameters_ptr->resource_type_len; + + resource_copy_ptr->resource_parameters_ptr->interface_description_len = resource_ptr->resource_parameters_ptr->interface_description_len; + + resource_copy_ptr->resource_parameters_ptr->mime_content_type = resource_ptr->resource_parameters_ptr->mime_content_type; + + resource_copy_ptr->resource_parameters_ptr->observable = resource_ptr->resource_parameters_ptr->observable; + + if (resource_ptr->resource_parameters_ptr->resource_type_ptr) { + resource_copy_ptr->resource_parameters_ptr->resource_type_ptr = handle->sn_grs_alloc(resource_ptr->resource_parameters_ptr->resource_type_len); + if (!resource_copy_ptr->resource_parameters_ptr->resource_type_ptr) { + sn_grs_resource_info_free(handle, resource_copy_ptr); + return SN_NSDL_FAILURE; + } + memcpy(resource_copy_ptr->resource_parameters_ptr->resource_type_ptr, resource_ptr->resource_parameters_ptr->resource_type_ptr, resource_ptr->resource_parameters_ptr->resource_type_len); + } + + if (resource_ptr->resource_parameters_ptr->interface_description_ptr) { + resource_copy_ptr->resource_parameters_ptr->interface_description_ptr = handle->sn_grs_alloc(resource_ptr->resource_parameters_ptr->interface_description_len); + if (!resource_copy_ptr->resource_parameters_ptr->interface_description_ptr) { + sn_grs_resource_info_free(handle, resource_copy_ptr); + return SN_NSDL_FAILURE; + } + memcpy(resource_copy_ptr->resource_parameters_ptr->interface_description_ptr, resource_ptr->resource_parameters_ptr->interface_description_ptr, resource_ptr->resource_parameters_ptr->interface_description_len); + } + + /* Copy auto observation parameter */ + /* todo: aobs not supported ATM - needs fixing */ + /* if(resource_ptr->resource_parameters_ptr->auto_obs_ptr && resource_ptr->resource_parameters_ptr->auto_obs_len) + { + resource_copy_ptr->resource_parameters_ptr->auto_obs_ptr = sn_grs_alloc(resource_ptr->resource_parameters_ptr->auto_obs_len); + if(!resource_copy_ptr->resource_parameters_ptr->auto_obs_ptr) + { + sn_grs_resource_info_free(resource_copy_ptr); + return SN_NSDL_FAILURE; + } + memcpy(resource_copy_ptr->resource_parameters_ptr->auto_obs_ptr, resource_ptr->resource_parameters_ptr->auto_obs_ptr, resource_ptr->resource_parameters_ptr->auto_obs_len); + resource_copy_ptr->resource_parameters_ptr->auto_obs_len = resource_ptr->resource_parameters_ptr->auto_obs_len; + } + + resource_copy_ptr->resource_parameters_ptr->coap_content_type = resource_ptr->resource_parameters_ptr->coap_content_type; + */ + } + + /* Add copied resource to the linked list */ + ns_list_add_to_start(&handle->resource_root_list, resource_copy_ptr); + ++handle->resource_root_count; + + return SN_NSDL_SUCCESS; +} + + +/** + * \fn static uint8_t *sn_grs_convert_uri(uint16_t *uri_len, uint8_t *uri_ptr) + * + * \brief Removes '/' from the beginning and from the end of uri string + * + * \param *uri_len Pointer to the length of the path string + * + * \param *uri_ptr Pointer to the path string + * + * \return start pointer of the uri + * +*/ + +static uint8_t *sn_grs_convert_uri(uint16_t *uri_len, uint8_t *uri_ptr) +{ + /* Local variables */ + uint8_t *uri_start_ptr = uri_ptr; + + /* If '/' in the beginning, update uri start pointer and uri len */ + if (*uri_ptr == '/') { + uri_start_ptr = uri_ptr + 1; + *uri_len = *uri_len - 1; + } + + /* If '/' at the end, update uri len */ + if (*(uri_start_ptr + *uri_len - 1) == '/') { + *uri_len = *uri_len - 1; + } + + /* Return start pointer */ + return uri_start_ptr; +} + +/** + * \fn static int8_t sn_grs_resource_info_free(sn_grs_resource_info_s *resource_ptr) + * + * \brief Frees resource info structure + * + * \param *resource_ptr Pointer to the resource + * + * \return 0 if success, -1 if failed + * +*/ +static int8_t sn_grs_resource_info_free(struct grs_s *handle, sn_nsdl_resource_info_s *resource_ptr) +{ + if (resource_ptr) { + if (resource_ptr->resource_parameters_ptr) { + if (resource_ptr->resource_parameters_ptr->interface_description_ptr) { + handle->sn_grs_free(resource_ptr->resource_parameters_ptr->interface_description_ptr); + resource_ptr->resource_parameters_ptr->interface_description_ptr = 0; + } + + if (resource_ptr->resource_parameters_ptr->resource_type_ptr) { + handle->sn_grs_free(resource_ptr->resource_parameters_ptr->resource_type_ptr); + resource_ptr->resource_parameters_ptr->resource_type_ptr = 0; + } + + /* Todo: aobs not supported ATM - needs fixing */ + /* + if(resource_ptr->resource_parameters_ptr->auto_obs_ptr) + { + sn_grs_free(resource_ptr->resource_parameters_ptr->auto_obs_ptr); + resource_ptr->resource_parameters_ptr->auto_obs_ptr = 0; + } + */ + + handle->sn_grs_free(resource_ptr->resource_parameters_ptr); + resource_ptr->resource_parameters_ptr = 0; + } + + if (resource_ptr->path) { + handle->sn_grs_free(resource_ptr->path); + resource_ptr->path = 0; + } + if (resource_ptr->resource) { + handle->sn_grs_free(resource_ptr->resource); + resource_ptr->resource = 0; + } + handle->sn_grs_free(resource_ptr); + + return SN_NSDL_SUCCESS; + } + return SN_NSDL_FAILURE; //Dead code? +} + +void sn_grs_mark_resources_as_registered(struct nsdl_s *handle) +{ + if( !handle ){ + return; + } + + const sn_nsdl_resource_info_s *temp_resource; + + temp_resource = sn_grs_get_first_resource(handle->grs); + + while (temp_resource) { + if (temp_resource->resource_parameters_ptr) { + if (temp_resource->resource_parameters_ptr->registered == SN_NDSL_RESOURCE_REGISTERING) { + temp_resource->resource_parameters_ptr->registered = SN_NDSL_RESOURCE_REGISTERED; + } + } + temp_resource = sn_grs_get_next_resource(handle->grs, temp_resource); + } +} diff --git a/features/FEATURE_CLIENT/mbed-client-c/source/libNsdl/src/sn_nsdl.c b/features/FEATURE_CLIENT/mbed-client-c/source/libNsdl/src/sn_nsdl.c new file mode 100755 index 0000000000..3827500fd6 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/source/libNsdl/src/sn_nsdl.c @@ -0,0 +1,2532 @@ +/* + * Copyright (c) 2011-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 sn_nsdl.c + * + * \brief Nano service device library + * + */ + +#include + +#include "ns_types.h" +#include "sn_nsdl.h" +#include "sn_coap_header.h" +#include "sn_coap_protocol.h" +#include "sn_coap_protocol_internal.h" +#include "sn_nsdl_lib.h" +#include "sn_grs.h" +#include "mbed-trace/mbed_trace.h" + +#define TRACE_GROUP "coap" +/* Defines */ +#define TRACE_GROUP "coap" +#define RESOURCE_DIR_LEN 2 +#define EP_NAME_PARAMETERS_LEN 3 +#define ET_PARAMETER_LEN 3 +#define LT_PARAMETER_LEN 3 +#define DOMAIN_PARAMETER_LEN 2 +#define RT_PARAMETER_LEN 3 +#define IF_PARAMETER_LEN 3 +#define OBS_PARAMETER_LEN 3 +#define AOBS_PARAMETER_LEN 8 +#define COAP_CON_PARAMETER_LEN 3 +#define BS_EP_PARAMETER_LEN 3 +#define BS_QUEUE_MODE_PARAMATER_LEN 2 + +#define SN_NSDL_EP_REGISTER_MESSAGE 1 +#define SN_NSDL_EP_UPDATE_MESSAGE 2 + +#define SN_NSDL_MSG_UNDEFINED 0 +#define SN_NSDL_MSG_REGISTER 1 +#define SN_NSDL_MSG_UNREGISTER 2 +#define SN_NSDL_MSG_UPDATE 3 +#define SN_NSDL_MSG_BOOTSTRAP 4 + +#ifdef YOTTA_CFG_DISABLE_OBS_FEATURE +#define COAP_DISABLE_OBS_FEATURE YOTTA_CFG_DISABLE_OBS_FEATURE +#elif defined MBED_CONF_MBED_CLIENT_COAP_DISABLE_OBS_FEATURE +#define COAP_DISABLE_OBS_FEATURE MBED_CONF_MBED_CLIENT_COAP_DISABLE_OBS_FEATURE +#endif + +#ifdef YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE +#define MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE +#elif defined MBED_CONF_MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +#define MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE MBED_CONF_MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +#endif + + +/* Constants */ +static uint8_t ep_name_parameter_string[] = {'e', 'p', '='}; /* Endpoint name. A unique name for the registering node in a domain. */ +static uint8_t resource_path_ptr[] = {'r', 'd'}; /* For resource directory */ +static uint8_t resource_type_parameter[] = {'r', 't', '='}; /* Resource type. Only once for registration */ +#ifndef COAP_DISABLE_OBS_FEATURE +static uint8_t obs_parameter[] = {'o', 'b', 's'}; /* Observable */ +#endif +//static uint8_t aobs_parameter[] = {'a','o','b','s',';','i','d','='}; /* Auto-observable - TBD */ +static uint8_t if_description_parameter[] = {'i', 'f', '='}; /* Interface description. Only once */ +static uint8_t ep_lifetime_parameter[] = {'l', 't', '='}; /* Lifetime. Number of seconds that this registration will be valid for. Must be updated within this time, or will be removed. */ +static uint8_t ep_domain_parameter[] = {'d', '='}; /* Domain name. If this parameter is missing, a default domain is assumed. */ +static uint8_t coap_con_type_parameter[] = {'c', 't', '='}; /* CoAP content type */ +/* * OMA BS parameters * */ +static uint8_t bs_uri[] = {'b', 's'}; +static uint8_t bs_ep_name[] = {'e', 'p', '='}; +static uint8_t et_parameter[] = {'e', 't', '='}; /* Endpoint type */ +static uint8_t bs_queue_mode[] = {'b', '='}; + +/* Function prototypes */ +static uint16_t sn_nsdl_internal_coap_send(struct nsdl_s *handle, sn_coap_hdr_s *coap_header_ptr, sn_nsdl_addr_s *dst_addr_ptr, uint8_t message_description); +static void sn_nsdl_resolve_nsp_address(struct nsdl_s *handle); +int8_t sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration); +static uint16_t sn_nsdl_calculate_registration_body_size(struct nsdl_s *handle, uint8_t updating_registeration, int8_t *error); +static uint8_t sn_nsdl_calculate_uri_query_option_len(sn_nsdl_ep_parameters_s *endpoint_info_ptr, uint8_t msg_type); +static int8_t sn_nsdl_fill_uri_query_options(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *parameter_ptr, sn_coap_hdr_s *source_msg_ptr, uint8_t msg_type); +static int8_t sn_nsdl_local_rx_function(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *address_ptr); +static int8_t sn_nsdl_resolve_ep_information(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr); +static uint8_t sn_nsdl_itoa_len(uint8_t value); +static uint8_t *sn_nsdl_itoa(uint8_t *ptr, uint8_t value); +static int32_t sn_nsdl_atoi(uint8_t *ptr, uint8_t len); +static uint32_t sn_nsdl_ahextoi(uint8_t *ptr, uint8_t len); +static int8_t sn_nsdl_resolve_lwm2m_address(struct nsdl_s *handle, uint8_t *uri, uint16_t uri_len); +static int8_t sn_nsdl_process_oma_tlv(struct nsdl_s *handle, uint8_t *data_ptr, uint16_t data_len); +static void sn_nsdl_check_oma_bs_status(struct nsdl_s *handle); +static int8_t sn_nsdl_create_oma_device_object_base(struct nsdl_s *handle, sn_nsdl_oma_device_t *oma_device_setup_ptr, sn_nsdl_oma_binding_and_mode_t binding_and_mode); +static int8_t set_endpoint_info(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr); +static bool validateParameters(sn_nsdl_ep_parameters_s *parameter_ptr); +static bool validate(uint8_t* ptr, uint32_t len, char illegalChar); +static bool sn_nsdl_check_uint_overflow(uint16_t resource_size, uint16_t param_a, uint16_t param_b); + +int8_t sn_nsdl_destroy(struct nsdl_s *handle) +{ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + + if (handle->ep_information_ptr) { + if (handle->ep_information_ptr->endpoint_name_ptr) { + handle->sn_nsdl_free(handle->ep_information_ptr->endpoint_name_ptr); + handle->ep_information_ptr->endpoint_name_ptr = 0; + } + if (handle->ep_information_ptr->domain_name_ptr) { + handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr); + handle->ep_information_ptr->domain_name_ptr = 0; + handle->ep_information_ptr->domain_name_len = 0; + } + if (handle->ep_information_ptr->location_ptr) { + handle->sn_nsdl_free(handle->ep_information_ptr->location_ptr); + handle->ep_information_ptr->location_ptr = 0; + handle->ep_information_ptr->location_len = 0; + } + if (handle->ep_information_ptr->type_ptr) { + handle->sn_nsdl_free(handle->ep_information_ptr->type_ptr); + handle->ep_information_ptr->type_ptr = 0; + } + + if (handle->ep_information_ptr->lifetime_ptr) + + { + handle->sn_nsdl_free(handle->ep_information_ptr->lifetime_ptr); + handle->ep_information_ptr->lifetime_ptr = 0; + } + + handle->sn_nsdl_free(handle->ep_information_ptr); + handle->ep_information_ptr = 0; + } + + if (handle->nsp_address_ptr) { + if (handle->nsp_address_ptr->omalw_address_ptr) { + if (handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { + handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr); + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = 0; + } + handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr); + } + + handle->sn_nsdl_free(handle->nsp_address_ptr); + handle->nsp_address_ptr = 0; + } + + if (handle->oma_bs_address_ptr) { + handle->sn_nsdl_free(handle->oma_bs_address_ptr); + } + + /* Destroy also libCoap and grs part of libNsdl */ + sn_coap_protocol_destroy(handle->grs->coap); + sn_grs_destroy(handle->grs); + handle->sn_nsdl_free(handle); + + return SN_NSDL_SUCCESS; +} + +struct nsdl_s *sn_nsdl_init(uint8_t (*sn_nsdl_tx_cb)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *), + uint8_t (*sn_nsdl_rx_cb)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *), + void *(*sn_nsdl_alloc)(uint16_t), void (*sn_nsdl_free)(void *)) +{ + /* Check pointers and define function pointers */ + if (!sn_nsdl_alloc || !sn_nsdl_free || !sn_nsdl_tx_cb || !sn_nsdl_rx_cb) { + return NULL; + } + + struct nsdl_s *handle = NULL; + + handle = sn_nsdl_alloc(sizeof(struct nsdl_s)); + + if (handle == NULL) { + return NULL; + } + + memset(handle, 0, sizeof(struct nsdl_s)); + + /* Define function pointers */ + handle->sn_nsdl_alloc = sn_nsdl_alloc; + handle->sn_nsdl_free = sn_nsdl_free; + + handle->sn_nsdl_tx_callback = sn_nsdl_tx_cb; + handle->sn_nsdl_rx_callback = sn_nsdl_rx_cb; + + /* Initialize ep parameters struct */ + if (!handle->ep_information_ptr) { + handle->ep_information_ptr = handle->sn_nsdl_alloc(sizeof(sn_nsdl_ep_parameters_s)); + if (!handle->ep_information_ptr) { + sn_nsdl_free(handle); + return NULL; + } + memset(handle->ep_information_ptr, 0, sizeof(sn_nsdl_ep_parameters_s)); + } + + handle->grs = sn_grs_init(sn_nsdl_tx_cb, &sn_nsdl_local_rx_function, sn_nsdl_alloc, sn_nsdl_free); + + /* Initialize GRS */ + if (handle->grs == NULL) { + handle->sn_nsdl_free(handle->ep_information_ptr); + handle->ep_information_ptr = 0; + sn_nsdl_free(handle); + return NULL; + } + + sn_nsdl_resolve_nsp_address(handle); + + handle->sn_nsdl_endpoint_registered = SN_NSDL_ENDPOINT_NOT_REGISTERED; + // By default bootstrap msgs are handled in nsdl + handle->handle_bootstrap_msg = true; + return handle; +} + +uint16_t sn_nsdl_register_endpoint(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr) +{ + /* Local variables */ + sn_coap_hdr_s *register_message_ptr; + uint16_t message_id = 0; + + if (endpoint_info_ptr == NULL || handle == NULL) { + return 0; + } + + /*** Build endpoint register message ***/ + + /* Allocate memory for header struct */ + register_message_ptr = sn_coap_parser_alloc_message(handle->grs->coap); + if (register_message_ptr == NULL) { + return 0; + } + + /* Fill message fields -> confirmable post to specified NSP path */ + register_message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + register_message_ptr->msg_code = COAP_MSG_CODE_REQUEST_POST; + + /* Allocate memory for the extended options list */ + if (sn_coap_parser_alloc_options(handle->grs->coap, register_message_ptr) == NULL) { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); + register_message_ptr = 0; + return 0; + } + + register_message_ptr->uri_path_len = sizeof(resource_path_ptr); + register_message_ptr->uri_path_ptr = resource_path_ptr; + + /* Fill Uri-query options */ + if( SN_NSDL_FAILURE == sn_nsdl_fill_uri_query_options(handle, endpoint_info_ptr, + register_message_ptr, SN_NSDL_EP_REGISTER_MESSAGE) ){ + register_message_ptr->uri_path_ptr = NULL; + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); + return 0; + } + + if (endpoint_info_ptr->ds_register_mode == REGISTER_WITH_RESOURCES) { + /* Built body for message */ + if (sn_nsdl_build_registration_body(handle, register_message_ptr, 0) == SN_NSDL_FAILURE) { + register_message_ptr->uri_path_ptr = NULL; + register_message_ptr->options_list_ptr->uri_host_ptr = NULL; + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); + return 0; + } + } + + /* Clean (possible) existing and save new endpoint info to handle */ + if (set_endpoint_info(handle, endpoint_info_ptr) == -1) { + if (register_message_ptr->payload_ptr) { + handle->sn_nsdl_free(register_message_ptr->payload_ptr); + register_message_ptr->payload_ptr = NULL; + } + + register_message_ptr->uri_path_ptr = NULL; + register_message_ptr->options_list_ptr->uri_host_ptr = NULL; + + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); + + return 0; + } + + /* Build and send coap message to NSP */ + message_id = sn_nsdl_internal_coap_send(handle, register_message_ptr, handle->nsp_address_ptr->omalw_address_ptr, SN_NSDL_MSG_REGISTER); + + if (register_message_ptr->payload_ptr) { + handle->sn_nsdl_free(register_message_ptr->payload_ptr); + register_message_ptr->payload_ptr = NULL; + } + + register_message_ptr->uri_path_ptr = NULL; + register_message_ptr->options_list_ptr->uri_host_ptr = NULL; + + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); + + return message_id; +} + +uint16_t sn_nsdl_unregister_endpoint(struct nsdl_s *handle) +{ + /* Local variables */ + sn_coap_hdr_s *unregister_message_ptr; + uint8_t *temp_ptr = 0; + uint16_t message_id = 0; + + /* Check parameters */ + if (handle == NULL) { + return 0; + } + + /* Check that EP have been registered */ + if (sn_nsdl_is_ep_registered(handle)) { + + /* Memory allocation for unregister message */ + unregister_message_ptr = sn_coap_parser_alloc_message(handle->grs->coap); + if (!unregister_message_ptr) { + return 0; + } + + /* Fill unregister message */ + unregister_message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + unregister_message_ptr->msg_code = COAP_MSG_CODE_REQUEST_DELETE; + + if(handle->ep_information_ptr->location_ptr) { + unregister_message_ptr->uri_path_len = handle->ep_information_ptr->location_len; + unregister_message_ptr->uri_path_ptr = handle->sn_nsdl_alloc(unregister_message_ptr->uri_path_len); + if (!unregister_message_ptr->uri_path_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, unregister_message_ptr); + return 0; + } + + temp_ptr = unregister_message_ptr->uri_path_ptr; + + memcpy(temp_ptr , handle->ep_information_ptr->location_ptr, handle->ep_information_ptr->location_len); + } else { + unregister_message_ptr->uri_path_len = (RESOURCE_DIR_LEN + 1 + handle->ep_information_ptr->domain_name_len + 1 + handle->ep_information_ptr->endpoint_name_len); + unregister_message_ptr->uri_path_ptr = handle->sn_nsdl_alloc(unregister_message_ptr->uri_path_len); + if (!unregister_message_ptr->uri_path_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, unregister_message_ptr); + return 0; + } + + temp_ptr = unregister_message_ptr->uri_path_ptr; + + memcpy(temp_ptr, resource_path_ptr, RESOURCE_DIR_LEN); + temp_ptr += RESOURCE_DIR_LEN; + + *temp_ptr++ = '/'; + + memcpy(temp_ptr , handle->ep_information_ptr->domain_name_ptr, handle->ep_information_ptr->domain_name_len); + temp_ptr += handle->ep_information_ptr->domain_name_len; + + *temp_ptr++ = '/'; + + memcpy(temp_ptr , handle->ep_information_ptr->endpoint_name_ptr, handle->ep_information_ptr->endpoint_name_len); + } + + /* Send message */ + message_id = sn_nsdl_internal_coap_send(handle, unregister_message_ptr, handle->nsp_address_ptr->omalw_address_ptr, SN_NSDL_MSG_UNREGISTER); + + /* Free memory */ + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, unregister_message_ptr); + + } + + return message_id; +} + +uint16_t sn_nsdl_update_registration(struct nsdl_s *handle, uint8_t *lt_ptr, uint8_t lt_len) +{ + /* Local variables */ + sn_coap_hdr_s *register_message_ptr; + uint8_t *temp_ptr; + sn_nsdl_ep_parameters_s temp_parameters; + uint16_t message_id = 0; + + /* Check parameters */ + if (handle == NULL) { + return 0; + } + + if (!sn_nsdl_is_ep_registered(handle)){ + return 0; + } + + memset(&temp_parameters, 0, sizeof(sn_nsdl_ep_parameters_s)); + + temp_parameters.lifetime_len = lt_len; + temp_parameters.lifetime_ptr = lt_ptr; + + /*** Build endpoint register update message ***/ + + /* Allocate memory for header struct */ + register_message_ptr = sn_coap_parser_alloc_message(handle->grs->coap); + if (register_message_ptr == NULL) { + return 0; + } + + /* Fill message fields -> confirmable post to specified NSP path */ + register_message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + register_message_ptr->msg_code = COAP_MSG_CODE_REQUEST_POST; + + if(handle->ep_information_ptr->location_ptr) { + register_message_ptr->uri_path_len = handle->ep_information_ptr->location_len; /* = Only location set by Device Server*/ + + register_message_ptr->uri_path_ptr = handle->sn_nsdl_alloc(register_message_ptr->uri_path_len); + if (!register_message_ptr->uri_path_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); + return 0; + } + + temp_ptr = register_message_ptr->uri_path_ptr; + + /* location */ + memcpy(temp_ptr, handle->ep_information_ptr->location_ptr, handle->ep_information_ptr->location_len); + } else { + register_message_ptr->uri_path_len = sizeof(resource_path_ptr) + handle->ep_information_ptr->domain_name_len + handle->ep_information_ptr->endpoint_name_len + 2; /* = rd/domain/endpoint */ + + register_message_ptr->uri_path_ptr = handle->sn_nsdl_alloc(register_message_ptr->uri_path_len); + if (!register_message_ptr->uri_path_ptr) { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); + return 0; + } + + temp_ptr = register_message_ptr->uri_path_ptr; + + /* rd/ */ + memcpy(temp_ptr, resource_path_ptr, sizeof(resource_path_ptr)); + temp_ptr += sizeof(resource_path_ptr); + *temp_ptr++ = '/'; + + /* rd/DOMAIN/ */ + memcpy(temp_ptr, handle->ep_information_ptr->domain_name_ptr, handle->ep_information_ptr->domain_name_len); + temp_ptr += handle->ep_information_ptr->domain_name_len; + *temp_ptr++ = '/'; + + /* rd/domain/ENDPOINT */ + memcpy(temp_ptr, handle->ep_information_ptr->endpoint_name_ptr, handle->ep_information_ptr->endpoint_name_len); + } + + /* Allocate memory for the extended options list */ + if (sn_coap_parser_alloc_options(handle->grs->coap, register_message_ptr) == NULL) { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); + return 0; + } + + /* Fill Uri-query options */ + sn_nsdl_fill_uri_query_options(handle, &temp_parameters, register_message_ptr, SN_NSDL_EP_UPDATE_MESSAGE); + + /* Build payload */ + if (handle->ep_information_ptr->ds_register_mode == REGISTER_WITH_RESOURCES) { + + if (sn_nsdl_build_registration_body(handle, register_message_ptr, 1) == SN_NSDL_FAILURE) { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); + return 0; + } + } + + /* Build and send coap message to NSP */ + message_id = sn_nsdl_internal_coap_send(handle, register_message_ptr, handle->nsp_address_ptr->omalw_address_ptr, SN_NSDL_MSG_UPDATE); + + if (register_message_ptr->payload_ptr) { + handle->sn_nsdl_free(register_message_ptr->payload_ptr); + } + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr); + + return message_id; +} + +int8_t sn_nsdl_set_endpoint_location(struct nsdl_s *handle, uint8_t *location_ptr, uint8_t location_len) +{ + if(!handle || !location_ptr || (location_len == 0)) { + return -1; + } + + handle->sn_nsdl_free(handle->ep_information_ptr->location_ptr); + handle->ep_information_ptr->location_ptr = handle->sn_nsdl_alloc(location_len); + memcpy(handle->ep_information_ptr->location_ptr, location_ptr, location_len); + handle->ep_information_ptr->location_len = location_len; + + return 0; +} + +void sn_nsdl_nsp_lost(struct nsdl_s *handle) +{ + /* Check parameters */ + if (handle == NULL) { + return; + } + + handle->sn_nsdl_endpoint_registered = SN_NSDL_ENDPOINT_NOT_REGISTERED; +} + +int8_t sn_nsdl_is_ep_registered(struct nsdl_s *handle) +{ + /* Check parameters */ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + + return handle->sn_nsdl_endpoint_registered; +} + +uint16_t sn_nsdl_send_observation_notification(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len, + uint8_t *payload_ptr, uint16_t payload_len, + uint8_t *observe_ptr, uint8_t observe_len, + sn_coap_msg_type_e message_type, uint8_t content_type) +{ + return sn_nsdl_send_observation_notification_with_uri_path(handle, + token_ptr, + token_len, + payload_ptr, + payload_len, + observe_ptr, + observe_len, + message_type, + content_type, + NULL, + 0); +} + +uint16_t sn_nsdl_send_observation_notification_with_uri_path(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len, + uint8_t *payload_ptr, uint16_t payload_len, + uint8_t *observe_ptr, uint8_t observe_len, + sn_coap_msg_type_e message_type, uint8_t content_type, + uint8_t *uri_path_ptr, uint16_t uri_path_len) +{ + sn_coap_hdr_s *notification_message_ptr; + uint16_t return_msg_id = 0; + + /* Check parameters */ + if (handle == NULL || handle->grs == NULL) { + return 0; + } + + /* Allocate and initialize memory for header struct */ + notification_message_ptr = sn_coap_parser_alloc_message(handle->grs->coap); + if (notification_message_ptr == NULL) { + return 0; + } + + if (sn_coap_parser_alloc_options(handle->grs->coap, notification_message_ptr) == NULL) { + handle->sn_nsdl_free(notification_message_ptr); + return 0; + } + + /* Fill header */ + notification_message_ptr->msg_type = message_type; + notification_message_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT; + + /* Fill token */ + notification_message_ptr->token_len = token_len; + notification_message_ptr->token_ptr = token_ptr; + + /* Fill payload */ + notification_message_ptr->payload_len = payload_len; + notification_message_ptr->payload_ptr = payload_ptr; + + /* Fill uri path */ + notification_message_ptr->uri_path_len = uri_path_len; + notification_message_ptr->uri_path_ptr = uri_path_ptr; + + /* Fill observe */ + notification_message_ptr->options_list_ptr->observe_len = observe_len; + notification_message_ptr->options_list_ptr->observe_ptr = observe_ptr; + + /* Fill content type */ + if (content_type) { + notification_message_ptr->content_type_len = 1; + notification_message_ptr->content_type_ptr = &content_type; + } + + /* Send message */ + if (sn_nsdl_send_coap_message(handle, handle->nsp_address_ptr->omalw_address_ptr, notification_message_ptr) == SN_NSDL_FAILURE) { + return_msg_id = 0; + } else { + return_msg_id = notification_message_ptr->msg_id; + } + + /* Free memory */ + notification_message_ptr->uri_path_ptr = NULL; + notification_message_ptr->payload_ptr = NULL; + notification_message_ptr->options_list_ptr->observe_ptr = NULL; + notification_message_ptr->token_ptr = NULL; + notification_message_ptr->content_type_ptr = NULL; + + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, notification_message_ptr); + + return return_msg_id; +} + + +/* * * * * * * * * * */ +/* ~ OMA functions ~ */ +/* * * * * * * * * * */ + +uint16_t sn_nsdl_oma_bootstrap(struct nsdl_s *handle, sn_nsdl_addr_s *bootstrap_address_ptr, + sn_nsdl_ep_parameters_s *endpoint_info_ptr, + sn_nsdl_bs_ep_info_t *bootstrap_endpoint_info_ptr) +{ +#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + /* Local variables */ + sn_coap_hdr_s bootstrap_coap_header; + uint8_t *uri_query_tmp_ptr; + uint16_t message_id = 0; + + /* Check parameters */ + if (!bootstrap_address_ptr || !bootstrap_endpoint_info_ptr || !endpoint_info_ptr || !handle) { + return 0; + } + /* Create device object */ + if (handle->handle_bootstrap_msg) { + if (sn_nsdl_create_oma_device_object_base(handle, bootstrap_endpoint_info_ptr->device_object, endpoint_info_ptr->binding_and_mode) < 0) { + return 0; + } + + handle->sn_nsdl_oma_bs_done_cb = bootstrap_endpoint_info_ptr->oma_bs_status_cb; + handle->sn_nsdl_oma_bs_done_cb_handle = bootstrap_endpoint_info_ptr->oma_bs_status_cb_handle; + } + + + /* XXX FIX -- Init CoAP header struct */ + sn_coap_parser_init_message(&bootstrap_coap_header); + + if (!sn_coap_parser_alloc_options(handle->grs->coap, &bootstrap_coap_header)) { + return 0; + } + + /* Build bootstrap start message */ + bootstrap_coap_header.msg_code = COAP_MSG_CODE_REQUEST_POST; + bootstrap_coap_header.msg_type = COAP_MSG_TYPE_CONFIRMABLE; + + bootstrap_coap_header.uri_path_ptr = bs_uri; + bootstrap_coap_header.uri_path_len = sizeof(bs_uri); + + uri_query_tmp_ptr = handle->sn_nsdl_alloc(endpoint_info_ptr->endpoint_name_len + BS_EP_PARAMETER_LEN); + if (!uri_query_tmp_ptr) { + handle->sn_nsdl_free(bootstrap_coap_header.options_list_ptr); + return 0; + } + + memcpy(uri_query_tmp_ptr, bs_ep_name, BS_EP_PARAMETER_LEN); + memcpy((uri_query_tmp_ptr + BS_EP_PARAMETER_LEN), endpoint_info_ptr->endpoint_name_ptr, endpoint_info_ptr->endpoint_name_len); + + bootstrap_coap_header.options_list_ptr->uri_query_len = endpoint_info_ptr->endpoint_name_len + BS_EP_PARAMETER_LEN; + bootstrap_coap_header.options_list_ptr->uri_query_ptr = uri_query_tmp_ptr; + + /* Save bootstrap server address */ + handle->oma_bs_address_len = bootstrap_address_ptr->addr_len; /* Length.. */ + handle->oma_bs_address_ptr = handle->sn_nsdl_alloc(handle->oma_bs_address_len); /* Address.. */ + if (!handle->oma_bs_address_ptr) { + handle->sn_nsdl_free(bootstrap_coap_header.options_list_ptr); + handle->sn_nsdl_free(uri_query_tmp_ptr); + return 0; + } + memcpy(handle->oma_bs_address_ptr, bootstrap_address_ptr->addr_ptr, handle->oma_bs_address_len); + handle->oma_bs_port = bootstrap_address_ptr->port; /* And port */ + + /* Send message */ + message_id = sn_nsdl_internal_coap_send(handle, &bootstrap_coap_header, bootstrap_address_ptr, SN_NSDL_MSG_BOOTSTRAP); + + /* Free allocated memory */ + handle->sn_nsdl_free(uri_query_tmp_ptr); + handle->sn_nsdl_free(bootstrap_coap_header.options_list_ptr); + + return message_id; +#else + return 0; +#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + +} + +omalw_certificate_list_t *sn_nsdl_get_certificates(struct nsdl_s *handle) +{ +#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + sn_nsdl_resource_info_s *resource_ptr = 0;; + omalw_certificate_list_t *certi_list_ptr = 0; + + /* Check parameters */ + if (handle == NULL) { + return NULL; + } + + certi_list_ptr = handle->sn_nsdl_alloc(sizeof(omalw_certificate_list_t)); + + if (!certi_list_ptr) { + return NULL; + } + + /* Get private key resource */ + resource_ptr = sn_nsdl_get_resource(handle, 5, (void *)"0/0/5"); + if (!resource_ptr) { + handle->sn_nsdl_free(certi_list_ptr); + return NULL; + } + certi_list_ptr->own_private_key_ptr = resource_ptr->resource; + certi_list_ptr->own_private_key_len = resource_ptr->resourcelen; + + /* Get client certificate resource */ + resource_ptr = sn_nsdl_get_resource(handle, 5, (void *)"0/0/4"); + if (!resource_ptr) { + handle->sn_nsdl_free(certi_list_ptr); + return NULL; + } + certi_list_ptr->certificate_ptr[0] = resource_ptr->resource; + certi_list_ptr->certificate_len[0] = resource_ptr->resourcelen; + + /* Get root certificate resource */ + resource_ptr = sn_nsdl_get_resource(handle, 5, (void *)"0/0/3"); + if (!resource_ptr) { + handle->sn_nsdl_free(certi_list_ptr); + return NULL; + } + certi_list_ptr->certificate_ptr[1] = resource_ptr->resource; + certi_list_ptr->certificate_len[1] = resource_ptr->resourcelen; + + /* return filled list */ + return certi_list_ptr; +#else + return NULL; +#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +} + +int8_t sn_nsdl_update_certificates(struct nsdl_s *handle, omalw_certificate_list_t *certificate_ptr, uint8_t certificate_chain) +{ +#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + (void)certificate_chain; + + /* Check pointers */ + if (!certificate_ptr || !handle) { + return SN_NSDL_FAILURE; + } + + sn_nsdl_resource_info_s *resource_ptr = 0;; + + /* Get private key resource */ + resource_ptr = sn_nsdl_get_resource(handle, 5, (void *)"0/0/5"); + if (!resource_ptr) { + return SN_NSDL_FAILURE; + } + handle->sn_nsdl_free(resource_ptr->resource); + resource_ptr->resource = certificate_ptr->own_private_key_ptr; + resource_ptr->resourcelen = certificate_ptr->own_private_key_len; + + /* Get client certificate resource */ + resource_ptr = sn_nsdl_get_resource(handle, 5, (void *)"0/0/4"); + if (!resource_ptr) { + return SN_NSDL_FAILURE; + } + handle->sn_nsdl_free(resource_ptr->resource); + resource_ptr->resource = certificate_ptr->certificate_ptr[0]; + resource_ptr->resourcelen = certificate_ptr->certificate_len[0]; + + /* Get root certificate resource */ + resource_ptr = sn_nsdl_get_resource(handle, 5, (void *)"0/0/3"); + if (!resource_ptr) { + return SN_NSDL_FAILURE; + } + handle->sn_nsdl_free(resource_ptr->resource); + resource_ptr->resource = certificate_ptr->certificate_ptr[1]; + resource_ptr->resourcelen = certificate_ptr->certificate_len[1]; + + return SN_NSDL_SUCCESS; +#else + return SN_NSDL_FAILURE; +#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +} + +int8_t sn_nsdl_create_oma_device_object(struct nsdl_s *handle, sn_nsdl_oma_device_t *device_object_ptr) +{ +#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + sn_nsdl_resource_info_s *resource_temp = 0; + uint8_t path[8] = "3/0/11/0"; + + if (!device_object_ptr || !handle) { + return SN_NSDL_FAILURE; + } + + /* * Error code * */ + + /* Get first error message */ + resource_temp = sn_grs_search_resource(handle->grs, 8, path, SN_GRS_SEARCH_METHOD); + + while (resource_temp) { + if (resource_temp->resource) { + /* If no error code set */ + if (*resource_temp->resource == 0) { + /* Set error code */ + *resource_temp->resource = (uint8_t)device_object_ptr->error_code; + resource_temp->resourcelen = 1; + + sn_nsdl_update_resource(handle, resource_temp); + return SN_NSDL_SUCCESS; + } + break; + } + + if (path[7] == '9') { + return SN_NSDL_FAILURE; + } + + path[7]++; + resource_temp = sn_grs_search_resource(handle->grs, 8, path, SN_GRS_SEARCH_METHOD); + } + + /* Create new resource for this error */ + resource_temp = handle->sn_nsdl_alloc(sizeof(sn_nsdl_resource_info_s)); + if (!resource_temp) { + return SN_NSDL_FAILURE; + } + + memset(resource_temp, 0, sizeof(sn_nsdl_resource_info_s)); + + resource_temp->access = SN_GRS_GET_ALLOWED; + resource_temp->mode = SN_GRS_DYNAMIC; + + resource_temp->path = path; + resource_temp->pathlen = 8; + + resource_temp->resource = handle->sn_nsdl_alloc(1); + if (!resource_temp->resource) { + handle->sn_nsdl_free(resource_temp); + return SN_NSDL_FAILURE; + } + + *resource_temp->resource = (uint8_t)device_object_ptr->error_code; + resource_temp->resourcelen = 1; + + resource_temp->resource_parameters_ptr = handle->sn_nsdl_alloc(sizeof(sn_nsdl_resource_parameters_s)); + + if (!resource_temp->resource_parameters_ptr) { + handle->sn_nsdl_free(resource_temp->resource); + handle->sn_nsdl_free(resource_temp); + + return SN_NSDL_FAILURE; + } + + memset(resource_temp->resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s)); + + sn_nsdl_create_resource(handle, resource_temp); + + handle->sn_nsdl_free(resource_temp->resource); + handle->sn_nsdl_free(resource_temp->resource_parameters_ptr); + handle->sn_nsdl_free(resource_temp); + + return SN_NSDL_SUCCESS; +#else + return SN_NSDL_FAILURE; +#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +} + +char *sn_nsdl_get_version(void) +{ +#if defined(YOTTA_MBED_CLIENT_C_VERSION_STRING) + return YOTTA_MBED_CLIENT_C_VERSION_STRING; +#elif defined(VERSION) + return VERSION; +#else + return "0.0.0"; +#endif +} + + +int8_t sn_nsdl_process_coap(struct nsdl_s *handle, uint8_t *packet_ptr, uint16_t packet_len, sn_nsdl_addr_s *src_ptr) +{ + sn_coap_hdr_s *coap_packet_ptr = NULL; + sn_coap_hdr_s *coap_response_ptr = NULL; + + /* Check parameters */ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + + /* Parse CoAP packet */ + coap_packet_ptr = sn_coap_protocol_parse(handle->grs->coap, src_ptr, packet_len, packet_ptr, (void *)handle); + + /* Check if parsing was successfull */ + if (coap_packet_ptr == (sn_coap_hdr_s *)NULL) { + return SN_NSDL_FAILURE; + } + + /* Check, if coap itself sends response, or block receiving is ongoing... */ + if (coap_packet_ptr->coap_status != COAP_STATUS_OK && coap_packet_ptr->coap_status != COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED) { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + return SN_NSDL_SUCCESS; + } + + /* If proxy options added, return not supported */ + if (coap_packet_ptr->options_list_ptr) { + if (coap_packet_ptr->options_list_ptr->proxy_uri_len) { + coap_response_ptr = sn_coap_build_response(handle->grs->coap, coap_packet_ptr, COAP_MSG_CODE_RESPONSE_PROXYING_NOT_SUPPORTED); + if (coap_response_ptr) { + sn_nsdl_send_coap_message(handle, src_ptr, coap_response_ptr); + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_response_ptr); + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + return SN_NSDL_SUCCESS; + } else { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + return SN_NSDL_FAILURE; + } + } + } + + /* * * * * * * * * * * * * * * * * * * * * * * * * * */ + /* If message is response message, call RX callback */ + /* * * * * * * * * * * * * * * * * * * * * * * * * * */ + + if ((coap_packet_ptr->msg_code > COAP_MSG_CODE_REQUEST_DELETE) || (coap_packet_ptr->msg_type == COAP_MSG_TYPE_ACKNOWLEDGEMENT)) { + int8_t retval = sn_nsdl_local_rx_function(handle, coap_packet_ptr, src_ptr); + if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) { + handle->sn_nsdl_free(coap_packet_ptr->payload_ptr); + coap_packet_ptr->payload_ptr = 0; + } + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + return retval; + } +#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + /* * If OMA bootstrap message... * */ + bool bootstrap_msg = src_ptr && (handle->oma_bs_address_len == src_ptr->addr_len) && + (handle->oma_bs_port == src_ptr->port) && + !memcmp(handle->oma_bs_address_ptr, src_ptr->addr_ptr, handle->oma_bs_address_len); + // Pass bootstrap data to application + if (bootstrap_msg && !handle->handle_bootstrap_msg) { + handle->sn_nsdl_rx_callback(handle, coap_packet_ptr,src_ptr); + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + return SN_NSDL_SUCCESS; + } + // Internal handling + else if (bootstrap_msg) { + /* TLV message. Parse message and check status of the OMA bootstrap */ + /* process. If ok, call cb function and return. Otherwise send error */ + /* and return failure. */ + + if (coap_packet_ptr->content_type_len == 1) { //todo check message type + if (*coap_packet_ptr->content_type_ptr == 99) { + /* TLV parsing failed. Send response to get non-tlv messages */ + if (sn_nsdl_process_oma_tlv(handle, coap_packet_ptr->payload_ptr, coap_packet_ptr->payload_len) == SN_NSDL_FAILURE) { + coap_response_ptr = sn_coap_build_response(handle->grs->coap, coap_packet_ptr, COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE); + if (coap_response_ptr) { + sn_nsdl_send_coap_message(handle, src_ptr, coap_response_ptr); + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_response_ptr); + } else { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + return SN_NSDL_FAILURE; + } + } + /* Success TLV parsing */ + else { + coap_response_ptr = sn_coap_build_response(handle->grs->coap, coap_packet_ptr, COAP_MSG_CODE_RESPONSE_CREATED); + if (coap_response_ptr) { + sn_nsdl_send_coap_message(handle, src_ptr, coap_response_ptr); + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_response_ptr); + + } else { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + return SN_NSDL_FAILURE; + } + sn_nsdl_check_oma_bs_status(handle); + } + + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + return SN_NSDL_SUCCESS; + } + + /* Non - TLV message */ + else if (*coap_packet_ptr->content_type_ptr == 97) { + sn_grs_process_coap(handle, coap_packet_ptr, src_ptr); + + /* Todo: move this copying to sn_nsdl_check_oma_bs_status(), also from TLV parser */ + /* Security mode */ + if (*(coap_packet_ptr->uri_path_ptr + (coap_packet_ptr->uri_path_len - 1)) == '2') { + handle->nsp_address_ptr->omalw_server_security = (omalw_server_security_t)sn_nsdl_atoi(coap_packet_ptr->payload_ptr, coap_packet_ptr->payload_len); + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + } + + /* NSP address */ + else if (*(coap_packet_ptr->uri_path_ptr + (coap_packet_ptr->uri_path_len - 1)) == '0') { + sn_nsdl_resolve_lwm2m_address(handle, coap_packet_ptr->payload_ptr, coap_packet_ptr->payload_len); + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + } + + sn_nsdl_check_oma_bs_status(handle); + } else { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + return SN_NSDL_FAILURE; + } + } else { + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr); + return SN_NSDL_FAILURE; + } + + + return SN_NSDL_SUCCESS; + } +#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + + /* * * * * * * * * * * * * * * */ + /* Other messages are for GRS */ + /* * * * * * * * * * * * * * * */ + + return sn_grs_process_coap(handle, coap_packet_ptr, src_ptr); +} + +int8_t sn_nsdl_exec(struct nsdl_s *handle, uint32_t time) +{ + if(!handle || !handle->grs){ + return SN_NSDL_FAILURE; + } + /* Call CoAP execution function */ + return sn_coap_protocol_exec(handle->grs->coap, time); +} + +sn_nsdl_resource_info_s *sn_nsdl_get_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path_ptr) +{ + /* Check parameters */ + if (handle == NULL) { + return NULL; + } + + return sn_grs_search_resource(handle->grs, pathlen, path_ptr, SN_GRS_SEARCH_METHOD); +} + + +/** + * \fn static uint16_t sn_nsdl_internal_coap_send(struct nsdl_s *handle, sn_coap_hdr_s *coap_header_ptr, sn_nsdl_addr_s *dst_addr_ptr, uint8_t message_description) + * + * + * \brief To send NSDL messages. Stores message id?s and message description to catch response from NSP server + * \param *handle Pointer to nsdl-library handle + * \param *coap_header_ptr Pointer to the CoAP message header to be sent + * \param *dst_addr_ptr Pointer to the address structure that contains destination address information + * \param message_description Message description to be stored to list for waiting response + * + * \return message id, 0 if failed + */ +static uint16_t sn_nsdl_internal_coap_send(struct nsdl_s *handle, sn_coap_hdr_s *coap_header_ptr, sn_nsdl_addr_s *dst_addr_ptr, uint8_t message_description) +{ + + tr_debug("sn_nsdl_internal_coap_send"); + uint8_t *coap_message_ptr = NULL; + int32_t coap_message_len = 0; + uint16_t coap_header_len = 0; + + coap_message_len = sn_coap_builder_calc_needed_packet_data_size_2(coap_header_ptr, handle->grs->coap->sn_coap_block_data_size); + tr_debug("sn_nsdl_internal_coap_send - msg len after calc: [%d]", coap_message_len); + if (coap_message_len == 0) { + return 0; + } + + coap_message_ptr = handle->sn_nsdl_alloc(coap_message_len); + if (!coap_message_ptr) { + return 0; + } + + coap_header_len = coap_header_ptr->payload_len; + /* Build message */ + if (sn_coap_protocol_build(handle->grs->coap, dst_addr_ptr, coap_message_ptr, coap_header_ptr, (void *)handle) < 0) { + handle->sn_nsdl_free(coap_message_ptr); + return 0; + } + + /* If mesage type is confirmable, save it to list to wait for reply */ + if (coap_header_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) { + if (message_description == SN_NSDL_MSG_REGISTER) { + handle->register_msg_id = coap_header_ptr->msg_id; + handle->register_msg_len = coap_header_len; + } + else if (message_description == SN_NSDL_MSG_UNREGISTER) { + handle->unregister_msg_id = coap_header_ptr->msg_id; + } + else if (message_description == SN_NSDL_MSG_UPDATE) { + handle->update_register_msg_id = coap_header_ptr->msg_id; + handle->update_register_msg_len = coap_header_len; + } + else if (message_description == SN_NSDL_MSG_BOOTSTRAP) { + handle->bootstrap_msg_id = coap_header_ptr->msg_id; + } + } + + handle->sn_nsdl_tx_callback(handle, SN_NSDL_PROTOCOL_COAP, coap_message_ptr, coap_message_len, dst_addr_ptr); + handle->sn_nsdl_free(coap_message_ptr); + + return coap_header_ptr->msg_id; +} + +/** + * \fn static void sn_nsdl_resolve_nsp_address(struct nsdl_s *handle) + * + * \brief Resolves NSP server address. + * + * \param *handle Pointer to nsdl-library handle + * \note Application must set NSP address with set_nsp_address + */ +static void sn_nsdl_resolve_nsp_address(struct nsdl_s *handle) +{ + /* Local variables */ + if (!handle->nsp_address_ptr) { + //allocate only if previously not allocated + handle->nsp_address_ptr = handle->sn_nsdl_alloc(sizeof(sn_nsdl_oma_server_info_t)); + } + + if (handle->nsp_address_ptr) { + handle->nsp_address_ptr->omalw_server_security = SEC_NOT_SET; + handle->nsp_address_ptr->omalw_address_ptr = handle->sn_nsdl_alloc(sizeof(sn_nsdl_addr_s)); + if (handle->nsp_address_ptr->omalw_address_ptr) { + memset(handle->nsp_address_ptr->omalw_address_ptr, 0, sizeof(sn_nsdl_addr_s)); + handle->nsp_address_ptr->omalw_address_ptr->type = SN_NSDL_ADDRESS_TYPE_NONE; + } + } +} + +static int8_t sn_nsdl_create_oma_device_object_base(struct nsdl_s *handle, sn_nsdl_oma_device_t *oma_device_setup_ptr, sn_nsdl_oma_binding_and_mode_t binding_and_mode) +{ +#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + sn_nsdl_resource_info_s new_resource; + uint8_t object_path[8] = "3/0/11/0"; + uint8_t resource_temp[3]; + uint8_t x = 0; + + if (!oma_device_setup_ptr) { + return SN_NSDL_FAILURE; + } + + /* * Create resources. * */ + + /* These resources can be created multiple times. */ + memset(&new_resource, 0, sizeof(sn_nsdl_resource_info_s)); + new_resource.resource_parameters_ptr = handle->sn_nsdl_alloc(sizeof(sn_nsdl_resource_parameters_s)); + if (!new_resource.resource_parameters_ptr) { + return SN_NSDL_FAILURE; + } + + memset(new_resource.resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s)); + + /* Create error - resource */ + new_resource.mode = SN_GRS_STATIC; + new_resource.access = SN_GRS_GET_ALLOWED; + + new_resource.path = object_path; + new_resource.pathlen = 8; + + sn_nsdl_itoa(resource_temp, (uint8_t)oma_device_setup_ptr->error_code); + + new_resource.resource = resource_temp; + new_resource.resourcelen = 1; + + if (sn_nsdl_create_resource(handle, &new_resource) != SN_NSDL_SUCCESS) { + handle->sn_nsdl_free(new_resource.resource_parameters_ptr); + return SN_NSDL_FAILURE; + } + + /* These resources can be only once, during OMA bootstrap.. */ + /* Create supported binding and modes */ + object_path[5] = '6'; + new_resource.path = object_path; + new_resource.pathlen = 6; + + if (binding_and_mode & 0x01) { + resource_temp[x] = 'U'; + x++; + if (binding_and_mode & 0x02) { + resource_temp[x] = 'Q'; + x++; + } + } + if (binding_and_mode & 0x04) { + resource_temp[x] = 'S'; + x++; + if ((binding_and_mode & 0x02) && !(binding_and_mode & 0x01)) { + resource_temp[x] = 'Q'; + x++; + } + } + + new_resource.resourcelen = x; + + if (new_resource.resourcelen) { + new_resource.resource = resource_temp; + } else { + new_resource.resource = 0; + } + + + if (sn_nsdl_create_resource(handle, &new_resource) != SN_NSDL_SUCCESS) { + handle->sn_nsdl_free(new_resource.resource_parameters_ptr); + return SN_NSDL_FAILURE; + } + + + /* Create dynamic reboot object */ + new_resource.mode = SN_GRS_DYNAMIC; + + new_resource.access = SN_GRS_POST_ALLOWED; + + object_path[4] = '4'; + + new_resource.path = object_path; + new_resource.pathlen = 5; + + new_resource.resourcelen = 0; + new_resource.resource = 0; + + new_resource.sn_grs_dyn_res_callback = oma_device_setup_ptr->sn_oma_device_boot_callback; + + if (sn_nsdl_create_resource(handle, &new_resource) != SN_NSDL_SUCCESS) { + handle->sn_nsdl_free(new_resource.resource_parameters_ptr); + return SN_NSDL_FAILURE; + } + + handle->sn_nsdl_free(new_resource.resource_parameters_ptr); + return SN_NSDL_SUCCESS; +#else + return SN_NSDL_FAILURE; +#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +} + +/** + * \fn int8_t sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration) + * + * \brief To build GRS resources to registration message payload + * \param *handle Pointer to nsdl-library handle + * \param *message_ptr Pointer to CoAP message header + * + * \return SN_NSDL_SUCCESS = 0, Failed = -1 + */ +int8_t sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration) +{ + tr_debug("sn_nsdl_build_registration_body"); + /* Local variables */ + uint8_t *temp_ptr; + const sn_nsdl_resource_info_s *resource_temp_ptr; + + /* Calculate needed memory and allocate */ + int8_t error = 0; + uint16_t msg_len = sn_nsdl_calculate_registration_body_size(handle, updating_registeration, &error); + if (SN_NSDL_FAILURE == error) { + return error; + } + + if (!msg_len) { + return SN_NSDL_SUCCESS; + } else { + message_ptr->payload_len = msg_len; + } + tr_debug("sn_nsdl_build_registration_body - body size: [%d]", message_ptr->payload_len); + message_ptr->payload_ptr = handle->sn_nsdl_alloc(message_ptr->payload_len); + if (!message_ptr->payload_ptr) { + return SN_NSDL_FAILURE; + } + + /* Build message */ + temp_ptr = message_ptr->payload_ptr; + + resource_temp_ptr = sn_grs_get_first_resource(handle->grs); + + /* Loop trough all resources */ + while (resource_temp_ptr) { + /* if resource needs to be registered */ + if (resource_temp_ptr->resource_parameters_ptr && resource_temp_ptr->publish_uri) { + if (updating_registeration && resource_temp_ptr->resource_parameters_ptr->registered == SN_NDSL_RESOURCE_REGISTERED) { + resource_temp_ptr = sn_grs_get_next_resource(handle->grs, resource_temp_ptr); + continue; + } else { + resource_temp_ptr->resource_parameters_ptr->registered = SN_NDSL_RESOURCE_REGISTERED; + } + + /* If not first resource, add '.' to separator */ + if (temp_ptr != message_ptr->payload_ptr) { + *temp_ptr++ = ','; + } + + *temp_ptr++ = '<'; + *temp_ptr++ = '/'; + memcpy(temp_ptr, resource_temp_ptr->path, resource_temp_ptr->pathlen); + temp_ptr += resource_temp_ptr->pathlen; + *temp_ptr++ = '>'; + + /* Resource attributes */ + if (resource_temp_ptr->resource_parameters_ptr->resource_type_len) { + *temp_ptr++ = ';'; + memcpy(temp_ptr, resource_type_parameter, RT_PARAMETER_LEN); + temp_ptr += RT_PARAMETER_LEN; + *temp_ptr++ = '"'; + memcpy(temp_ptr, resource_temp_ptr->resource_parameters_ptr->resource_type_ptr, resource_temp_ptr->resource_parameters_ptr->resource_type_len); + temp_ptr += resource_temp_ptr->resource_parameters_ptr->resource_type_len; + *temp_ptr++ = '"'; + } + + if (resource_temp_ptr->resource_parameters_ptr->interface_description_len) { + *temp_ptr++ = ';'; + memcpy(temp_ptr, if_description_parameter, IF_PARAMETER_LEN); + temp_ptr += IF_PARAMETER_LEN; + *temp_ptr++ = '"'; + memcpy(temp_ptr, resource_temp_ptr->resource_parameters_ptr->interface_description_ptr, resource_temp_ptr->resource_parameters_ptr->interface_description_len); + temp_ptr += resource_temp_ptr->resource_parameters_ptr->interface_description_len; + *temp_ptr++ = '"'; + } + + if (resource_temp_ptr->resource_parameters_ptr->coap_content_type != 0) { + *temp_ptr++ = ';'; + memcpy(temp_ptr, coap_con_type_parameter, COAP_CON_PARAMETER_LEN); + temp_ptr += COAP_CON_PARAMETER_LEN; + *temp_ptr++ = '"'; + temp_ptr = sn_nsdl_itoa(temp_ptr, resource_temp_ptr->resource_parameters_ptr->coap_content_type); + *temp_ptr++ = '"'; + } + + /* ;obs */ + // This needs to be re-visited and may be need an API for maganging obs value for different server implementation +#ifndef COAP_DISABLE_OBS_FEATURE + if (resource_temp_ptr->resource_parameters_ptr->observable) { + *temp_ptr++ = ';'; + memcpy(temp_ptr, obs_parameter, OBS_PARAMETER_LEN); + temp_ptr += OBS_PARAMETER_LEN; + } +#endif + /* ;aobs;id= */ + /* todo: aosb not supported ATM */ + /* + if((resource_temp_ptr->resource_parameters_ptr->auto_obs_len > 0 && resource_temp_ptr->resource_parameters_ptr->auto_obs_len <= 8) && + resource_temp_ptr->resource_parameters_ptr->auto_obs_ptr) + { + uint8_t i = 0; + + *temp_ptr++ = ';'; + memcpy(temp_ptr, aobs_parameter, AOBS_PARAMETER_LEN); + temp_ptr += AOBS_PARAMETER_LEN; + + while(i < resource_temp_ptr->resource_parameters_ptr->auto_obs_len) + { + temp_ptr = sn_nsdl_itoa(temp_ptr, *(resource_temp_ptr->resource_parameters_ptr->auto_obs_ptr + i)); + i++; + } + } + */ + + } + + resource_temp_ptr = sn_grs_get_next_resource(handle->grs, resource_temp_ptr); + } + + return SN_NSDL_SUCCESS; +} + +/** + * \fn static uint16_t sn_nsdl_calculate_registration_body_size(struct nsdl_s *handle, uint8_t updating_registeration, int8_t *error) + * + * + * \brief Calculates registration message payload size + * \param *handle Pointer to nsdl-library handle + * \param *updating_registeration Pointer to list of GRS resources + * \param *error Error code, SN_NSDL_SUCCESS or SN_NSDL_FAILURE + * + * \return Needed payload size + */ +static uint16_t sn_nsdl_calculate_registration_body_size(struct nsdl_s *handle, uint8_t updating_registeration, int8_t *error) +{ + tr_debug("sn_nsdl_calculate_registration_body_size"); + /* Local variables */ + uint16_t return_value = 0; + *error = SN_NSDL_SUCCESS; + const sn_nsdl_resource_info_s *resource_temp_ptr; + + /* check pointer */ + resource_temp_ptr = sn_grs_get_first_resource(handle->grs); + + while (resource_temp_ptr) { + if (resource_temp_ptr->resource_parameters_ptr && resource_temp_ptr->publish_uri) { + if (updating_registeration && resource_temp_ptr->resource_parameters_ptr->registered == SN_NDSL_RESOURCE_REGISTERED) { + resource_temp_ptr = sn_grs_get_next_resource(handle->grs, resource_temp_ptr); + continue; + } + + /* If not first resource, then '.' will be added */ + if (return_value) { + if (sn_nsdl_check_uint_overflow(return_value, 1, 0)) { + return_value++; + } else { + *error = SN_NSDL_FAILURE; + break; + } + } + + /* Count length for the resource path */ + if (sn_nsdl_check_uint_overflow(return_value, 3,resource_temp_ptr->pathlen)) { + return_value += (3 + resource_temp_ptr->pathlen); + } else { + *error = SN_NSDL_FAILURE; + break; + } + + /* Count lengths of the attributes */ + + /* Resource type parameter */ + if (resource_temp_ptr->resource_parameters_ptr->resource_type_len) { + /* ;rt="restype" */ + if (sn_nsdl_check_uint_overflow(return_value, 6, resource_temp_ptr->resource_parameters_ptr->resource_type_len)) { + return_value += (6 + resource_temp_ptr->resource_parameters_ptr->resource_type_len); + } else { + *error = SN_NSDL_FAILURE; + break; + } + } + + /* Interface description parameter */ + if (resource_temp_ptr->resource_parameters_ptr->interface_description_len) { + /* ;if="iftype" */ + if (sn_nsdl_check_uint_overflow(return_value, 6, resource_temp_ptr->resource_parameters_ptr->interface_description_len)) { + return_value += (6 + resource_temp_ptr->resource_parameters_ptr->interface_description_len); + } else { + *error = SN_NSDL_FAILURE; + break; + } + } + + if (resource_temp_ptr->resource_parameters_ptr->coap_content_type != 0) { + /* ;if="content" */ + uint8_t len = sn_nsdl_itoa_len(resource_temp_ptr->resource_parameters_ptr->coap_content_type); + if (sn_nsdl_check_uint_overflow(return_value, 6, len)) { + return_value += (6 + len); + } else { + *error = SN_NSDL_FAILURE; + break; + } + } +#ifndef COAP_DISABLE_OBS_FEATURE + // This needs to be re-visited and may be need an API for maganging obs value for different server implementation + if (resource_temp_ptr->resource_parameters_ptr->observable) { + if (sn_nsdl_check_uint_overflow(return_value, 4, 0)) { + return_value += 4; + } else { + *error = SN_NSDL_FAILURE; + break; + } + } +#endif + } + resource_temp_ptr = sn_grs_get_next_resource(handle->grs, resource_temp_ptr); + } + return return_value; +} + +/** + * \fn static uint8_t sn_nsdl_calculate_uri_query_option_len(sn_nsdl_ep_parameters_s *endpoint_info_ptr, uint8_t msg_type) + * + * + * \brief Calculates needed uri query option length + * + * \param *endpoint_info_ptr Pointer to endpoint info structure + * \param msg_type Message type + * + * \return number of parameters in uri query + */ +static uint8_t sn_nsdl_calculate_uri_query_option_len(sn_nsdl_ep_parameters_s *endpoint_info_ptr, uint8_t msg_type) +{ + uint8_t return_value = 0; + uint8_t number_of_parameters = 0; + + + if ((endpoint_info_ptr->endpoint_name_len != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE) && endpoint_info_ptr->endpoint_name_ptr != 0) { + return_value += endpoint_info_ptr->endpoint_name_len; + return_value += EP_NAME_PARAMETERS_LEN; //ep= + number_of_parameters++; + } + + if ((endpoint_info_ptr->type_len != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE) && (endpoint_info_ptr->type_ptr != 0)) { + return_value += endpoint_info_ptr->type_len; + return_value += ET_PARAMETER_LEN; //et= + number_of_parameters++; + } + + if ((endpoint_info_ptr->lifetime_len != 0) && (endpoint_info_ptr->lifetime_ptr != 0)) { + return_value += endpoint_info_ptr->lifetime_len; + return_value += LT_PARAMETER_LEN; //lt= + number_of_parameters++; + } + + if ((endpoint_info_ptr->domain_name_len != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE) && (endpoint_info_ptr->domain_name_ptr != 0)) { + return_value += endpoint_info_ptr->domain_name_len; + return_value += DOMAIN_PARAMETER_LEN; //d= + number_of_parameters++; + } + + if (((endpoint_info_ptr->binding_and_mode & 0x04) || (endpoint_info_ptr->binding_and_mode & 0x01)) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) { + return_value += BS_QUEUE_MODE_PARAMATER_LEN; + + if (endpoint_info_ptr->binding_and_mode & 0x01) { + return_value++; + } + if (endpoint_info_ptr->binding_and_mode & 0x04) { + return_value++; + } + if ((endpoint_info_ptr->binding_and_mode & 0x02) && ((endpoint_info_ptr->binding_and_mode & 0x04) || (endpoint_info_ptr->binding_and_mode & 0x01))) { + return_value++; + } + + number_of_parameters++; + } + + if (number_of_parameters != 0) { + return_value += (number_of_parameters - 1); + } + + return return_value; +} + +/** + * \fn static int8_t sn_nsdl_fill_uri_query_options(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *parameter_ptr, sn_coap_hdr_s *source_msg_ptr, uint8_t msg_type) + * + * + * \brief Fills uri-query options to message header struct + * \param *handle Pointer to nsdl-library handle + * \param *parameter_ptr Pointer to endpoint parameters struct + * \param *source_msg_ptr Pointer to CoAP header struct + * \param msg_type Message type + * + * \return SN_NSDL_SUCCESS = 0, Failed = -1 + */ +static int8_t sn_nsdl_fill_uri_query_options(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *parameter_ptr, sn_coap_hdr_s *source_msg_ptr, uint8_t msg_type) +{ + uint8_t *temp_ptr = NULL; + if( !validateParameters(parameter_ptr) ){ + return SN_NSDL_FAILURE; + } + source_msg_ptr->options_list_ptr->uri_query_len = sn_nsdl_calculate_uri_query_option_len(parameter_ptr, msg_type); + if (source_msg_ptr->options_list_ptr->uri_query_len == 0) { + return 0; + } + + source_msg_ptr->options_list_ptr->uri_query_ptr = handle->sn_nsdl_alloc(source_msg_ptr->options_list_ptr->uri_query_len); + + if (source_msg_ptr->options_list_ptr->uri_query_ptr == NULL) { + return SN_NSDL_FAILURE; + } + memset(source_msg_ptr->options_list_ptr->uri_query_ptr,0,source_msg_ptr->options_list_ptr->uri_query_len); + + temp_ptr = source_msg_ptr->options_list_ptr->uri_query_ptr; + + /******************************************************/ + /* If endpoint name is configured, fill needed fields */ + /******************************************************/ + + if ((parameter_ptr->endpoint_name_len != 0) && (parameter_ptr->endpoint_name_ptr != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) { + /* fill endpoint name, first ?ep=, then endpoint name */ + memcpy(temp_ptr, ep_name_parameter_string, sizeof(ep_name_parameter_string)); + temp_ptr += EP_NAME_PARAMETERS_LEN; + memcpy(temp_ptr, parameter_ptr->endpoint_name_ptr, parameter_ptr->endpoint_name_len); + temp_ptr += parameter_ptr->endpoint_name_len; + } + + /******************************************************/ + /* If endpoint type is configured, fill needed fields */ + /******************************************************/ + + if ((parameter_ptr->type_len != 0) && (parameter_ptr->type_ptr != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) { + if (temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr) { + *temp_ptr++ = '&'; + } + + memcpy(temp_ptr, et_parameter, sizeof(et_parameter)); + temp_ptr += ET_PARAMETER_LEN; + memcpy(temp_ptr, parameter_ptr->type_ptr, parameter_ptr->type_len); + temp_ptr += parameter_ptr->type_len; + } + + + /******************************************************/ + /* If lifetime is configured, fill needed fields */ + /******************************************************/ + + if ((parameter_ptr->lifetime_len != 0) && (parameter_ptr->lifetime_ptr != 0)) { + if (temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr) { + *temp_ptr++ = '&'; + } + + memcpy(temp_ptr, ep_lifetime_parameter, sizeof(ep_lifetime_parameter)); + temp_ptr += LT_PARAMETER_LEN; + memcpy(temp_ptr, parameter_ptr->lifetime_ptr, parameter_ptr->lifetime_len); + temp_ptr += parameter_ptr->lifetime_len; + } + + /******************************************************/ + /* If domain is configured, fill needed fields */ + /******************************************************/ + + if ((parameter_ptr->domain_name_len != 0) && (parameter_ptr->domain_name_ptr != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) { + if (temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr) { + *temp_ptr++ = '&'; + } + + memcpy(temp_ptr, ep_domain_parameter, sizeof(ep_domain_parameter)); + temp_ptr += DOMAIN_PARAMETER_LEN; + memcpy(temp_ptr, parameter_ptr->domain_name_ptr, parameter_ptr->domain_name_len); + temp_ptr += parameter_ptr->domain_name_len; + } + + /******************************************************/ + /* If queue-mode is configured, fill needed fields */ + /******************************************************/ + + if (((parameter_ptr->binding_and_mode & 0x01) || (parameter_ptr->binding_and_mode & 0x04)) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) { + if (temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr) { + *temp_ptr++ = '&'; + } + + memcpy(temp_ptr, bs_queue_mode, sizeof(bs_queue_mode)); + temp_ptr += BS_QUEUE_MODE_PARAMATER_LEN; + + if (parameter_ptr->binding_and_mode & 0x01) { + *temp_ptr++ = 'U'; + if (parameter_ptr->binding_and_mode & 0x02) { + *temp_ptr++ = 'Q'; + } + } + + if (parameter_ptr->binding_and_mode & 0x04) { + *temp_ptr++ = 'S'; + if ((parameter_ptr->binding_and_mode & 0x02) && !(parameter_ptr->binding_and_mode & 0x01)) { + *temp_ptr++ = 'Q'; + } + } + } + + return SN_NSDL_SUCCESS; +} + +static bool validateParameters(sn_nsdl_ep_parameters_s *parameter_ptr) +{ + if( !validate( parameter_ptr->domain_name_ptr, parameter_ptr->domain_name_len, '&' ) ){ + return false; + } + + if( !validate( parameter_ptr->endpoint_name_ptr, parameter_ptr->endpoint_name_len, '&' ) ){ + return false; + } + + if( !validate( parameter_ptr->lifetime_ptr, parameter_ptr->lifetime_len, '&' ) ){ + return false; + } + + if( !validate( parameter_ptr->type_ptr, parameter_ptr->type_len, '&' ) ){ + return false; + } + return true; +} + +static bool validate(uint8_t* ptr, uint32_t len, char illegalChar) +{ + if( ptr ){ + for( uint32_t i=0; i < len; i++ ){ + if( ptr[i] == illegalChar ){ + return false; + } + } + } + return true; +} + +/** + * \fn static int8_t sn_nsdl_local_rx_function(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *address_ptr) + * + * \brief If received message is reply for the message that NSDL has been sent, it is processed here. Else, packet will be sent to application. + * \param *handle Pointer to nsdl-library handle + * \param *coap_packet_ptr Pointer to received CoAP packet + * \param *address_ptr Pointer to source address struct + * + * \return SN_NSDL_SUCCESS = 0, Failed = -1 + */ +static int8_t sn_nsdl_local_rx_function(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *address_ptr) +{ + if ((coap_packet_ptr == 0) || (address_ptr == 0)) { + return -1; + } + + bool is_reg_msg = false; + bool is_update_reg_msg = false; + bool is_unreg_msg = false; + if (coap_packet_ptr->msg_code == COAP_MSG_CODE_RESPONSE_CREATED) { + if (handle->grs->coap->sn_coap_block_data_size > 0) { + handle->register_msg_id += handle->register_msg_len / handle->grs->coap->sn_coap_block_data_size; + } + if (coap_packet_ptr->msg_id == handle->register_msg_id) { + handle->sn_nsdl_endpoint_registered = SN_NSDL_ENDPOINT_IS_REGISTERED; + is_reg_msg = true; + sn_grs_mark_resources_as_registered(handle); + if (sn_nsdl_resolve_ep_information(handle, coap_packet_ptr) != SN_NSDL_SUCCESS) { + return SN_NSDL_FAILURE; + } + } + } + + else if (coap_packet_ptr->msg_code == COAP_MSG_CODE_RESPONSE_CHANGED) { + if (handle->grs->coap->sn_coap_block_data_size > 0) { + handle->update_register_msg_id += handle->update_register_msg_len / handle->grs->coap->sn_coap_block_data_size; + } + if (coap_packet_ptr->msg_id == handle->update_register_msg_id) { + is_update_reg_msg = true; + } + } + + if (coap_packet_ptr->msg_id == handle->unregister_msg_id) { + is_unreg_msg = true; + if (coap_packet_ptr->msg_code == COAP_MSG_CODE_RESPONSE_DELETED) { + if (handle->ep_information_ptr->endpoint_name_ptr) { + handle->sn_nsdl_free(handle->ep_information_ptr->endpoint_name_ptr); + handle->ep_information_ptr->endpoint_name_ptr = 0; + handle->ep_information_ptr->endpoint_name_len = 0; + } + if (handle->ep_information_ptr->domain_name_ptr) { + handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr); + handle->ep_information_ptr->domain_name_ptr = 0; + handle->ep_information_ptr->domain_name_len = 0; + } + } + } + + /* No messages to wait for, or message was not response to our request */ + int ret = handle->sn_nsdl_rx_callback(handle, coap_packet_ptr, address_ptr); + if (is_reg_msg) { + handle->register_msg_id = 0; + handle->register_msg_len = 0; + } + else if (is_unreg_msg) { + handle->unregister_msg_id = 0; + } + else if (is_update_reg_msg) { + handle->update_register_msg_id = 0; + handle->update_register_msg_len = 0; + } + return ret; +} + +/** + * \fn static int8_t sn_nsdl_resolve_ep_information(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr) + * + * + * \brief Resolves endpoint information from received CoAP message + * \param *handle Pointer to nsdl-library handle + * \param *coap_packet_ptr Pointer to received CoAP message + * + * \return SN_NSDL_SUCCESS = 0, Failed = -1 + */ +static int8_t sn_nsdl_resolve_ep_information(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr) +{ + uint8_t *temp_ptr; + uint8_t parameter_count = 0; + uint16_t parameter_len = 0; + + if (!coap_packet_ptr || !coap_packet_ptr->options_list_ptr || + !coap_packet_ptr->options_list_ptr->location_path_ptr) { + return SN_NSDL_FAILURE; + } + + temp_ptr = coap_packet_ptr->options_list_ptr->location_path_ptr; + + while (temp_ptr <= (coap_packet_ptr->options_list_ptr->location_path_ptr + coap_packet_ptr->options_list_ptr->location_path_len)) { + + if ((temp_ptr == (coap_packet_ptr->options_list_ptr->location_path_ptr + coap_packet_ptr->options_list_ptr->location_path_len)) || (*temp_ptr == '/')) { + + parameter_count++; + if (parameter_count == 2) { + if (!handle->ep_information_ptr->domain_name_ptr) { + handle->ep_information_ptr->domain_name_len = parameter_len - 1; + handle->ep_information_ptr->domain_name_ptr = handle->sn_nsdl_alloc(handle->ep_information_ptr->domain_name_len); + if (!handle->ep_information_ptr->domain_name_ptr) { + return SN_NSDL_FAILURE; + } + memcpy(handle->ep_information_ptr->domain_name_ptr, temp_ptr - handle->ep_information_ptr->domain_name_len, handle->ep_information_ptr->domain_name_len); + } + + } + if (parameter_count == 3) { + if (!handle->ep_information_ptr->endpoint_name_ptr) { + handle->ep_information_ptr->endpoint_name_len = parameter_len - 1; + handle->ep_information_ptr->endpoint_name_ptr = handle->sn_nsdl_alloc(handle->ep_information_ptr->endpoint_name_len); + if (!handle->ep_information_ptr->endpoint_name_ptr) { + if (handle->ep_information_ptr->domain_name_ptr) { + handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr); + handle->ep_information_ptr->domain_name_ptr = NULL; + handle->ep_information_ptr->domain_name_len = 0; + } + + return SN_NSDL_FAILURE; + + } + memcpy(handle->ep_information_ptr->endpoint_name_ptr, temp_ptr - handle->ep_information_ptr->endpoint_name_len, handle->ep_information_ptr->endpoint_name_len); + } + } + parameter_len = 0; + } + parameter_len++; + temp_ptr++; + } + + + return SN_NSDL_SUCCESS; +} + +int8_t set_NSP_address(struct nsdl_s *handle, uint8_t *NSP_address, uint16_t port, sn_nsdl_addr_type_e address_type) +{ + + /* Check parameters and source pointers */ + if (!handle || !handle->nsp_address_ptr || !handle->nsp_address_ptr->omalw_address_ptr || !NSP_address) { + return SN_NSDL_FAILURE; + } + + handle->nsp_address_ptr->omalw_address_ptr->type = address_type; + handle->nsp_address_ptr->omalw_server_security = SEC_NOT_SET; + + if (address_type == SN_NSDL_ADDRESS_TYPE_IPV4) { + if (handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { + handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr); + } + + handle->nsp_address_ptr->omalw_address_ptr->addr_len = 4; + + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = handle->sn_nsdl_alloc(handle->nsp_address_ptr->omalw_address_ptr->addr_len); + if (!handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { + return SN_NSDL_FAILURE; + } + + memcpy(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr, NSP_address, handle->nsp_address_ptr->omalw_address_ptr->addr_len); + handle->nsp_address_ptr->omalw_address_ptr->port = port; + } + + else if (address_type == SN_NSDL_ADDRESS_TYPE_IPV6) { + if (handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { + handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr); + } + + handle->nsp_address_ptr->omalw_address_ptr->addr_len = 16; + + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = handle->sn_nsdl_alloc(handle->nsp_address_ptr->omalw_address_ptr->addr_len); + if (!handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { + return SN_NSDL_FAILURE; + } + + memcpy(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr, NSP_address, handle->nsp_address_ptr->omalw_address_ptr->addr_len); + handle->nsp_address_ptr->omalw_address_ptr->port = port; + } + return SN_NSDL_SUCCESS; +} + + +static uint8_t sn_nsdl_itoa_len(uint8_t value) +{ + uint8_t i = 0; + + do { + i++; + } while ((value /= 10) > 0); + + return i; +} + +static uint8_t *sn_nsdl_itoa(uint8_t *ptr, uint8_t value) +{ + + uint8_t start = 0; + uint8_t end = 0; + uint8_t i; + + i = 0; + + /* ITOA */ + do { + ptr[i++] = (value % 10) + '0'; + } while ((value /= 10) > 0); + + end = i - 1; + + /* reverse (part of ITOA) */ + while (start < end) { + uint8_t chr; + + chr = ptr[start]; + ptr[start] = ptr[end]; + ptr[end] = chr; + + start++; + end--; + + } + return (ptr + i); +} + +static int32_t sn_nsdl_atoi(uint8_t *ptr, uint8_t len) +{ + + int32_t result = 0; + + while (len--) { + + if (result) { + result *= 10; + } + + if (*ptr >= '0' && *ptr <= '9') { + result += *ptr - '0'; + } else{ + return -1; + } + + ptr++; + + } + return result; + +} + +static uint32_t sn_nsdl_ahextoi(uint8_t *ptr, uint8_t len) +{ + + uint32_t result = 0; + + while (len--) { + + if (result) { + result *= 16; + } + + if (*ptr >= '0' && *ptr <= '9') { + result += *ptr - '0'; + } else if (*ptr >= 'a' && *ptr <= 'f') { + result += *ptr - 87; + } else if (*ptr >= 'A' && *ptr <= 'F') { + result += *ptr - 55; + } + + ptr++; + + } + return result; + +} + +static int8_t sn_nsdl_resolve_lwm2m_address(struct nsdl_s *handle, uint8_t *uri, uint16_t uri_len) +{ +#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + if( uri_len < 2 ){ + return SN_NSDL_FAILURE; + } + uint8_t *temp_ptr = uri+2; + uint16_t i = 0; + uint8_t char_cnt = 0; + + /* jump over coap// */ + while ((*(temp_ptr - 2) != '/') || (*(temp_ptr - 1) != '/')) { + temp_ptr++; + if (temp_ptr - uri >= uri_len) { + return SN_NSDL_FAILURE; + } + } + + /* Resolve address type */ + /* Count semicolons */ + + int8_t endPos = -1; + + while (i < (uri_len - (temp_ptr - uri))) { + if (*(temp_ptr + i) == ':') { + char_cnt++; + }else if(*(temp_ptr + i) == ']'){ + endPos = i; + } + i++; + } + + uint8_t *temp_pos = temp_ptr; //store starting point in case of IPv4 parsing fails + + /* IPv6 */ + if (char_cnt > 2) { + i = 0; + + if( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr ){ + handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr); + } + + handle->nsp_address_ptr->omalw_address_ptr->type = SN_NSDL_ADDRESS_TYPE_IPV6; + handle->nsp_address_ptr->omalw_address_ptr->addr_len = 16; + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = handle->sn_nsdl_alloc(16); + if (!handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { + return SN_NSDL_FAILURE; + } + + memset(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr, 0, 16); + if (*temp_ptr == '[' && endPos > 0 && (temp_ptr - uri) + endPos < uri_len && *(temp_ptr + endPos + 1) == ':') { + temp_ptr++; + endPos--; + }else{ + /* return failure, because port is mandatory */ + return SN_NSDL_FAILURE; + } + + int8_t loopbackPos = -1; + if( char_cnt != 8 ){ + i = 0; + char_cnt -= 1; + while( i+1 < endPos ){ + if(*(temp_ptr + i) == ':' && *(temp_ptr + i+1) == ':') { + loopbackPos = i; + break; + } + i++; + } + } + i = 0; + + uint8_t numberOfZeros = 8 - char_cnt; + if(loopbackPos == 0){ + numberOfZeros++; + } + + if(loopbackPos == endPos-2){ + numberOfZeros++; + } + + /* Resolve address */ + int8_t pos = loopbackPos == 0?0:-1; + while (i < 16 && ((temp_ptr - uri) + char_cnt) < uri_len) { + char_cnt = 0; + if( pos == loopbackPos ){ + for( int k=0; k < numberOfZeros; k++ ){ + i+=2; + } + pos+=2; + temp_ptr += 2; + if( numberOfZeros == 8 ){ + temp_ptr++; + } + continue; + } + while (*(temp_ptr + char_cnt) != ':' && *(temp_ptr + char_cnt) != ']') { + char_cnt++; + pos++; + } + pos++; + + if (char_cnt <= 2) { + i++; + } + + while (char_cnt) { + if (char_cnt % 2) { + *(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr + i) = (uint8_t)sn_nsdl_ahextoi(temp_ptr, 1); + temp_ptr++; + char_cnt --; + } else { + *(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr + i) = (uint8_t)sn_nsdl_ahextoi(temp_ptr, 2); + temp_ptr += 2; + char_cnt -= 2; + } + i++; + } + temp_ptr++; + } + + temp_ptr++; + uint16_t handled = (temp_ptr - uri); + if( handled < uri_len ){ + if( *(temp_ptr + (uri_len - (temp_ptr - uri) -1)) == '/' ){ + handle->nsp_address_ptr->omalw_address_ptr->port = sn_nsdl_atoi(temp_ptr, uri_len - (temp_ptr - uri) - 1); + }else{ + handle->nsp_address_ptr->omalw_address_ptr->port = sn_nsdl_atoi(temp_ptr, uri_len - (temp_ptr - uri)); + } + } + } + /* IPv4 or Hostname */ + else if (char_cnt == 1) { + char_cnt = 0; + i = 0; + + if( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr ){ + handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr); + } + + /* Check address type */ + while (i < (uri_len - (temp_ptr - uri))) { + if (*(temp_ptr + i) == '.') { + char_cnt++; + } + i++; + } + + bool parseOk = true; + + /* Try IPv4 first */ + if (char_cnt == 3) { + i = 0; + char_cnt = 0; + + handle->nsp_address_ptr->omalw_address_ptr->type = SN_NSDL_ADDRESS_TYPE_IPV4; + handle->nsp_address_ptr->omalw_address_ptr->addr_len = 4; + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = handle->sn_nsdl_alloc(4); + if (!handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { + return SN_NSDL_FAILURE; + } + + while (parseOk && ((temp_ptr - uri) < uri_len) && *(temp_ptr - 1) != ':') { + i++; + + if (*(temp_ptr + i) == ':' || *(temp_ptr + i) == '.') { + int8_t value = (int8_t)sn_nsdl_atoi(temp_ptr, i); + if( value == -1 ){ + parseOk = false; + char_cnt = 3; + handle->sn_nsdl_free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr); + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = NULL; + break; + } + *(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr + char_cnt) = value; + temp_ptr = temp_ptr + i + 1; + char_cnt++; + i = 0; + } + } + if(parseOk) { + if( *(temp_ptr + (uri_len - (temp_ptr - uri) -1)) == '/' ){ + handle->nsp_address_ptr->omalw_address_ptr->port = sn_nsdl_atoi(temp_ptr, uri_len - (temp_ptr - uri) - 1); + }else{ + handle->nsp_address_ptr->omalw_address_ptr->port = sn_nsdl_atoi(temp_ptr, uri_len - (temp_ptr - uri)); + } + } + }else{ + parseOk = false; + } + + /* Then try Hostname */ + if(!parseOk) { + i = 0; + temp_ptr = temp_pos; + + handle->nsp_address_ptr->omalw_address_ptr->type = SN_NSDL_ADDRESS_TYPE_HOSTNAME; + + /* Resolve address length */ + if (uri_len > 0xff) { + return SN_NSDL_FAILURE; + } + + while (((temp_ptr - uri) + i < uri_len) && *(temp_ptr + i) != ':') { + i++; + } + + handle->nsp_address_ptr->omalw_address_ptr->addr_len = i; + + /* Copy address */ + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = handle->sn_nsdl_alloc(i); + if (!handle->nsp_address_ptr->omalw_address_ptr->addr_ptr) { + return SN_NSDL_FAILURE; + } + + memcpy(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr, temp_ptr, i); + + temp_ptr += i + 1; + + /* Set port */ + if( *(temp_ptr + (uri_len - (temp_ptr - uri) - 1)) == '/' ){ + handle->nsp_address_ptr->omalw_address_ptr->port = sn_nsdl_atoi(temp_ptr, uri_len - (temp_ptr - uri) - 1); + }else{ + handle->nsp_address_ptr->omalw_address_ptr->port = sn_nsdl_atoi(temp_ptr, uri_len - (temp_ptr - uri)); + } + } + } else { + return SN_NSDL_FAILURE; + } + + return SN_NSDL_SUCCESS; +#else + return SN_NSDL_FAILURE; +#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +} + + +int8_t sn_nsdl_process_oma_tlv(struct nsdl_s *handle, uint8_t *data_ptr, uint16_t data_len) +{ +#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + uint8_t *temp_ptr = data_ptr; + uint8_t type = 0; + uint16_t identifier = 0; + uint32_t length = 0; + uint8_t path_temp[5] = "0/0/x"; + + sn_nsdl_resource_info_s resource_temp = { + .resource_parameters_ptr = 0, + .mode = SN_GRS_STATIC, + .pathlen = 5, + .path = path_temp, + .resourcelen = 0, + .resource = 0, + .access = (sn_grs_resource_acl_e) 0x0f, /* All allowed */ + .sn_grs_dyn_res_callback = 0 + }; + + while ((temp_ptr - data_ptr) < data_len) { + /* Save type for future use */ + type = *temp_ptr++; + + /* * Bit 5: Indicates the Length of the Identifier. * */ + if (type & 0x20) { + /* 1=The Identifier field of this TLV is 16 bits long */ + identifier = (uint8_t)(*temp_ptr++) << 8; + identifier += (uint8_t) * temp_ptr++; + } else { + /* 0=The Identifier field of this TLV is 8 bits long */ + identifier = (uint8_t) * temp_ptr++; + } + + /* * Bit 4-3: Indicates the type of Length. * */ + if ((type & 0x18) == 0) { + /* 00 = No length field, the value immediately follows the Identifier field in is of the length indicated by Bits 2-0 of this field */ + length = (type & 0x07); + } else if ((type & 0x18) == 0x08) { + /* 01 = The Length field is 8-bits and Bits 2-0 MUST be ignored */ + length = *temp_ptr++; + } else if ((type & 0x18) == 0x10) { + /* 10 = The Length field is 16-bits and Bits 2-0 MUST be ignored */ + length = (uint8_t)(*temp_ptr++) << 8; + length += (uint8_t) * temp_ptr++; + } else if ((type & 0x18) == 0x18) { + /* 11 = The Length field is 24-bits and Bits 2-0 MUST be ignored */ + length = (uint8_t)(*temp_ptr++); + length = length << 16; + length += (uint8_t)(*temp_ptr++) << 8; + length += (uint8_t) * temp_ptr++; + } + + /* * Bits 7-6: Indicates the type of Identifier. * */ + if ((type & 0xC0) == 0x00) { + /* 00 = Object Instance in which case the Value contains one or more Resource TLVs */ + /* Not implemented, return failure */ + } else if ((type & 0xC0) == 0xC0) { + /* 11 = Resource with Value */ + switch (identifier) { + case 0: + /* Resolve LWM2M Server URI */ + sn_nsdl_resolve_lwm2m_address(handle, temp_ptr, length); + path_temp[4] = '0'; + resource_temp.resource = temp_ptr; + resource_temp.resourcelen = length; + if (sn_nsdl_create_resource(handle, &resource_temp) != SN_NSDL_SUCCESS) { + return SN_NSDL_FAILURE; + } + break; + case 2: + /* Resolve security Mode */ + handle->nsp_address_ptr->omalw_server_security = (omalw_server_security_t)sn_nsdl_atoi(temp_ptr, length); + path_temp[4] = '2'; + resource_temp.resource = temp_ptr; + resource_temp.resourcelen = length; + if (sn_nsdl_create_resource(handle, &resource_temp) != SN_NSDL_SUCCESS) { + return SN_NSDL_FAILURE; + } + + break; + case 3: + /* Public Key or Identity */ + path_temp[4] = '3'; + resource_temp.resource = temp_ptr; + resource_temp.resourcelen = length; + if (sn_nsdl_create_resource(handle, &resource_temp) != SN_NSDL_SUCCESS) { + return SN_NSDL_FAILURE; + } + break; + case 4: + /* Server Public Key or Identity */ + ; + path_temp[4] = '4'; + resource_temp.resource = temp_ptr; + resource_temp.resourcelen = length; + if (sn_nsdl_create_resource(handle, &resource_temp) != SN_NSDL_SUCCESS) { + return SN_NSDL_FAILURE; + } + + break; + case 5: + /* Secret Key */ + path_temp[4] = '5'; + resource_temp.resource = temp_ptr; + resource_temp.resourcelen = length; + if (sn_nsdl_create_resource(handle, &resource_temp) != SN_NSDL_SUCCESS) { + return SN_NSDL_FAILURE; + } + break; + default: + break; + } + + /* Move pointer to next TLV message */ + temp_ptr += length; + } + } + + return SN_NSDL_SUCCESS; +#else + return SN_NSDL_FAILURE; +#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +} + +static void sn_nsdl_check_oma_bs_status(struct nsdl_s *handle) +{ +#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + /* Check OMA BS status */ + if ((handle->nsp_address_ptr->omalw_server_security == PSK) && (handle->nsp_address_ptr->omalw_address_ptr->type != SN_NSDL_ADDRESS_TYPE_NONE)) { + /* call cb that oma bootstrap is done */ + if(handle->sn_nsdl_oma_bs_done_cb != 0){ + handle->sn_nsdl_oma_bs_done_cb(handle->nsp_address_ptr); + } + if(handle->sn_nsdl_oma_bs_done_cb_handle != 0){ + handle->sn_nsdl_oma_bs_done_cb_handle(handle->nsp_address_ptr, handle); + } + + } else if ((handle->nsp_address_ptr->omalw_server_security == CERTIFICATE) && (handle->nsp_address_ptr->omalw_address_ptr->type != SN_NSDL_ADDRESS_TYPE_NONE) && + ((sn_nsdl_get_resource(handle, 5, (void *)"0/0/5") != 0) && + (sn_nsdl_get_resource(handle, 5, (void *)"0/0/4") != 0) && + (sn_nsdl_get_resource(handle, 5, (void *)"0/0/3") != 0))) { + if( handle->sn_nsdl_oma_bs_done_cb ){ + handle->sn_nsdl_oma_bs_done_cb(handle->nsp_address_ptr); + } + if( handle->sn_nsdl_oma_bs_done_cb_handle ){ + handle->sn_nsdl_oma_bs_done_cb_handle(handle->nsp_address_ptr, handle); + } + } +#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +} + +static int8_t set_endpoint_info(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr) +{ + if (handle->ep_information_ptr->domain_name_ptr) { + handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr); + handle->ep_information_ptr->domain_name_ptr = 0; + handle->ep_information_ptr->domain_name_len = 0; + } + + if (handle->ep_information_ptr->endpoint_name_ptr) { + handle->sn_nsdl_free(handle->ep_information_ptr->endpoint_name_ptr); + handle->ep_information_ptr->endpoint_name_ptr = 0; + handle->ep_information_ptr->endpoint_name_len = 0; + } + + if (endpoint_info_ptr->domain_name_ptr && endpoint_info_ptr->domain_name_len) { + handle->ep_information_ptr->domain_name_ptr = handle->sn_nsdl_alloc(endpoint_info_ptr->domain_name_len); + + if (!handle->ep_information_ptr->domain_name_ptr) { + return -1; + } + + memcpy(handle->ep_information_ptr->domain_name_ptr, endpoint_info_ptr->domain_name_ptr, endpoint_info_ptr->domain_name_len); + handle->ep_information_ptr->domain_name_len = endpoint_info_ptr->domain_name_len; + } + + if (endpoint_info_ptr->endpoint_name_ptr && endpoint_info_ptr->endpoint_name_len) { + handle->ep_information_ptr->endpoint_name_ptr = handle->sn_nsdl_alloc(endpoint_info_ptr->endpoint_name_len); + + if (!handle->ep_information_ptr->endpoint_name_ptr) { + if (handle->ep_information_ptr->domain_name_ptr) { + handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr); + handle->ep_information_ptr->domain_name_ptr = 0; + handle->ep_information_ptr->domain_name_len = 0; + } + return -1; + } + + memcpy(handle->ep_information_ptr->endpoint_name_ptr, endpoint_info_ptr->endpoint_name_ptr, endpoint_info_ptr->endpoint_name_len); + handle->ep_information_ptr->endpoint_name_len = endpoint_info_ptr->endpoint_name_len; + } + + handle->ep_information_ptr->binding_and_mode = endpoint_info_ptr->binding_and_mode; + handle->ep_information_ptr->ds_register_mode = endpoint_info_ptr->ds_register_mode; + + handle->ep_information_ptr->location_ptr = 0; + handle->ep_information_ptr->location_len = 0; + + return 0; +} + +/* Wrapper */ +sn_grs_resource_list_s *sn_nsdl_list_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path) +{ + /* Check parameters */ + if (handle == NULL) { + return NULL; + } + + return sn_grs_list_resource(handle->grs, pathlen, path); +} + +void sn_nsdl_free_resource_list(struct nsdl_s *handle, sn_grs_resource_list_s *list) +{ + /* Check parameters */ + if (handle == NULL) { + return; + } + + sn_grs_free_resource_list(handle->grs, list); +} + +extern int8_t sn_nsdl_update_resource(struct nsdl_s *handle, sn_nsdl_resource_info_s *res) +{ + /* Check parameters */ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + + return sn_grs_update_resource(handle->grs, res); +} + +extern int8_t sn_nsdl_send_coap_message(struct nsdl_s *handle, sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr) +{ + /* Check parameters */ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + + return sn_grs_send_coap_message(handle, address_ptr, coap_hdr_ptr); +} + +extern int8_t sn_nsdl_create_resource(struct nsdl_s *handle, sn_nsdl_resource_info_s *res) +{ + /* Check parameters */ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + + return sn_grs_create_resource(handle->grs, res); +} + +extern int8_t sn_nsdl_delete_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path) +{ + /* Check parameters */ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + + return sn_grs_delete_resource(handle->grs, pathlen, path); +} +extern const sn_nsdl_resource_info_s *sn_nsdl_get_first_resource(struct nsdl_s *handle) +{ + /* Check parameters */ + if (handle == NULL) { + return NULL; + } + + return sn_grs_get_first_resource(handle->grs); +} +extern const sn_nsdl_resource_info_s *sn_nsdl_get_next_resource(struct nsdl_s *handle, const sn_nsdl_resource_info_s *resource) +{ + /* Check parameters */ + if (handle == NULL) { + return NULL; + } + + return sn_grs_get_next_resource(handle->grs, resource); +} + +extern sn_coap_hdr_s *sn_nsdl_build_response(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code) +{ + if (handle == NULL) { + return NULL; + } + + return sn_coap_build_response(handle->grs->coap, coap_packet_ptr, msg_code); +} + +extern void sn_nsdl_release_allocated_coap_msg_mem(struct nsdl_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr) +{ + if (handle == NULL) { + return; + } + + sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, freed_coap_msg_ptr); +} + +extern int8_t sn_nsdl_set_retransmission_parameters(struct nsdl_s *handle, + uint8_t resending_count, uint8_t resending_interval) +{ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + return sn_coap_protocol_set_retransmission_parameters(handle->grs->coap, + resending_count,resending_interval); +} + +extern int8_t sn_nsdl_set_retransmission_buffer(struct nsdl_s *handle, + uint8_t buffer_size_messages, uint16_t buffer_size_bytes) +{ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + return sn_coap_protocol_set_retransmission_buffer(handle->grs->coap, + buffer_size_messages, buffer_size_bytes); +} + +extern int8_t sn_nsdl_set_block_size(struct nsdl_s *handle, uint16_t block_size) +{ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + return sn_coap_protocol_set_block_size(handle->grs->coap, block_size); +} + +extern int8_t sn_nsdl_set_duplicate_buffer_size(struct nsdl_s *handle, uint8_t message_count) +{ + if (handle == NULL) { + return SN_NSDL_FAILURE; + } + return sn_coap_protocol_set_duplicate_buffer_size(handle->grs->coap, message_count); +} + +bool sn_nsdl_check_uint_overflow(uint16_t resource_size, uint16_t param_a, uint16_t param_b) +{ + uint16_t first_check = param_a + param_b; + if (first_check < param_b) { + return false; + } else { + uint16_t total = resource_size + first_check; + if (total < first_check) { + return false; + } else { + return true; + } + } +} diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/CMakeLists.txt b/features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/CMakeLists.txt new file mode 100644 index 0000000000..ea8f375813 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/CMakeLists.txt @@ -0,0 +1,15 @@ +# NB external pthreads dependency!! +find_package (Threads) +add_executable(multithread-linux-test + "main.c" + "mbed_client.c" +) +target_link_libraries(multithread-linux-test + mbed-client-c +) + +target_link_libraries(multithread-linux-test + ${CMAKE_THREAD_LIBS_INIT} +) + + diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/arguments.h b/features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/arguments.h new file mode 100644 index 0000000000..de133d4263 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/arguments.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 _ARGUMENTS_ +#define _ARGUMENTS_ +#include "resource_generation_help.h" + +#ifdef MACOSX +// ---------------------------------------- +// Mac OS X +#ifdef __DARWIN_UNIX03 +typedef unsigned short port_t; +#else +#include +#endif // __DARWIN_UNIX03 +typedef unsigned long ipaddr_t; +#endif + +/* Argument variables */ +uint16_t arg_port, arg_sport, arg_dport; //0-65535 +char arg_dst[64]; + +#endif /* _ARGUMENTS_ */ + + diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/main.c b/features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/main.c new file mode 100644 index 0000000000..f03a893dc3 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/main.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "sn_nsdl.h" +#include "sn_coap_header.h" +#include "sn_coap_protocol.h" +#include "sn_nsdl_lib.h" +#include "ns_list.h" +#include "arguments.h" + +#define NUMTHREADS 10 + +extern int register_endpoint(int port, sn_nsdl_ep_parameters_s *endpoint_ptr, int thread_id); +void stop_pgm(char *s) +{ + perror(s); + exit(1); +} + +void *own_alloc(uint16_t size) +{ + if(size) { + return malloc(size); + } + else { + return 0; + } +} + +void own_free(void *ptr) +{ + free(ptr); +} + +void arg_init(void) +{ + memcpy(arg_dst,"::1",32); //default localhost + arg_sport=5683; + arg_dport=5683; +} + + +void usage_show(void) +{ + printf("Usage:\n\n" + + "multithread-linux-test [-d 127.0.0.1] \n" + "-d NSP IPv4 address (default = ::1)\n" + "-dp NSP port number (default = 5683)\n"); +} + +/* function to be executed by the new thread */ +void* create_endpoint(void *arg) +{ + int index = *((int *) arg); + int port = 8100 + index; + sn_nsdl_ep_parameters_s *endpoint_ptr; + uint8_t endpoint_type[] = {"type"}; + uint8_t lifetime_ptr[] = {"120"}; + char str[10]; + sprintf(str, "THREAD_%d", index); + endpoint_ptr = own_alloc(sizeof(sn_nsdl_ep_parameters_s)); + if(endpoint_ptr) + { + memset(endpoint_ptr, 0, sizeof(sn_nsdl_ep_parameters_s)); + endpoint_ptr->endpoint_name_ptr = str; + endpoint_ptr->endpoint_name_len = strlen(str); + endpoint_ptr->type_ptr = endpoint_type; + endpoint_ptr->type_len = sizeof(endpoint_type)-1; + endpoint_ptr->lifetime_ptr = lifetime_ptr; + endpoint_ptr->lifetime_len = sizeof(lifetime_ptr)-1; + } + register_endpoint(port, endpoint_ptr, index); + if(endpoint_ptr) { + own_free(endpoint_ptr); + endpoint_ptr = 0; + } +} + +int main(int argc, char **argv) +{ + uint8_t i; + arg_init(); + + if (argc<1) + { + usage_show(); + } + else + { + i=1; //argv[0] is the command itself + + argc--; //get the real number of arguments + while (i<=argc) + { + //check arguments + if (!(strcmp("-h",argv[i]))) + { + usage_show(); + stop_pgm(""); + } + else if (!(strcmp("-d",argv[i]))) + { + if (i++==argc) stop_pgm("Argument missed for option -d\n"); + memcpy(arg_dst,argv[i],strlen((const char*)argv[i])+1); + i++; + continue; + } + else if (!(strcmp("-p",argv[i]))) + { + if (i++==argc) stop_pgm("Argument missed for option -p\n"); + arg_port=atoi(argv[i]); + i++; + continue; + } + else if (!(strcmp("-dp",argv[i]))) + { + if (i++==argc) stop_pgm("Argument missed for option -dp\n"); + arg_dport=atoi(argv[i]); + i++; + continue; + } + else + { + usage_show(); + stop_pgm("\n--- Argument error ---\n"); + } + + } + } + + pthread_t threads[NUMTHREADS]; + for (int index = 0; index < NUMTHREADS; index++) { + pthread_create(&threads[index], NULL, create_endpoint, (void *) &index); + sleep(1); + } + + for (int i = 0; i < NUMTHREADS; i) { + pthread_join(threads[i], NULL); + } + exit(0); +} + + + diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/mbed_client.c b/features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/mbed_client.c new file mode 100644 index 0000000000..973d71cb48 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/mbed_client.c @@ -0,0 +1,518 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 /* For SIGIGN and SIGINT */ +#include +#include +#include +#include "sn_nsdl.h" +#include "sn_coap_header.h" +#include "sn_coap_protocol.h" +#include "sn_nsdl_lib.h" +#include "ns_list.h" +#include "sn_grs.h" +#include "arguments.h" +#include "resource_generation_help.h" + +#define BUFLEN 1024 + +/* Resource paths and values */ +static uint8_t res_manufacturer[] = {"3/0/0"}; +static uint8_t res_manufacturer_val[] = {"ARM"}; +static uint8_t res_model_number[] = {"3/0/1"}; +static uint8_t res_model_number_val[] = {"1.00"}; + +static uint8_t res_temp[] = {"3303/0/temp"}; +static uint8_t res_type_test[] = {"t"}; + +struct thread_data_struct { + struct nsdl_s *handle; + struct sockaddr_in sa_dst; + struct sockaddr_in sa_src; + int sock_server; + socklen_t slen_sa_dst; + int thread_id; + sn_nsdl_ep_parameters_s *endpoint_ptr; + sn_nsdl_addr_s received_packet_address; + ns_list_link_t link; + bool registered; + uint32_t ns_system_time; + uint8_t delayed_token[8]; + uint8_t delayed_token_len; + sn_coap_msg_type_e delayed_msg_type; + uint8_t delayed_response_cnt; + uint8_t res_temp_val[16]; +}; +typedef struct thread_data_struct thread_data_struct_s; + +extern void stop_pgm(); +extern void *own_alloc(uint16_t size); +extern void own_free(void* ptr); + +/* Function templates */ +int register_endpoint(int port, sn_nsdl_ep_parameters_s *endpoint, int thread_id); +uint8_t tx_function(struct nsdl_s *handle, sn_nsdl_capab_e protocol , uint8_t *data, uint16_t len, sn_nsdl_addr_s *address); +uint8_t rx_function(struct nsdl_s *handle, sn_coap_hdr_s *coap_header, sn_nsdl_addr_s *address); +static void ctrl_c_handle_function(); +typedef void (*signalhandler_t)(int); +void coap_exec_poll_function(int thread_id); +int16_t receive_msg(thread_data_struct_s *data_item, uint8_t *buf); +uint8_t general_resource_cb(struct nsdl_s *handle, sn_coap_hdr_s *coap_ptr, sn_nsdl_addr_s *address, sn_nsdl_capab_e protocol); +int8_t compare_uripaths(sn_coap_hdr_s *coap_header, const uint8_t *uri_path_to_compare); +void send_ack(struct nsdl_s *handle, sn_coap_hdr_s *received_coap_ptr, sn_nsdl_addr_s *address); + +/* CoAP related globals*/ +uint8_t text_plain = COAP_CT_TEXT_PLAIN; +uint8_t link_format = COAP_CT_LINK_FORMAT; + +/* Resource related globals*/ +uint8_t *reg_location = 0; +int8_t reg_location_len; + +/* List containing thread specific data */ +typedef NS_LIST_HEAD(thread_data_struct_s, link) thread_data_struct_t; +static thread_data_struct_t NS_LIST_NAME_INIT(data_list); + +/*****************************************************/ +/* This is called from main to start the CoAP server */ +/*****************************************************/ +int register_endpoint(int port, sn_nsdl_ep_parameters_s *endpoint, int thread_id) +{ + printf("Register endpoint, port: %d, thread id: %d\n", port, thread_id); + thread_data_struct_s *data_item = NULL; + uint8_t nsp_addr[16]; + pthread_t coap_exec_thread; + uint8_t received_address[4]; + uint8_t buf[BUFLEN]; + int16_t rcv_size=0; + + data_item = malloc(sizeof(thread_data_struct_s)); + data_item->slen_sa_dst = sizeof(data_item->sa_dst); + memset(&data_item->received_packet_address, 0, sizeof(sn_nsdl_addr_s)); + memset(&data_item->sa_dst, 0, sizeof(struct sockaddr_in)); + memset(&data_item->sa_src, 0, sizeof(struct sockaddr_in)); + data_item->received_packet_address.addr_ptr = received_address; + data_item->endpoint_ptr = endpoint; + data_item->registered = false; + data_item->thread_id = thread_id; + data_item->ns_system_time = 1; + data_item->delayed_token_len = 0; + data_item->delayed_response_cnt = 0; + + /* Initial values for temperature */ + char temp[10]; + if (thread_id >= 9) { + sprintf(temp, "25.%d", thread_id); + } else { + sprintf(temp, "2%d.0", thread_id); + } + strcpy(data_item->res_temp_val,temp); + + sn_nsdl_resource_info_s *resource_ptr = 0; + + if (signal(SIGINT, (signalhandler_t)ctrl_c_handle_function) == SIG_ERR) { + printf("Error with SIGINT: %s\n", strerror(errno)); + return -1; + } + + /* Open the server socket*/ + if ((data_item->sock_server=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) ==-1 ) { + stop_pgm("socket() error"); + } + + /* Init the listen port addr*/ + memset((char *) &data_item->sa_src, 0, sizeof(data_item->sa_src)); + data_item->sa_src.sin_family = AF_INET; + data_item->sa_src.sin_port = htons(port); + + /* Listen to the port */ + data_item->sa_src.sin_addr.s_addr = INADDR_ANY; + if (bind(data_item->sock_server, (struct sockaddr *) &data_item->sa_src, sizeof(data_item->sa_src) ) == -1) { + stop_pgm("bind() error"); + } + + data_item->handle = sn_nsdl_init(&tx_function, &rx_function, &own_alloc, &own_free); + inet_pton(AF_INET, arg_dst, &nsp_addr); + + set_NSP_address(data_item->handle, nsp_addr, arg_dport, SN_NSDL_ADDRESS_TYPE_IPV4); + ns_list_add_to_start(&data_list, data_item); + + pthread_create(&coap_exec_thread, NULL, (void *)coap_exec_poll_function, data_item->thread_id); + + resource_ptr = own_alloc(sizeof(sn_nsdl_resource_info_s)); + if(!resource_ptr) { + return 0; + } + + memset(resource_ptr, 0, sizeof(sn_nsdl_resource_info_s)); + resource_ptr->resource_parameters_ptr = own_alloc(sizeof(sn_nsdl_resource_parameters_s)); + if(!resource_ptr->resource_parameters_ptr) { + own_free(resource_ptr); + return 0; + } + memset(resource_ptr->resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s)); + + /* Create resources */ + CREATE_STATIC_RESOURCE(resource_ptr, sizeof(res_manufacturer)-1, (uint8_t*) res_manufacturer, sizeof(res_type_test)-1, + (uint8_t*)res_type_test, (uint8_t*) res_manufacturer_val, + sizeof(res_manufacturer_val)-1, data_item->handle); + + CREATE_STATIC_RESOURCE(resource_ptr, sizeof(res_model_number)-1, (uint8_t*) res_model_number, sizeof(res_type_test)-1, + (uint8_t*)res_type_test, (uint8_t*) res_model_number_val, + sizeof(res_model_number_val)-1, data_item->handle); + + CREATE_DYNAMIC_RESOURCE(resource_ptr, sizeof(res_temp)-1, (uint8_t*) res_temp, sizeof(res_type_test)-1, + (uint8_t*)res_type_test, 0, &general_resource_cb, data_item->handle) + + /* Start registration */ + if(sn_nsdl_register_endpoint(data_item->handle, data_item->endpoint_ptr) == SN_NSDL_FAILURE) { + printf("NSP registration failed, thread:%d\n", data_item->thread_id); + } + + /* Free resource_ptr */ + if(resource_ptr->resource_parameters_ptr) { + own_free(resource_ptr->resource_parameters_ptr); + } + if(resource_ptr) { + own_free(resource_ptr); + } + + /* Main loop. */ + /* Listen and process incoming messages */ + while (1) + { + usleep(100); + memset(buf, 0, BUFLEN); + rcv_size = receive_msg(data_item,buf); + if(rcv_size > 0) { + sn_nsdl_process_coap(data_item->handle, buf, rcv_size, &data_item->received_packet_address); + } + } + return 0; +} + +int16_t receive_msg(thread_data_struct_s *data_item, uint8_t *buf) +{ + char rcv_in_addr[32]; + int16_t rcv_size=0; + + memset(rcv_in_addr,0,32); + + if ((rcv_size=recvfrom(data_item->sock_server, buf, BUFLEN, 0, + (struct sockaddr *)&data_item->sa_dst, (socklen_t*)&data_item->slen_sa_dst))==-1) { + stop_pgm("recvfrom()"); + } + else { + inet_ntop(AF_INET, &(data_item->sa_dst.sin_addr),rcv_in_addr,INET_ADDRSTRLEN); + data_item->received_packet_address.port = ntohs(data_item->sa_dst.sin_port); + data_item->received_packet_address.type = SN_NSDL_ADDRESS_TYPE_IPV4; + data_item->received_packet_address.addr_len = 4; + memcpy(data_item->received_packet_address.addr_ptr, &data_item->sa_dst.sin_addr, 4); + printf("\nRX %s.%d [%d B] - thread id: %d\n", rcv_in_addr, ntohs(data_item->sa_dst.sin_port), rcv_size, data_item->thread_id); + } + return rcv_size; +} + +/* Function needed for libCoap protocol. */ +uint8_t tx_function(struct nsdl_s *handle, sn_nsdl_capab_e protocol, + uint8_t *data, uint16_t len, sn_nsdl_addr_s *address) +{ + /* Set NSP address and port */ + thread_data_struct_s *data_item = NULL; + ns_list_foreach(thread_data_struct_s, item, &data_list) { + if (item->handle == handle) { + data_item = item; + break; + } + } + + if (data_item != NULL) { + printf("TX function - thread id: %d\n", data_item->thread_id); + ns_list_remove(&data_list, data_item); + data_item->sa_dst.sin_family = AF_INET; + data_item->sa_dst.sin_port = htons(address->port); + memcpy(&data_item->sa_dst.sin_addr, address->addr_ptr, address->addr_len); + ns_list_add_to_end(&data_list, data_item); + + int ret = sendto(data_item->sock_server, + data, + len, + 0, + (const struct sockaddr *)&data_item->sa_dst, + data_item->slen_sa_dst); + if (ret == -1) { + stop_pgm("sendto() failed"); + } + } + return 1; +} + +/* RX function for libNsdl. Passes CoAP responses sent from application to this function. Also response to registration message */ +uint8_t rx_function(struct nsdl_s *handle, sn_coap_hdr_s *coap_header, sn_nsdl_addr_s *address) +{ + if(!coap_header) + return 0; + + thread_data_struct_s *data_item = NULL; + ns_list_foreach(thread_data_struct_s, item, &data_list) { + if (item->handle == handle) { + data_item = item; + break; + } + } + if (!data_item) + return 0; + printf("\nRX callback mid:%d, thread id: %d\n", coap_header->msg_id, data_item->thread_id); + + /* If message is response to NSP registration */ + if(coap_header->msg_code == COAP_MSG_CODE_RESPONSE_CREATED && + !data_item->registered) { + reg_location_len = coap_header->options_list_ptr->location_path_len; + if(reg_location) + free(reg_location); + reg_location = malloc(reg_location_len); + + if(!reg_location) { + return 0; + } + + memcpy(reg_location, coap_header->options_list_ptr->location_path_ptr, reg_location_len); + printf("Registered to NSP: "); + for(int i = 0; i < reg_location_len; i++) + printf("%c", *(reg_location+i)); + printf("\n"); + + data_item->registered = true; + } + return 0; +} + +static void ctrl_c_handle_function() +{ + printf("Pressed ctrl-c\n"); + ns_list_foreach(thread_data_struct_s, item, &data_list) { + if (item->handle) { + sn_nsdl_unregister_endpoint(item->handle); + } + } + if(reg_location) + own_free(reg_location); + exit(1); +} + +void coap_exec_poll_function(int thread_id) +{ + uint8_t i = 0; + sn_coap_hdr_s coap_header; + + while(1) + { + sleep(1); + thread_data_struct_s *data_item = NULL; + ns_list_foreach(thread_data_struct_s, item, &data_list) { + if (item->thread_id == thread_id) { + data_item = item; + break; + } + } + if (data_item) { + /* nsdl execution function, must be called at least once / second. System time must be increased every second. */ + /* Cleans saved and unused data from libraries. Recommend to run this in same thread with other nsdl - functions */ + sn_nsdl_exec(data_item->handle, data_item->ns_system_time); + data_item->ns_system_time++; + + /* Check if reregistration needed */ + if(!(data_item->ns_system_time % (uint32_t)30) && data_item->ns_system_time) + { + printf("Update registration - thread id: %d\n", data_item->thread_id); + sn_nsdl_update_registration(data_item->handle, data_item->endpoint_ptr->lifetime_ptr, data_item->endpoint_ptr->lifetime_len); + } + + /* Send delayed response to request */ + /* This is just example. When receiving request to sen/temp, application send ack and after few seconds value for this resource */ + if(data_item->delayed_response_cnt == 1) { + printf("Delayed response - thread: %d\n", data_item->thread_id); + memset(&coap_header, 0, sizeof(sn_coap_hdr_s)); + + if(data_item->delayed_msg_type == COAP_MSG_TYPE_CONFIRMABLE) + coap_header.msg_type = COAP_MSG_TYPE_CONFIRMABLE; + else if(data_item->delayed_msg_type == COAP_MSG_TYPE_NON_CONFIRMABLE) + coap_header.msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE; + + coap_header.msg_code = COAP_MSG_CODE_RESPONSE_CONTENT; + + if(data_item->delayed_token_len) + { + coap_header.token_len = data_item->delayed_token_len; + coap_header.token_ptr = data_item->delayed_token; + data_item->delayed_token_len = 0; + } + + coap_header.payload_len = sizeof(data_item->res_temp_val) - 1; + coap_header.payload_ptr = data_item->res_temp_val; + + sn_nsdl_send_coap_message(data_item->handle, &data_item->received_packet_address, &coap_header); + + data_item->delayed_response_cnt = 0; + + } + else if(data_item->delayed_response_cnt > 1) { + data_item->delayed_response_cnt--; + } + } + } +} + +/* This is callback for other DYNAMIC resources */ +uint8_t general_resource_cb(struct nsdl_s *handle, sn_coap_hdr_s *received_coap_ptr, + sn_nsdl_addr_s *address, sn_nsdl_capab_e protocol) +{ + sn_coap_hdr_s *coap_res_ptr = 0; + thread_data_struct_s *data_item = NULL; + ns_list_foreach(thread_data_struct_s, item, &data_list) { + if (item->handle == handle) { + data_item = item; + break; + } + } + if (!data_item) { + return 0; + } + + if (received_coap_ptr->msg_code == COAP_MSG_CODE_REQUEST_GET) { + printf("\nGeneral callback - thread id: %d\n", data_item->thread_id); + coap_res_ptr = sn_nsdl_build_response(data_item->handle, received_coap_ptr, COAP_MSG_CODE_RESPONSE_CONTENT); + coap_res_ptr->content_type_ptr = &text_plain; + coap_res_ptr->content_type_len = sizeof(text_plain); + + /* Temperature resource */ + /* This makes delayed response, first ack and after that real value */ + if(compare_uripaths(received_coap_ptr, res_temp)) + { + send_ack(data_item->handle,received_coap_ptr, &data_item->received_packet_address); + if(coap_res_ptr->token_ptr) { + own_free(coap_res_ptr->token_ptr); + } + if(coap_res_ptr->options_list_ptr) { + own_free(coap_res_ptr->options_list_ptr); + } + own_free(coap_res_ptr); + return 0; + } + sn_nsdl_send_coap_message(data_item->handle, address, coap_res_ptr); + } + else if (received_coap_ptr->msg_code == COAP_MSG_CODE_REQUEST_PUT) { + if (received_coap_ptr->payload_ptr && received_coap_ptr->payload_len < 16) { + ns_list_remove(&data_list, data_item); + memcpy(data_item->res_temp_val,received_coap_ptr->payload_ptr, received_coap_ptr->payload_len); + printf("Update resource value to %s, thread id: %d\n", data_item->res_temp_val, data_item->thread_id); + ns_list_add_to_end(&data_list, data_item); + } + coap_res_ptr = sn_nsdl_build_response(data_item->handle, received_coap_ptr, COAP_MSG_CODE_RESPONSE_CHANGED); + sn_nsdl_send_coap_message(data_item->handle, address, coap_res_ptr); + } + /* Method not supported */ + else { + printf("Method not supported\n"); + coap_res_ptr = sn_coap_build_response(handle->grs->coap, received_coap_ptr, COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED); + sn_nsdl_send_coap_message(handle, address, coap_res_ptr); + } + + if(coap_res_ptr->token_ptr) { + own_free(coap_res_ptr->token_ptr); + } + + if(coap_res_ptr->options_list_ptr) { + own_free(coap_res_ptr->options_list_ptr); + } + own_free(coap_res_ptr); + + return 0; +} + +int8_t compare_uripaths(sn_coap_hdr_s *coap_header, const uint8_t *uri_path_to_compare) +{ + if(memcmp(coap_header->uri_path_ptr,&uri_path_to_compare[0], coap_header->uri_path_len) == 0) + { + return 1; + } + return 0; +} + +void send_ack(struct nsdl_s *handle, sn_coap_hdr_s *received_coap_ptr, sn_nsdl_addr_s *address/*, sn_nsdl_addr_s *received_packet_address*/) +{ + printf("Send acknowledgement\n"); + sn_coap_hdr_s *coap_res_ptr = 0; + uint16_t message_len = 0; + uint8_t *message_ptr; + thread_data_struct_s *data_item = NULL; + ns_list_foreach(thread_data_struct_s, item, &data_list) { + if (item->handle == handle) { + data_item = item; + break; + } + } + if (data_item) { + if (received_coap_ptr->msg_code == COAP_MSG_CODE_REQUEST_GET) + { + if (received_coap_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) { + coap_res_ptr = own_alloc(sizeof(sn_coap_hdr_s)); + if(!coap_res_ptr) { + return; + } + memset(coap_res_ptr, 0x00, sizeof(sn_coap_hdr_s)); + coap_res_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + coap_res_ptr->msg_code = COAP_MSG_CODE_EMPTY; + coap_res_ptr->msg_id = received_coap_ptr->msg_id; + data_item->delayed_msg_type = COAP_MSG_TYPE_CONFIRMABLE; + } + else { + data_item->delayed_msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE; + } + + if(received_coap_ptr->token_len) { + memset(data_item->delayed_token, 0, 8); + data_item->delayed_token_len = received_coap_ptr->token_len; + memcpy(data_item->delayed_token, received_coap_ptr->token_ptr, received_coap_ptr->token_len); + } + data_item->delayed_response_cnt = 1; + } + } + + if(coap_res_ptr) { + message_len = sn_coap_builder_calc_needed_packet_data_size(coap_res_ptr); + message_ptr = own_alloc(message_len); + if(!message_ptr) { + return; + } + + sn_coap_builder(message_ptr, coap_res_ptr); + tx_function(handle,SN_NSDL_PROTOCOL_COAP, message_ptr, message_len, address); + + /* Free memory */ + if(coap_res_ptr) { + own_free(coap_res_ptr); + } + own_free(message_ptr); + } + return; +} diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/module.json b/features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/module.json new file mode 100644 index 0000000000..36989d394f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/module.json @@ -0,0 +1,13 @@ +{ + "name": "multithread-linux-test", + "version": "1.0.0", + "description": "Example application how to use mbed-client-c library", + "private": true, + "keywords": [], + "author": "Antti Yli-Tokola ", + "license": "Apache-2.0", + "dependencies": { + "mbed-client-c": "^2.0.0" + }, + "bin": "./" +} diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/resource_generation_help.h b/features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/resource_generation_help.h new file mode 100644 index 0000000000..29c3117692 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/resource_generation_help.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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_GENERATION_HELP_H_ +#define RESOURCE_GENERATION_HELP_H_ + +/* + * A helper macro to create a static resoure + */ +#define CREATE_STATIC_RESOURCE(resource_structure, pt_len, pt, rpp_len, rpp_ptr, rsc, rsc_len, handle) \ +{ \ + resource_structure->access = (sn_grs_resource_acl_e)0xff; \ + resource_structure->mode = SN_GRS_STATIC; \ + resource_structure->pathlen = pt_len; \ + resource_structure->path = pt; \ + resource_structure->resource_parameters_ptr->resource_type_len = rpp_len; \ + resource_structure->resource_parameters_ptr->resource_type_ptr = rpp_ptr; \ + resource_structure->resource = rsc; \ + resource_structure->resourcelen = rsc_len; \ + sn_nsdl_create_resource(handle,resource_structure); \ +} + + +/* + * A helper macro to create a dynamic resoure + */ +#define CREATE_DYNAMIC_RESOURCE(resource_structure, pt_len, pt, rpp_len, rpp_ptr, is_observable, callback_ptr, handle) \ +{ \ + resource_structure->access = (sn_grs_resource_acl_e)0xff; \ + resource_structure->resource = 0; \ + resource_structure->resourcelen = 0; \ + resource_structure->sn_grs_dyn_res_callback = callback_ptr; \ + resource_structure->mode = SN_GRS_DYNAMIC; \ + resource_structure->pathlen = pt_len; \ + resource_structure->path = pt; \ + resource_structure->resource_parameters_ptr->resource_type_len = rpp_len; \ + resource_structure->resource_parameters_ptr->resource_type_ptr = rpp_ptr; \ + resource_structure->resource_parameters_ptr->observable = is_observable; \ + sn_nsdl_create_resource(handle,resource_structure); \ +} + +#define INIT_REGISTER_NSDL_ENDPOINT(endpoint_structure, name, typename_ptr, lifetime_ptr) \ +{ \ + if(!endpoint_structure) \ + { \ + endpoint_structure = own_alloc(sizeof(sn_nsdl_ep_parameters_s)); \ + } \ + if(endpoint_structure) \ + { \ + memset(endpoint_structure, 0, sizeof(sn_nsdl_ep_parameters_s)); \ + endpoint_structure->endpoint_name_ptr = name; \ + endpoint_structure->endpoint_name_len = sizeof(name)-1; \ + endpoint_structure->type_ptr = typename_ptr; \ + endpoint_structure->type_len = sizeof(typename_ptr)-1; \ + endpoint_structure->lifetime_ptr = lifetime_ptr; \ + endpoint_structure->lifetime_len = sizeof(lifetime_ptr)-1; \ + } \ +} + +#define CLEAN_REGISTER_NSDL_ENDPOINT(endpoint_structure) \ +{ \ + if(endpoint_structure) \ + { \ + own_free(endpoint_structure); \ + endpoint_structure = 0; \ + } \ +} \ + +#endif /* RESOURCE_GENERATION_HELP_H_ */ diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/tester.sh b/features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/tester.sh new file mode 100755 index 0000000000..1ce8c9edf8 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/multithread-linux-test/tester.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# Copyright (c) 2015 ARM Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# * http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +initial_values=(20.0 21.0 22.0 23.0 24.0 25.0 26.0 27.0 28.0 25.9 ) +new_values=(30.0 31.0 32.0 33.0 34.0 35.0 36.0 37.0 38.0 35.9 ) +DESTINATION=$1 +function read_default_values { + echo "Read default values" + for i in {0..9} + do + value=`curl -s -H "Authorization: Basic YWRtaW46c2VjcmV0" "http://${DESTINATION}:8080/endpoints/THREAD_${i}/3303/0/temp?sync=true"` + echo "Thread${i} $value" + if [ "${initial_values[$i]}" != "$value" ]; + then + echo "Value ${initial_values[$i]} does not match to $value" + exit 1 + fi + done +} + +function read_new_values { + echo "Read new values" + for i in {0..9} + do + value=`curl -s -H "Authorization: Basic YWRtaW46c2VjcmV0" "http://${DESTINATION}:8080/endpoints/THREAD_${i}/3303/0/temp?sync=true"` + echo "Thread${i} $value" + if [ "${new_values[$i]}" != "$value" ]; + then + echo "Value ${new_values[$i]} does not match to $value" + exit 1 + fi + done +} + +function post_new_values { + echo "Post new values" + for i in {0..9} + do + curl -X PUT -H "Authorization: Basic YWRtaW46c2VjcmV0" "http://${DESTINATION}:8080/endpoints/THREAD_${i}/3303/0/temp?sync=true" -d "${new_values[$i]}" + done +} + +function post_default_values { + echo "Post default values" + for i in {0..9} + do + curl -X PUT -H "Authorization: Basic YWRtaW46c2VjcmV0" "http://${DESTINATION}:8080/endpoints/THREAD_${i}/3303/0/temp?sync=true" -d "${initial_values[$i]}" + done +} +post_default_values +while [ true ]; do + read_default_values + sleep 2 + post_new_values + sleep 2 + read_new_values + sleep 2 + post_default_values + sleep 2 +done + + + + diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/MakefileWorker.mk b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/MakefileWorker.mk new file mode 100755 index 0000000000..2096ced036 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/MakefileWorker.mk @@ -0,0 +1,562 @@ +#--------- +# +# MakefileWorker.mk +# +# Include this helper file in your makefile +# It makes +# A static library +# A test executable +# +# See this example for parameter settings +# examples/Makefile +# +#---------- +# Inputs - these variables describe what to build +# +# INCLUDE_DIRS - Directories used to search for include files. +# This generates a -I for each directory +# SRC_DIRS - Directories containing source file to built into the library +# SRC_FILES - Specific source files to build into library. Helpful when not all code +# in a directory can be built for test (hopefully a temporary situation) +# TEST_SRC_DIRS - Directories containing unit test code build into the unit test runner +# These do not go in a library. They are explicitly included in the test runner +# TEST_SRC_FILES - Specific source files to build into the unit test runner +# These do not go in a library. They are explicitly included in the test runner +# MOCKS_SRC_DIRS - Directories containing mock source files to build into the test runner +# These do not go in a library. They are explicitly included in the test runner +#---------- +# You can adjust these variables to influence how to build the test target +# and where to put and name outputs +# See below to determine defaults +# COMPONENT_NAME - the name of the thing being built +# TEST_TARGET - name the test executable. By default it is +# $(COMPONENT_NAME)_tests +# Helpful if you want 1 > make files in the same directory with different +# executables as output. +# CPPUTEST_HOME - where CppUTest home dir found +# TARGET_PLATFORM - Influences how the outputs are generated by modifying the +# CPPUTEST_OBJS_DIR and CPPUTEST_LIB_DIR to use a sub-directory under the +# normal objs and lib directories. Also modifies where to search for the +# CPPUTEST_LIB to link against. +# CPPUTEST_OBJS_DIR - a directory where o and d files go +# CPPUTEST_LIB_DIR - a directory where libs go +# CPPUTEST_ENABLE_DEBUG - build for debug +# CPPUTEST_USE_MEM_LEAK_DETECTION - Links with overridden new and delete +# CPPUTEST_USE_STD_CPP_LIB - Set to N to keep the standard C++ library out +# of the test harness +# CPPUTEST_USE_GCOV - Turn on coverage analysis +# Clean then build with this flag set to Y, then 'make gcov' +# CPPUTEST_MAPFILE - generate a map file +# CPPUTEST_WARNINGFLAGS - overly picky by default +# OTHER_MAKEFILE_TO_INCLUDE - a hook to use this makefile to make +# other targets. Like CSlim, which is part of fitnesse +# CPPUTEST_USE_VPATH - Use Make's VPATH functionality to support user +# specification of source files and directories that aren't below +# the user's Makefile in the directory tree, like: +# SRC_DIRS += ../../lib/foo +# It defaults to N, and shouldn't be necessary except in the above case. +#---------- +# +# Other flags users can initialize to sneak in their settings +# CPPUTEST_CXXFLAGS - flags for the C++ compiler +# CPPUTEST_CPPFLAGS - flags for the C++ AND C preprocessor +# CPPUTEST_CFLAGS - flags for the C complier +# CPPUTEST_LDFLAGS - Linker flags +#---------- + +# Some behavior is weird on some platforms. Need to discover the platform. + +# Platforms +UNAME_OUTPUT = "$(shell uname -a)" +MACOSX_STR = Darwin +MINGW_STR = MINGW +CYGWIN_STR = CYGWIN +LINUX_STR = Linux +SUNOS_STR = SunOS +UNKNWOWN_OS_STR = Unknown + +# Compilers +CC_VERSION_OUTPUT ="$(shell $(CXX) -v 2>&1)" +CLANG_STR = clang +SUNSTUDIO_CXX_STR = SunStudio + +UNAME_OS = $(UNKNWOWN_OS_STR) + +ifeq ($(findstring $(MINGW_STR),$(UNAME_OUTPUT)),$(MINGW_STR)) + UNAME_OS = $(MINGW_STR) +endif + +ifeq ($(findstring $(CYGWIN_STR),$(UNAME_OUTPUT)),$(CYGWIN_STR)) + UNAME_OS = $(CYGWIN_STR) +endif + +ifeq ($(findstring $(LINUX_STR),$(UNAME_OUTPUT)),$(LINUX_STR)) + UNAME_OS = $(LINUX_STR) +endif + +ifeq ($(findstring $(MACOSX_STR),$(UNAME_OUTPUT)),$(MACOSX_STR)) + UNAME_OS = $(MACOSX_STR) +#lion has a problem with the 'v' part of -a + UNAME_OUTPUT = "$(shell uname -pmnrs)" +endif + +ifeq ($(findstring $(SUNOS_STR),$(UNAME_OUTPUT)),$(SUNOS_STR)) + UNAME_OS = $(SUNOS_STR) + + SUNSTUDIO_CXX_ERR_STR = CC -flags +ifeq ($(findstring $(SUNSTUDIO_CXX_ERR_STR),$(CC_VERSION_OUTPUT)),$(SUNSTUDIO_CXX_ERR_STR)) + CC_VERSION_OUTPUT ="$(shell $(CXX) -V 2>&1)" + COMPILER_NAME = $(SUNSTUDIO_CXX_STR) +endif +endif + +ifeq ($(findstring $(CLANG_STR),$(CC_VERSION_OUTPUT)),$(CLANG_STR)) + COMPILER_NAME = $(CLANG_STR) +endif + +#Kludge for mingw, it does not have cc.exe, but gcc.exe will do +ifeq ($(UNAME_OS),$(MINGW_STR)) + CC := gcc +endif + +#And another kludge. Exception handling in gcc 4.6.2 is broken when linking the +# Standard C++ library as a shared library. Unbelievable. +ifeq ($(UNAME_OS),$(MINGW_STR)) + CPPUTEST_LDFLAGS += -static +endif +ifeq ($(UNAME_OS),$(CYGWIN_STR)) + CPPUTEST_LDFLAGS += -static +endif + + +#Kludge for MacOsX gcc compiler on Darwin9 who can't handle pendantic +ifeq ($(UNAME_OS),$(MACOSX_STR)) +ifeq ($(findstring Version 9,$(UNAME_OUTPUT)),Version 9) + CPPUTEST_PEDANTIC_ERRORS = N +endif +endif + +ifndef COMPONENT_NAME + COMPONENT_NAME = name_this_in_the_makefile +endif + +# Debug on by default +ifndef CPPUTEST_ENABLE_DEBUG + CPPUTEST_ENABLE_DEBUG = Y +endif + +# new and delete for memory leak detection on by default +ifndef CPPUTEST_USE_MEM_LEAK_DETECTION + CPPUTEST_USE_MEM_LEAK_DETECTION = Y +endif + +# Use the standard C library +ifndef CPPUTEST_USE_STD_C_LIB + CPPUTEST_USE_STD_C_LIB = Y +endif + +# Use the standard C++ library +ifndef CPPUTEST_USE_STD_CPP_LIB + CPPUTEST_USE_STD_CPP_LIB = Y +endif + +# Use gcov, off by default +ifndef CPPUTEST_USE_GCOV + CPPUTEST_USE_GCOV = N +endif + +ifndef CPPUTEST_PEDANTIC_ERRORS + CPPUTEST_PEDANTIC_ERRORS = Y +endif + +# Default warnings +ifndef CPPUTEST_WARNINGFLAGS + CPPUTEST_WARNINGFLAGS = -Wall -Wextra -Wshadow -Wswitch-default -Wswitch-enum -Wconversion +ifeq ($(CPPUTEST_PEDANTIC_ERRORS), Y) +# CPPUTEST_WARNINGFLAGS += -pedantic-errors + CPPUTEST_WARNINGFLAGS += -pedantic +endif +ifeq ($(UNAME_OS),$(LINUX_STR)) + CPPUTEST_WARNINGFLAGS += -Wsign-conversion +endif + CPPUTEST_CXX_WARNINGFLAGS = -Woverloaded-virtual + CPPUTEST_C_WARNINGFLAGS = -Wstrict-prototypes +endif + +#Wonderful extra compiler warnings with clang +ifeq ($(COMPILER_NAME),$(CLANG_STR)) +# -Wno-disabled-macro-expansion -> Have to disable the macro expansion warning as the operator new overload warns on that. +# -Wno-padded -> I sort-of like this warning but if there is a bool at the end of the class, it seems impossible to remove it! (except by making padding explicit) +# -Wno-global-constructors Wno-exit-time-destructors -> Great warnings, but in CppUTest it is impossible to avoid as the automatic test registration depends on the global ctor and dtor +# -Wno-weak-vtables -> The TEST_GROUP macro declares a class and will automatically inline its methods. Thats ok as they are only in one translation unit. Unfortunately, the warning can't detect that, so it must be disabled. + CPPUTEST_CXX_WARNINGFLAGS += -Weverything -Wno-disabled-macro-expansion -Wno-padded -Wno-global-constructors -Wno-exit-time-destructors -Wno-weak-vtables + CPPUTEST_C_WARNINGFLAGS += -Weverything -Wno-padded +endif + +# Uhm. Maybe put some warning flags for SunStudio here? +ifeq ($(COMPILER_NAME),$(SUNSTUDIO_CXX_STR)) + CPPUTEST_CXX_WARNINGFLAGS = + CPPUTEST_C_WARNINGFLAGS = +endif + +# Default dir for temporary files (d, o) +ifndef CPPUTEST_OBJS_DIR +ifndef TARGET_PLATFORM + CPPUTEST_OBJS_DIR = objs +else + CPPUTEST_OBJS_DIR = objs/$(TARGET_PLATFORM) +endif +endif + +# Default dir for the outout library +ifndef CPPUTEST_LIB_DIR +ifndef TARGET_PLATFORM + CPPUTEST_LIB_DIR = lib +else + CPPUTEST_LIB_DIR = lib/$(TARGET_PLATFORM) +endif +endif + +# No map by default +ifndef CPPUTEST_MAP_FILE + CPPUTEST_MAP_FILE = N +endif + +# No extentions is default +ifndef CPPUTEST_USE_EXTENSIONS + CPPUTEST_USE_EXTENSIONS = N +endif + +# No VPATH is default +ifndef CPPUTEST_USE_VPATH + CPPUTEST_USE_VPATH := N +endif +# Make empty, instead of 'N', for usage in $(if ) conditionals +ifneq ($(CPPUTEST_USE_VPATH), Y) + CPPUTEST_USE_VPATH := +endif + +ifndef TARGET_PLATFORM +#CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_HOME)/lib +CPPUTEST_LIB_LINK_DIR = /usr/lib/x86_64-linux-gnu +else +CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_HOME)/lib/$(TARGET_PLATFORM) +endif + +# -------------------------------------- +# derived flags in the following area +# -------------------------------------- + +# Without the C library, we'll need to disable the C++ library and ... +ifeq ($(CPPUTEST_USE_STD_C_LIB), N) + CPPUTEST_USE_STD_CPP_LIB = N + CPPUTEST_USE_MEM_LEAK_DETECTION = N + CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_C_LIB_DISABLED + CPPUTEST_CPPFLAGS += -nostdinc +endif + +CPPUTEST_CPPFLAGS += -DCPPUTEST_COMPILATION + +ifeq ($(CPPUTEST_USE_MEM_LEAK_DETECTION), N) + CPPUTEST_CPPFLAGS += -DCPPUTEST_MEM_LEAK_DETECTION_DISABLED +else + ifndef CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE + CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE = -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorNewMacros.h + endif + ifndef CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE + CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE = -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorMallocMacros.h + endif +endif + +ifeq ($(CPPUTEST_ENABLE_DEBUG), Y) + CPPUTEST_CXXFLAGS += -g + CPPUTEST_CFLAGS += -g + CPPUTEST_LDFLAGS += -g +endif + +ifeq ($(CPPUTEST_USE_STD_CPP_LIB), N) + CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_CPP_LIB_DISABLED +ifeq ($(CPPUTEST_USE_STD_C_LIB), Y) + CPPUTEST_CXXFLAGS += -nostdinc++ +endif +endif + +ifdef $(GMOCK_HOME) + GTEST_HOME = $(GMOCK_HOME)/gtest + CPPUTEST_CPPFLAGS += -I$(GMOCK_HOME)/include + GMOCK_LIBRARY = $(GMOCK_HOME)/lib/.libs/libgmock.a + LD_LIBRARIES += $(GMOCK_LIBRARY) + CPPUTEST_CPPFLAGS += -DINCLUDE_GTEST_TESTS + CPPUTEST_WARNINGFLAGS = + CPPUTEST_CPPFLAGS += -I$(GTEST_HOME)/include -I$(GTEST_HOME) + GTEST_LIBRARY = $(GTEST_HOME)/lib/.libs/libgtest.a + LD_LIBRARIES += $(GTEST_LIBRARY) +endif + + +ifeq ($(CPPUTEST_USE_GCOV), Y) + CPPUTEST_CXXFLAGS += -fprofile-arcs -ftest-coverage + CPPUTEST_CFLAGS += -fprofile-arcs -ftest-coverage +endif + +CPPUTEST_CXXFLAGS += $(CPPUTEST_WARNINGFLAGS) $(CPPUTEST_CXX_WARNINGFLAGS) +CPPUTEST_CPPFLAGS += $(CPPUTEST_WARNINGFLAGS) +CPPUTEST_CXXFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE) +CPPUTEST_CPPFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE) +CPPUTEST_CFLAGS += $(CPPUTEST_C_WARNINGFLAGS) + +TARGET_MAP = $(COMPONENT_NAME).map.txt +ifeq ($(CPPUTEST_MAP_FILE), Y) + CPPUTEST_LDFLAGS += -Wl,-map,$(TARGET_MAP) +endif + +# Link with CppUTest lib +CPPUTEST_LIB = $(CPPUTEST_LIB_LINK_DIR)/libCppUTest.a + +ifeq ($(CPPUTEST_USE_EXTENSIONS), Y) +CPPUTEST_LIB += $(CPPUTEST_LIB_LINK_DIR)/libCppUTestExt.a +endif + +ifdef CPPUTEST_STATIC_REALTIME + LD_LIBRARIES += -lrt +endif + +TARGET_LIB = \ + $(CPPUTEST_LIB_DIR)/lib$(COMPONENT_NAME).a + +ifndef TEST_TARGET + ifndef TARGET_PLATFORM + TEST_TARGET = $(COMPONENT_NAME)_tests + else + TEST_TARGET = $(COMPONENT_NAME)_$(TARGET_PLATFORM)_tests + endif +endif + +#Helper Functions +get_src_from_dir = $(wildcard $1/*.cpp) $(wildcard $1/*.cc) $(wildcard $1/*.c) +get_dirs_from_dirspec = $(wildcard $1) +get_src_from_dir_list = $(foreach dir, $1, $(call get_src_from_dir,$(dir))) +__src_to = $(subst .c,$1, $(subst .cc,$1, $(subst .cpp,$1,$(if $(CPPUTEST_USE_VPATH),$(notdir $2),$2)))) +src_to = $(addprefix $(CPPUTEST_OBJS_DIR)/,$(call __src_to,$1,$2)) +src_to_o = $(call src_to,.o,$1) +src_to_d = $(call src_to,.d,$1) +src_to_gcda = $(call src_to,.gcda,$1) +src_to_gcno = $(call src_to,.gcno,$1) +time = $(shell date +%s) +delta_t = $(eval minus, $1, $2) +debug_print_list = $(foreach word,$1,echo " $(word)";) echo; + +#Derived +STUFF_TO_CLEAN += $(TEST_TARGET) $(TEST_TARGET).exe $(TARGET_LIB) $(TARGET_MAP) + +SRC += $(call get_src_from_dir_list, $(SRC_DIRS)) $(SRC_FILES) +OBJ = $(call src_to_o,$(SRC)) + +STUFF_TO_CLEAN += $(OBJ) + +TEST_SRC += $(call get_src_from_dir_list, $(TEST_SRC_DIRS)) $(TEST_SRC_FILES) +TEST_OBJS = $(call src_to_o,$(TEST_SRC)) +STUFF_TO_CLEAN += $(TEST_OBJS) + + +MOCKS_SRC += $(call get_src_from_dir_list, $(MOCKS_SRC_DIRS)) +MOCKS_OBJS = $(call src_to_o,$(MOCKS_SRC)) +STUFF_TO_CLEAN += $(MOCKS_OBJS) + +ALL_SRC = $(SRC) $(TEST_SRC) $(MOCKS_SRC) + +# If we're using VPATH +ifeq ($(CPPUTEST_USE_VPATH), Y) +# gather all the source directories and add them + VPATH += $(sort $(dir $(ALL_SRC))) +# Add the component name to the objs dir path, to differentiate between same-name objects + CPPUTEST_OBJS_DIR := $(addsuffix /$(COMPONENT_NAME),$(CPPUTEST_OBJS_DIR)) +endif + +#Test coverage with gcov +GCOV_OUTPUT = gcov_output.txt +GCOV_REPORT = gcov_report.txt +GCOV_ERROR = gcov_error.txt +GCOV_GCDA_FILES = $(call src_to_gcda, $(ALL_SRC)) +GCOV_GCNO_FILES = $(call src_to_gcno, $(ALL_SRC)) +TEST_OUTPUT = $(TEST_TARGET).txt +STUFF_TO_CLEAN += \ + $(GCOV_OUTPUT)\ + $(GCOV_REPORT)\ + $(GCOV_REPORT).html\ + $(GCOV_ERROR)\ + $(GCOV_GCDA_FILES)\ + $(GCOV_GCNO_FILES)\ + $(TEST_OUTPUT) + +#The gcda files for gcov need to be deleted before each run +#To avoid annoying messages. +GCOV_CLEAN = $(SILENCE)rm -f $(GCOV_GCDA_FILES) $(GCOV_OUTPUT) $(GCOV_REPORT) $(GCOV_ERROR) +RUN_TEST_TARGET = $(SILENCE) $(GCOV_CLEAN) ; echo "Running $(TEST_TARGET)"; ./$(TEST_TARGET) $(CPPUTEST_EXE_FLAGS) -ojunit + +ifeq ($(CPPUTEST_USE_GCOV), Y) + + ifeq ($(COMPILER_NAME),$(CLANG_STR)) + LD_LIBRARIES += --coverage + else + LD_LIBRARIES += -lgcov + endif +endif + + +INCLUDES_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(INCLUDE_DIRS)) +INCLUDES += $(foreach dir, $(INCLUDES_DIRS_EXPANDED), -I$(dir)) +MOCK_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(MOCKS_SRC_DIRS)) +INCLUDES += $(foreach dir, $(MOCK_DIRS_EXPANDED), -I$(dir)) + +CPPUTEST_CPPFLAGS += $(INCLUDES) $(CPPUTESTFLAGS) + +DEP_FILES = $(call src_to_d, $(ALL_SRC)) +STUFF_TO_CLEAN += $(DEP_FILES) $(PRODUCTION_CODE_START) $(PRODUCTION_CODE_END) +STUFF_TO_CLEAN += $(STDLIB_CODE_START) $(MAP_FILE) cpputest_*.xml junit_run_output + +# We'll use the CPPUTEST_CFLAGS etc so that you can override AND add to the CppUTest flags +CFLAGS = $(CPPUTEST_CFLAGS) $(CPPUTEST_ADDITIONAL_CFLAGS) +CPPFLAGS = $(CPPUTEST_CPPFLAGS) $(CPPUTEST_ADDITIONAL_CPPFLAGS) +CXXFLAGS = $(CPPUTEST_CXXFLAGS) $(CPPUTEST_ADDITIONAL_CXXFLAGS) +LDFLAGS = $(CPPUTEST_LDFLAGS) $(CPPUTEST_ADDITIONAL_LDFLAGS) + +# Don't consider creating the archive a warning condition that does STDERR output +ARFLAGS := $(ARFLAGS)c + +DEP_FLAGS=-MMD -MP + +# Some macros for programs to be overridden. For some reason, these are not in Make defaults +RANLIB = ranlib + +# Targets + +.PHONY: all +all: start $(TEST_TARGET) + $(RUN_TEST_TARGET) + +.PHONY: start +start: $(TEST_TARGET) + $(SILENCE)START_TIME=$(call time) + +.PHONY: all_no_tests +all_no_tests: $(TEST_TARGET) + +.PHONY: flags +flags: + @echo + @echo "OS ${UNAME_OS}" + @echo "Compile C and C++ source with CPPFLAGS:" + @$(call debug_print_list,$(CPPFLAGS)) + @echo "Compile C++ source with CXXFLAGS:" + @$(call debug_print_list,$(CXXFLAGS)) + @echo "Compile C source with CFLAGS:" + @$(call debug_print_list,$(CFLAGS)) + @echo "Link with LDFLAGS:" + @$(call debug_print_list,$(LDFLAGS)) + @echo "Link with LD_LIBRARIES:" + @$(call debug_print_list,$(LD_LIBRARIES)) + @echo "Create libraries with ARFLAGS:" + @$(call debug_print_list,$(ARFLAGS)) + +TEST_DEPS = $(TEST_OBJS) $(MOCKS_OBJS) $(PRODUCTION_CODE_START) $(TARGET_LIB) $(USER_LIBS) $(PRODUCTION_CODE_END) $(CPPUTEST_LIB) $(STDLIB_CODE_START) +test-deps: $(TEST_DEPS) + +$(TEST_TARGET): $(TEST_DEPS) + @echo Linking $@ + $(SILENCE)$(CXX) -o $@ $^ $(LD_LIBRARIES) $(LDFLAGS) + +$(TARGET_LIB): $(OBJ) + @echo Building archive $@ + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(AR) $(ARFLAGS) $@ $^ + $(SILENCE)$(RANLIB) $@ + +test: $(TEST_TARGET) + $(RUN_TEST_TARGET) | tee $(TEST_OUTPUT) + +vtest: $(TEST_TARGET) + $(RUN_TEST_TARGET) -v | tee $(TEST_OUTPUT) + +$(CPPUTEST_OBJS_DIR)/%.o: %.cc + @echo compiling $(notdir $<) + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $< + +$(CPPUTEST_OBJS_DIR)/%.o: %.cpp + @echo compiling $(notdir $<) + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $< + +$(CPPUTEST_OBJS_DIR)/%.o: %.c + @echo compiling $(notdir $<) + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(COMPILE.c) $(DEP_FLAGS) $(OUTPUT_OPTION) $< + +ifneq "$(MAKECMDGOALS)" "clean" +-include $(DEP_FILES) +endif + +.PHONY: clean +clean: + @echo Making clean + $(SILENCE)$(RM) $(STUFF_TO_CLEAN) + $(SILENCE)rm -rf gcov objs #$(CPPUTEST_OBJS_DIR) + $(SILENCE)rm -rf $(CPPUTEST_LIB_DIR) + $(SILENCE)find . -name "*.gcno" | xargs rm -f + $(SILENCE)find . -name "*.gcda" | xargs rm -f + +#realclean gets rid of all gcov, o and d files in the directory tree +#not just the ones made by this makefile +.PHONY: realclean +realclean: clean + $(SILENCE)rm -rf gcov + $(SILENCE)find . -name "*.gdcno" | xargs rm -f + $(SILENCE)find . -name "*.[do]" | xargs rm -f + +gcov: test +ifeq ($(CPPUTEST_USE_VPATH), Y) + $(SILENCE)gcov --object-directory $(CPPUTEST_OBJS_DIR) $(SRC) >> $(GCOV_OUTPUT) 2>> $(GCOV_ERROR) +else + $(SILENCE)for d in $(SRC_DIRS) ; do \ + gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$d $$d/*.c $$d/*.cpp >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \ + done + $(SILENCE)for f in $(SRC_FILES) ; do \ + gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$f $$f >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \ + done +endif +# $(CPPUTEST_HOME)/scripts/filterGcov.sh $(GCOV_OUTPUT) $(GCOV_ERROR) $(GCOV_REPORT) $(TEST_OUTPUT) + /usr/share/cpputest/scripts/filterGcov.sh $(GCOV_OUTPUT) $(GCOV_ERROR) $(GCOV_REPORT) $(TEST_OUTPUT) + $(SILENCE)cat $(GCOV_REPORT) + $(SILENCE)mkdir -p gcov + $(SILENCE)mv *.gcov gcov + $(SILENCE)mv gcov_* gcov + @echo "See gcov directory for details" + +.PHONEY: format +format: + $(CPPUTEST_HOME)/scripts/reformat.sh $(PROJECT_HOME_DIR) + +.PHONEY: debug +debug: + @echo + @echo "Target Source files:" + @$(call debug_print_list,$(SRC)) + @echo "Target Object files:" + @$(call debug_print_list,$(OBJ)) + @echo "Test Source files:" + @$(call debug_print_list,$(TEST_SRC)) + @echo "Test Object files:" + @$(call debug_print_list,$(TEST_OBJS)) + @echo "Mock Source files:" + @$(call debug_print_list,$(MOCKS_SRC)) + @echo "Mock Object files:" + @$(call debug_print_list,$(MOCKS_OBJS)) + @echo "All Input Dependency files:" + @$(call debug_print_list,$(DEP_FILES)) + @echo Stuff to clean: + @$(call debug_print_list,$(STUFF_TO_CLEAN)) + @echo Includes: + @$(call debug_print_list,$(INCLUDES)) + +-include $(OTHER_MAKEFILE_TO_INCLUDE) diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/makefile_defines.txt b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/makefile_defines.txt new file mode 100755 index 0000000000..cd0e17a963 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/makefile_defines.txt @@ -0,0 +1,23 @@ +#--- Inputs ----# +CPPUTEST_HOME = /usr +CPPUTEST_USE_EXTENSIONS = Y +CPPUTEST_USE_VPATH = Y +CPPUTEST_USE_GCOV = Y +CPP_PLATFORM = gcc +INCLUDE_DIRS =\ + .\ + ../common\ + ../stubs\ + ../../../..\ + ../../../../source\ + ../../../../nsdl-c\ + ../../../../yotta_modules/nanostack-libservice/mbed-client-libservice\ + ../../../../yotta_modules/mbed-trace\ + ../../../../../libService/libService\ + ../../../../source/libCoap/src/include\ + ../../../../source/libNsdl/src/include\ + /usr/include\ + $(CPPUTEST_HOME)/include\ + +CPPUTESTFLAGS = -D__thumb2__ -w +CPPUTEST_CFLAGS += -std=gnu99 diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/run_tests b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/run_tests new file mode 100755 index 0000000000..5698cf246f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/run_tests @@ -0,0 +1,44 @@ +#!/bin/bash +echo +echo Build libCoap unit tests +echo + +# Remember to add new test folder to Makefile +make clean +make all + +echo +echo Create results +echo +mkdir results + +find ./ -name '*.xml' | xargs cp -t ./results/ + +echo +echo Create coverage document +echo +mkdir coverages +cd coverages + +#copy the .gcda & .gcno for all test projects (no need to modify +#cp ../../../source/*.gc* . +#find ../ -name '*.gcda' | xargs cp -t . +#find ../ -name '*.gcno' | xargs cp -t . +#find . -name "test*" -type f -delete +#find . -name "*test*" -type f -delete +#find . -name "*stub*" -type f -delete +#rm -rf main.* + +lcov -q -d ../. -c -o app.info +lcov -q -r app.info "/test*" -o app.info +lcov -q -r app.info "/mbed-client-libservice*" -o app.info +lcov -q -r app.info "/usr*" -o app.info +genhtml --no-branch-coverage app.info +cd .. +echo +echo +echo +echo Have a nice bug hunt! +echo +echo +echo diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_builder/libCoap_builder_test.cpp b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_builder/libCoap_builder_test.cpp new file mode 100644 index 0000000000..156b66d1de --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_builder/libCoap_builder_test.cpp @@ -0,0 +1,510 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include +#include +#include "sn_nsdl.h" +#include "sn_coap_header.h" +#include "sn_coap_protocol_internal.h" + +#include "sn_coap_header_check_stub.h" +#include "sn_coap_parser_stub.h" + +sn_coap_hdr_s coap_header; +sn_coap_options_list_s option_list; +uint8_t buffer[256]; +uint8_t temp[10]; + +uint8_t retCounter = 0; + +static void *own_alloc(uint16_t size) +{ + if( retCounter > 0 ){ + retCounter--; + return malloc(size); + } + return NULL; +} + +static void own_free(void *ptr) +{ + free(ptr); +} + +TEST_GROUP(libCoap_builder) +{ + void setup() { + sn_coap_header_check_stub.expectedInt8 = 0; + retCounter = 0; + memset(&coap_header, 0, sizeof(sn_coap_hdr_s)); + memset(&option_list, 0, sizeof(sn_coap_options_list_s)); + + coap_header.options_list_ptr = &option_list; + coap_header.msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + coap_header.msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + coap_header.msg_id = 12; + } + + void teardown() { + + } +}; + +TEST(libCoap_builder, build_confirmable_response) +{ + struct coap_s handle; + sn_coap_hdr_s *response = NULL; + + handle.sn_coap_protocol_malloc = &own_alloc; + handle.sn_coap_protocol_free = &own_free; + + coap_header.msg_type = COAP_MSG_TYPE_RESET; + coap_header.msg_code = COAP_MSG_CODE_REQUEST_GET; + coap_header.msg_id = 12; + + //NULL pointer + CHECK(sn_coap_build_response(NULL, NULL, 0) == NULL); + CHECK(sn_coap_build_response(&handle, NULL, 0) == NULL); + CHECK(sn_coap_build_response(NULL, &coap_header, 0) == NULL); + CHECK(sn_coap_build_response(&handle, &coap_header, COAP_MSG_CODE_RESPONSE_CONTENT) == NULL); + + retCounter = 1; + CHECK(sn_coap_build_response(&handle, &coap_header, COAP_MSG_CODE_RESPONSE_CONTENT) == NULL); + + coap_header.msg_type = COAP_MSG_TYPE_CONFIRMABLE; + + retCounter = 2; + response = sn_coap_build_response(&handle, &coap_header, COAP_MSG_CODE_RESPONSE_CONTENT); + + CHECK(response != NULL); + CHECK(response->msg_type == COAP_MSG_TYPE_ACKNOWLEDGEMENT); + CHECK(response->msg_id == 12); + CHECK(response->msg_code == COAP_MSG_CODE_RESPONSE_CONTENT); + + own_free(response); +} + +TEST(libCoap_builder, build_non_confirmable_response) +{ + struct coap_s handle; + sn_coap_hdr_s *response = NULL; + uint8_t token_val = 0x99; + + handle.sn_coap_protocol_malloc = &own_alloc; + handle.sn_coap_protocol_free = &own_free; + + coap_header.msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE; + coap_header.msg_code = COAP_MSG_CODE_REQUEST_GET; + coap_header.msg_id = 12; + coap_header.token_len = 1; + coap_header.token_ptr = &token_val; + + retCounter = 1; + CHECK( NULL == sn_coap_build_response(&handle, &coap_header, COAP_MSG_CODE_RESPONSE_CONTENT)); + + retCounter = 2; + response = sn_coap_build_response(&handle, &coap_header, COAP_MSG_CODE_RESPONSE_CONTENT); + + CHECK(response != NULL); + CHECK(response->msg_type == COAP_MSG_TYPE_NON_CONFIRMABLE); + CHECK(response->msg_code == COAP_MSG_CODE_RESPONSE_CONTENT); + CHECK(response->token_ptr != NULL); + CHECK(memcmp(response->token_ptr, coap_header.token_ptr, coap_header.token_len) == 0); + CHECK(response->token_len == coap_header.token_len); + + own_free(response->token_ptr); + own_free(response); +} + + +TEST(libCoap_builder, build_message_negative_cases) +{ + // Null pointers as a parameter + CHECK(sn_coap_builder(NULL, NULL) == -2); + CHECK(sn_coap_builder(NULL, &coap_header) == -2); + CHECK(sn_coap_builder(buffer, NULL) == -2); + + // Invalid option length + coap_header.token_ptr = temp; + CHECK(sn_coap_builder(buffer, &coap_header) == -1); +} + +TEST(libCoap_builder, build_message_ok_cases) +{ + CHECK(sn_coap_builder(buffer, &coap_header) == 4); +} + +TEST(libCoap_builder, build_message_options_token) +{ + coap_header.token_ptr = temp; + coap_header.token_len = 2; + CHECK(sn_coap_builder(buffer, &coap_header) == 6); +} + +TEST(libCoap_builder, build_message_options_uri_path) +{ + coap_header.uri_path_ptr = temp; + coap_header.uri_path_len = 2; + CHECK(sn_coap_builder(buffer, &coap_header) == 7); +} + +TEST(libCoap_builder, build_message_options_content_type) +{ + coap_header.content_type_ptr = temp; + coap_header.content_type_len = 2; + CHECK(sn_coap_builder(buffer, &coap_header) == 7); +} + +TEST(libCoap_builder, build_message_options_max_age) +{ + coap_header.options_list_ptr->max_age_ptr = temp; + coap_header.options_list_ptr->max_age_len = 2; + CHECK(sn_coap_builder(buffer, &coap_header) == 8); +} + +TEST(libCoap_builder, build_message_options_proxy_uri) +{ + coap_header.options_list_ptr->proxy_uri_ptr = temp; + coap_header.options_list_ptr->proxy_uri_len = 2; + CHECK(sn_coap_builder(buffer, &coap_header) == 8); +} + +TEST(libCoap_builder, build_message_options_etag) +{ + coap_header.options_list_ptr->etag_ptr = temp; + coap_header.options_list_ptr->etag_len = 2; + CHECK(sn_coap_builder(buffer, &coap_header) == 7); +} + +TEST(libCoap_builder, build_message_options_uri_host) +{ + coap_header.options_list_ptr->uri_host_ptr = temp; + coap_header.options_list_ptr->uri_host_len = 2; + CHECK(sn_coap_builder(buffer, &coap_header) == 7); +} + +TEST(libCoap_builder, build_message_options_location_path) +{ + coap_header.options_list_ptr->location_path_ptr = temp; + coap_header.options_list_ptr->location_path_len = 2; + CHECK(sn_coap_builder(buffer, &coap_header) == 7); +} + +TEST(libCoap_builder, build_message_options_uri_port) +{ + coap_header.options_list_ptr->uri_port_ptr = temp; + coap_header.options_list_ptr->uri_port_len = 2; + CHECK(sn_coap_builder(buffer, &coap_header) == 7); +} + +TEST(libCoap_builder, build_message_options_location_query) +{ + coap_header.options_list_ptr->location_query_ptr = temp; + coap_header.options_list_ptr->location_query_len = 2; + CHECK(sn_coap_builder(buffer, &coap_header) == 8); +} + +TEST(libCoap_builder, build_message_options_observe) +{ + coap_header.options_list_ptr->observe_ptr = temp; + coap_header.options_list_ptr->observe_len = 2; + CHECK(sn_coap_builder(buffer, &coap_header) == 7); +} + + +TEST(libCoap_builder, build_message_options_accept) +{ + coap_header.options_list_ptr->accept_ptr = temp; + coap_header.options_list_ptr->accept_len = 2; + CHECK(sn_coap_builder(buffer, &coap_header) == 8); +} + + +TEST(libCoap_builder, build_message_options_uri_query) +{ + coap_header.options_list_ptr->uri_query_ptr = temp; + coap_header.options_list_ptr->uri_query_len = 2; + CHECK(sn_coap_builder(buffer, &coap_header) == 8); +} + + +TEST(libCoap_builder, build_message_options_block1) +{ + coap_header.options_list_ptr->block1_ptr = temp; + coap_header.options_list_ptr->block1_len = 2; + CHECK(sn_coap_builder(buffer, &coap_header) == 8); +} + +TEST(libCoap_builder, build_message_options_block2) +{ + coap_header.options_list_ptr->block2_ptr = temp; + coap_header.options_list_ptr->block2_len = 2; + + sn_coap_header_check_stub.expectedInt8 = 44; + CHECK(sn_coap_builder(buffer, &coap_header) == -1); + + sn_coap_header_check_stub.expectedInt8 = 0; + CHECK(sn_coap_builder(buffer, &coap_header) == 8); + + coap_header.options_list_ptr = NULL; //return from sn_coap_builder_options_build immediately + sn_coap_header_check_stub.expectedInt8 = 0; + CHECK( 4 == sn_coap_builder(buffer, &coap_header) ); +} + +TEST(libCoap_builder, sn_coap_builder_calc_needed_packet_data_size) +{ + CHECK(sn_coap_builder_calc_needed_packet_data_size(NULL) == 0); + + sn_coap_hdr_s header; + memset(&header, 0, sizeof(sn_coap_hdr_s)); + header.msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + header.token_ptr = (uint8_t*)malloc(10); + header.token_len = 10; + CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0); + free(header.token_ptr); + header.token_ptr = (uint8_t*)malloc(6); + header.token_len = 6; + + //Test variations of sn_coap_builder_options_calc_option_size here --> + header.uri_path_ptr = (uint8_t*)malloc(290); + memset(header.uri_path_ptr, '1', 290); + header.uri_path_len = 290; + header.uri_path_ptr[5] = '/'; + header.uri_path_ptr[285] = '/'; + + CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0); + + header.uri_path_ptr[285] = '1'; + header.uri_path_ptr[170] = '/'; + + header.content_type_ptr = (uint8_t*)malloc(6); + header.content_type_len = 6; + + CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0); + + header.content_type_len = 2; + sn_coap_options_list_s opt_list; + memset(&opt_list, 0, sizeof(sn_coap_options_list_s)); + header.options_list_ptr = &opt_list; + header.options_list_ptr->accept_ptr = (uint8_t*)malloc(6); + header.options_list_ptr->accept_len = 6; + CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0); + + header.options_list_ptr->accept_len = 2; + header.options_list_ptr->max_age_ptr = (uint8_t*)malloc(6); + header.options_list_ptr->max_age_len = 6; + CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0); + + //proxy uri tests (4) + header.options_list_ptr->max_age_len = 2; + header.options_list_ptr->proxy_uri_ptr = (uint8_t*)malloc(270); + header.options_list_ptr->proxy_uri_len = 1800; + + CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0); + header.options_list_ptr->proxy_uri_len = 6; + header.options_list_ptr->etag_ptr = (uint8_t*)malloc(6); + header.options_list_ptr->etag_len = 0; + CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0); + + header.options_list_ptr->proxy_uri_len = 14; + CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0); + + header.options_list_ptr->proxy_uri_len = 281; + CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0); + + header.options_list_ptr->etag_len = 4; + header.options_list_ptr->uri_host_ptr = (uint8_t*)malloc(6); + header.options_list_ptr->uri_host_len = 0; + CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0); + + header.options_list_ptr->uri_host_len = 4; + header.options_list_ptr->location_path_ptr = (uint8_t*)malloc(6); + header.options_list_ptr->location_path_len = 270; + CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0); + + header.options_list_ptr->uri_host_len = 44; + CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0); + + header.options_list_ptr->location_path_len = 27; + header.options_list_ptr->uri_port_ptr = (uint8_t*)malloc(6); + header.options_list_ptr->uri_port_len = 6; + CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0); + + header.options_list_ptr->uri_port_len = 2; + header.options_list_ptr->location_query_ptr = (uint8_t*)malloc(6); + header.options_list_ptr->location_query_len = 277; + CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0); + + header.options_list_ptr->location_query_len = 27; + header.options_list_ptr->observe_ptr = (uint8_t*)malloc(6); + header.options_list_ptr->observe_len = 6; + CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0); + + header.options_list_ptr->observe_len = 2; + header.options_list_ptr->uri_query_ptr = (uint8_t*)malloc(6); + header.options_list_ptr->uri_query_len = 0; + CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0); + + header.options_list_ptr->observe = 1; + + header.options_list_ptr->uri_query_len = 4; + header.options_list_ptr->block2_ptr = (uint8_t*)malloc(6); + header.options_list_ptr->block2_len = 0; + CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0); + + header.options_list_ptr->block2_len = 2; + header.options_list_ptr->block1_ptr = (uint8_t*)malloc(6); + header.options_list_ptr->block1_len = 0; + CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0); + + header.options_list_ptr->block1_len = 2; + header.payload_len = 1; + CHECK(431 == sn_coap_builder_calc_needed_packet_data_size(&header)); + + + header.options_list_ptr->size1_ptr = (uint8_t*)malloc(6); + header.options_list_ptr->size1_len = 6; + CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0); + + header.options_list_ptr->size2_ptr = (uint8_t*)malloc(6); + header.options_list_ptr->size1_len = 2; + header.options_list_ptr->size2_len = 6; + CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0); + + free(header.options_list_ptr->observe_ptr); + header.options_list_ptr->observe_ptr = NULL; + header.options_list_ptr->observe_len = 0; + header.options_list_ptr->block1_len = 2; + header.options_list_ptr->size1_len = 2; + header.options_list_ptr->size2_len = 2; + header.payload_len = 1; + CHECK(729 == sn_coap_builder_calc_needed_packet_data_size(&header)); + + // <-- + + //free(header.options_list_ptr->observe_ptr); Called earlier! + free(header.options_list_ptr->location_query_ptr); + free(header.options_list_ptr->uri_port_ptr); + free(header.options_list_ptr->location_path_ptr); + free(header.options_list_ptr->uri_host_ptr); + free(header.options_list_ptr->etag_ptr); + free(header.options_list_ptr->proxy_uri_ptr); + free(header.options_list_ptr->max_age_ptr); + free(header.options_list_ptr->accept_ptr); + free(header.options_list_ptr->size1_ptr); + free(header.options_list_ptr->block1_ptr); + free(header.options_list_ptr->block2_ptr); + header.options_list_ptr->location_query_ptr = NULL; + header.options_list_ptr->uri_port_ptr = NULL; + header.options_list_ptr->location_path_ptr = NULL; + header.options_list_ptr->uri_host_ptr = NULL; + header.options_list_ptr->etag_ptr = NULL; + header.options_list_ptr->proxy_uri_ptr = NULL; + header.options_list_ptr->max_age_ptr = NULL; + header.options_list_ptr->accept_ptr = NULL; + header.options_list_ptr->size1_ptr = NULL; + header.options_list_ptr->block1_ptr = NULL; + header.options_list_ptr->block2_ptr = NULL; + + CHECK(318 == sn_coap_builder_calc_needed_packet_data_size(&header)); + free(header.options_list_ptr->size2_ptr); + free(header.options_list_ptr->uri_query_ptr); + + //Test sn_coap_builder_options_calculate_jump_need "else" case + header.options_list_ptr = NULL; + uint16_t val = sn_coap_builder_calc_needed_packet_data_size(&header); + CHECK( 308 == val ); + + free(header.content_type_ptr); + free(header.uri_path_ptr); + free(header.token_ptr); +} + +TEST(libCoap_builder, sn_coap_builder_options_build_add_one_option) +{ + coap_header.options_list_ptr->proxy_uri_ptr = (uint8_t*)malloc(280); + memset(coap_header.options_list_ptr->proxy_uri_ptr, '1', 280); + coap_header.options_list_ptr->proxy_uri_len = 2; + sn_coap_header_check_stub.expectedInt8 = 0; + CHECK(sn_coap_builder(buffer, &coap_header) == 8); + + coap_header.options_list_ptr->proxy_uri_len = 27; + sn_coap_header_check_stub.expectedInt8 = 0; + CHECK(34 == sn_coap_builder(buffer, &coap_header)); + + coap_header.options_list_ptr->proxy_uri_len = 277; + sn_coap_header_check_stub.expectedInt8 = 0; + CHECK(285 == sn_coap_builder(buffer, &coap_header)); + + free(coap_header.options_list_ptr->proxy_uri_ptr); + coap_header.options_list_ptr->proxy_uri_ptr = NULL; +} + +TEST(libCoap_builder, sn_coap_builder_options_build_add_zero_length_option) +{ + coap_header.options_list_ptr->proxy_uri_ptr = (uint8_t*)malloc(280); + memset(coap_header.options_list_ptr->proxy_uri_ptr, '1', 280); + coap_header.options_list_ptr->proxy_uri_len = 2; + sn_coap_header_check_stub.expectedInt8 = 0; + coap_header.options_list_ptr->observe = 1; + int16_t val = sn_coap_builder(buffer, &coap_header); + CHECK(val == 9); + + free(coap_header.options_list_ptr->proxy_uri_ptr); +} + +TEST(libCoap_builder, sn_coap_builder_options_get_option_part_position) +{ + sn_coap_hdr_s header; + memset(&header, 0, sizeof(sn_coap_hdr_s)); + sn_coap_options_list_s opt_list; + memset(&opt_list, 0, sizeof(sn_coap_options_list_s)); + header.options_list_ptr = &opt_list; + header.options_list_ptr->accept_ptr = (uint8_t*)malloc(20); + memset(header.options_list_ptr->accept_ptr, '&', 20); + header.options_list_ptr->accept_len = 20; + uint16_t val = sn_coap_builder(buffer, &header); + CHECK(val == 24); + + header.options_list_ptr->accept_ptr[0] = 'a'; + header.options_list_ptr->accept_ptr[1] = 'n'; + header.options_list_ptr->accept_ptr[19] = 'n'; + val = sn_coap_builder(buffer, &header); + CHECK(val == 42); + + free(header.options_list_ptr->accept_ptr); + header.options_list_ptr->accept_ptr = NULL; +} + +TEST(libCoap_builder, sn_coap_builder_payload_build) +{ + sn_coap_hdr_s header; + memset(&header, 0, sizeof(sn_coap_hdr_s)); + header.payload_ptr = (uint8_t*)malloc(5); + header.payload_len = 5; + sn_coap_options_list_s opt_list; + memset(&opt_list, 0, sizeof(sn_coap_options_list_s)); + header.options_list_ptr = &opt_list; + header.options_list_ptr->accept_ptr = (uint8_t*)malloc(20); + memset(header.options_list_ptr->accept_ptr, '&', 20); + header.options_list_ptr->accept_len = 20; + uint16_t val = sn_coap_builder(buffer, &header); + CHECK(val == 30); + + free(header.payload_ptr); + free(header.options_list_ptr->accept_ptr); + header.options_list_ptr->accept_ptr = NULL; +} diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_builder/main.cpp b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_builder/main.cpp new file mode 100644 index 0000000000..8011201522 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_builder/main.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" + + + +int main(int ac, char **av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP(libCoap_builder); diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_header_check/libCoap_header_test.cpp b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_header_check/libCoap_header_test.cpp new file mode 100644 index 0000000000..688da4147b --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_header_check/libCoap_header_test.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include +#include +#include "sn_nsdl.h" +#include "sn_coap_protocol.h" +#include "sn_nsdl_lib.h" +#include "sn_coap_header_internal.h" + + +TEST_GROUP(libCoap_header_check) +{ + void setup() { + + } + + void teardown() { + + } +}; + +TEST(libCoap_header_check, header_check) +{ + sn_coap_hdr_s coap_header; + + memset(&coap_header, 0, sizeof(sn_coap_hdr_s)); + coap_header.msg_type = COAP_MSG_TYPE_CONFIRMABLE; + coap_header.msg_code = COAP_MSG_CODE_REQUEST_GET; + + /* Happy-happy case */ + CHECK(sn_coap_header_validity_check(&coap_header, (coap_version_e)COAP_VERSION_1) == 0); + + + CHECK(sn_coap_header_validity_check(&coap_header, (coap_version_e) 0) == -1); + + coap_header.msg_type = (sn_coap_msg_type_e)0x40; + + CHECK(sn_coap_header_validity_check(&coap_header, (coap_version_e)COAP_VERSION_1) == -1); + + coap_header.msg_type = (sn_coap_msg_type_e)COAP_MSG_TYPE_CONFIRMABLE; + coap_header.msg_code = (sn_coap_msg_code_e)5; + + CHECK(sn_coap_header_validity_check(&coap_header, (coap_version_e)COAP_VERSION_1) == -1); +} diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_header_check/main.cpp b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_header_check/main.cpp new file mode 100644 index 0000000000..2195410940 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_header_check/main.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" + + + +int main(int ac, char **av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP(libCoap_header_check); diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/main.cpp b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/main.cpp new file mode 100644 index 0000000000..d0539a2e5d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/main.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ + +#include "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP(sn_coap_parser); + diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/sn_coap_parsertest.cpp b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/sn_coap_parsertest.cpp new file mode 100644 index 0000000000..418f57668e --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/sn_coap_parsertest.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ +#include "CppUTest/TestHarness.h" +#include "test_sn_coap_parser.h" + +TEST_GROUP(sn_coap_parser) +{ + void setup() + { + } + + void teardown() + { + } +}; + +TEST(sn_coap_parser, test_sn_coap_parser) +{ + CHECK(test_sn_coap_parser()); +} + +TEST(sn_coap_parser, test_sn_coap_parser_options_parsing) +{ + CHECK(test_sn_coap_parser_options_parsing()); +} + +TEST(sn_coap_parser, test_sn_coap_parser_options_parsing_switches) +{ + CHECK(test_sn_coap_parser_options_parsing_switches()); +} + +TEST(sn_coap_parser, test_sn_coap_parser_options_count_needed_memory_multiple_option) +{ + CHECK(test_sn_coap_parser_options_count_needed_memory_multiple_option()); +} + +TEST(sn_coap_parser, test_sn_coap_parser_options_parse_multiple_options) +{ + CHECK(test_sn_coap_parser_options_parse_multiple_options()); +} + +TEST(sn_coap_parser, test_sn_coap_parser_parsing) +{ + CHECK(test_sn_coap_parser_parsing()); +} + +TEST(sn_coap_parser, test_sn_coap_parser_release_allocated_coap_msg_mem) +{ + CHECK(test_sn_coap_parser_release_allocated_coap_msg_mem()); +} diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/test_sn_coap_parser.c b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/test_sn_coap_parser.c new file mode 100644 index 0000000000..7770c5f3a0 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/test_sn_coap_parser.c @@ -0,0 +1,1020 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ +#include "test_sn_coap_parser.h" +#include +#include "stdint.h" +#include "sn_nsdl.h" +#include "sn_coap_header.h" +#include "sn_coap_header_internal.h" +#include "sn_coap_protocol_internal.h" + +int retCounter = 0; + +void* myMalloc(uint16_t size) +{ + if( retCounter > 0 ){ + retCounter--; + return malloc(size); + }else { + return NULL; + } +} + +void myFree(void* ptr){ + free(ptr); +} + +bool test_sn_coap_parser() +{ + retCounter = 0; + bool ret = true; + uint8_t* ptr = (uint8_t*)malloc(20); + sn_coap_hdr_s * hdr = sn_coap_parser(NULL, 8, ptr, NULL); + if( hdr != NULL ){ + free(hdr); + ret = false; + } + + if( ret ){ + struct coap_s* coap = (struct coap_s*)malloc(sizeof(struct coap_s)); + coap->sn_coap_protocol_malloc = myMalloc; + coap->sn_coap_protocol_free = myFree; + retCounter = 0; + coap_version_e* ver = (coap_version_e*)malloc(sizeof(coap_version_e)); + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( hdr != NULL ){ + free(hdr); + ret = false; + } + + if( ret ){ + retCounter = 1; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + free(hdr); + ret = false; + } + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + } + free(ver); + free(coap); + + } + + free(ptr); + return ret; +} + +bool test_sn_coap_parser_options_parsing() +{ + bool ret = true; + uint8_t* ptr = (uint8_t*)malloc(20); + memset(ptr, 0, 20); + ptr[0] = 9; + struct coap_s* coap = (struct coap_s*)malloc(sizeof(struct coap_s)); + coap->sn_coap_protocol_malloc = myMalloc; + coap->sn_coap_protocol_free = myFree; + + retCounter = 1; + coap_version_e* ver = (coap_version_e*)malloc(sizeof(coap_version_e)); + sn_coap_hdr_s * hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[0] = 1; + retCounter = 1; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 255; //this point is sufficient to test parsing of payload + retCounter = 2; + hdr = sn_coap_parser(coap, 6, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 239; + retCounter = 2; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 254; //15 | 14 + retCounter = 2; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 238; //14 | 14 + ptr[6] = 6; + ptr[7] = 7; + retCounter = 2; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 221; //13 | 13 + ptr[6] = 6; + retCounter = 2; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + } else { + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + } + } + } + } + } + } + } + + free(ver); + free(coap); + free(ptr); + return ret; +} + +bool test_sn_coap_parser_options_parsing_switches() +{ + bool ret = true; + uint8_t* ptr = (uint8_t*)malloc(20); + memset(ptr, 0, 20); + struct coap_s* coap = (struct coap_s*)malloc(sizeof(struct coap_s)); + coap->sn_coap_protocol_malloc = myMalloc; + coap->sn_coap_protocol_free = myFree; + coap_version_e* ver = (coap_version_e*)malloc(sizeof(coap_version_e)); + + //These should be tested: + /* + COAP_OPTION_IF_MATCH = 1, + COAP_OPTION_URI_HOST = 3, + COAP_OPTION_ETAG = 4, + COAP_OPTION_IF_NONE_MATCH = 5, + COAP_OPTION_OBSERVE = 6, + COAP_OPTION_URI_PORT = 7, + COAP_OPTION_LOCATION_PATH = 8, + COAP_OPTION_URI_PATH = 11, + COAP_OPTION_CONTENT_FORMAT = 12, + COAP_OPTION_MAX_AGE = 14, + COAP_OPTION_URI_QUERY = 15, + COAP_OPTION_ACCEPT = 17, + COAP_OPTION_LOCATION_QUERY = 20, + COAP_OPTION_BLOCK2 = 23, + COAP_OPTION_BLOCK1 = 27, + COAP_OPTION_SIZE2 = 28, + COAP_OPTION_PROXY_URI = 35, + COAP_OPTION_PROXY_SCHEME = 39, + COAP_OPTION_SIZE1 = 60 + */ + + ptr[0] = 1; + + retCounter = 2; + ptr[5] = 17; //1 | 1 (number | length) + sn_coap_hdr_s * hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 51; //1 | 3 + retCounter = 2; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 48; //3 | 0 + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 51; //3 | 3 + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 51; //3 | 3 + retCounter = 4; + //overflows, so not valid data + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 68; //4 | 4 + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 68; //4 | 4 + retCounter = 4; + //This should test if (ret_status >= 0) {} + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 85; //5 | 5 + retCounter = 2; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 102; //6 | 6 + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 97; //6 | 1 + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 97; //6 | 1 + retCounter = 4; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 119; //7 | 7 + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 113; //7 | 1 + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 113; //7 | 1 + retCounter = 4; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 128; //8 | 8 + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 136; //8 | 8 + retCounter = 4; + //This should test if (ret_status >= 0) {} + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 187; //11 | 11 + retCounter = 2; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 187; //11 | 11 + retCounter = 3; + //This should test if (ret_status >= 0) {} + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 204; //12 | 12 + retCounter = 2; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 193; //12 | 1 + retCounter = 2; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 193; //12 | 1 + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 216; //13 | 8 + ptr[6] = 1; //1 -> 14 + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 209; //13 | 1 + ptr[6] = 1; //1 -> 14 + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 210; //13 | 2 + ptr[6] = 1; //1 -> 14 + retCounter = 4; + hdr = sn_coap_parser(coap, 6, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 208; //13 | 0 + ptr[6] = 2; //2 -> 15 ??? + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 209; //13 | 1 + ptr[6] = 2; //2 -> 15 ??? + retCounter = 5; + //This should test if (ret_status >= 0) {} + hdr = sn_coap_parser(coap, 7, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 208; //13 | 0 + ptr[6] = 4; + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 209; //13 | 1 + ptr[6] = 4; + retCounter = 5; + //This should test if (ret_status >= 0) {} + hdr = sn_coap_parser(coap, 7, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 208; //13 | 0 + ptr[6] = 7; + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 209; //13 | 1 + ptr[6] = 7; + retCounter = 5; + //This should test if (ret_status >= 0) {} + hdr = sn_coap_parser(coap, 7, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 216; //13 | 8 + ptr[6] = 10; + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 209; //13 | 1 + ptr[6] = 10; + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 210; //13 | 2 + ptr[6] = 10; + retCounter = 4; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 216; //13 | 8 + ptr[6] = 14; + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 209; //13 | 1 + ptr[6] = 14; + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 210; //13 | 2 + ptr[6] = 14; + retCounter = 4; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 208; //13 | 0 + ptr[6] = 22; + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 209; //13 | 1 + ptr[6] = 22; + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 209; //13 | 1 + ptr[6] = 22; + retCounter = 4; + hdr = sn_coap_parser(coap, 7, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 208; //13 | 0 + ptr[6] = 26; + retCounter = 2; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 208; //13 | 0 + ptr[6] = 47; + retCounter = 2; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 216; //13 | 8 + ptr[6] = 47; + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 209; //13 | 1 + ptr[6] = 47; + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 210; //13 | 2 + ptr[6] = 47; + retCounter = 4; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 209; //13 | 1 + ptr[6] = 15; + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + } else { + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 210; //13 | 2 + ptr[6] = 15; + retCounter = 4; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + ptr[5] = 216; //13 | 8 + ptr[6] = 15; + retCounter = 3; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + }else{ + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + + ptr[5] = 209; //13 | 1 + ptr[6] = 10; + retCounter = 4; + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( hdr == NULL ){ + ret = false; + }else{ + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + } + + free(ver); + free(coap); + free(ptr); + return ret; +} + +bool test_sn_coap_parser_options_count_needed_memory_multiple_option() +{ + bool ret = true; + uint8_t* ptr = (uint8_t*)malloc(65635); + memset(ptr, 0, 65635); + struct coap_s* coap = (struct coap_s*)malloc(sizeof(struct coap_s)); + coap->sn_coap_protocol_malloc = myMalloc; + coap->sn_coap_protocol_free = myFree; + coap_version_e* ver = (coap_version_e*)malloc(sizeof(coap_version_e)); + + //Some of these should be tested: + //These 6 will test sn_coap_parser_options_count_needed_memory_multiple_option overflows + ptr[0] = 1; + ptr[5] = 0x4d; //4 | 13 + ptr[6] = 254; + retCounter = 4; + //This should test if (ret_status >= 0) {} + sn_coap_hdr_s * hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + goto end; + } + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + + ptr[0] = 1; + ptr[5] = 0x8d; //4 | 13 + ptr[6] = 254; + retCounter = 4; + //This should test if (ret_status >= 0) {} + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + goto end; + } + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + + ptr[0] = 1; + ptr[5] = 0xbd; + ptr[6] = 254; + retCounter = 4; + //This should test if (ret_status >= 0) {} + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + goto end; + } + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + + ptr[0] = 1; + ptr[5] = 0xdd; + ptr[6] = 2; + ptr[7] = 254; + retCounter = 4; + //This should test if (ret_status >= 0) {} + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + goto end; + } + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + + ptr[0] = 1; + ptr[5] = 0xdd; + ptr[6] = 4; + ptr[7] = 254; + retCounter = 4; + //This should test if (ret_status >= 0) {} + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + goto end; + } + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + + ptr[0] = 1; + ptr[5] = 0xdd; + ptr[6] = 7; + ptr[7] = 254; + retCounter = 4; + //This should test if (ret_status >= 0) {} + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + goto end; + } + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + + ptr[0] = 1; + ptr[5] = 0x81; + ptr[6] = 0x00; + ptr[7] = 0x20; + retCounter = 4; + //This should test if (ret_status >= 0) {} + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + goto end; + } + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + + ptr[0] = 1; + ptr[5] = 0x81; + ptr[6] = 0x00; + ptr[7] = 0x00; + retCounter = 4; + //This should test if (ret_status >= 0) {} + hdr = sn_coap_parser(coap, 6, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + goto end; + } + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + + ptr[0] = 1; + ptr[5] = 0x81; + ptr[6] = 0x00; + ptr[7] = 0x0d; + retCounter = 4; + //This should test if (ret_status >= 0) {} + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + goto end; + } + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + + ptr[0] = 1; + ptr[5] = 0x81; + ptr[6] = 0x00; + ptr[7] = 0x0e; + retCounter = 4; + //This should test if (ret_status >= 0) {} + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + goto end; + } + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + + ptr[0] = 1; + ptr[5] = 0x81; + ptr[6] = 0x00; + ptr[7] = 0x0f; + retCounter = 4; + //This should test if (ret_status >= 0) {} + hdr = sn_coap_parser(coap, 8, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + goto end; + } + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + +end: + free(ver); + free(coap); + free(ptr); + return ret; +} + +bool test_sn_coap_parser_options_parse_multiple_options() +{ + bool ret = true; + uint8_t* ptr = (uint8_t*)malloc(33); + memset(ptr, 0, 33); + struct coap_s* coap = (struct coap_s*)malloc(sizeof(struct coap_s)); + coap->sn_coap_protocol_malloc = myMalloc; + coap->sn_coap_protocol_free = myFree; + coap_version_e* ver = (coap_version_e*)malloc(sizeof(coap_version_e)); + + ptr[0] = 0x60; + ptr[4] = 0x82; //opt 8 & len 2 + ptr[5] = 0x00; + ptr[6] = 0x00; + ptr[7] = 0x0d; + ptr[8] = 0x00; + ptr[9] = 0x6f; + ptr[10] = 0x6d; + ptr[11] = 0x61; + ptr[12] = 0x69; + ptr[13] = 0x6e; + retCounter = 4; + sn_coap_hdr_s *hdr = sn_coap_parser(coap, 14, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + goto end2; + } + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + + + ptr[7] = 0x0e; + ptr[8] = 0xff; + ptr[9] = 0x00; + retCounter = 4; + hdr = sn_coap_parser(coap, 14, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + goto end2; + } + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + + ptr[0] = 0x60; + ptr[4] = 0x42; + ptr[5] = 0x00; + ptr[6] = 0x00; + ptr[7] = 0x06; + ptr[8] = 0x00; + ptr[9] = 0x6f; + ptr[10] = 0x6d; + ptr[11] = 0x61; + ptr[12] = 0x69; + ptr[13] = 0x6e; + retCounter = 4; + hdr = sn_coap_parser(coap, 14, ptr, ver); + if( hdr == NULL ){ + ret = false; + goto end2; + }else{ + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + } + + free(ptr); + ptr = (uint8_t*)malloc(10); + memset(ptr, 0, 10); + + //this should be checked after bug http://jira.arm.com/browse/IOTCLT-244 is fixed + //This is illegal options message, but gets parsed though + //this test passes because parsing of data still fails (expected) + ptr[0] = 0x60; + ptr[4] = 0x82; + ptr[5] = 0x00; + ptr[6] = 0x00; + ptr[7] = 0x06; + ptr[8] = 0x00; + ptr[9] = 0x6f; + retCounter = 4; + hdr = sn_coap_parser(coap, 10, ptr, ver); + if( !hdr || (hdr && hdr->coap_status != COAP_STATUS_PARSER_ERROR_IN_HEADER) ){ + ret = false; + goto end2; + } + if (hdr) + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + +end2: + free(ver); + free(coap); + free(ptr); + return ret; +} + +bool test_sn_coap_parser_parsing() +{ + bool ret = true; + uint8_t* ptr = (uint8_t*)malloc(33); + memset(ptr, 0, 33); + struct coap_s* coap = (struct coap_s*)malloc(sizeof(struct coap_s)); + coap->sn_coap_protocol_malloc = myMalloc; + coap->sn_coap_protocol_free = myFree; + coap_version_e* ver = (coap_version_e*)malloc(sizeof(coap_version_e)); + + ptr[0] = 0x60; + ptr[4] = 0x42; + ptr[5] = 0x00; + ptr[6] = 0x00; + retCounter = 4; + + //TODO: add sn_coap_parser_parsing related stuff + ptr[7] = 0x20; + ptr[8] = 0x00; + + sn_coap_hdr_s *hdr = NULL; + + //this should test parsing without payload marker, but it is not possible +// hdr = sn_coap_parser(coap, 9, ptr, ver); + +// if( hdr != NULL ){ +// ret = false; +// goto end3; +// } +// sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + + ptr[0] = 0x60; + ptr[4] = 0x42; + ptr[5] = 0x00; + ptr[6] = 0x00; + ptr[7] = 0x06; + ptr[8] = 0x00; + ptr[9] = 0x6f; + ptr[10] = 0x6d; + ptr[11] = 0x61; + ptr[12] = 0x69; + ptr[13] = 0x6e; + ptr[14] = 0xff; + ptr[15] = 0x1; + retCounter = 4; + + hdr = sn_coap_parser(coap, 16, ptr, ver); + + if( hdr == NULL ){ + ret = false; + goto end3; + } + + sn_coap_parser_release_allocated_coap_msg_mem(coap, hdr); + +end3: + free(ver); + free(coap); + free(ptr); + return ret; +} + +bool test_sn_coap_parser_release_allocated_coap_msg_mem() +{ + struct coap_s* coap = (struct coap_s*)malloc(sizeof(struct coap_s)); + coap->sn_coap_protocol_malloc = myMalloc; + coap->sn_coap_protocol_free = myFree; + retCounter = 99; + + sn_coap_parser_release_allocated_coap_msg_mem( NULL, NULL ); + + sn_coap_hdr_s* ptr = (sn_coap_hdr_s*)myMalloc(sizeof(sn_coap_hdr_s)); + ptr->uri_path_ptr = (uint8_t*)malloc(sizeof(uint8_t)); + ptr->token_ptr = (uint8_t*)malloc(sizeof(uint8_t)); + ptr->content_type_ptr = (uint8_t*)malloc(sizeof(uint8_t)); + //ptr->payload_ptr = (uint8_t*)malloc(sizeof(uint8_t)); + ptr->options_list_ptr = (sn_coap_options_list_s*)myMalloc(sizeof(sn_coap_options_list_s)); + + ptr->options_list_ptr->max_age_ptr = (uint8_t*)malloc(sizeof(uint8_t)); + ptr->options_list_ptr->proxy_uri_ptr = (uint8_t*)malloc(sizeof(uint8_t)); + ptr->options_list_ptr->etag_ptr = (uint8_t*)malloc(sizeof(uint8_t)); + ptr->options_list_ptr->uri_host_ptr = (uint8_t*)malloc(sizeof(uint8_t)); + ptr->options_list_ptr->location_path_ptr = (uint8_t*)malloc(sizeof(uint8_t)); + ptr->options_list_ptr->uri_port_ptr = (uint8_t*)malloc(sizeof(uint8_t)); + ptr->options_list_ptr->location_query_ptr = (uint8_t*)malloc(sizeof(uint8_t)); + ptr->options_list_ptr->observe_ptr = (uint8_t*)malloc(sizeof(uint8_t)); + ptr->options_list_ptr->accept_ptr = (uint8_t*)malloc(sizeof(uint8_t)); + ptr->options_list_ptr->uri_query_ptr = (uint8_t*)malloc(sizeof(uint8_t)); + ptr->options_list_ptr->block1_ptr = (uint8_t*)malloc(sizeof(uint8_t)); + ptr->options_list_ptr->block2_ptr = (uint8_t*)malloc(sizeof(uint8_t)); + + sn_coap_parser_release_allocated_coap_msg_mem( coap, ptr ); + + free(coap); + return true; //this is a memory leak check, so that will pass/fail +} + diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/test_sn_coap_parser.h b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/test_sn_coap_parser.h new file mode 100644 index 0000000000..4bf29dbd5d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/test_sn_coap_parser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ +#ifndef TEST_SN_COAP_PARSER_H +#define TEST_SN_COAP_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +bool test_sn_coap_parser(); + +//These splits above test to keep things more simpler +bool test_sn_coap_parser_options_parsing(); +bool test_sn_coap_parser_options_parsing_switches(); + +bool test_sn_coap_parser_options_count_needed_memory_multiple_option(); + +bool test_sn_coap_parser_options_parse_multiple_options(); + +bool test_sn_coap_parser_parsing(); +//<- split + +bool test_sn_coap_parser_release_allocated_coap_msg_mem(); + + +#ifdef __cplusplus +} +#endif + +#endif // TEST_SN_COAP_PARSER_H + diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_protocol/libCoap_protocol_test.cpp b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_protocol/libCoap_protocol_test.cpp new file mode 100644 index 0000000000..0079a0c0a8 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_protocol/libCoap_protocol_test.cpp @@ -0,0 +1,2295 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include +#include +#include +#include "sn_nsdl.h" +#include "sn_coap_protocol.h" +#include "sn_nsdl_lib.h" +#include "sn_coap_header_internal.h" +#include "sn_coap_protocol_internal.h" + +#include "sn_coap_builder_stub.h" +#include "sn_coap_parser_stub.h" +#include "sn_coap_header_check_stub.h" + +int retCounter = 0; +static coap_s *coap_handle = NULL; +void myFree(void* addr); +void* myMalloc(uint16_t size); +uint8_t null_tx_cb(uint8_t *a, uint16_t b, sn_nsdl_addr_s *c, void *d); + +TEST_GROUP(libCoap_protocol) +{ + void setup() { + retCounter = 1; + coap_handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL); + } + + void teardown() { + retCounter = 0; + sn_coap_protocol_destroy(coap_handle); + } +}; + +void* myMalloc(uint16_t size) +{ + if( retCounter > 0 ){ + retCounter--; + return malloc(size); + }else { + return NULL; + } +} + +void myFree(void* addr){ + if( addr ){ + free(addr); + } +} + +uint8_t null_tx_cb(uint8_t *a, uint16_t b, sn_nsdl_addr_s *c, void *d) +{ + return 0; +} + +int8_t null_rx_cb(sn_coap_hdr_s *a, sn_nsdl_addr_s *b, void *c) +{ + +} + +TEST(libCoap_protocol, sn_coap_protocol_destroy) +{ + CHECK( -1 == sn_coap_protocol_destroy(NULL)); + int temp = sizeof(struct coap_s); + struct coap_s *handle = (struct coap_s *)malloc(sizeof(struct coap_s)); + handle->sn_coap_protocol_free = &myFree; + handle->sn_coap_protocol_malloc = &myMalloc; + ns_list_init(&handle->linked_list_resent_msgs); + ns_list_init(&handle->linked_list_duplication_msgs); + ns_list_init(&handle->linked_list_blockwise_sent_msgs); + ns_list_init(&handle->linked_list_blockwise_received_payloads); + CHECK( 0 == sn_coap_protocol_destroy(handle)); +} + +TEST(libCoap_protocol, sn_coap_protocol_init_null_func_ptrs) +{ + POINTERS_EQUAL(NULL, sn_coap_protocol_init(NULL, NULL, NULL, NULL)); +} + +TEST(libCoap_protocol, sn_coap_protocol_init_null_malloc) +{ + POINTERS_EQUAL(NULL, sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL)); + + retCounter = 1; + struct coap_s * handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL); + CHECK(NULL != handle); + + sn_coap_protocol_destroy(handle); +} + +TEST(libCoap_protocol, sn_coap_protocol_set_block_size) +{ +#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + CHECK( 0 == sn_coap_protocol_set_block_size(coap_handle,16) ); + CHECK( -1 == sn_coap_protocol_set_block_size(NULL,1) ); +#endif + CHECK( -1 == sn_coap_protocol_set_block_size(coap_handle,1) ); +} + +TEST(libCoap_protocol, sn_coap_protocol_set_duplicate_buffer_size) +{ +#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT + CHECK( 0 == sn_coap_protocol_set_duplicate_buffer_size(coap_handle,3)); + CHECK( -1 == sn_coap_protocol_set_duplicate_buffer_size(NULL,3)); +#endif + CHECK( -1 == sn_coap_protocol_set_duplicate_buffer_size(coap_handle,999)); +} + +TEST(libCoap_protocol, sn_coap_protocol_set_retransmission_parameters) +{ +#if ENABLE_RESENDINGS + CHECK( 0 == sn_coap_protocol_set_retransmission_parameters(coap_handle,3,0) ); + CHECK( 0 == sn_coap_protocol_set_retransmission_parameters(coap_handle,3, 10) ); + CHECK( -1 == sn_coap_protocol_set_retransmission_parameters(NULL,3,0) ); +#endif + CHECK( -1 == sn_coap_protocol_set_retransmission_parameters(coap_handle,999,0) ) +} + +TEST(libCoap_protocol, sn_coap_protocol_set_retransmission_buffer) +{ +#if ENABLE_RESENDINGS + CHECK( 0 == sn_coap_protocol_set_retransmission_buffer(coap_handle,3,3) ); + CHECK( -1 == sn_coap_protocol_set_retransmission_buffer(NULL,3,3) ); +#endif + CHECK( -1 == sn_coap_protocol_set_retransmission_buffer(coap_handle,3,999) ); +} + +//TEST(libCoap_protocol, sn_coap_protocol_clear_retransmission_buffer) +//{ +// sn_coap_protocol_clear_retransmission_buffer(); +//} + +#include + +TEST(libCoap_protocol, sn_coap_protocol_build) +{ + retCounter = 1; + struct coap_s * handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL); + sn_nsdl_addr_s addr; + memset(&addr, 0, sizeof(sn_nsdl_addr_s)); + sn_coap_hdr_s hdr; + memset(&hdr, 0, sizeof(sn_coap_hdr_s)); + + uint8_t* dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + CHECK( -2 == sn_coap_protocol_build(NULL, NULL, NULL, NULL, NULL)); + + CHECK( -2 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, &hdr, NULL)); + + hdr.msg_type = COAP_MSG_TYPE_CONFIRMABLE; + hdr.msg_id = 0; + + addr.addr_ptr = (uint8_t*)malloc(5); + memset(addr.addr_ptr, '1', 5); + + sn_coap_builder_stub.expectedInt16 = 0; + + CHECK( 0 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, &hdr, NULL)); + + hdr.payload_ptr = (uint8_t*)malloc(SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20); + memset(hdr.payload_ptr, '1', SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20); + hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + + sn_coap_builder_stub.expectedInt16 = -3; + CHECK( -2 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, &hdr, NULL)); + + retCounter = 0; + hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + hdr.options_list_ptr->block1_ptr = (uint8_t*)malloc(3); + CHECK( -2 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, &hdr, NULL)); + hdr.options_list_ptr = NULL; + + retCounter = 2; + CHECK( -3 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, &hdr, NULL)); + + free(hdr.options_list_ptr->block1_ptr); + hdr.options_list_ptr->block1_ptr = NULL; + free(hdr.options_list_ptr); + hdr.options_list_ptr = NULL; + + hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + hdr.msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; + hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + hdr.options_list_ptr->block2_ptr = (uint8_t*)malloc(1); + retCounter = 0; + CHECK( -2 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, &hdr, NULL)); + hdr.options_list_ptr = NULL; + + free(hdr.payload_ptr); + hdr.payload_ptr = NULL; + hdr.payload_len = 0; + + //Test variations of sn_coap_convert_block_size here --> + for( int i=0; i < 8; i++ ){ + uint16_t multiplier = 16*pow(2, i); + sn_coap_protocol_set_block_size(handle,multiplier); + hdr.payload_ptr = (uint8_t*)malloc(multiplier + 20); + memset(hdr.payload_ptr, '1', multiplier + 20); + hdr.payload_len = multiplier + 20; + retCounter = 2; + hdr.msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; + CHECK( -3 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, &hdr, NULL)); + hdr.msg_code = COAP_MSG_CODE_EMPTY; + + free(hdr.options_list_ptr->block2_ptr); + free(hdr.options_list_ptr->size2_ptr); + hdr.options_list_ptr->block2_ptr = NULL; + free(hdr.options_list_ptr); + hdr.options_list_ptr = NULL; + + free(hdr.payload_ptr); + hdr.payload_ptr = NULL; + hdr.payload_len = 0; + } + sn_coap_protocol_set_block_size(handle,SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE); + + // <-- Test variations of sn_coap_convert_block_size here + + retCounter = 1; + sn_coap_builder_stub.expectedInt16 = -1; + CHECK( -1 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, &hdr, NULL)); + + retCounter = 1; + sn_coap_builder_stub.expectedInt16 = 1; + CHECK( 1 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, &hdr, NULL)); + + hdr.msg_code = COAP_MSG_CODE_EMPTY; + + retCounter = 2; + sn_coap_builder_stub.expectedInt16 = 1; + CHECK( 1 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, &hdr, NULL)); + + retCounter = 3; + sn_coap_builder_stub.expectedInt16 = 1; + CHECK( 1 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, &hdr, NULL)); + + retCounter = 4; + sn_coap_builder_stub.expectedInt16 = 1; + CHECK( 1 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, &hdr, NULL)); + + retCounter = 5; + sn_coap_builder_stub.expectedInt16 = 1; + CHECK( 1 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, &hdr, NULL)); + + // Test second SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE --> + hdr.payload_ptr = (uint8_t*)malloc(SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20); + memset(hdr.payload_ptr, '1', SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20); + hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + + retCounter = 2; + sn_coap_builder_stub.expectedInt16 = 1; + CHECK( 1 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, &hdr, NULL)); + free(hdr.payload_ptr); + + hdr.payload_ptr = (uint8_t*)malloc(SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20); + memset(hdr.payload_ptr, '1', SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20); + hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + + retCounter = 6; + sn_coap_builder_stub.expectedInt16 = 1; + CHECK( 1 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, &hdr, NULL)); + + free(hdr.payload_ptr); + hdr.payload_ptr = (uint8_t*)malloc(UINT16_MAX); + memset(hdr.payload_ptr, '1', UINT16_MAX); + hdr.payload_len = UINT16_MAX; + + retCounter = 6; + sn_coap_builder_stub.expectedInt16 = 1; + CHECK( 1 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, &hdr, NULL)); + + free(hdr.payload_ptr); + hdr.payload_ptr = (uint8_t*)malloc(UINT16_MAX - 1); + memset(hdr.payload_ptr, '1', UINT16_MAX - 1); + hdr.payload_len = UINT16_MAX - 1; + + retCounter = 6; + sn_coap_builder_stub.expectedInt16 = 1; + CHECK( 1 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, &hdr, NULL)); + + sn_coap_protocol_destroy(handle); + handle = NULL; + retCounter = 1; + handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL); + free(hdr.options_list_ptr->block1_ptr); + hdr.options_list_ptr->block1_ptr = NULL; + free(hdr.options_list_ptr->size1_ptr); + hdr.options_list_ptr->size1_ptr = NULL; + free(hdr.options_list_ptr); + hdr.options_list_ptr = NULL; + //Test sn_coap_protocol_copy_header here --> + retCounter = 9; + sn_coap_builder_stub.expectedInt16 = 1; + hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + CHECK( -2 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, &hdr, NULL)); + + free(hdr.options_list_ptr->block1_ptr); + hdr.options_list_ptr->block1_ptr = NULL; + free(hdr.options_list_ptr->size1_ptr); + hdr.options_list_ptr->size1_ptr = NULL; + free(hdr.options_list_ptr); + hdr.options_list_ptr = NULL; + + sn_coap_hdr_s* hdr2 = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr2, 0, sizeof(sn_coap_hdr_s)); + hdr2->msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE; + hdr2->uri_path_ptr = (uint8_t*)malloc(3); + hdr2->uri_path_len = 3; + hdr2->token_ptr = (uint8_t*)malloc(3); + hdr2->token_len = 3; + hdr2->content_type_ptr = (uint8_t*)malloc(3); + hdr2->content_type_len = 3; + + hdr2->options_list_ptr = (sn_coap_options_list_s *)malloc(sizeof(sn_coap_options_list_s)); + memset(hdr2->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + hdr2->options_list_ptr->accept_ptr = (uint8_t*)malloc(3); + hdr2->options_list_ptr->accept_len = 3; + hdr2->options_list_ptr->block1_ptr = (uint8_t*)malloc(3); + hdr2->options_list_ptr->block1_len = 3; + + hdr2->options_list_ptr->block2_ptr = (uint8_t*)malloc(3); + hdr2->options_list_ptr->block2_len = 3; + hdr2->options_list_ptr->etag_ptr = (uint8_t*)malloc(3); + hdr2->options_list_ptr->etag_len = 3; + hdr2->options_list_ptr->location_path_ptr = (uint8_t*)malloc(3); + hdr2->options_list_ptr->location_path_len = 3; + hdr2->options_list_ptr->location_query_ptr = (uint8_t*)malloc(3); + hdr2->options_list_ptr->location_query_len = 3; + hdr2->options_list_ptr->max_age_ptr = (uint8_t*)malloc(3); + hdr2->options_list_ptr->max_age_len = 3; + hdr2->options_list_ptr->observe_ptr = (uint8_t*)malloc(3); + hdr2->options_list_ptr->observe_len = 3; + hdr2->options_list_ptr->proxy_uri_ptr = (uint8_t*)malloc(3); + hdr2->options_list_ptr->proxy_uri_len = 3; + hdr2->options_list_ptr->uri_host_ptr = (uint8_t*)malloc(3); + hdr2->options_list_ptr->uri_host_len = 3; + hdr2->options_list_ptr->uri_port_ptr = (uint8_t*)malloc(3); + hdr2->options_list_ptr->uri_port_len = 3; + hdr2->options_list_ptr->uri_query_ptr = (uint8_t*)malloc(3); + hdr2->options_list_ptr->uri_query_len = 3; + hdr2->options_list_ptr->size1_ptr = (uint8_t*)malloc(3); + hdr2->options_list_ptr->size1_len = 3; + + hdr2->payload_ptr = (uint8_t*)malloc(3); + + for( int i=0; i < 17; i++ ){ + retCounter = 3 + i; + sn_coap_builder_stub.expectedInt16 = 1; + hdr2->payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + int8_t rett = sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, hdr2, NULL); + CHECK( -2 == rett ); + } + + retCounter = 20; + sn_coap_builder_stub.expectedInt16 = 1; + hdr2->payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + CHECK( 1 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, hdr2, NULL)); + + retCounter = 20; + sn_coap_builder_stub.expectedInt16 = 1; + hdr2->payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + CHECK( 1 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, hdr2, NULL)); + + free(hdr2->payload_ptr); + sn_coap_parser_release_allocated_coap_msg_mem(handle, hdr2); + hdr2 = NULL; + + //<-- Test sn_coap_protocol_copy_header here + + hdr.msg_code = COAP_MSG_CODE_REQUEST_GET; + retCounter = 5; + sn_coap_builder_stub.expectedInt16 = 1; + hdr.payload_len = 0; + CHECK( 1 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, &hdr, NULL)); + + sn_coap_protocol_destroy(handle); + handle = NULL; + retCounter = 1; + handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL); + + retCounter = 6; + sn_coap_builder_stub.expectedInt16 = 1; + hdr.payload_len = 0; + CHECK( -2 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, &hdr, NULL)); + + retCounter = 7; + sn_coap_builder_stub.expectedInt16 = 1; + hdr.payload_len = 0; + CHECK( 1 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, &hdr, NULL)); + + free(hdr.payload_ptr); + hdr.payload_ptr = NULL; + hdr.payload_len = 0; + + hdr.msg_code = COAP_MSG_CODE_EMPTY; + + // <-- Test second SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + + free(addr.addr_ptr); + free(dst_packet_data_ptr); + sn_coap_protocol_destroy(handle); +} + +TEST(libCoap_protocol, sn_coap_protocol_parse) +{ + CHECK( NULL == sn_coap_protocol_parse(NULL, NULL, 0, NULL, NULL) ); + + retCounter = 1; + struct coap_s * handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL); + + sn_nsdl_addr_s* addr = (sn_nsdl_addr_s*)malloc(sizeof(sn_nsdl_addr_s)); + memset(addr, 0, sizeof(sn_nsdl_addr_s)); + + addr->addr_ptr = (uint8_t*)malloc(5); + + uint8_t *packet_data_ptr = (uint8_t*)malloc(5); + uint16_t packet_data_len = 5; + + sn_coap_parser_stub.expectedHeader = NULL; + CHECK( NULL == sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL) ); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_header_check_stub.expectedInt8 = 1; + sn_coap_parser_stub.expectedHeader->coap_status = COAP_STATUS_PARSER_ERROR_IN_HEADER; + CHECK( NULL == sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL) ); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_header_check_stub.expectedInt8 = 1; + sn_coap_parser_stub.expectedHeader->msg_code = sn_coap_msg_code_e(COAP_MSG_CODE_RESPONSE_PROXYING_NOT_SUPPORTED + 60); + + CHECK( NULL == sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL) ); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_header_check_stub.expectedInt8 = 0; + + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_EMPTY; + + CHECK( NULL == sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL) ); + + //Test sn_coap_handle_blockwise_message, block1_ptr != NULL --> + sn_coap_protocol_set_duplicate_buffer_size(handle,1); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 4; + + sn_coap_options_list_s* list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->msg_id = 4; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_GET; + + sn_coap_hdr_s *ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 4; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->msg_id = 4; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_GET; + uint8_t* payload = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 5; + + retCounter = 1; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 4; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->msg_id = 4; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_GET; + payload = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 5; + + retCounter = 2; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 4; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->msg_id = 4; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_GET; + payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + + retCounter = 3; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( COAP_STATUS_PARSER_DUPLICATED_MSG == ret->coap_status ); + + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 5; + + retCounter = 3; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 6; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->msg_id = 4; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_GET; + payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + + retCounter = 4; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 7; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_GET; + payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + + retCounter = 5; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 8; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_GET; + + retCounter = 6; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED == ret->coap_status ); + free(ret->payload_ptr); + free(sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr); + free(list); + free(sn_coap_parser_stub.expectedHeader); + + // block1_ptr[0] == 0x08 --> + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 9; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(1); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_len = 1; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_GET; + payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + + retCounter = 2; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 10; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(1); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_len = 1; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_GET; + payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + + retCounter = 6; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 11; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(1); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_len = 1; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_GET; + payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + + retCounter = 7; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + free(sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr); + free(list); + free(sn_coap_parser_stub.expectedHeader); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 12; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(1); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_len = 1; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr[0] = 0x0F; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_POST; + payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + sn_coap_builder_stub.expectedUint16 = 1; + + retCounter = 8; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 13; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(1); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_len = 1; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_PUT; + payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + sn_coap_builder_stub.expectedUint16 = 1; + + retCounter = 9; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL != ret ); + CHECK(COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING == ret->coap_status); + free(payload); + free(sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr); + free(list); + free(sn_coap_parser_stub.expectedHeader); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 14; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(1); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_len = 1; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_DELETE; + payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + + retCounter = 7; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + free(sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr); + free(list); + free(sn_coap_parser_stub.expectedHeader); + + /* Size is more than we can handle */ + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 100; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(1); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_len = 1; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->options_list_ptr->size1_ptr = (uint8_t*)malloc(3); + sn_coap_parser_stub.expectedHeader->options_list_ptr->size1_ptr[0] = 0xFF; + sn_coap_parser_stub.expectedHeader->options_list_ptr->size1_ptr[1] = 0xFF; + sn_coap_parser_stub.expectedHeader->options_list_ptr->size1_ptr[2] = 0x01; + sn_coap_parser_stub.expectedHeader->options_list_ptr->size1_len = 3; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_PUT; + payload = (uint8_t*)malloc(65535); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 65535; + + retCounter = 10; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL != ret ); + free(payload); + free(sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr); + free(sn_coap_parser_stub.expectedHeader->options_list_ptr->size1_ptr); + free(list); + free(sn_coap_parser_stub.expectedHeader); + + + // received_coap_msg_ptr->msg_code > COAP_MSG_CODE_REQUEST_DELETE --> + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 15; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(1); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_len = 1; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr[0] = 0x00; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + + retCounter = 2; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL != ret ); + CHECK( COAP_STATUS_OK == ret->coap_status ); + free(payload); + free(sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr); + free(list); + free(sn_coap_parser_stub.expectedHeader); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 16; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(1); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_len = 1; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + + + sn_nsdl_addr_s tmp_addr; + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + sn_coap_hdr_s tmp_hdr; + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + uint8_t* dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 1; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); + tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + tmp_hdr.options_list_ptr->block2_ptr = (uint8_t*)malloc(1); + tmp_hdr.msg_id = 16; + tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.options_list_ptr->block2_ptr); + free(tmp_hdr.options_list_ptr->block1_ptr); + free(tmp_hdr.options_list_ptr->size1_ptr); + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + retCounter = 2; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + + sn_coap_protocol_destroy(handle); + retCounter = 1; + handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 17; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(1); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_len = 1; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + + retCounter = 22; + sn_coap_builder_stub.expectedInt16 = 1; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); + tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + tmp_hdr.options_list_ptr->block1_ptr = NULL; + tmp_hdr.options_list_ptr->block2_ptr = (uint8_t*)malloc(1); + tmp_hdr.msg_id = 17; + tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + + free(tmp_hdr.options_list_ptr->block2_ptr); + free(tmp_hdr.options_list_ptr->block1_ptr); + free(tmp_hdr.options_list_ptr->size1_ptr); + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + retCounter = 3; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 18; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(2); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_len = 2; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr[1] = 0xe8; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + + + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 1; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); +// tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); +// memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); +// tmp_hdr.options_list_ptr->block2_ptr = (uint8_t*)malloc(1); + tmp_hdr.msg_id = 18; + tmp_hdr.msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.options_list_ptr->block2_ptr); + free(tmp_hdr.options_list_ptr->block1_ptr); + free(tmp_hdr.options_list_ptr->size1_ptr); + free(tmp_hdr.options_list_ptr->size2_ptr); + tmp_hdr.options_list_ptr->block2_ptr = NULL; + tmp_hdr.options_list_ptr->block1_ptr = NULL; + tmp_hdr.options_list_ptr->size1_ptr = NULL; + tmp_hdr.options_list_ptr->size2_ptr = NULL; + free(tmp_hdr.options_list_ptr); + tmp_hdr.options_list_ptr = NULL; + + tmp_hdr.payload_len = UINT16_MAX; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + free(tmp_hdr.options_list_ptr->block2_ptr); + free(tmp_hdr.options_list_ptr->block1_ptr); + free(tmp_hdr.options_list_ptr->size1_ptr); + free(tmp_hdr.options_list_ptr->size2_ptr); + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + tmp_hdr.payload_ptr = NULL; + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + retCounter = 3; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 19; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(3); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_len = 3; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr[1] = 0xe8; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr[2] = 0xee; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 1; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); +// tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); +// memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); +// tmp_hdr.options_list_ptr->block2_ptr = (uint8_t*)malloc(1); + tmp_hdr.msg_id = 19; + tmp_hdr.msg_code = COAP_MSG_CODE_REQUEST_GET; + tmp_hdr.payload_len = 1; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + tmp_hdr.payload_ptr = NULL; + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + retCounter = 2; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 20; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(3); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_len = 3; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr[1] = 0xe8; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr[2] = 0xee; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 1; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); +// tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); +// memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); +// tmp_hdr.options_list_ptr->block2_ptr = (uint8_t*)malloc(1); + tmp_hdr.msg_id = 20; + tmp_hdr.msg_code = COAP_MSG_CODE_REQUEST_GET; + tmp_hdr.payload_len = 1; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + tmp_hdr.payload_ptr = NULL; + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + retCounter = 5; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL != ret ); + CHECK( COAP_STATUS_PARSER_BLOCKWISE_ACK == ret->coap_status ); + free(payload); + sn_coap_parser_release_allocated_coap_msg_mem(handle, ret); + + //<-- block1_ptr[0] == 0x08 + //<-- Test sn_coap_handle_blockwise_message, block1_ptr != NULL + + sn_coap_protocol_destroy(handle); + retCounter = 1; + handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL); + + //Test sn_coap_handle_blockwise_message, block2_ptr != NULL --> + sn_coap_protocol_set_duplicate_buffer_size(handle,1); + + // block2_ptr length == 1,2,3 --> + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 16; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr = (uint8_t*)malloc(1); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_len = 1; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_DELETE; + payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 1; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); + tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + tmp_hdr.options_list_ptr->block2_ptr = (uint8_t*)malloc(1); + tmp_hdr.msg_id = 16; + tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.options_list_ptr->block2_ptr); + free(tmp_hdr.options_list_ptr->block1_ptr); + free(tmp_hdr.options_list_ptr->size1_ptr); + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + retCounter = 2; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + sn_coap_parser_release_allocated_coap_msg_mem(handle, sn_coap_parser_stub.expectedHeader); + + sn_coap_protocol_destroy(handle); + retCounter = 1; + handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 17; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr = (uint8_t*)malloc(1); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_len = 1; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_DELETE; + payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + + retCounter = 22; + sn_coap_builder_stub.expectedInt16 = 1; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); + tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + tmp_hdr.options_list_ptr->block1_ptr = NULL; + tmp_hdr.options_list_ptr->block2_ptr = (uint8_t*)malloc(1); + tmp_hdr.msg_id = 17; + tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + + free(tmp_hdr.options_list_ptr->block2_ptr); + free(tmp_hdr.options_list_ptr->block1_ptr); + free(tmp_hdr.options_list_ptr->size1_ptr); + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + retCounter = 3; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + sn_coap_parser_release_allocated_coap_msg_mem(handle, sn_coap_parser_stub.expectedHeader); + + sn_coap_protocol_destroy(handle); + retCounter = 1; + handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 18; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr = (uint8_t*)malloc(2); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_len = 2; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[1] = 0xe8; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_DELETE; + payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + + + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 1; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); +// tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); +// memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); +// tmp_hdr.options_list_ptr->block2_ptr = (uint8_t*)malloc(1); + tmp_hdr.msg_id = 18; + tmp_hdr.msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.options_list_ptr->block2_ptr); + free(tmp_hdr.options_list_ptr->block1_ptr); + free(tmp_hdr.options_list_ptr->size1_ptr); + free(tmp_hdr.options_list_ptr->size2_ptr); + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + tmp_hdr.payload_ptr = NULL; + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + retCounter = 3; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + sn_coap_parser_release_allocated_coap_msg_mem(handle, sn_coap_parser_stub.expectedHeader); + + sn_coap_protocol_destroy(handle); + retCounter = 1; + handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 19; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr = (uint8_t*)malloc(3); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_len = 3; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[1] = 0xe8; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[2] = 0xee; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_DELETE; + payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 1; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); +// tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); +// memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); +// tmp_hdr.options_list_ptr->block2_ptr = (uint8_t*)malloc(1); + tmp_hdr.msg_id = 19; + tmp_hdr.msg_code = COAP_MSG_CODE_REQUEST_GET; + tmp_hdr.payload_len = 1; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + tmp_hdr.payload_ptr = NULL; + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + retCounter = 2; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + sn_coap_parser_release_allocated_coap_msg_mem(handle, sn_coap_parser_stub.expectedHeader); + + sn_coap_protocol_destroy(handle); + retCounter = 1; + handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 200; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr = (uint8_t*)malloc(3); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_len = 3; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[1] = 0xe8; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[2] = 0xee; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_DELETE; + payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 1; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); + tmp_hdr.msg_id = 200; + tmp_hdr.msg_code = COAP_MSG_CODE_REQUEST_GET; + tmp_hdr.payload_len = 1; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + tmp_hdr.payload_ptr = NULL; + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + retCounter = 3; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + sn_coap_parser_release_allocated_coap_msg_mem(handle, sn_coap_parser_stub.expectedHeader); + + + sn_coap_protocol_destroy(handle); + retCounter = 1; + handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 20; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr = (uint8_t*)malloc(3); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_len = 3; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[1] = 0xe8; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[2] = 0xee; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_DELETE; + payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 1; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); + + tmp_hdr.msg_id = 20; + tmp_hdr.msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.options_list_ptr->block2_ptr); + free(tmp_hdr.options_list_ptr->size2_ptr); + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + tmp_hdr.payload_ptr = NULL; + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + retCounter = 5; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL != ret ); + CHECK( COAP_STATUS_PARSER_BLOCKWISE_ACK == ret->coap_status ); + free(payload); + sn_coap_parser_release_allocated_coap_msg_mem(handle, sn_coap_parser_stub.expectedHeader); + + //<-- block2_ptr length == 1,2,3 + + // block2_ptr[0] == 0x08 --> + + sn_coap_protocol_destroy(handle); + retCounter = 1; + handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_len = 1; + sn_coap_parser_stub.expectedHeader->msg_id = 41; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + payload = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 5; + + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_len = 1; + sn_coap_parser_stub.expectedHeader->msg_id = 41; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + payload = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 5; + + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 1; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); + tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + tmp_hdr.options_list_ptr->block2_ptr = (uint8_t*)malloc(1); + tmp_hdr.msg_id = 41; + tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.options_list_ptr->block2_ptr); + free(tmp_hdr.options_list_ptr->block1_ptr); + free(tmp_hdr.options_list_ptr->size1_ptr); + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + retCounter = 0; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + sn_coap_parser_release_allocated_coap_msg_mem(handle, sn_coap_parser_stub.expectedHeader); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_len = 1; + sn_coap_parser_stub.expectedHeader->msg_id = 42; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + payload = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 5; + + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 1; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); + tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + tmp_hdr.options_list_ptr->block2_ptr = (uint8_t*)malloc(1); + tmp_hdr.msg_id = 42; + tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.options_list_ptr->block2_ptr); + free(tmp_hdr.options_list_ptr->block1_ptr); + free(tmp_hdr.options_list_ptr->size1_ptr); + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + retCounter = 6; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); +// sn_coap_parser_release_allocated_coap_msg_mem(handle, sn_coap_parser_stub.expectedHeader); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_len = 1; + sn_coap_parser_stub.expectedHeader->msg_id = 43; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + payload = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 5; + + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 1; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); + tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + tmp_hdr.options_list_ptr->block2_ptr = (uint8_t*)malloc(1); + tmp_hdr.msg_id = 43; + tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.options_list_ptr->block2_ptr); + free(tmp_hdr.options_list_ptr->block1_ptr); + free(tmp_hdr.options_list_ptr->size1_ptr); + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + retCounter = 7; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); +// sn_coap_parser_release_allocated_coap_msg_mem(handle, sn_coap_parser_stub.expectedHeader); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[0] = 0x08; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_len = 1; + sn_coap_parser_stub.expectedHeader->msg_id = 44; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + payload = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 5; + + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 1; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); + tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + tmp_hdr.options_list_ptr->block2_ptr = (uint8_t*)malloc(1); + tmp_hdr.msg_id = 44; + tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.options_list_ptr->block2_ptr); + free(tmp_hdr.options_list_ptr->block1_ptr); + free(tmp_hdr.options_list_ptr->size1_ptr); + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + retCounter = 8; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[0] = 0xa8; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[1] = 0xa8; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_len = 2; + sn_coap_parser_stub.expectedHeader->msg_id = 45; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + payload = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 5; + + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 1; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); + tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + tmp_hdr.options_list_ptr->block2_ptr = (uint8_t*)malloc(1); + tmp_hdr.msg_id = 45; + tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.options_list_ptr->block2_ptr); + free(tmp_hdr.options_list_ptr->block1_ptr); + free(tmp_hdr.options_list_ptr->size1_ptr); + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + sn_coap_builder_stub.expectedInt16 = -1; + retCounter = 9; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[0] = 0xc8; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[1] = 0xc8; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[2] = 0xc8; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_len = 3; + sn_coap_parser_stub.expectedHeader->msg_id = 46; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + payload = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 5; + + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 1; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); + tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + tmp_hdr.options_list_ptr->block2_ptr = (uint8_t*)malloc(1); + tmp_hdr.msg_id = 46; + tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.options_list_ptr->block2_ptr); + free(tmp_hdr.options_list_ptr->block1_ptr); + free(tmp_hdr.options_list_ptr->size1_ptr); + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + sn_coap_builder_stub.expectedInt16 = 1; + retCounter = 9; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + + sn_coap_protocol_destroy(handle); + retCounter = 1; + handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[0] = 0xc8; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[1] = 0xc8; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[2] = 0xc8; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_len = 3; + sn_coap_parser_stub.expectedHeader->msg_id = 47; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + payload = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 5; + + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 1; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); + tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + tmp_hdr.options_list_ptr->block2_ptr = (uint8_t*)malloc(1); + tmp_hdr.msg_id = 47; + tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.options_list_ptr->block2_ptr); + free(tmp_hdr.options_list_ptr->block1_ptr); + free(tmp_hdr.options_list_ptr->size1_ptr); + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + sn_coap_builder_stub.expectedInt16 = 1; + retCounter = 10; + sn_coap_protocol_set_retransmission_buffer(handle,0,0); + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL != ret ); + free(payload); + sn_coap_parser_release_allocated_coap_msg_mem(handle, ret); + + sn_coap_protocol_destroy(handle); + retCounter = 1; + handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[0] = 0xc8; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[1] = 0xc8; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr[2] = 0xc8; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_len = 3; + sn_coap_parser_stub.expectedHeader->msg_id = 47; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + payload = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 5; + + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 1; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); + tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + tmp_hdr.options_list_ptr->block2_ptr = (uint8_t*)malloc(1); + tmp_hdr.msg_id = 47; + tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.options_list_ptr->block2_ptr); + free(tmp_hdr.options_list_ptr->block1_ptr); + free(tmp_hdr.options_list_ptr->size1_ptr); + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + sn_coap_builder_stub.expectedInt16 = 1; + retCounter = 10; + sn_coap_protocol_set_retransmission_buffer(handle,2,1); + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL != ret ); + free(payload); + sn_coap_parser_release_allocated_coap_msg_mem(handle, ret); + + // <-- block2_ptr[0] == 0x08 + + //<-- Test sn_coap_handle_blockwise_message, block2_ptr != NULL + + sn_coap_protocol_destroy(handle); + retCounter = 1; + handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->msg_id = 41; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + payload = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 5; + + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + sn_coap_parser_release_allocated_coap_msg_mem(handle, sn_coap_parser_stub.expectedHeader); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->msg_id = 42; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + payload = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 5; + + retCounter = 1; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + sn_coap_parser_release_allocated_coap_msg_mem(handle, sn_coap_parser_stub.expectedHeader); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->msg_id = 43; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + payload = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 5; + + retCounter = 2; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + sn_coap_parser_release_allocated_coap_msg_mem(handle, sn_coap_parser_stub.expectedHeader); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->msg_id = 44; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + payload = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 5; + + retCounter = 3; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + sn_coap_parser_release_allocated_coap_msg_mem(handle, sn_coap_parser_stub.expectedHeader); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->msg_id = 45; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + payload = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 5; + + retCounter = 4; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL == ret ); + free(payload); + sn_coap_parser_release_allocated_coap_msg_mem(handle, sn_coap_parser_stub.expectedHeader); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + + list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block2_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->msg_id = 46; + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + payload = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 5; + + retCounter = 6; + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( NULL != ret ); + free(payload); + free(ret->payload_ptr); + sn_coap_parser_release_allocated_coap_msg_mem(handle, ret); + + sn_coap_protocol_destroy(handle); + retCounter = 1; + handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 18; + + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + dst_packet_data_ptr[2]=0; + dst_packet_data_ptr[3]=18; + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + tmp_addr.port = 0; + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 5; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); + tmp_hdr.msg_id = 18; + tmp_hdr.msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.options_list_ptr->block2_ptr); + free(tmp_hdr.options_list_ptr->size2_ptr); + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( ret != NULL ); + sn_coap_parser_release_allocated_coap_msg_mem(handle, ret); + + sn_coap_protocol_destroy(handle); + + retCounter = 1; + handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_RESET; + sn_coap_parser_stub.expectedHeader->msg_id = 18; + + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + dst_packet_data_ptr[2]=0; + dst_packet_data_ptr[3]=18; + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + tmp_addr.port = 0; + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 5; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); + tmp_hdr.msg_id = 18; + tmp_hdr.msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + tmp_hdr.uri_path_ptr = (uint8_t*)malloc(7); + snprintf((char *)tmp_hdr.uri_path_ptr, 7, "13/0/1"); + tmp_hdr.uri_path_len = 7; + + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.uri_path_ptr); + free(tmp_hdr.options_list_ptr->block2_ptr); + free(tmp_hdr.options_list_ptr->size2_ptr); + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( ret != NULL ); + sn_coap_parser_release_allocated_coap_msg_mem(handle, ret); + + sn_coap_protocol_destroy(handle); + + retCounter = 1; + handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 18; + + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + dst_packet_data_ptr[2]=0; + dst_packet_data_ptr[3]=185; + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + tmp_addr.port = 0; + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 5; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); + tmp_hdr.msg_id = 18; + tmp_hdr.msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + tmp_hdr.uri_path_ptr = (uint8_t*)malloc(7); + snprintf((char *)tmp_hdr.uri_path_ptr, 7, "13/0/1"); + tmp_hdr.uri_path_len = 7; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.options_list_ptr->block2_ptr); + free(tmp_hdr.options_list_ptr->size2_ptr); + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + ret = sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + CHECK( ret != NULL ); + sn_coap_parser_release_allocated_coap_msg_mem(handle, ret); + + free(tmp_hdr.uri_path_ptr); + free(packet_data_ptr); + free(addr->addr_ptr); + free(addr); + sn_coap_protocol_destroy(handle); +} + +TEST(libCoap_protocol, sn_coap_protocol_exec) +{ + CHECK(-1 == sn_coap_protocol_exec(NULL, 0)); + + retCounter = 1; + struct coap_s * handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL); + + sn_nsdl_addr_s tmp_addr; + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + sn_coap_hdr_s tmp_hdr; + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + uint8_t* dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 5; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); + tmp_hdr.msg_id = 18; + tmp_hdr.msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.options_list_ptr->block2_ptr); + free(tmp_hdr.options_list_ptr->size2_ptr); + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 7; + + sn_coap_options_list_s* list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_GET; + uint8_t* payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + + uint8_t *packet_data_ptr = (uint8_t*)malloc(5); + uint16_t packet_data_len = 5; + + sn_nsdl_addr_s* addr = (sn_nsdl_addr_s*)malloc(sizeof(sn_nsdl_addr_s)); + memset(addr, 0, sizeof(sn_nsdl_addr_s)); + + addr->addr_ptr = (uint8_t*)malloc(5); + + retCounter = 5; + sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + free(payload); + free(packet_data_ptr); + free(addr->addr_ptr); + free(addr); + + CHECK(0 == sn_coap_protocol_exec(handle, 600)); + + sn_coap_builder_stub.expectedInt16 = 0; + retCounter = 0; + sn_coap_protocol_destroy(handle); +} + +TEST(libCoap_protocol, sn_coap_protocol_exec2) +{ + retCounter = 1; + struct coap_s * handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, null_rx_cb); + + sn_nsdl_addr_s tmp_addr; + memset(&tmp_addr, 0, sizeof(sn_nsdl_addr_s)); + sn_coap_hdr_s tmp_hdr; + memset(&tmp_hdr, 0, sizeof(sn_coap_hdr_s)); + + uint8_t* dst_packet_data_ptr = (uint8_t*)malloc(5); + memset(dst_packet_data_ptr, '1', 5); + + tmp_addr.addr_ptr = (uint8_t*)malloc(5); + memset(tmp_addr.addr_ptr, '1', 5); + + retCounter = 21; + sn_coap_builder_stub.expectedInt16 = 5; + tmp_hdr.payload_ptr = (uint8_t*)malloc(3); + tmp_hdr.msg_id = 18; + tmp_hdr.msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20; + sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL); + + free(tmp_hdr.options_list_ptr->block2_ptr); + free(tmp_hdr.options_list_ptr->size2_ptr); + free(tmp_hdr.options_list_ptr); + free(tmp_hdr.payload_ptr); + free(tmp_addr.addr_ptr); + free(dst_packet_data_ptr); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_coap_parser_stub.expectedHeader->msg_id = 7; + + sn_coap_options_list_s* list = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(list, 0, sizeof(sn_coap_options_list_s)); + sn_coap_parser_stub.expectedHeader->options_list_ptr = list; + sn_coap_parser_stub.expectedHeader->options_list_ptr->block1_ptr = (uint8_t*)malloc(5); + sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_GET; + uint8_t* payload = (uint8_t*)malloc(17); + sn_coap_parser_stub.expectedHeader->payload_ptr = payload; + sn_coap_parser_stub.expectedHeader->payload_len = 17; + + uint8_t *packet_data_ptr = (uint8_t*)malloc(5); + uint16_t packet_data_len = 5; + + sn_nsdl_addr_s* addr = (sn_nsdl_addr_s*)malloc(sizeof(sn_nsdl_addr_s)); + memset(addr, 0, sizeof(sn_nsdl_addr_s)); + + addr->addr_ptr = (uint8_t*)malloc(5); + + retCounter = 5; + sn_coap_protocol_parse(handle, addr, packet_data_len, packet_data_ptr, NULL); + free(payload); + free(packet_data_ptr); + free(addr->addr_ptr); + free(addr); + + sn_coap_parser_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_parser_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + + sn_coap_protocol_set_retransmission_parameters(handle,0, 5); + CHECK(0 == sn_coap_protocol_exec(handle, 600)); + + sn_coap_builder_stub.expectedInt16 = 0; + retCounter = 0; + sn_coap_protocol_destroy(handle); +} + diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_protocol/main.cpp b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_protocol/main.cpp new file mode 100644 index 0000000000..f352953caa --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_coap_protocol/main.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" + + + +int main(int ac, char **av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP(libCoap_protocol); diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_grs/main.cpp b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_grs/main.cpp new file mode 100644 index 0000000000..3f777d0dc3 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_grs/main.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ + +#include "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP(sn_grs); + diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_grs/sn_grstest.cpp b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_grs/sn_grstest.cpp new file mode 100644 index 0000000000..b0a6a8cbb5 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_grs/sn_grstest.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ +#include "CppUTest/TestHarness.h" +#include "test_sn_grs.h" + +TEST_GROUP(sn_grs) +{ + void setup() + { + } + + void teardown() + { + } +}; + +TEST(sn_grs, test_sn_grs_get_first_resource) +{ + CHECK(test_sn_grs_get_first_resource()); +} + + +TEST(sn_grs, test_sn_grs_get_next_resource) +{ + CHECK(test_sn_grs_get_next_resource()); +} + +TEST(sn_grs, test_sn_grs_process_coap) +{ + CHECK(test_sn_grs_process_coap()); +} + +TEST(sn_grs, test_sn_grs_search_resource) +{ + CHECK(test_sn_grs_search_resource()); +} + +TEST(sn_grs, test_sn_grs_destroy) +{ + CHECK(test_sn_grs_destroy()); +} + +TEST(sn_grs, test_sn_grs_init) +{ + CHECK(test_sn_grs_init()); +} + +TEST(sn_grs, test_sn_grs_list_resource) +{ + CHECK(test_sn_grs_list_resource()); +} + +TEST(sn_grs, test_sn_grs_free_resource_list) +{ + CHECK(test_sn_grs_free_resource_list()); +} + +TEST(sn_grs, test_sn_grs_update_resource) +{ + CHECK(test_sn_grs_update_resource()); +} + +TEST(sn_grs, test_sn_grs_send_coap_message) +{ + CHECK(test_sn_grs_send_coap_message()); +} + +TEST(sn_grs, test_sn_grs_create_resource) +{ + CHECK(test_sn_grs_create_resource()); +} + +TEST(sn_grs, test_sn_grs_delete_resource) +{ + CHECK(test_sn_grs_delete_resource()); +} + +TEST(sn_grs, test_sn_grs_mark_resources_as_registered) +{ + CHECK(test_sn_grs_mark_resources_as_registered()); +} + diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_grs/test_sn_grs.c b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_grs/test_sn_grs.c new file mode 100644 index 0000000000..e371fa8a9f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_grs/test_sn_grs.c @@ -0,0 +1,1191 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ +#include "test_sn_grs.h" +#include +#include +#include "sn_coap_header.h" +#include "sn_nsdl.h" +#include "sn_nsdl_lib.h" +#include "sn_grs.h" +#include "ns_list.h" + +#include "sn_nsdl_stub.h" +#include "sn_coap_protocol_stub.h" +#include "sn_coap_builder_stub.h" + +int retCounter = 0; +uint8_t retValUint8 = 0; + +void* myMalloc(uint16_t size) +{ + if( retCounter > 0 ){ + retCounter--; + return malloc(size); + }else { + return NULL; + } +} + +void myFree(void* ptr){ + free(ptr); +} + +uint8_t myTxCallback(struct nsdl_s *a, sn_nsdl_capab_e b, uint8_t *c, uint16_t d, + sn_nsdl_addr_s *e) +{ + return retValUint8; +} + +int8_t myRxCallback(struct nsdl_s *a, sn_coap_hdr_s *b, sn_nsdl_addr_s *c) +{ + return 0; +} + +uint8_t myResCallback(struct nsdl_s *a, sn_coap_hdr_s *b, sn_nsdl_addr_s *c, sn_nsdl_capab_e d) +{ + +} + + +bool test_sn_grs_destroy() +{ + if( SN_NSDL_SUCCESS != sn_grs_destroy(NULL)){ + return false; + } + struct grs_s* handle = (struct grs_s*)malloc(sizeof(struct grs_s)); + memset(handle, 0, sizeof(struct grs_s)); + handle->sn_grs_alloc = myMalloc; + handle->sn_grs_free = myFree; + + sn_nsdl_resource_info_s* res = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(res, 0, sizeof(sn_nsdl_resource_info_s)); + ns_list_add_to_start(&handle->resource_root_list, res); + ++handle->resource_root_count; + + if( SN_NSDL_SUCCESS != sn_grs_destroy(handle)){ + return false; + } + + return true; +} + +bool test_sn_grs_init() +{ + if( NULL != sn_grs_init(NULL, NULL, NULL, NULL) ){ + return false; + } + + if( NULL != sn_grs_init(&myTxCallback, &myRxCallback, &myMalloc, &myFree) ){ + return false; + } + + retCounter = 1; + sn_coap_protocol_stub.expectedCoap = (struct coap_s*)malloc(sizeof(struct coap_s)); + memset(sn_coap_protocol_stub.expectedCoap, 0, sizeof(struct coap_s)); + + struct grs_s* handle = sn_grs_init(&myTxCallback, &myRxCallback, &myMalloc, &myFree); + if( handle == NULL ){ + return false; + } + + struct nsdl_s* h = (struct nsdl_s*)malloc(sizeof(struct nsdl_s)); + memset(h, 0, sizeof(struct nsdl_s)); + h->grs = handle; + + if( 0 != sn_coap_protocol_stub.expectedCoap->sn_coap_rx_callback(NULL, NULL, NULL) ){ + return false; + } + + h->sn_nsdl_rx_callback = &myRxCallback; + if( 0 != sn_coap_protocol_stub.expectedCoap->sn_coap_rx_callback(NULL, NULL, h) ){ + return false; + } + + if( 0 != sn_coap_protocol_stub.expectedCoap->sn_coap_tx_callback(NULL, 0, NULL, NULL)){ + return false; + } + + retValUint8 = 0; + if( 0 != sn_coap_protocol_stub.expectedCoap->sn_coap_tx_callback(NULL, 0, NULL, h)){ + return false; + } + + free(sn_coap_protocol_stub.expectedCoap); + sn_coap_protocol_stub.expectedCoap = NULL; + + sn_grs_destroy(handle); + h->grs = NULL; + free(h); + + return true; +} + +bool test_sn_grs_list_resource() +{ + if( NULL != sn_grs_list_resource(NULL, 0, NULL) ){ + return false; + } + + retCounter = 1; + struct grs_s* handle = sn_grs_init(&myTxCallback, &myRxCallback, &myMalloc, &myFree); + + uint8_t* path = (uint8_t*)malloc(5); + if( NULL != sn_grs_list_resource(handle, 5, path) ){ + return false; + } + + handle->resource_root_count = 1; + retCounter = 1; + if( NULL != sn_grs_list_resource(handle, 5, path) ){ + return false; + } + + handle->resource_root_count = 0; + sn_nsdl_resource_info_s* res = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(res, 0, sizeof(sn_nsdl_resource_info_s)); + res->path = (uint8_t*)malloc(5); + res->pathlen = 5; + ns_list_add_to_start(&handle->resource_root_list, res); + ++handle->resource_root_count; + sn_nsdl_resource_info_s* res2 = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(res2, 0, sizeof(sn_nsdl_resource_info_s)); + res2->path = (uint8_t*)malloc(4); + res2->pathlen = 4; + ns_list_add_to_start(&handle->resource_root_list, res2); + ++handle->resource_root_count; + retCounter = 2; + if( NULL != sn_grs_list_resource(handle, 5, path) ){ + return false; + } + + retCounter = 4; + sn_grs_resource_list_s *list_ptr = sn_grs_list_resource(handle, 5, path); + if( NULL == list_ptr ){ + return false; + } + + sn_grs_free_resource_list(handle, list_ptr); + + free(path); + sn_grs_destroy(handle); + return true; +} + +bool test_sn_grs_free_resource_list() +{ + sn_grs_free_resource_list(NULL, NULL); + + retCounter = 1; + struct grs_s* handle = sn_grs_init(&myTxCallback, &myRxCallback, &myMalloc, &myFree); + + sn_grs_resource_list_s *grs_resource_list_ptr = (sn_grs_resource_list_s*)malloc(sizeof(sn_grs_resource_list_s)); + memset(grs_resource_list_ptr, 0, sizeof(sn_grs_resource_list_s)); + grs_resource_list_ptr->res_count = 1; + grs_resource_list_ptr->res = (sn_grs_resource_s*)malloc(sizeof(sn_grs_resource_s)); + grs_resource_list_ptr->res[0].path = (uint8_t*)malloc(2); + grs_resource_list_ptr->res[0].pathlen = 2; + + sn_grs_free_resource_list(handle, grs_resource_list_ptr); + + sn_grs_destroy(handle); + return true; +} + +bool test_sn_grs_get_first_resource() +{ + if( NULL != sn_grs_get_first_resource(NULL) ){ + return false; + } + + struct grs_s* handle = (struct grs_s*)malloc(sizeof(struct grs_s)); + memset(handle, 0, sizeof(struct grs_s)); + handle->sn_grs_alloc = myMalloc; + handle->sn_grs_free = myFree; + + sn_nsdl_resource_info_s* res = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(res, 0, sizeof(sn_nsdl_resource_info_s)); + ns_list_add_to_start(&handle->resource_root_list, res); + ++handle->resource_root_count; + + if( NULL == sn_grs_get_first_resource(handle) ){ + return false; + } + + sn_grs_destroy(handle); + return true; +} + +bool test_sn_grs_get_next_resource() +{ + if( NULL != sn_grs_get_next_resource(NULL, NULL) ){ + return false; + } + + struct grs_s* handle = (struct grs_s*)malloc(sizeof(struct grs_s)); + memset(handle, 0, sizeof(struct grs_s)); + handle->sn_grs_alloc = myMalloc; + handle->sn_grs_free = myFree; + + sn_nsdl_resource_info_s* res = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(res, 0, sizeof(sn_nsdl_resource_info_s)); + ns_list_add_to_start(&handle->resource_root_list, res); + ++handle->resource_root_count; + sn_nsdl_resource_info_s* res2 = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(res2, 0, sizeof(sn_nsdl_resource_info_s)); + ns_list_add_to_start(&handle->resource_root_list, res2); + ++handle->resource_root_count; + + if( NULL != sn_grs_get_next_resource(handle, NULL) ){ + return false; + } + + if( NULL == sn_grs_get_next_resource(handle, res2) ){ + return false; + } + + sn_grs_destroy(handle); + return true; +} + +bool test_sn_grs_delete_resource() +{ + if( SN_NSDL_FAILURE != sn_grs_delete_resource(NULL, 0, NULL) ){ + return false; + } + + struct grs_s* handle = (struct grs_s*)malloc(sizeof(struct grs_s)); + memset(handle, 0, sizeof(struct grs_s)); + handle->sn_grs_alloc = myMalloc; + handle->sn_grs_free = myFree; + + sn_nsdl_resource_info_s* res = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(res, 0, sizeof(sn_nsdl_resource_info_s)); + res->path = (uint8_t*)malloc(2); + res->pathlen = 1; + res->path[0] = 'a'; + res->path[1] = '\0'; + ns_list_add_to_start(&handle->resource_root_list, res); + ++handle->resource_root_count; + + sn_nsdl_resource_info_s* res2 = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(res2, 0, sizeof(sn_nsdl_resource_info_s)); + res2->path = (uint8_t*)malloc(4); + res2->pathlen = 3; + res2->path[0] = 'a'; + res2->path[1] = '/'; + res2->path[2] = '1'; + res2->path[3] = '\0'; + ns_list_add_to_start(&handle->resource_root_list, res2); + ++handle->resource_root_count; + + uint8_t path[2] = {'a', '\0'}; + if( SN_NSDL_SUCCESS != sn_grs_delete_resource(handle, 1, &path) ){ + return false; + } + + if (handle->resource_root_count != 0) { + return false; + } + + sn_nsdl_resource_info_s* res3 = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(res3, 0, sizeof(sn_nsdl_resource_info_s)); + res3->path = (uint8_t*)malloc(2); + res3->pathlen = 1; + res3->path[0] = 'a'; + res3->path[1] = '\0'; + ns_list_add_to_start(&handle->resource_root_list, res3); + ++handle->resource_root_count; + + /* a/1 */ + sn_nsdl_resource_info_s* res4 = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(res4, 0, sizeof(sn_nsdl_resource_info_s)); + res4->path = (uint8_t*)malloc(4); + res4->pathlen = 3; + res4->path[0] = 'a'; + res4->path[1] = '/'; + res4->path[2] = '1'; + res4->path[3] = '\0'; + ns_list_add_to_start(&handle->resource_root_list, res4); + ++handle->resource_root_count; + + /* a/1/0 */ + sn_nsdl_resource_info_s* res5 = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(res5, 0, sizeof(sn_nsdl_resource_info_s)); + res5->path = (uint8_t*)malloc(6); + res5->pathlen = 5; + res5->path[0] = 'a'; + res5->path[1] = '/'; + res5->path[2] = '1'; + res5->path[3] = '/'; + res5->path[4] = '0'; + res5->path[5] = '\0'; + ns_list_add_to_start(&handle->resource_root_list, res5); + ++handle->resource_root_count; + + /* a/10 */ + sn_nsdl_resource_info_s* res6 = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(res6, 0, sizeof(sn_nsdl_resource_info_s)); + res6->path = (uint8_t*)malloc(5); + res6->pathlen = 4; + res6->path[0] = 'a'; + res6->path[1] = '/'; + res6->path[2] = '1'; + res6->path[3] = '0'; + res6->path[4] = '\0'; + ns_list_add_to_start(&handle->resource_root_list, res6); + ++handle->resource_root_count; + + + /* a/10/0 */ + sn_nsdl_resource_info_s* res7 = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(res7, 0, sizeof(sn_nsdl_resource_info_s)); + res7->path = (uint8_t*)malloc(7); + res7->pathlen = 6; + res7->path[0] = 'a'; + res7->path[1] = '/'; + res7->path[2] = '1'; + res7->path[3] = '0'; + res7->path[4] = '/'; + res7->path[5] = '0'; + res7->path[6] = '\0'; + ns_list_add_to_start(&handle->resource_root_list, res7); + ++handle->resource_root_count; + + uint8_t path2[4] = {'a', '/', '1', '\0'}; + if( SN_NSDL_SUCCESS != sn_grs_delete_resource(handle, 3, &path2) ){ + return false; + } + + // "a/1" and "a/1/0" removed + if (handle->resource_root_count != 3) { + return false; + } + + uint8_t path3[5] = {'a', '/', '1', '0', '\0'}; + if( SN_NSDL_SUCCESS != sn_grs_delete_resource(handle, 4, &path3) ){ + return false; + } + + if (handle->resource_root_count != 1) { + return false; + } + + if( SN_NSDL_SUCCESS != sn_grs_delete_resource(handle, 1, &path) ){ + return false; + } + + if (handle->resource_root_count != 0) { + return false; + } + + sn_grs_destroy(handle); + return true; +} + +bool test_sn_grs_update_resource() +{ + if( SN_NSDL_FAILURE != sn_grs_update_resource(NULL, NULL) ){ + return false; + } + + struct grs_s* handle = (struct grs_s*)malloc(sizeof(struct grs_s)); + memset(handle, 0, sizeof(struct grs_s)); + handle->sn_grs_alloc = myMalloc; + handle->sn_grs_free = myFree; + + sn_nsdl_resource_info_s* res = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(res, 0, sizeof(sn_nsdl_resource_info_s)); + res->path = (uint8_t*)malloc(2); + res->pathlen = 1; + res->path[0] = 'a'; + res->path[1] = '\0'; + res->resource = (uint8_t*)malloc(2); + res->resourcelen = 2; + ns_list_add_to_start(&handle->resource_root_list, res); + ++handle->resource_root_count; + sn_nsdl_resource_info_s* res2 = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(res2, 0, sizeof(sn_nsdl_resource_info_s)); + res2->path = (uint8_t*)malloc(2); + res2->pathlen = 1; + res2->path[0] = 'b'; + res2->path[1] = '\0'; + ns_list_add_to_start(&handle->resource_root_list, res2); + ++handle->resource_root_count; + + sn_nsdl_resource_info_s* res3 = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(res3, 0, sizeof(sn_nsdl_resource_info_s)); + res3->path = (uint8_t*)malloc(2); + res3->pathlen = 1; + res3->path[0] = 't'; + res3->path[1] = '\0'; + + if( SN_NSDL_FAILURE != sn_grs_update_resource(handle, res3) ){ + return false; + } + + if( SN_NSDL_FAILURE != sn_grs_update_resource(handle, res) ){ + return false; + } + + retCounter = 1; + res3->path[0] = 'a'; + res3->resource = (uint8_t*)malloc(2); + res3->resourcelen = 2; + if( SN_NSDL_SUCCESS != sn_grs_update_resource(handle, res3) ){ + return false; + } + free(res3->resource); + free(res3->path); + free(res3); + + sn_grs_destroy(handle); + return true; +} + +bool test_sn_grs_create_resource() +{ + if( SN_NSDL_FAILURE != sn_grs_create_resource(NULL, NULL) ){ + return false; + } + + struct grs_s* handle = (struct grs_s*)malloc(sizeof(struct grs_s)); + memset(handle, 0, sizeof(struct grs_s)); + handle->sn_grs_alloc = myMalloc; + handle->sn_grs_free = myFree; + + sn_nsdl_resource_info_s* res = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(res, 0, sizeof(sn_nsdl_resource_info_s)); + res->pathlen = 1; + + if( SN_GRS_INVALID_PATH != sn_grs_create_resource(handle, res) ){ + return false; + } + + res->path = (uint8_t*)malloc(2); + res->path[0] = 'a'; + res->path[1] = '\0'; + res->resource = (uint8_t*)malloc(2); + res->resource[0] = 'a'; + res->resource[1] = '\0'; + res->resourcelen = 1; + res->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s)); + memset(res->resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s)); + + res->resource_parameters_ptr->resource_type_ptr = (uint8_t*)malloc(2); + memset(res->resource_parameters_ptr->resource_type_ptr, 0, 2); + + res->resource_parameters_ptr->interface_description_ptr = (uint8_t*)malloc(2); + memset(res->resource_parameters_ptr->interface_description_ptr, 0, 2); + + if( SN_GRS_LIST_ADDING_FAILURE != sn_grs_create_resource(handle, res) ){ + return false; + } + + retCounter = 1; + if( SN_GRS_LIST_ADDING_FAILURE != sn_grs_create_resource(handle, res) ){ + return false; + } + + retCounter = 2; + if( SN_GRS_LIST_ADDING_FAILURE != sn_grs_create_resource(handle, res) ){ + return false; + } + + retCounter = 3; + if( SN_GRS_LIST_ADDING_FAILURE != sn_grs_create_resource(handle, res) ){ + return false; + } + + retCounter = 4; + if( SN_GRS_LIST_ADDING_FAILURE != sn_grs_create_resource(handle, res) ){ + return false; + } + + retCounter = 5; + if( SN_GRS_LIST_ADDING_FAILURE != sn_grs_create_resource(handle, res) ){ + return false; + } + + retCounter = 6; + if( SN_NSDL_SUCCESS != sn_grs_create_resource(handle, res) ){ + return false; + } + + if( SN_GRS_RESOURCE_ALREADY_EXISTS != sn_grs_create_resource(handle, res) ){ + return false; + } + + ns_list_add_to_start(&handle->resource_root_list, res); + sn_grs_destroy(handle); + return true; +} + +bool test_sn_grs_process_coap() +{ + if( SN_NSDL_FAILURE != sn_grs_process_coap(NULL, NULL, NULL) ){ + return false; + } + + sn_coap_protocol_stub.expectedCoap = (struct coap_s*)malloc(sizeof(struct coap_s)); + memset(sn_coap_protocol_stub.expectedCoap, 0, sizeof(struct coap_s)); + + struct nsdl_s* handle = (struct nsdl_s*)malloc(sizeof(struct nsdl_s)); + memset(handle, 0, sizeof(struct nsdl_s)); + + retCounter = 1; + //sn_coap_protocol_stub.expectedCoap = NULL; + struct grs_s* grs = sn_grs_init(&myTxCallback, &myRxCallback, &myMalloc, &myFree); + + handle->grs = grs; + + sn_coap_hdr_s* hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + + sn_nsdl_addr_s* addr = (sn_nsdl_addr_s*)malloc(sizeof(sn_nsdl_addr_s)); + memset(addr, 0, sizeof(sn_nsdl_addr_s)); + + hdr->msg_code = COAP_MSG_CODE_REQUEST_GET; + //Let's test first only upper if clause -> + hdr->msg_type = COAP_MSG_TYPE_RESET; + + hdr->uri_path_ptr = (uint8_t*)malloc(16); + memcpy(hdr->uri_path_ptr, ".well-known/core", 16); + hdr->uri_path_len = 16; + + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + + if( SN_NSDL_FAILURE != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = COAP_MSG_CODE_REQUEST_GET; + hdr->msg_type = COAP_MSG_TYPE_RESET; + hdr->uri_path_ptr = (uint8_t*)malloc(16); + memcpy(hdr->uri_path_ptr, ".well-known/core", 16); + hdr->uri_path_len = 16; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + + retCounter = 1; + if( SN_NSDL_FAILURE != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = COAP_MSG_CODE_REQUEST_GET; + hdr->msg_type = COAP_MSG_TYPE_RESET; + hdr->uri_path_ptr = (uint8_t*)malloc(16); + memcpy(hdr->uri_path_ptr, ".well-known/core", 16); + hdr->uri_path_len = 16; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + + sn_nsdl_stub.allocatePayloadPtr = true; + handle->sn_nsdl_alloc = &myMalloc; + retCounter = 3; + if( SN_NSDL_SUCCESS != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + + sn_nsdl_stub.allocatePayloadPtr = false; + + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = COAP_MSG_CODE_REQUEST_GET; + hdr->msg_type = COAP_MSG_TYPE_RESET; + hdr->uri_path_ptr = (uint8_t*)malloc(2); + hdr->uri_path_len = 2; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + + if( SN_NSDL_SUCCESS != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + grs->sn_grs_rx_callback = &myRxCallback; + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = COAP_MSG_CODE_REQUEST_POST; + hdr->msg_type = COAP_MSG_TYPE_RESET; + hdr->uri_path_ptr = (uint8_t*)malloc(2); + hdr->uri_path_len = 2; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + + if( SN_NSDL_SUCCESS != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + sn_nsdl_resource_info_s* res = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(res, 0, sizeof(sn_nsdl_resource_info_s)); + res->path = (uint8_t*)malloc(2); + res->pathlen = 1; + res->path[0] = 'a'; + res->path[1] = '\0'; + res->mode = SN_GRS_DYNAMIC; + res->sn_grs_dyn_res_callback = &myResCallback; + res->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s)); + memset(res->resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s)); + ns_list_add_to_start(&handle->grs->resource_root_list, res); + ++handle->grs->resource_root_count; + + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = COAP_MSG_CODE_REQUEST_POST; + hdr->msg_type = COAP_MSG_TYPE_RESET; + hdr->uri_path_ptr = (uint8_t*)malloc(2); + hdr->uri_path_ptr[0] = 'a'; + hdr->uri_path_ptr[1] = '\0'; + hdr->uri_path_len = 1; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + + if( SN_NSDL_SUCCESS != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + res->access = SN_GRS_GET_ALLOWED; + + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = COAP_MSG_CODE_REQUEST_GET; + hdr->msg_type = COAP_MSG_TYPE_RESET; + hdr->uri_path_ptr = (uint8_t*)malloc(2); + hdr->uri_path_ptr[0] = 'a'; + hdr->uri_path_ptr[1] = '\0'; + hdr->uri_path_len = 1; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + + if( SN_NSDL_SUCCESS != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + res->mode = SN_GRS_STATIC; + + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = COAP_MSG_CODE_REQUEST_GET; + hdr->msg_type = COAP_MSG_TYPE_RESET; + hdr->uri_path_ptr = (uint8_t*)malloc(2); + hdr->uri_path_ptr[0] = 'a'; + hdr->uri_path_ptr[1] = '\0'; + hdr->uri_path_len = 1; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + + if( SN_NSDL_SUCCESS != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + res->access = 0; + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = COAP_MSG_CODE_REQUEST_GET; + hdr->msg_type = COAP_MSG_TYPE_RESET; + hdr->uri_path_ptr = (uint8_t*)malloc(2); + hdr->uri_path_ptr[0] = 'a'; + hdr->uri_path_ptr[1] = '\0'; + hdr->uri_path_len = 1; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + + if( SN_NSDL_SUCCESS != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + res->access = SN_GRS_POST_ALLOWED; + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = COAP_MSG_CODE_REQUEST_POST; + hdr->msg_type = COAP_MSG_TYPE_RESET; + hdr->uri_path_ptr = (uint8_t*)malloc(2); + hdr->uri_path_ptr[0] = 'a'; + hdr->uri_path_ptr[1] = '\0'; + hdr->uri_path_len = 1; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + hdr->payload_len = 2; + + if( SN_NSDL_SUCCESS != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + retCounter = 1; + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = COAP_MSG_CODE_REQUEST_POST; + hdr->msg_type = COAP_MSG_TYPE_RESET; + hdr->uri_path_ptr = (uint8_t*)malloc(2); + hdr->uri_path_ptr[0] = 'a'; + hdr->uri_path_ptr[1] = '\0'; + hdr->uri_path_len = 1; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + hdr->payload_len = 2; + hdr->content_type_ptr = (uint8_t*)malloc(1); + hdr->content_type_ptr[0] = 1; + hdr->content_type_len = 1; + + if( SN_NSDL_SUCCESS != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + res->access = 0; + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = COAP_MSG_CODE_REQUEST_POST; + hdr->msg_type = COAP_MSG_TYPE_RESET; + hdr->uri_path_ptr = (uint8_t*)malloc(2); + hdr->uri_path_ptr[0] = 'a'; + hdr->uri_path_ptr[1] = '\0'; + hdr->uri_path_len = 1; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + hdr->payload_len = 2; + + if( SN_NSDL_SUCCESS != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + res->access = SN_GRS_PUT_ALLOWED; + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = COAP_MSG_CODE_REQUEST_PUT; + hdr->msg_type = COAP_MSG_TYPE_RESET; + hdr->uri_path_ptr = (uint8_t*)malloc(2); + hdr->uri_path_ptr[0] = 'a'; + hdr->uri_path_ptr[1] = '\0'; + hdr->uri_path_len = 1; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + hdr->payload_len = 2; + + if( SN_NSDL_SUCCESS != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + retCounter = 1; + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = COAP_MSG_CODE_REQUEST_PUT; + hdr->msg_type = COAP_MSG_TYPE_RESET; + hdr->uri_path_ptr = (uint8_t*)malloc(2); + hdr->uri_path_ptr[0] = 'a'; + hdr->uri_path_ptr[1] = '\0'; + hdr->uri_path_len = 1; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + hdr->payload_len = 2; + hdr->content_type_ptr = (uint8_t*)malloc(1); + hdr->content_type_ptr[0] = 1; + hdr->content_type_len = 1; + + if( SN_NSDL_SUCCESS != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + res->access = 0; + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = COAP_MSG_CODE_REQUEST_PUT; + hdr->msg_type = COAP_MSG_TYPE_RESET; + hdr->uri_path_ptr = (uint8_t*)malloc(2); + hdr->uri_path_ptr[0] = 'a'; + hdr->uri_path_ptr[1] = '\0'; + hdr->uri_path_len = 1; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + hdr->payload_len = 2; + + if( SN_NSDL_SUCCESS != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + //default: + res->access = 0; + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = COAP_MSG_CODE_EMPTY; + hdr->msg_type = COAP_MSG_TYPE_RESET; + hdr->uri_path_ptr = (uint8_t*)malloc(2); + hdr->uri_path_ptr[0] = 'a'; + hdr->uri_path_ptr[1] = '\0'; + hdr->uri_path_len = 1; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + hdr->payload_len = 2; + + if( SN_NSDL_SUCCESS != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + //DELETE + res->access = 0; + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = COAP_MSG_CODE_REQUEST_DELETE; + hdr->msg_type = COAP_MSG_TYPE_RESET; + hdr->uri_path_ptr = (uint8_t*)malloc(2); + hdr->uri_path_ptr[0] = 'a'; + hdr->uri_path_ptr[1] = '\0'; + hdr->uri_path_len = 1; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + hdr->payload_len = 2; + + if( SN_NSDL_SUCCESS != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + res->access = SN_GRS_DELETE_ALLOWED; + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = COAP_MSG_CODE_REQUEST_DELETE; + hdr->msg_type = COAP_MSG_TYPE_RESET; + hdr->uri_path_ptr = (uint8_t*)malloc(2); + hdr->uri_path_ptr[0] = 'a'; + hdr->uri_path_ptr[1] = '\0'; + hdr->uri_path_len = 1; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + hdr->payload_len = 2; + + if( SN_NSDL_SUCCESS != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + //This tries to test dead code +// res = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); +// memset(res, 0, sizeof(sn_nsdl_resource_info_s)); +// res->path = (uint8_t*)malloc(2); +// res->pathlen = 1; +// res->path[0] = 'a'; +// res->path[1] = '\0'; +// res->mode = SN_GRS_STATIC; +// res->sn_grs_dyn_res_callback = &myResCallback; +// res->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s)); +// res->access = SN_GRS_DELETE_ALLOWED; +// memset(res->resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s)); +// ns_list_add_to_start(&handle->grs->resource_root_list, res); +// ++handle->grs->resource_root_count; + +// hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); +// memset(hdr, 0, sizeof(sn_coap_hdr_s)); +// hdr->msg_code = COAP_MSG_CODE_REQUEST_DELETE; +// hdr->msg_type = COAP_MSG_TYPE_RESET; +// hdr->uri_path_ptr = (uint8_t*)malloc(2); +// hdr->uri_path_ptr[0] = 'a'; +// hdr->uri_path_ptr[1] = '\0'; +// hdr->uri_path_len = 1; +// hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; +// hdr->payload_ptr = (uint8_t*)malloc(2); +// hdr->payload_len = 2; +// hdr->content_type_ptr = (uint8_t*)malloc(1); +// hdr->content_type_ptr[0] = 1; +// hdr->content_type_len = 1; + +// if( SN_NSDL_SUCCESS != sn_grs_process_coap(handle, hdr, addr) ){ +// return false; +// } + +//*********************************************** + // Test below if clause -> + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = 999; + hdr->msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE; + hdr->uri_path_ptr = (uint8_t*)malloc(2); + hdr->uri_path_ptr[0] = 'a'; + hdr->uri_path_ptr[1] = '\0'; + hdr->uri_path_len = 1; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + hdr->payload_len = 2; + hdr->content_type_ptr = (uint8_t*)malloc(1); + hdr->content_type_ptr[0] = 1; + hdr->content_type_len = 1; + + if( SN_NSDL_FAILURE != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = COAP_MSG_CODE_EMPTY; + hdr->msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE; + hdr->uri_path_ptr = (uint8_t*)malloc(2); + hdr->uri_path_ptr[0] = 'a'; + hdr->uri_path_ptr[1] = '\0'; + hdr->uri_path_len = 1; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + hdr->payload_len = 2; + hdr->content_type_ptr = (uint8_t*)malloc(1); + hdr->content_type_ptr[0] = 1; + hdr->content_type_len = 1; + hdr->token_ptr = (uint8_t*)malloc(1); + hdr->token_len = 1; + + retCounter = 1; + if( SN_NSDL_FAILURE != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + res = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(res, 0, sizeof(sn_nsdl_resource_info_s)); + res->path = (uint8_t*)malloc(2); + res->pathlen = 1; + res->path[0] = 'a'; + res->path[1] = '\0'; + res->mode = SN_GRS_STATIC; + res->sn_grs_dyn_res_callback = &myResCallback; + res->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s)); + res->access = SN_GRS_GET_ALLOWED; + memset(res->resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s)); + res->resource_parameters_ptr->coap_content_type = 1; + ns_list_add_to_start(&handle->grs->resource_root_list, res); + ++handle->grs->resource_root_count; + + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = 999; + hdr->msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE; + hdr->uri_path_ptr = (uint8_t*)malloc(2); + hdr->uri_path_ptr[0] = 'a'; + hdr->uri_path_ptr[1] = '\0'; + hdr->uri_path_len = 1; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + hdr->payload_len = 2; + hdr->content_type_ptr = (uint8_t*)malloc(1); + hdr->content_type_ptr[0] = 1; + hdr->content_type_len = 1; + hdr->token_ptr = (uint8_t*)malloc(1); + hdr->token_len = 1; + + retCounter = 1; + if( SN_NSDL_FAILURE != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = COAP_MSG_CODE_REQUEST_GET; + hdr->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + hdr->uri_path_ptr = (uint8_t*)malloc(2); + hdr->uri_path_ptr[0] = 'a'; + hdr->uri_path_ptr[1] = '\0'; + hdr->uri_path_len = 1; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + hdr->payload_len = 2; + hdr->content_type_ptr = (uint8_t*)malloc(1); + hdr->content_type_ptr[0] = 1; + hdr->content_type_len = 1; + hdr->token_ptr = (uint8_t*)malloc(1); + hdr->token_len = 1; + + retCounter = 2; + if( SN_NSDL_FAILURE != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + res->resource = (uint8_t*)malloc(2); + res->resourcelen = 2; + + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = COAP_MSG_CODE_REQUEST_GET; + hdr->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + hdr->uri_path_ptr = (uint8_t*)malloc(2); + hdr->uri_path_ptr[0] = 'a'; + hdr->uri_path_ptr[1] = '\0'; + hdr->uri_path_len = 1; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + hdr->payload_len = 2; + hdr->content_type_ptr = (uint8_t*)malloc(1); + hdr->content_type_ptr[0] = 1; + hdr->content_type_len = 1; + hdr->token_ptr = (uint8_t*)malloc(1); + hdr->token_len = 1; + + retCounter = 3; + if( SN_NSDL_FAILURE != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(hdr, 0, sizeof(sn_coap_hdr_s)); + hdr->msg_code = COAP_MSG_CODE_REQUEST_GET; + hdr->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + hdr->uri_path_ptr = (uint8_t*)malloc(2); + hdr->uri_path_ptr[0] = 'a'; + hdr->uri_path_ptr[1] = '\0'; + hdr->uri_path_len = 1; + hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; + hdr->payload_ptr = (uint8_t*)malloc(2); + hdr->payload_len = 2; + hdr->content_type_ptr = (uint8_t*)malloc(1); + hdr->content_type_ptr[0] = 1; + hdr->content_type_len = 1; + hdr->token_ptr = (uint8_t*)malloc(1); + hdr->token_len = 1; + + retCounter = 6; + if( SN_NSDL_SUCCESS != sn_grs_process_coap(handle, hdr, addr) ){ + return false; + } + + + free(sn_coap_protocol_stub.expectedCoap); + sn_coap_protocol_stub.expectedCoap = NULL; + free(addr); + sn_grs_destroy(handle->grs); + free(handle); + return true; +} + +bool test_sn_grs_send_coap_message() +{ + if( SN_NSDL_FAILURE != sn_grs_send_coap_message(NULL, NULL, NULL) ){ + return false; + } + sn_coap_protocol_stub.expectedCoap = (struct coap_s*)malloc(sizeof(struct coap_s)); + memset(sn_coap_protocol_stub.expectedCoap, 0, sizeof(struct coap_s)); + + struct nsdl_s* handle = (struct nsdl_s*)malloc(sizeof(struct nsdl_s)); + memset(handle, 0, sizeof(struct nsdl_s)); + + retCounter = 1; + struct grs_s* grs = sn_grs_init(&myTxCallback, &myRxCallback, &myMalloc, &myFree); + + handle->grs = grs; + +// sn_coap_hdr_s* hdr = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); +// memset(hdr, 0, sizeof(sn_coap_hdr_s)); + +// sn_nsdl_addr_s* addr = (sn_nsdl_addr_s*)malloc(sizeof(sn_nsdl_addr_s)); +// memset(addr, 0, sizeof(sn_nsdl_addr_s)); + + sn_coap_builder_stub.expectedUint16 = 2; + + if( SN_NSDL_FAILURE != sn_grs_send_coap_message(handle, NULL, NULL) ){ + return false; + } + + retCounter = 1; + sn_coap_protocol_stub.expectedInt16 = -1; + if( SN_NSDL_FAILURE != sn_grs_send_coap_message(handle, NULL, NULL) ){ + return false; + } + + retCounter = 1; + sn_coap_protocol_stub.expectedInt16 = 2; + if( SN_NSDL_FAILURE != sn_grs_send_coap_message(handle, NULL, NULL) ){ + return false; + } + + retValUint8 = 1; + retCounter = 1; + sn_coap_protocol_stub.expectedInt16 = 2; + if( SN_NSDL_SUCCESS != sn_grs_send_coap_message(handle, NULL, NULL) ){ + return false; + } + free(sn_coap_protocol_stub.expectedCoap); + sn_coap_protocol_stub.expectedCoap = NULL; + sn_grs_destroy(handle->grs); + free(handle); + return true; +} + + +bool test_sn_grs_search_resource() +{ + if( NULL != sn_grs_search_resource(NULL, 0, NULL, 0) ){ + return false; + } + struct grs_s* handle = (struct grs_s*)malloc(sizeof(struct grs_s)); + memset(handle, 0, sizeof(struct grs_s)); + handle->sn_grs_alloc = myMalloc; + handle->sn_grs_free = myFree; + + uint8_t* path = (uint8_t*)malloc(6); + path[0] = '/'; + path[1] = 'a'; + path[2] = 'b'; + path[3] = 'c'; + path[4] = '/'; + if( NULL != sn_grs_search_resource(handle, 5, path, SN_GRS_SEARCH_METHOD) ){ + return false; + } + + handle->resource_root_count = 0; + sn_nsdl_resource_info_s* res = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(res, 0, sizeof(sn_nsdl_resource_info_s)); + res->path = (uint8_t*)malloc(4); + res->path[0] = 'a'; + res->path[1] = 'b'; + res->path[2] = 'c'; + res->pathlen = 3; + ns_list_add_to_start(&handle->resource_root_list, res); + ++handle->resource_root_count; + + if( NULL == sn_grs_search_resource(handle, 5, path, SN_GRS_SEARCH_METHOD) ){ + return false; + } + + res->path[3] = '/'; + res->pathlen = 4; + + if( NULL == sn_grs_search_resource(handle, 5, path, SN_GRS_DELETE_METHOD) ){ + return false; + } + + free(path); + sn_grs_destroy(handle); + return true; +} + +bool test_sn_grs_mark_resources_as_registered() +{ + sn_grs_mark_resources_as_registered(NULL); + + struct nsdl_s* handle = (struct nsdl_s*)malloc(sizeof(struct nsdl_s)); + memset(handle, 0, sizeof(struct nsdl_s)); + + retCounter = 1; + struct grs_s* grs = sn_grs_init(&myTxCallback, &myRxCallback, &myMalloc, &myFree); + handle->grs = grs; + + sn_nsdl_resource_info_s* res = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(res, 0, sizeof(sn_nsdl_resource_info_s)); + res->path = (uint8_t*)malloc(2); + res->pathlen = 1; + res->path[0] = 'a'; + res->path[1] = '\0'; + res->mode = SN_GRS_DYNAMIC; + res->sn_grs_dyn_res_callback = &myResCallback; + res->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s)); + memset(res->resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s)); + res->resource_parameters_ptr->registered = SN_NDSL_RESOURCE_REGISTERING; + ns_list_add_to_start(&handle->grs->resource_root_list, res); + ++handle->grs->resource_root_count; + + sn_grs_mark_resources_as_registered(handle); + if( SN_NDSL_RESOURCE_REGISTERED != res->resource_parameters_ptr->registered ){ + return false; + } + + sn_grs_destroy(handle->grs); + free(handle); + return true; +} + diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_grs/test_sn_grs.h b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_grs/test_sn_grs.h new file mode 100644 index 0000000000..fc0dbeb82a --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_grs/test_sn_grs.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ +#ifndef TEST_SN_GRS_H +#define TEST_SN_GRS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +bool test_sn_grs_get_first_resource(); +bool test_sn_grs_get_next_resource(); +bool test_sn_grs_process_coap(); +bool test_sn_grs_search_resource(); +bool test_sn_grs_destroy(); +bool test_sn_grs_init(); +bool test_sn_grs_list_resource(); +bool test_sn_grs_free_resource_list(); +bool test_sn_grs_update_resource(); +bool test_sn_grs_send_coap_message(); +bool test_sn_grs_create_resource(); +bool test_sn_grs_delete_resource(); +bool test_sn_grs_mark_resources_as_registered(); + +#ifdef __cplusplus +} +#endif + +#endif // TEST_SN_GRS_H + diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_nsdl/main.cpp b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_nsdl/main.cpp new file mode 100644 index 0000000000..f0ed8e4254 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_nsdl/main.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ + +#include "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP(sn_nsdl); + diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_nsdl/sn_nsdltest.cpp b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_nsdl/sn_nsdltest.cpp new file mode 100644 index 0000000000..88dfa351c8 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_nsdl/sn_nsdltest.cpp @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ +#include "CppUTest/TestHarness.h" +#include "test_sn_nsdl.h" + +TEST_GROUP(sn_nsdl) +{ + void setup() + { + } + + void teardown() + { + } +}; + +TEST(sn_nsdl, test_sn_nsdl_destroy) +{ + CHECK(test_sn_nsdl_destroy()); +} + +TEST(sn_nsdl, test_sn_nsdl_init) +{ + CHECK(test_sn_nsdl_init()); +} + +TEST(sn_nsdl, test_sn_nsdl_register_endpoint) +{ + CHECK(test_sn_nsdl_register_endpoint()); +} + +TEST(sn_nsdl, test_sn_nsdl_unregister_endpoint) +{ + CHECK(test_sn_nsdl_unregister_endpoint()); +} + +TEST(sn_nsdl, test_sn_nsdl_update_registration) +{ + CHECK(test_sn_nsdl_update_registration()); +} + +TEST(sn_nsdl, test_sn_nsdl_set_endpoint_location) +{ + CHECK(test_sn_nsdl_set_endpoint_location()); +} + +TEST(sn_nsdl, test_sn_nsdl_nsp_lost) +{ + CHECK(test_sn_nsdl_nsp_lost()); +} + +TEST(sn_nsdl, test_sn_nsdl_is_ep_registered) +{ + CHECK(test_sn_nsdl_is_ep_registered()); +} + +TEST(sn_nsdl, test_sn_nsdl_send_observation_notification) +{ + CHECK(test_sn_nsdl_send_observation_notification()); +} + +TEST(sn_nsdl, test_sn_nsdl_send_observation_notification_with_uri_path) +{ + CHECK(test_sn_nsdl_send_observation_notification_with_uri_path()); +} + +TEST(sn_nsdl, test_sn_nsdl_oma_bootstrap) +{ + CHECK(test_sn_nsdl_oma_bootstrap()); +} + +TEST(sn_nsdl, test_sn_nsdl_get_certificates) +{ + CHECK(test_sn_nsdl_get_certificates()); +} + +TEST(sn_nsdl, test_sn_nsdl_update_certificates) +{ + CHECK(test_sn_nsdl_update_certificates()); +} + +TEST(sn_nsdl, test_sn_nsdl_create_oma_device_object) +{ + CHECK(test_sn_nsdl_create_oma_device_object()); +} + +TEST(sn_nsdl, test_sn_nsdl_get_version) +{ + CHECK(test_sn_nsdl_get_version()); +} + +TEST(sn_nsdl, test_sn_nsdl_process_coap) +{ + CHECK(test_sn_nsdl_process_coap()); +} + + +TEST(sn_nsdl, test_sn_nsdl_exec) +{ + CHECK(test_sn_nsdl_exec()); +} + +TEST(sn_nsdl, test_sn_nsdl_get_resource) +{ + CHECK(test_sn_nsdl_get_resource()); +} + +TEST(sn_nsdl, test_set_NSP_address) +{ + CHECK(test_set_NSP_address()); +} + +TEST(sn_nsdl, test_sn_nsdl_list_resource) +{ + CHECK(test_sn_nsdl_list_resource()); +} + +TEST(sn_nsdl, test_sn_nsdl_free_resource_list) +{ + CHECK(test_sn_nsdl_free_resource_list()); +} + +TEST(sn_nsdl, test_sn_nsdl_update_resource) +{ + CHECK(test_sn_nsdl_update_resource()); +} + +TEST(sn_nsdl, test_sn_nsdl_send_coap_message) +{ + CHECK(test_sn_nsdl_send_coap_message()); +} + +TEST(sn_nsdl, test_sn_nsdl_create_resource) +{ + CHECK(test_sn_nsdl_create_resource()); +} + +TEST(sn_nsdl, test_sn_nsdl_delete_resource) +{ + CHECK(test_sn_nsdl_delete_resource()); +} + +TEST(sn_nsdl, test_sn_nsdl_get_first_resource) +{ + CHECK(test_sn_nsdl_get_first_resource()); +} + +TEST(sn_nsdl, test_sn_nsdl_get_next_resource) +{ + CHECK(test_sn_nsdl_get_next_resource()); +} + +TEST(sn_nsdl, test_sn_nsdl_build_response) +{ + CHECK(test_sn_nsdl_build_response()); +} + +TEST(sn_nsdl, test_sn_nsdl_release_allocated_coap_msg_mem) +{ + CHECK(test_sn_nsdl_release_allocated_coap_msg_mem()); +} + +TEST(sn_nsdl, test_sn_nsdl_set_retransmission_parameters) +{ + CHECK(test_sn_nsdl_set_retransmission_parameters()); +} + +TEST(sn_nsdl, test_sn_nsdl_set_retransmission_buffer) +{ + CHECK(test_sn_nsdl_set_retransmission_buffer()); +} + +TEST(sn_nsdl, test_sn_nsdl_set_block_size) +{ + CHECK(test_sn_nsdl_set_block_size()); +} + +TEST(sn_nsdl, test_sn_nsdl_set_duplicate_buffer_size) +{ + CHECK(test_sn_nsdl_set_duplicate_buffer_size()); +} + + + diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_nsdl/test_sn_nsdl.c b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_nsdl/test_sn_nsdl.c new file mode 100644 index 0000000000..75142b7282 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_nsdl/test_sn_nsdl.c @@ -0,0 +1,2968 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ +#include "test_sn_nsdl.h" +#include +#include + +#include "sn_coap_header.h" +#include "sn_nsdl.h" +#include "sn_nsdl_lib.h" +#include "sn_grs.h" + +#include "sn_grs_stub.h" +#include "sn_coap_builder_stub.h" +#include "sn_coap_protocol_stub.h" + +int retCounter = 0; +uint8_t rxRetVal = 0; + +void* myMalloc(uint16_t size) +{ + if( retCounter > 0 ){ + retCounter--; + return malloc(size); + }else { + return NULL; + } +} + +void myFree(void* ptr){ + free(ptr); +} + +void myBootstrapCallback(sn_nsdl_oma_server_info_t *server_info_ptr){ + +} + +void myBootstrapCallbackHandle(sn_nsdl_oma_server_info_t *server_info_ptr, struct nsdl_s *a){ + +} + +uint8_t nsdl_tx_callback(struct nsdl_s *a, sn_nsdl_capab_e b, uint8_t *c, uint16_t d, sn_nsdl_addr_s *e) +{ + +} + +uint8_t nsdl_rx_callback(struct nsdl_s *a, sn_coap_hdr_s *b, sn_nsdl_addr_s *c) +{ + return rxRetVal; +} + +bool test_sn_nsdl_destroy() +{ + if( SN_NSDL_FAILURE != sn_nsdl_destroy(NULL) ){ + return false; + } + + struct nsdl_s* handle = (struct nsdl_s*)malloc(sizeof(struct nsdl_s)); + handle->sn_nsdl_alloc = myMalloc; + handle->sn_nsdl_free = myFree; + handle->oma_bs_address_ptr = (uint8_t*)malloc(5); + + handle->ep_information_ptr = (sn_nsdl_ep_parameters_s *)malloc(sizeof(sn_nsdl_ep_parameters_s)); + memset(handle->ep_information_ptr,0,sizeof(sn_nsdl_ep_parameters_s)); + handle->ep_information_ptr->endpoint_name_ptr = (uint8_t*)malloc(5); + handle->ep_information_ptr->domain_name_ptr = (uint8_t*)malloc(5); + handle->ep_information_ptr->type_ptr = (uint8_t*)malloc(5); + handle->ep_information_ptr->lifetime_ptr = (uint8_t*)malloc(5); + handle->ep_information_ptr->location_ptr = (uint8_t*)malloc(5); + + handle->nsp_address_ptr = (sn_nsdl_oma_server_info_t *)malloc(sizeof(sn_nsdl_oma_server_info_t)); + handle->nsp_address_ptr->omalw_address_ptr = (sn_nsdl_addr_s*)malloc(sizeof(sn_nsdl_addr_s)); + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = (uint8_t*)malloc(5); + + handle->grs = (struct grs_s *)malloc(sizeof(struct grs_s)); + + int8_t ret = sn_nsdl_destroy(handle); + return ret == SN_NSDL_SUCCESS; +} + +bool test_sn_nsdl_init() +{ + if( NULL != sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, NULL) ){ + return false; + } + + retCounter = 0; + if( NULL != sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree) ){ + return false; + } + + retCounter = 1; + if( NULL != sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree) ){ + return false; + } + + sn_grs_stub.retNull = true; + retCounter = 2; + if( NULL != sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree) ){ + return false; + } + + sn_grs_stub.retNull = false; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); //gets deleted during call + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + retCounter = 4; + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + sn_grs_stub.expectedGrs = NULL; + if( NULL == handle ){ + return false; + } + sn_nsdl_destroy(handle); + + return true; +} + +bool test_sn_nsdl_register_endpoint() +{ + if( 0 != sn_nsdl_register_endpoint(NULL, NULL) ){ + return false; + } + sn_grs_stub.retNull = false; + retCounter = 5; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + sn_grs_stub.expectedGrs->coap = (struct coap_s *)malloc(sizeof(struct coap_s)); + sn_grs_stub.expectedGrs->coap->sn_coap_protocol_free = myFree; + sn_grs_stub.expectedGrs->coap->sn_coap_protocol_malloc = myMalloc; + sn_grs_stub.expectedGrs->coap->sn_coap_rx_callback = nsdl_rx_callback; + sn_grs_stub.expectedGrs->coap->sn_coap_tx_callback = nsdl_tx_callback; + + sn_nsdl_ep_parameters_s *eptr = (sn_nsdl_ep_parameters_s*)malloc(sizeof(sn_nsdl_ep_parameters_s)); + memset(eptr, 0, sizeof(sn_nsdl_ep_parameters_s)); + + if( 0 != sn_nsdl_register_endpoint(handle, eptr) ){ + return false; + } + + retCounter = 0; + if( 0 != sn_nsdl_register_endpoint(handle, eptr) ){ + return false; + } + + retCounter = 1; + if( 0 != sn_nsdl_register_endpoint(handle, eptr) ){ + return false; + } + + bool ret = true; + + retCounter = 2; + eptr->endpoint_name_ptr = (uint8_t*)malloc(2); + eptr->endpoint_name_ptr[0] = 'a'; + eptr->endpoint_name_ptr[1] = '\0'; + eptr->endpoint_name_len = 1; + eptr->type_ptr = (uint8_t*)malloc(2); + eptr->type_ptr[0] = 'a'; + eptr->type_ptr[1] = '\0'; + eptr->type_len = 1; + eptr->lifetime_ptr = (uint8_t*)malloc(2); + eptr->lifetime_ptr[0] = 'a'; + eptr->lifetime_ptr[1] = '\0'; + eptr->lifetime_len = 1; + eptr->domain_name_ptr = (uint8_t*)malloc(2); + eptr->domain_name_ptr[0] = 'a'; + eptr->domain_name_ptr[1] = '\0'; + eptr->domain_name_len = 1; + eptr->binding_and_mode = 0x07; + + if( 0 != sn_nsdl_register_endpoint(handle, eptr) ){ + ret = false; + goto end; + } + + //Test validateParameters here --> + ret = true; + + retCounter = 2; + eptr->endpoint_name_ptr[0] = '&'; + eptr->endpoint_name_ptr[1] = '\0'; + eptr->endpoint_name_len = 1; + eptr->type_ptr[0] = 'a'; + eptr->type_ptr[1] = '\0'; + eptr->type_len = 1; + eptr->lifetime_ptr[0] = 'a'; + eptr->lifetime_ptr[1] = '\0'; + eptr->lifetime_len = 1; + eptr->domain_name_ptr[0] = 'a'; + eptr->domain_name_ptr[1] = '\0'; + eptr->domain_name_len = 1; + eptr->binding_and_mode = 0x07; + + if( 0 != sn_nsdl_register_endpoint(handle, eptr) ){ + ret = false; + goto end; + } + + ret = true; + + retCounter = 2; + eptr->endpoint_name_ptr[0] = 'a'; + eptr->endpoint_name_ptr[1] = '\0'; + eptr->endpoint_name_len = 1; + eptr->type_ptr[0] = '&'; + eptr->type_ptr[1] = '\0'; + eptr->type_len = 1; + eptr->lifetime_ptr[0] = 'a'; + eptr->lifetime_ptr[1] = '\0'; + eptr->lifetime_len = 1; + eptr->domain_name_ptr[0] = 'a'; + eptr->domain_name_ptr[1] = '\0'; + eptr->domain_name_len = 1; + eptr->binding_and_mode = 0x07; + + if( 0 != sn_nsdl_register_endpoint(handle, eptr) ){ + ret = false; + goto end; + } + + ret = true; + + retCounter = 2; + eptr->endpoint_name_ptr[0] = 'a'; + eptr->endpoint_name_ptr[1] = '\0'; + eptr->endpoint_name_len = 1; + eptr->type_ptr[0] = 'a'; + eptr->type_ptr[1] = '\0'; + eptr->type_len = 1; + eptr->lifetime_ptr[0] = '&'; + eptr->lifetime_ptr[1] = '\0'; + eptr->lifetime_len = 1; + eptr->domain_name_ptr[0] = 'a'; + eptr->domain_name_ptr[1] = '\0'; + eptr->domain_name_len = 1; + eptr->binding_and_mode = 0x07; + + if( 0 != sn_nsdl_register_endpoint(handle, eptr) ){ + ret = false; + goto end; + } + + ret = true; + + retCounter = 2; + eptr->endpoint_name_ptr[0] = 'a'; + eptr->endpoint_name_ptr[1] = '\0'; + eptr->endpoint_name_len = 1; + eptr->type_ptr[0] = 'a'; + eptr->type_ptr[1] = '\0'; + eptr->type_len = 1; + eptr->lifetime_ptr[0] = 'a'; + eptr->lifetime_ptr[1] = '\0'; + eptr->lifetime_len = 1; + eptr->domain_name_ptr[0] = '&'; + eptr->domain_name_ptr[1] = '\0'; + eptr->domain_name_len = 1; + eptr->binding_and_mode = 0x07; + + if( 0 != sn_nsdl_register_endpoint(handle, eptr) ){ + ret = false; + goto end; + } + eptr->domain_name_ptr[0] = 'a'; + //<-- Test validateParameters here + + eptr->binding_and_mode = 0x07; + retCounter = 3; + sn_grs_stub.infoRetCounter = 2; + sn_grs_stub.expectedInfo = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset( sn_grs_stub.expectedInfo, 0, sizeof(sn_nsdl_resource_info_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_len = 1; + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr[0] = 'a'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr[1] = '\0'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr[0] = 'a'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr[1] = '\0'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_len = 1; + sn_grs_stub.expectedInfo->resource_parameters_ptr->observable = 1; + + sn_grs_stub.expectedInfo->path = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->path[0] = 'a'; + sn_grs_stub.expectedInfo->path[1] = '\0'; + sn_grs_stub.expectedInfo->pathlen = 1; + sn_grs_stub.expectedInfo->resource = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource[0] = 'a'; + sn_grs_stub.expectedInfo->resource[1] = '\0'; + sn_grs_stub.expectedInfo->resourcelen = 1; + sn_grs_stub.expectedInfo->publish_uri = 1; + //sn_nsdl_build_registration_body == SN_NSDL_FAILURE + int8_t val = sn_nsdl_register_endpoint(handle, eptr); + + free(sn_grs_stub.expectedInfo->resource); + free(sn_grs_stub.expectedInfo->path); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr); + free(sn_grs_stub.expectedInfo); + sn_grs_stub.expectedInfo = NULL; + if( 0 != val ){ + ret = false; + goto end; + } + + //creates payload + sn_grs_stub.info2ndRetCounter = 0; + sn_grs_stub.infoRetCounter = 1; + sn_grs_stub.expectedInfo = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset( sn_grs_stub.expectedInfo, 0, sizeof(sn_nsdl_resource_info_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr->observable = 1; + sn_grs_stub.expectedInfo->publish_uri = 1; + eptr->binding_and_mode = 0x06; + retCounter = 4; + //set_endpoint_info == -1 + val = sn_nsdl_register_endpoint(handle, eptr); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr); + free(sn_grs_stub.expectedInfo); + + if( 0 != val ){ + ret = false; + goto end; + } + + + handle->ep_information_ptr->domain_name_ptr = (uint8_t*)malloc(3); + handle->ep_information_ptr->endpoint_name_ptr = (uint8_t*)malloc(3); + eptr->binding_and_mode = 0x06; + retCounter = 4; + //set_endpoint_info == -1 + val = sn_nsdl_register_endpoint(handle, eptr); + if( 0 != val ){ + ret = false; + goto end; + } + + //creates payload + sn_grs_stub.info2ndRetCounter = 2; + sn_grs_stub.infoRetCounter = 2; + sn_grs_stub.expectedInfo = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset( sn_grs_stub.expectedInfo, 0, sizeof(sn_nsdl_resource_info_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_len = 1; + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr[0] = 'a'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr[1] = '\0'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr[0] = 'a'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr[1] = '\0'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_len = 1; + sn_grs_stub.expectedInfo->resource_parameters_ptr->observable = 1; + + sn_grs_stub.expectedInfo->path = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->path[0] = 'a'; + sn_grs_stub.expectedInfo->path[1] = '\0'; + sn_grs_stub.expectedInfo->pathlen = 1; + sn_grs_stub.expectedInfo->resource = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource[0] = 'a'; + sn_grs_stub.expectedInfo->resource[1] = '\0'; + sn_grs_stub.expectedInfo->resourcelen = 1; + sn_grs_stub.expectedInfo->publish_uri = 1; + eptr->binding_and_mode = 0x06; + retCounter = 7; + + sn_coap_builder_stub.expectedUint16 = 1; + sn_coap_protocol_stub.expectedInt16 = 1; + //passes + val = sn_nsdl_register_endpoint(handle, eptr); + free(sn_grs_stub.expectedInfo->resource); + free(sn_grs_stub.expectedInfo->path); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr); + free(sn_grs_stub.expectedInfo); + + if( 0 != val ){ + ret = false; + goto end; + } + + //test resource_type_len overflow + sn_grs_stub.info2ndRetCounter = 2; + sn_grs_stub.infoRetCounter = 2; + sn_grs_stub.expectedInfo = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset( sn_grs_stub.expectedInfo, 0, sizeof(sn_nsdl_resource_info_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_len = UINT16_MAX; + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr = (uint8_t*)malloc(UINT16_MAX); + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr[0] = 'a'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr[1] = '\0'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr[0] = 'a'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr[1] = '\0'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_len = 1; + sn_grs_stub.expectedInfo->resource_parameters_ptr->observable = 1; + + sn_grs_stub.expectedInfo->path = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->path[0] = 'a'; + sn_grs_stub.expectedInfo->path[1] = '\0'; + sn_grs_stub.expectedInfo->pathlen = 1; + sn_grs_stub.expectedInfo->resource = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource[0] = 'a'; + sn_grs_stub.expectedInfo->resource[1] = '\0'; + sn_grs_stub.expectedInfo->resourcelen = 1; + sn_grs_stub.expectedInfo->publish_uri = 1; + eptr->binding_and_mode = 0x06; + retCounter = 7; + + sn_coap_builder_stub.expectedUint16 = 1; + sn_coap_protocol_stub.expectedInt16 = 1; + //passes + val = sn_nsdl_register_endpoint(handle, eptr); + free(sn_grs_stub.expectedInfo->resource); + free(sn_grs_stub.expectedInfo->path); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr); + free(sn_grs_stub.expectedInfo); + + if( 0 != val ){ + ret = false; + goto end; + } + + //test interface len overflow + sn_grs_stub.info2ndRetCounter = 2; + sn_grs_stub.infoRetCounter = 2; + sn_grs_stub.expectedInfo = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset( sn_grs_stub.expectedInfo, 0, sizeof(sn_nsdl_resource_info_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_len = 1; + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr[0] = 'a'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr[1] = '\0'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr[0] = 'a'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr[1] = '\0'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_len = 1; + sn_grs_stub.expectedInfo->resource_parameters_ptr->observable = 1; + + sn_grs_stub.expectedInfo->path = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->path[0] = 'a'; + sn_grs_stub.expectedInfo->path[1] = '\0'; + sn_grs_stub.expectedInfo->pathlen = UINT16_MAX; + sn_grs_stub.expectedInfo->resource = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource[0] = 'a'; + sn_grs_stub.expectedInfo->resource[1] = '\0'; + sn_grs_stub.expectedInfo->resourcelen = 1; + sn_grs_stub.expectedInfo->publish_uri = 1; + eptr->binding_and_mode = 0x06; + retCounter = 7; + + sn_coap_builder_stub.expectedUint16 = 1; + sn_coap_protocol_stub.expectedInt16 = 1; + //passes + val = sn_nsdl_register_endpoint(handle, eptr); + free(sn_grs_stub.expectedInfo->resource); + free(sn_grs_stub.expectedInfo->path); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr); + free(sn_grs_stub.expectedInfo); + + if( 0 != val ){ + ret = false; + goto end; + } + + //test coap content overflow + sn_grs_stub.info2ndRetCounter = 2; + sn_grs_stub.infoRetCounter = 2; + sn_grs_stub.expectedInfo = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset( sn_grs_stub.expectedInfo, 0, sizeof(sn_nsdl_resource_info_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_len = 1; + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr[0] = 'a'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr[1] = '\0'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr[0] = 'a'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr[1] = '\0'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_len = UINT16_MAX - 20; + sn_grs_stub.expectedInfo->resource_parameters_ptr->observable = 1; + sn_grs_stub.expectedInfo->resource_parameters_ptr->coap_content_type = UINT8_MAX; + + sn_grs_stub.expectedInfo->path = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->path[0] = 'a'; + sn_grs_stub.expectedInfo->path[1] = '\0'; + sn_grs_stub.expectedInfo->pathlen = 1; + sn_grs_stub.expectedInfo->resource = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource[0] = 'a'; + sn_grs_stub.expectedInfo->resource[1] = '\0'; + sn_grs_stub.expectedInfo->resourcelen = 1; + sn_grs_stub.expectedInfo->publish_uri = 1; + eptr->binding_and_mode = 0x06; + retCounter = 7; + + sn_coap_builder_stub.expectedUint16 = 1; + sn_coap_protocol_stub.expectedInt16 = 1; + //passes + val = sn_nsdl_register_endpoint(handle, eptr); + free(sn_grs_stub.expectedInfo->resource); + free(sn_grs_stub.expectedInfo->path); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr); + free(sn_grs_stub.expectedInfo); + + if( 0 != val ){ + ret = false; + goto end; + } + + //test observe len overflow + sn_grs_stub.info2ndRetCounter = 2; + sn_grs_stub.infoRetCounter = 2; + sn_grs_stub.expectedInfo = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset( sn_grs_stub.expectedInfo, 0, sizeof(sn_nsdl_resource_info_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_len = 1; + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr[0] = 'a'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr[1] = '\0'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr[0] = 'a'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr[1] = '\0'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_len = UINT16_MAX - 25; + sn_grs_stub.expectedInfo->resource_parameters_ptr->observable = 1; + sn_grs_stub.expectedInfo->resource_parameters_ptr->coap_content_type = 1; + + sn_grs_stub.expectedInfo->path = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->path[0] = 'a'; + sn_grs_stub.expectedInfo->path[1] = '\0'; + sn_grs_stub.expectedInfo->pathlen = 1; + sn_grs_stub.expectedInfo->resource = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource[0] = 'a'; + sn_grs_stub.expectedInfo->resource[1] = '\0'; + sn_grs_stub.expectedInfo->resourcelen = 1; + sn_grs_stub.expectedInfo->publish_uri = 1; + eptr->binding_and_mode = 0x06; + retCounter = 7; + + sn_coap_builder_stub.expectedUint16 = 1; + sn_coap_protocol_stub.expectedInt16 = 1; + //passes + val = sn_nsdl_register_endpoint(handle, eptr); + free(sn_grs_stub.expectedInfo->resource); + free(sn_grs_stub.expectedInfo->path); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr); + free(sn_grs_stub.expectedInfo); + + if( 0 != val ){ + ret = false; + goto end; + } + + //test observe len overflow + sn_grs_stub.info2ndRetCounter = 2; + sn_grs_stub.infoRetCounter = 2; + sn_grs_stub.expectedInfo = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset( sn_grs_stub.expectedInfo, 0, sizeof(sn_nsdl_resource_info_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_len = 1; + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr[0] = 'a'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr[1] = '\0'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr[0] = 'a'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr[1] = '\0'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_len = UINT16_MAX - 28; + sn_grs_stub.expectedInfo->resource_parameters_ptr->observable = 1; + sn_grs_stub.expectedInfo->resource_parameters_ptr->coap_content_type = 1; + + sn_grs_stub.expectedInfo->path = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->path[0] = 'a'; + sn_grs_stub.expectedInfo->path[1] = '\0'; + sn_grs_stub.expectedInfo->pathlen = 1; + sn_grs_stub.expectedInfo->resource = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource[0] = 'a'; + sn_grs_stub.expectedInfo->resource[1] = '\0'; + sn_grs_stub.expectedInfo->resourcelen = 1; + sn_grs_stub.expectedInfo->publish_uri = 1; + eptr->binding_and_mode = 0x06; + retCounter = 7; + + sn_coap_builder_stub.expectedUint16 = 1; + sn_coap_protocol_stub.expectedInt16 = 1; + //passes + val = sn_nsdl_register_endpoint(handle, eptr); + free(sn_grs_stub.expectedInfo->resource); + free(sn_grs_stub.expectedInfo->path); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr); + free(sn_grs_stub.expectedInfo); + + if( 0 != val ){ + ret = false; + goto end; + } + + sn_grs_stub.info2ndRetCounter = 2; + sn_grs_stub.infoRetCounter = 2; + sn_grs_stub.expectedInfo = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset( sn_grs_stub.expectedInfo, 0, sizeof(sn_nsdl_resource_info_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_len = 1; + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr[0] = 'a'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr[1] = '\0'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr[0] = 'a'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr[1] = '\0'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_len = 1; + sn_grs_stub.expectedInfo->resource_parameters_ptr->observable = 1; + sn_grs_stub.expectedInfo->path = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->path[0] = 'a'; + sn_grs_stub.expectedInfo->path[1] = '\0'; + sn_grs_stub.expectedInfo->pathlen = 1; + sn_grs_stub.expectedInfo->resource = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource[0] = 'a'; + sn_grs_stub.expectedInfo->resource[1] = '\0'; + sn_grs_stub.expectedInfo->resourcelen = 1; + sn_grs_stub.expectedInfo->publish_uri = 1; + eptr->binding_and_mode = 0x06; + retCounter = 4; + sn_coap_builder_stub.expectedUint16 = 1; + sn_coap_protocol_stub.expectedInt16 = 1; + //set_endpoint_info == -1 + val = sn_nsdl_register_endpoint(handle, eptr); + free(sn_grs_stub.expectedInfo->resource); + free(sn_grs_stub.expectedInfo->path); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr); + free(sn_grs_stub.expectedInfo); + + if( 0 != val ){ + ret = false; + goto end; + } + +end: + free(sn_grs_stub.expectedGrs->coap); + free(eptr->domain_name_ptr); + free(eptr->lifetime_ptr); + free(eptr->type_ptr); + free(eptr->endpoint_name_ptr); + + free(eptr); + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_unregister_endpoint() +{ + if( 0 != sn_nsdl_unregister_endpoint(NULL) ){ + return false; + } + + sn_grs_stub.retNull = false; + retCounter = 5; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + sn_grs_stub.expectedGrs->coap = (struct coap_s *)malloc(sizeof(struct coap_s)); + sn_grs_stub.expectedGrs->coap->sn_coap_protocol_free = myFree; + sn_grs_stub.expectedGrs->coap->sn_coap_protocol_malloc = myMalloc; + sn_grs_stub.expectedGrs->coap->sn_coap_rx_callback = nsdl_rx_callback; + sn_grs_stub.expectedGrs->coap->sn_coap_tx_callback = nsdl_tx_callback; + + if( 0 != sn_nsdl_unregister_endpoint(handle) ){ + return false; + } + + handle->sn_nsdl_endpoint_registered = 1; + if( 0 != sn_nsdl_unregister_endpoint(handle) ){ + return false; + } + + retCounter = 0; + handle->sn_nsdl_endpoint_registered = 1; + if( 0 != sn_nsdl_unregister_endpoint(handle) ){ + return false; + } + + retCounter = 1; + handle->sn_nsdl_endpoint_registered = 1; + if( 0 != sn_nsdl_unregister_endpoint(handle) ){ + return false; + } + + retCounter = 2; + handle->sn_nsdl_endpoint_registered = 1; + sn_coap_builder_stub.expectedUint16 = 0; + if( 0 != sn_nsdl_unregister_endpoint(handle) ){ + return false; + } + + //Following tests will test sn_nsdl_internal_coap_send() + stuff + retCounter = 2; + handle->sn_nsdl_endpoint_registered = 1; + sn_coap_builder_stub.expectedUint16 = 1; + if( 0 != sn_nsdl_unregister_endpoint(handle) ){ + return false; + } + + retCounter = 3; + handle->sn_nsdl_endpoint_registered = 1; + sn_coap_builder_stub.expectedUint16 = 1; + sn_coap_protocol_stub.expectedInt16 = -1; + if( 0 != sn_nsdl_unregister_endpoint(handle) ){ + return false; + } + + retCounter = 3; + handle->sn_nsdl_endpoint_registered = 1; + sn_coap_builder_stub.expectedUint16 = 1; + sn_coap_protocol_stub.expectedInt16 = 1; + if( 0 != sn_nsdl_unregister_endpoint(handle) ){ + return false; + } + + u_int8_t loc[] = {"location"}; + + handle->ep_information_ptr->location_ptr = (uint8_t*)malloc(sizeof(loc)); + handle->ep_information_ptr->location_len = (uint8_t)sizeof(loc); + + retCounter = 1; + handle->sn_nsdl_endpoint_registered = 1; + sn_coap_builder_stub.expectedUint16 = 1; + if( 0 != sn_nsdl_unregister_endpoint(handle) ){ + return false; + } + + retCounter = 2; + handle->sn_nsdl_endpoint_registered = 1; + sn_coap_builder_stub.expectedUint16 = 1; + sn_coap_protocol_stub.expectedInt16 = -1; + if( 0 != sn_nsdl_unregister_endpoint(handle) ){ + return false; + } + free(sn_grs_stub.expectedGrs->coap); + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_update_registration() +{ + if( 0 != sn_nsdl_update_registration(NULL, NULL, 0) ){ + return false; + } + + sn_grs_stub.retNull = false; + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + sn_grs_stub.expectedGrs->coap = (struct coap_s *)malloc(sizeof(struct coap_s)); + sn_grs_stub.expectedGrs->coap->sn_coap_protocol_free = myFree; + sn_grs_stub.expectedGrs->coap->sn_coap_protocol_malloc = myMalloc; + sn_grs_stub.expectedGrs->coap->sn_coap_rx_callback = nsdl_rx_callback; + sn_grs_stub.expectedGrs->coap->sn_coap_tx_callback = nsdl_tx_callback; + + if( 0 != sn_nsdl_update_registration(handle, NULL, 0) ){ + return false; + } + + handle->sn_nsdl_endpoint_registered = 1; + if( 0 != sn_nsdl_update_registration(handle, NULL, 0) ){ + return false; + } + + retCounter = 1; + if( 0 != sn_nsdl_update_registration(handle, NULL, 0) ){ + return false; + } + + retCounter = 2; + if( 0 != sn_nsdl_update_registration(handle, NULL, 0) ){ + return false; + } + + retCounter = 4; + sn_grs_stub.infoRetCounter = 2; + sn_grs_stub.expectedInfo = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset( sn_grs_stub.expectedInfo, 0, sizeof(sn_nsdl_resource_info_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr->registered = SN_NDSL_RESOURCE_REGISTERED; + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_len = 1; + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr[0] = 'a'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr[1] = '\0'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr[0] = 'a'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr[1] = '\0'; + sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_len = 1; + sn_grs_stub.expectedInfo->resource_parameters_ptr->observable = 1; + + sn_grs_stub.expectedInfo->path = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->path[0] = 'a'; + sn_grs_stub.expectedInfo->path[1] = '\0'; + sn_grs_stub.expectedInfo->pathlen = 1; + sn_grs_stub.expectedInfo->resource = (uint8_t*)malloc(2); + sn_grs_stub.expectedInfo->resource[0] = 'a'; + sn_grs_stub.expectedInfo->resource[1] = '\0'; + sn_grs_stub.expectedInfo->resourcelen = 1; + sn_grs_stub.expectedInfo->publish_uri = 1; + + sn_coap_builder_stub.expectedUint16 = 1; + int8_t val = sn_nsdl_update_registration(handle, NULL, 0); + + free(sn_grs_stub.expectedInfo->resource); + free(sn_grs_stub.expectedInfo->path); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr->resource_type_ptr); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr); + free(sn_grs_stub.expectedInfo); + sn_grs_stub.expectedInfo = NULL; + + if( 0 != val ){ + return false; + } + + sn_grs_stub.info2ndRetCounter = 1; + sn_grs_stub.infoRetCounter = 1; + sn_grs_stub.expectedInfo = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset( sn_grs_stub.expectedInfo, 0, sizeof(sn_nsdl_resource_info_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr->observable = 1; + sn_grs_stub.expectedInfo->publish_uri = 1; + retCounter = 3; + //set_endpoint_info == -1 + //sn_nsdl_build_registration_body == SN_NSDL_FAILURE + val = sn_nsdl_update_registration(handle, NULL, 0); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr); + free(sn_grs_stub.expectedInfo); + + if( 0 != val ){ + return false; + } + + sn_grs_stub.info2ndRetCounter = 2; + sn_grs_stub.infoRetCounter = 2; + sn_grs_stub.expectedInfo = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset( sn_grs_stub.expectedInfo, 0, sizeof(sn_nsdl_resource_info_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s)); + memset( sn_grs_stub.expectedInfo->resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr->observable = 1; + sn_grs_stub.expectedInfo->publish_uri = 1; + retCounter = 4; + sn_grs_stub.expectedInfo->resource_parameters_ptr->registered = SN_NDSL_RESOURCE_REGISTERING; + //set_endpoint_info == -1 + val = sn_nsdl_update_registration(handle, NULL, 0); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr); + free(sn_grs_stub.expectedInfo); + + if( 0 != val ){ + return false; + } + + u_int8_t loc[] = {"location"}; + + handle->ep_information_ptr->location_ptr = (uint8_t*)malloc(sizeof(loc)); + handle->ep_information_ptr->location_len = (uint8_t)sizeof(loc); + + sn_grs_stub.info2ndRetCounter = 1; + sn_grs_stub.infoRetCounter = 1; + sn_grs_stub.expectedInfo = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset( sn_grs_stub.expectedInfo, 0, sizeof(sn_nsdl_resource_info_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s)); + memset( sn_grs_stub.expectedInfo->resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr->observable = 1; + sn_grs_stub.expectedInfo->publish_uri = 1; + retCounter = 1; + sn_grs_stub.expectedInfo->resource_parameters_ptr->registered = SN_NDSL_RESOURCE_REGISTERING; + //set_endpoint_info == -1 + val = sn_nsdl_update_registration(handle, NULL, 0); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr); + free(sn_grs_stub.expectedInfo); + + if( 0 != val ){ + return false; + } + + sn_grs_stub.info2ndRetCounter = 2; + sn_grs_stub.infoRetCounter = 2; + sn_grs_stub.expectedInfo = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset( sn_grs_stub.expectedInfo, 0, sizeof(sn_nsdl_resource_info_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s)); + memset( sn_grs_stub.expectedInfo->resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s)); + sn_grs_stub.expectedInfo->resource_parameters_ptr->observable = 1; + sn_grs_stub.expectedInfo->publish_uri = 1; + retCounter = 2; + sn_grs_stub.expectedInfo->resource_parameters_ptr->registered = SN_NDSL_RESOURCE_REGISTERING; + //set_endpoint_info == -1 + val = sn_nsdl_update_registration(handle, NULL, 0); + free(sn_grs_stub.expectedInfo->resource_parameters_ptr); + free(sn_grs_stub.expectedInfo); + + if( 0 != val ){ + return false; + } + free(sn_grs_stub.expectedGrs->coap); + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_set_endpoint_location() +{ + + u_int8_t loc[] = {"location"}; + + uint8_t* location_ptr = (uint8_t*)malloc(sizeof(loc)); + uint8_t location_len = (uint8_t)sizeof(loc); + + sn_grs_stub.retNull = false; + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + + + if(sn_nsdl_set_endpoint_location(NULL,location_ptr,location_len) != -1){ + return false; + } + + if(sn_nsdl_set_endpoint_location(NULL,NULL,location_len) != -1){ + return false; + } + + if(sn_nsdl_set_endpoint_location(handle,NULL,location_len) != -1){ + return false; + } + + if(sn_nsdl_set_endpoint_location(handle,location_ptr,0) != -1){ + return false; + } + + if(sn_nsdl_set_endpoint_location(NULL,location_ptr,0) != -1){ + return false; + } + + retCounter = 1; + + if(sn_nsdl_set_endpoint_location(handle,location_ptr,location_len) != 0){ + return false; + } + + sn_nsdl_destroy(handle); + free(location_ptr); + + return true; +} + +bool test_sn_nsdl_nsp_lost() +{ + sn_nsdl_nsp_lost(NULL); + + sn_grs_stub.retNull = false; + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + + bool ret = true; + sn_nsdl_nsp_lost(handle); + if( SN_NSDL_ENDPOINT_NOT_REGISTERED != handle->sn_nsdl_endpoint_registered ){ + ret = false; + } + sn_nsdl_destroy(handle); + return ret; +} + +bool test_sn_nsdl_is_ep_registered() +{ + if( SN_NSDL_FAILURE != sn_nsdl_is_ep_registered(NULL)){ + return false; + } + sn_grs_stub.retNull = false; + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + handle->sn_nsdl_endpoint_registered = 1; + + bool ret = sn_nsdl_is_ep_registered(handle) == 1; + + sn_nsdl_destroy(handle); + return ret; +} + +bool test_sn_nsdl_send_observation_notification() +{ + if( 0 != sn_nsdl_send_observation_notification(NULL, NULL, 0,NULL,0,NULL,0,0,0) ){ + return false; + } + sn_grs_stub.retNull = false; + sn_grs_stub.expectedInt8 = SN_NSDL_SUCCESS; + retCounter = 5; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + sn_grs_stub.expectedGrs->coap = (struct coap_s *)malloc(sizeof(struct coap_s)); + sn_grs_stub.expectedGrs->coap->sn_coap_protocol_free = myFree; + sn_grs_stub.expectedGrs->coap->sn_coap_protocol_malloc = myMalloc; + sn_grs_stub.expectedGrs->coap->sn_coap_rx_callback = nsdl_rx_callback; + sn_grs_stub.expectedGrs->coap->sn_coap_tx_callback = nsdl_tx_callback; + + if( 0 != sn_nsdl_send_observation_notification(handle, NULL, 0,NULL,0,NULL,0,0,0) ){ + return false; + } + + retCounter = 0; + if( 0 != sn_nsdl_send_observation_notification(handle, NULL, 0,NULL,0,NULL,0,0,0) ){ + return false; + } + + retCounter = 1; + if( 0 != sn_nsdl_send_observation_notification(handle, NULL, 0,NULL,0,NULL,0,0,0) ){ + return false; + } + + retCounter = 2; + if( 0 != sn_nsdl_send_observation_notification(handle, NULL, 0,NULL,0,NULL,0,0,1) ){ + return false; + } + + retCounter = 2; + if( 0 != sn_nsdl_send_observation_notification(handle, NULL, 0,NULL,0,NULL,0,0,1) ){ + return false; + } + + retCounter = 2; + sn_grs_stub.int8SuccessCounter = 0; + sn_grs_stub.expectedInt8 = SN_NSDL_FAILURE; + if( 0 != sn_nsdl_send_observation_notification(handle, NULL, 0,NULL,0,NULL,0,0,1) ){ + return false; + } + free(sn_grs_stub.expectedGrs->coap); + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_send_observation_notification_with_uri_path() +{ + if( 0 != sn_nsdl_send_observation_notification_with_uri_path(NULL, NULL, 0,NULL,0,NULL,0,0,0, NULL,0) ){ + return false; + } + sn_grs_stub.retNull = false; + retCounter = 5; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + sn_grs_stub.expectedGrs->coap = (struct coap_s *)malloc(sizeof(struct coap_s)); + sn_grs_stub.expectedGrs->coap->sn_coap_protocol_free = myFree; + sn_grs_stub.expectedGrs->coap->sn_coap_protocol_malloc = myMalloc; + sn_grs_stub.expectedGrs->coap->sn_coap_rx_callback = nsdl_rx_callback; + sn_grs_stub.expectedGrs->coap->sn_coap_tx_callback = nsdl_tx_callback; + + u_int8_t path[] = {"13/0/1"}; + uint8_t* uri_path_ptr = (uint8_t*)malloc(sizeof(path)); + uint8_t uri_path_len = (uint8_t)sizeof(path); + if( 0 != sn_nsdl_send_observation_notification_with_uri_path(handle, NULL, 0,NULL,0,NULL,0,0,0,uri_path_ptr,uri_path_len) ){ + return false; + } + + retCounter = 0; + if( 0 != sn_nsdl_send_observation_notification_with_uri_path(handle, NULL, 0,NULL,0,NULL,0,0,0,uri_path_ptr,uri_path_len) ){ + return false; + } + + retCounter = 1; + if( 0 != sn_nsdl_send_observation_notification_with_uri_path(handle, NULL, 0,NULL,0,NULL,0,0,0,uri_path_ptr,uri_path_len) ){ + return false; + } + + retCounter = 2; + if( 0 != sn_nsdl_send_observation_notification_with_uri_path(handle, NULL, 0,NULL,0,NULL,0,0,1,uri_path_ptr,uri_path_len) ){ + return false; + } + + retCounter = 2; + if( 0 != sn_nsdl_send_observation_notification_with_uri_path(handle, NULL, 0,NULL,0,NULL,0,0,1,uri_path_ptr,uri_path_len) ){ + return false; + } + + retCounter = 2; + if( 0 != sn_nsdl_send_observation_notification_with_uri_path(handle, NULL, 0,NULL,0,NULL,0,0,1,uri_path_ptr,uri_path_len) ){ + return false; + } + + retCounter = 2; + sn_grs_stub.int8SuccessCounter = 0; + sn_grs_stub.expectedInt8 = SN_NSDL_FAILURE; + if( 0 != sn_nsdl_send_observation_notification_with_uri_path(handle, NULL, 0,NULL,0,NULL,0,0,1,NULL,0) ){ + return false; + } + free(sn_grs_stub.expectedGrs->coap); + free(uri_path_ptr); + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_oma_bootstrap() +{ + if( 0 != sn_nsdl_oma_bootstrap(NULL, NULL, NULL, NULL)){ + return false; + } + sn_grs_stub.retNull = false; + retCounter = 5; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + sn_grs_stub.expectedGrs->coap = (struct coap_s *)malloc(sizeof(struct coap_s)); + sn_grs_stub.expectedGrs->coap->sn_coap_protocol_free = myFree; + sn_grs_stub.expectedGrs->coap->sn_coap_protocol_malloc = myMalloc; + sn_grs_stub.expectedGrs->coap->sn_coap_rx_callback = nsdl_rx_callback; + sn_grs_stub.expectedGrs->coap->sn_coap_tx_callback = nsdl_tx_callback; + + sn_nsdl_addr_s *addr = (sn_nsdl_addr_s*)malloc(sizeof(sn_nsdl_addr_s)); + memset(addr, 0, sizeof(sn_nsdl_addr_s)); + sn_nsdl_ep_parameters_s *param = (sn_nsdl_ep_parameters_s*)malloc(sizeof(sn_nsdl_ep_parameters_s)); + memset(param, 0, sizeof(sn_nsdl_ep_parameters_s)); + sn_nsdl_bs_ep_info_t *info = (sn_nsdl_bs_ep_info_t*)malloc(sizeof(sn_nsdl_bs_ep_info_t)); + memset(info, 0, sizeof(sn_nsdl_bs_ep_info_t)); + + if( 0 != sn_nsdl_oma_bootstrap(handle, addr, param, info)){ + return false; + } + + info->device_object = (sn_nsdl_oma_device_t*)malloc(sizeof(sn_nsdl_oma_device_t)); + memset(info->device_object, 0, sizeof(sn_nsdl_oma_device_t)); + + if( 0 != sn_nsdl_oma_bootstrap(handle, addr, param, info)){ + return false; + } + + retCounter = 0; + sn_grs_stub.expectedInt8 = -1; + if( 0 != sn_nsdl_oma_bootstrap(handle, addr, param, info)){ + return false; + } + + retCounter = 1; + sn_grs_stub.expectedInt8 = -1; + if( 0 != sn_nsdl_oma_bootstrap(handle, addr, param, info)){ + return false; + } + + retCounter = 1; + sn_grs_stub.expectedInt8 = -1; + sn_grs_stub.int8SuccessCounter = 1; + param->binding_and_mode = 0; + if( 0 != sn_nsdl_oma_bootstrap(handle, addr, param, info)){ + return false; + } + + retCounter = 1; + sn_grs_stub.int8SuccessCounter = 2; + param->binding_and_mode = 3; + if( 0 != sn_nsdl_oma_bootstrap(handle, addr, param, info)){ + return false; + } + + retCounter = 1; + sn_grs_stub.int8SuccessCounter = 3; + param->binding_and_mode = 6; + if( 0 != sn_nsdl_oma_bootstrap(handle, addr, param, info)){ + return false; + } + + retCounter = 2; + sn_grs_stub.int8SuccessCounter = 3; + param->binding_and_mode = 6; + if( 0 != sn_nsdl_oma_bootstrap(handle, addr, param, info)){ + return false; + } + + retCounter = 3; + sn_grs_stub.int8SuccessCounter = 3; + param->binding_and_mode = 6; + if( 0 != sn_nsdl_oma_bootstrap(handle, addr, param, info)){ + return false; + } + + retCounter = 6; + sn_grs_stub.expectedInt8 = 0; + sn_grs_stub.int8SuccessCounter = 3; + param->binding_and_mode = 6; + sn_coap_builder_stub.expectedUint16 = 1; + if( 0 != sn_nsdl_oma_bootstrap(handle, addr, param, info)){ + return false; + } + + free(info->device_object); + free(info); + free(param); + free(addr); + free(sn_grs_stub.expectedGrs->coap); + retCounter = 1; + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_get_certificates() +{ + if( 0 != sn_nsdl_get_certificates(NULL)){ + return false; + } + sn_grs_stub.retNull = false; + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + + if( 0 != sn_nsdl_get_certificates(handle)){ + return false; + } + + retCounter = 1; + sn_grs_stub.retNull = true; + if( 0 != sn_nsdl_get_certificates(handle)){ + return false; + } + + retCounter = 1; + sn_grs_stub.retNull = false; + sn_grs_stub.infoRetCounter = 1; + sn_grs_stub.expectedInfo = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset( sn_grs_stub.expectedInfo, 0, sizeof(sn_nsdl_resource_info_s)); + if( 0 != sn_nsdl_get_certificates(handle)){ + return false; + } + + retCounter = 1; + sn_grs_stub.retNull = false; + sn_grs_stub.infoRetCounter = 2; + if( 0 != sn_nsdl_get_certificates(handle)){ + return false; + } + + retCounter = 1; + sn_grs_stub.retNull = false; + sn_grs_stub.infoRetCounter = 3; + omalw_certificate_list_t* list = sn_nsdl_get_certificates(handle); + if( 0 == list ){ + return false; + } + free(list); + free(sn_grs_stub.expectedInfo); + + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_update_certificates() +{ + if( -1 != sn_nsdl_update_certificates(NULL, NULL, 0) ){ + return false; + } + sn_grs_stub.retNull = false; + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + + omalw_certificate_list_t* list = (omalw_certificate_list_t*)malloc(sizeof(omalw_certificate_list_t)); + memset( list, 0, sizeof(omalw_certificate_list_t)); + + sn_grs_stub.retNull = true; + if( -1 != sn_nsdl_update_certificates(handle, list, 0) ){ + return false; + } + + sn_grs_stub.retNull = false; + sn_grs_stub.infoRetCounter = 1; + sn_grs_stub.expectedInfo = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset( sn_grs_stub.expectedInfo, 0, sizeof(sn_nsdl_resource_info_s)); + if( -1 != sn_nsdl_update_certificates(handle, list, 0) ){ + return false; + } + + sn_grs_stub.retNull = false; + sn_grs_stub.infoRetCounter = 2; + if( -1 != sn_nsdl_update_certificates(handle, list, 0) ){ + return false; + } + + sn_grs_stub.retNull = false; + sn_grs_stub.infoRetCounter = 3; + if( 0 != sn_nsdl_update_certificates(handle, list, 0) ){ + return false; + } + + free(sn_grs_stub.expectedInfo); + free(list); + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_create_oma_device_object() +{ + if( -1 != sn_nsdl_create_oma_device_object(NULL, NULL) ){ + return false; + } + sn_grs_stub.retNull = false; + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + + sn_nsdl_oma_device_t *device = (sn_nsdl_oma_device_t*)malloc(sizeof(sn_nsdl_oma_device_t)); + memset( device, 0, sizeof(sn_nsdl_oma_device_t)); + + sn_grs_stub.retNull = true; + if( -1 != sn_nsdl_create_oma_device_object(handle, device) ){ + return false; + } + + sn_grs_stub.retNull = false; + sn_grs_stub.infoRetCounter = 1; + sn_grs_stub.expectedInfo = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset( sn_grs_stub.expectedInfo, 0, sizeof(sn_nsdl_resource_info_s)); + + sn_grs_stub.useMockedPath = true; + sn_grs_stub.mockedPath[0] = '9'; + sn_grs_stub.mockedPath[1] = '9'; + sn_grs_stub.mockedPath[2] = '9'; + sn_grs_stub.mockedPath[3] = '9'; + sn_grs_stub.mockedPath[4] = '9'; + sn_grs_stub.mockedPath[5] = '9'; + sn_grs_stub.mockedPath[6] = '9'; + sn_grs_stub.mockedPath[7] = '9'; + sn_grs_stub.mockedPathLen = 8; + + if( -1 != sn_nsdl_create_oma_device_object(handle, device) ){ + return false; + } + + sn_grs_stub.infoRetCounter = 1; + sn_grs_stub.useMockedPath = true; + sn_grs_stub.mockedPath[0] = '1'; + sn_grs_stub.mockedPath[1] = '1'; + sn_grs_stub.mockedPath[2] = '1'; + sn_grs_stub.mockedPath[3] = '1'; + sn_grs_stub.mockedPath[4] = '1'; + sn_grs_stub.mockedPath[5] = '1'; + sn_grs_stub.mockedPath[6] = '1'; + sn_grs_stub.mockedPath[7] = '1'; + sn_grs_stub.mockedPathLen = 8; + + if( -1 != sn_nsdl_create_oma_device_object(handle, device) ){ + return false; + } + + sn_grs_stub.useMockedPath = false; + sn_grs_stub.infoRetCounter = 1; + + sn_grs_stub.expectedInfo->resource = (uint8_t*)malloc(4); + *sn_grs_stub.expectedInfo->resource = 0; + + if( SN_NSDL_SUCCESS != sn_nsdl_create_oma_device_object(handle, device) ){ + return false; + } + + sn_grs_stub.infoRetCounter = 1; + *sn_grs_stub.expectedInfo->resource = 1; + if( -1 != sn_nsdl_create_oma_device_object(handle, device) ){ + return false; + } + + free( sn_grs_stub.expectedInfo->resource ); + + retCounter = 1; + if( -1 != sn_nsdl_create_oma_device_object(handle, device) ){ + return false; + } + + retCounter = 2; + if( -1 != sn_nsdl_create_oma_device_object(handle, device) ){ + return false; + } + + retCounter = 3; + if( SN_NSDL_SUCCESS != sn_nsdl_create_oma_device_object(handle, device) ){ + return false; + } + + free(sn_grs_stub.expectedInfo); + free(device); + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_get_version() +{ + char* ret = sn_nsdl_get_version(); + if( strcmp(ret, "0.0.0") != 0 ){ + return false; + } + + return true; +} + +bool test_sn_nsdl_process_coap() +{ + if( -1 != sn_nsdl_process_coap(NULL, NULL, 0, NULL) ){ + return false; + } + sn_grs_stub.retNull = false; + retCounter = 5; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + + sn_coap_protocol_stub.expectedHeader = NULL; + if( -1 != sn_nsdl_process_coap(handle, NULL, 0, NULL) ){ + return false; + } + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_grs_stub.expectedGrs->coap = (struct coap_s *)malloc(sizeof(struct coap_s)); + sn_grs_stub.expectedGrs->coap->sn_coap_protocol_free = myFree; + sn_grs_stub.expectedGrs->coap->sn_coap_protocol_malloc = myMalloc; + sn_grs_stub.expectedGrs->coap->sn_coap_rx_callback = nsdl_rx_callback; + sn_grs_stub.expectedGrs->coap->sn_coap_tx_callback = nsdl_tx_callback; + + sn_coap_protocol_stub.expectedHeader->coap_status = 2; // != 0 && != 6 + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, NULL) ){ + return false; + } + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 0; + sn_coap_protocol_stub.expectedHeader->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(sn_coap_protocol_stub.expectedHeader->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + sn_coap_protocol_stub.expectedHeader->options_list_ptr->proxy_uri_len = 2; + sn_coap_protocol_stub.expectedHeader->options_list_ptr->proxy_uri_ptr = (uint8_t*)malloc(2); + memset(sn_coap_protocol_stub.expectedHeader->options_list_ptr->proxy_uri_ptr, 0, 2); + + if( -1 != sn_nsdl_process_coap(handle, NULL, 0, NULL) ){ + return false; + } + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 0; + sn_coap_protocol_stub.expectedHeader->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(sn_coap_protocol_stub.expectedHeader->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + sn_coap_protocol_stub.expectedHeader->options_list_ptr->proxy_uri_len = 2; + sn_coap_protocol_stub.expectedHeader->options_list_ptr->proxy_uri_ptr = (uint8_t*)malloc(2); + + sn_coap_builder_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_builder_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, NULL) ){ + return false; + } + sn_coap_builder_stub.expectedHeader = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_DELETE + 1; + sn_coap_protocol_stub.expectedHeader->payload_ptr = (uint8_t*)malloc(2); + + if( -1 != sn_nsdl_process_coap(handle, NULL, 0, NULL) ){ + return false; + } + + sn_nsdl_addr_s *addr = (sn_nsdl_addr_s*)malloc(sizeof(sn_nsdl_addr_s)); + memset(addr, 0, sizeof(sn_nsdl_addr_s)); + + //Test sn_nsdl_local_rx_function fully here + sn_coap_builder_stub.expectedHeader = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_DELETE + 1; + sn_coap_protocol_stub.expectedHeader->payload_ptr = (uint8_t*)malloc(2); + sn_coap_protocol_stub.expectedHeader->msg_id = 5; + sn_coap_protocol_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + handle->register_msg_id = 5; + handle->unregister_msg_id = 5; + if( -1 != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + + sn_coap_builder_stub.expectedHeader = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_DELETE + 1; + sn_coap_protocol_stub.expectedHeader->payload_ptr = (uint8_t*)malloc(2); + sn_coap_protocol_stub.expectedHeader->msg_id = 5; + sn_coap_protocol_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + sn_coap_protocol_stub.expectedHeader->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(sn_coap_protocol_stub.expectedHeader->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_ptr = (uint8_t*)malloc(2); + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_len = 2; + handle->register_msg_id = 5; + + if( 0 != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + + sn_coap_builder_stub.expectedHeader = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_DELETE + 1; + sn_coap_protocol_stub.expectedHeader->payload_ptr = (uint8_t*)malloc(2); + sn_coap_protocol_stub.expectedHeader->msg_id = 5; + sn_coap_protocol_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + sn_coap_protocol_stub.expectedHeader->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(sn_coap_protocol_stub.expectedHeader->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_ptr = (uint8_t*)malloc(3); + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_len = 3; + + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_ptr[0] = '/'; + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_ptr[1] = '/'; + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_ptr[2] = '/'; + handle->register_msg_id = 5; + + if( -1 != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + + sn_coap_builder_stub.expectedHeader = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_DELETE + 1; + sn_coap_protocol_stub.expectedHeader->payload_ptr = (uint8_t*)malloc(2); + sn_coap_protocol_stub.expectedHeader->msg_id = 5; + sn_coap_protocol_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + sn_coap_protocol_stub.expectedHeader->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(sn_coap_protocol_stub.expectedHeader->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_ptr = (uint8_t*)malloc(3); + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_len = 3; + + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_ptr[0] = '/'; + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_ptr[1] = '/'; + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_ptr[2] = '/'; + handle->register_msg_id = 5; + + retCounter = 1; + if( -1 != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + + sn_coap_builder_stub.expectedHeader = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_DELETE + 1; + sn_coap_protocol_stub.expectedHeader->payload_ptr = (uint8_t*)malloc(2); + sn_coap_protocol_stub.expectedHeader->msg_id = 5; + sn_coap_protocol_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + sn_coap_protocol_stub.expectedHeader->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(sn_coap_protocol_stub.expectedHeader->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_ptr = (uint8_t*)malloc(3); + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_len = 3; + + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_ptr[0] = '/'; + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_ptr[1] = '/'; + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_ptr[2] = '/'; + + handle->register_msg_id = 5; + retCounter = 2; + if( 0 != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + free(handle->ep_information_ptr->endpoint_name_ptr); + handle->ep_information_ptr->endpoint_name_ptr = NULL; + free(handle->ep_information_ptr->domain_name_ptr); + handle->ep_information_ptr->domain_name_ptr = NULL; + + sn_coap_builder_stub.expectedHeader = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_DELETE + 1; + sn_coap_protocol_stub.expectedHeader->payload_ptr = (uint8_t*)malloc(2); + sn_coap_protocol_stub.expectedHeader->msg_id = 5; + sn_coap_protocol_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; + sn_coap_protocol_stub.expectedHeader->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(sn_coap_protocol_stub.expectedHeader->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_ptr = (uint8_t*)malloc(3); + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_len = 3; + + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_ptr[0] = '/'; + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_ptr[1] = '/'; + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_ptr[2] = '/'; + + handle->register_msg_id = 0; + handle->unregister_msg_id = 0; + handle->update_register_msg_id = 5; + + retCounter = 2; + if( 0 != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + free(handle->ep_information_ptr->endpoint_name_ptr); + handle->ep_information_ptr->endpoint_name_ptr = NULL; + free(handle->ep_information_ptr->domain_name_ptr); + handle->ep_information_ptr->domain_name_ptr = NULL; + + sn_coap_builder_stub.expectedHeader = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_DELETE + 1; + sn_coap_protocol_stub.expectedHeader->payload_ptr = (uint8_t*)malloc(2); + sn_coap_protocol_stub.expectedHeader->msg_id = 5; + sn_coap_protocol_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_DELETED; + sn_coap_protocol_stub.expectedHeader->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(sn_coap_protocol_stub.expectedHeader->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_ptr = (uint8_t*)malloc(3); + sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_len = 3; + handle->register_msg_id = 5; + handle->unregister_msg_id = 5; + + handle->ep_information_ptr->endpoint_name_ptr = (uint8_t*)malloc(2); + handle->ep_information_ptr->domain_name_ptr = (uint8_t*)malloc(2); + + if( 0 != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + + // <-- Test sn_nsdl_local_rx_function fully here + + sn_coap_builder_stub.expectedHeader = NULL; + + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_grs_stub.expectedInt8 = -1; + + if( -1 != sn_nsdl_process_coap(handle, NULL, 0, NULL) ){ + return false; + } + // sn_coap_protocol_stub.expectedHeader is not deleted + + if( -1 != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + + + sn_grs_stub.expectedInt8 = 0; + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 9; + + if( -1 != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + + uint8_t * payload_ptr = (uint8_t*)malloc(40); + memset(payload_ptr, 0, 40); + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 99; + + payload_ptr[0] = 0x20; + payload_ptr[1] = 0x00; + payload_ptr[2] = 0x01; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + sn_coap_protocol_stub.expectedHeader->payload_len = 3; + + if( -1 != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 99; + + payload_ptr[0] = 0x18; + payload_ptr[1] = 0x00; + payload_ptr[2] = 0x00; + payload_ptr[3] = 0x01; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + sn_coap_protocol_stub.expectedHeader->payload_len = 4; + + if( -1 != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 99; + + payload_ptr[0] = 0x08; + payload_ptr[1] = 0x01; + sn_coap_protocol_stub.expectedHeader->payload_len = 2; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + + sn_coap_builder_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_builder_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + sn_coap_builder_stub.expectedHeader = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 99; + + payload_ptr[0] = 0x10; + payload_ptr[1] = 0x00; + payload_ptr[2] = 0x01; + sn_coap_protocol_stub.expectedHeader->payload_len = 3; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + + sn_coap_builder_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_builder_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + sn_coap_builder_stub.expectedHeader = NULL; + + //Test sn_nsdl_process_oma_tlv switches with failing + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 99; + + payload_ptr[0] = 0xC0; + payload_ptr[1] = 0x00; + payload_ptr[2] = 0xC0; + payload_ptr[3] = 0x00; + sn_coap_protocol_stub.expectedHeader->payload_len = 4; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + sn_grs_stub.int8SuccessCounter = 1; + sn_grs_stub.expectedInt8 = -1; + + sn_coap_builder_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_builder_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + sn_coap_builder_stub.expectedHeader = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 99; + + payload_ptr[0] = 0xC0; + payload_ptr[1] = 0x02; + payload_ptr[2] = 0xC0; + payload_ptr[3] = 0x02; + sn_coap_protocol_stub.expectedHeader->payload_len = 4; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + sn_grs_stub.int8SuccessCounter = 1; + sn_grs_stub.expectedInt8 = -1; + + sn_coap_builder_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_builder_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + sn_coap_builder_stub.expectedHeader = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 99; + + payload_ptr[0] = 0xC0; + payload_ptr[1] = 0x03; + payload_ptr[2] = 0xC0; + payload_ptr[3] = 0x03; + sn_coap_protocol_stub.expectedHeader->payload_len = 4; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + sn_grs_stub.int8SuccessCounter = 1; + sn_grs_stub.expectedInt8 = -1; + + sn_coap_builder_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_builder_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + sn_coap_builder_stub.expectedHeader = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 99; + + payload_ptr[0] = 0xC0; + payload_ptr[1] = 0x04; + payload_ptr[2] = 0xC0; + payload_ptr[3] = 0x04; + sn_coap_protocol_stub.expectedHeader->payload_len = 4; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + sn_grs_stub.int8SuccessCounter = 1; + sn_grs_stub.expectedInt8 = -1; + + sn_coap_builder_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_builder_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + sn_coap_builder_stub.expectedHeader = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 99; + + payload_ptr[0] = 0xC0; + payload_ptr[1] = 0x05; + payload_ptr[2] = 0xC0; + payload_ptr[3] = 0x05; + sn_coap_protocol_stub.expectedHeader->payload_len = 4; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + sn_grs_stub.int8SuccessCounter = 1; + sn_grs_stub.expectedInt8 = -1; + + if( SN_NSDL_FAILURE != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 99; + + payload_ptr[0] = 0xC0; + payload_ptr[1] = 0x01; + sn_coap_protocol_stub.expectedHeader->payload_len = 2; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + sn_grs_stub.int8SuccessCounter = 1; + sn_grs_stub.expectedInt8 = -1; + + if( SN_NSDL_FAILURE != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + + // Content type 97 tests + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '2'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + + // --> + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '2'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + sn_grs_stub.infoRetCounter = 3; + sn_grs_stub.expectedInfo = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset( sn_grs_stub.expectedInfo, 0, sizeof(sn_nsdl_resource_info_s)); + + handle->nsp_address_ptr->omalw_address_ptr->type = 1; + + payload_ptr[0] = '2'; + payload_ptr[1] = '\0'; + sn_coap_protocol_stub.expectedHeader->payload_len = 1; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + + handle->sn_nsdl_oma_bs_done_cb = myBootstrapCallback; + handle->sn_nsdl_oma_bs_done_cb_handle = myBootstrapCallbackHandle; + + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + + free(sn_grs_stub.expectedInfo); + sn_grs_stub.expectedInfo = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '2'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + sn_grs_stub.infoRetCounter = 3; + sn_grs_stub.expectedInfo = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset( sn_grs_stub.expectedInfo, 0, sizeof(sn_nsdl_resource_info_s)); + handle->nsp_address_ptr->omalw_server_security = CERTIFICATE; + handle->nsp_address_ptr->omalw_address_ptr->type = 1; + + payload_ptr[0] = 'a'; + payload_ptr[1] = 'F'; + sn_coap_protocol_stub.expectedHeader->payload_len = 2; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + + handle->sn_nsdl_oma_bs_done_cb = myBootstrapCallback; + handle->sn_nsdl_oma_bs_done_cb_handle = myBootstrapCallbackHandle; + + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + + free(sn_grs_stub.expectedInfo); + sn_grs_stub.expectedInfo = NULL; + + handle->nsp_address_ptr->omalw_server_security = 0; + // <-- + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '0'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + + payload_ptr[0] = 0xC0; + payload_ptr[1] = 0x01; + sn_coap_protocol_stub.expectedHeader->payload_len = 1; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + + //TODO: test rest of sn_nsdl_resolve_lwm2m_address here + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '0'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + + payload_ptr[0] = 0xC0; + payload_ptr[1] = 0x01; + sn_coap_protocol_stub.expectedHeader->payload_len = 2; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '0'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + + payload_ptr[0] = 0xC0; + payload_ptr[1] = 0x01; + sn_coap_protocol_stub.expectedHeader->payload_len = 2; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '0'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + + payload_ptr[0] = '/'; + payload_ptr[1] = '/'; + sn_coap_protocol_stub.expectedHeader->payload_len = 2; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + + // --> Test IPv6 parsing here + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '0'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + + payload_ptr[0] = '/'; + payload_ptr[1] = '/'; + payload_ptr[2] = ':'; + payload_ptr[3] = ':'; + payload_ptr[4] = 'A'; + payload_ptr[5] = ':'; + payload_ptr[6] = 'd'; + payload_ptr[7] = ':'; + payload_ptr[8] = '7'; + sn_coap_protocol_stub.expectedHeader->payload_len = 9; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '0'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + + payload_ptr[0] = '/'; + payload_ptr[1] = '/'; + payload_ptr[2] = '['; + payload_ptr[3] = ':'; + payload_ptr[4] = 'A'; + payload_ptr[5] = ':'; + payload_ptr[6] = 'd'; + payload_ptr[7] = '7'; + payload_ptr[8] = ':'; + payload_ptr[9] = ':'; + payload_ptr[10] = ']'; + sn_coap_protocol_stub.expectedHeader->payload_len = 11; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + + retCounter = 1; + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + free( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr ); //Investigate why would leak if removed? + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '0'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + + payload_ptr[0] = '/'; + payload_ptr[1] = '/'; + payload_ptr[2] = '['; + payload_ptr[3] = '1'; + payload_ptr[4] = ':'; + payload_ptr[5] = 'A'; + payload_ptr[6] = '7'; + payload_ptr[7] = ':'; + payload_ptr[8] = 'd'; + payload_ptr[9] = '7'; + payload_ptr[10] = '7'; + payload_ptr[11] = ':'; + payload_ptr[12] = 'd'; + payload_ptr[13] = 'E'; + payload_ptr[14] = '7'; + payload_ptr[15] = '7'; + payload_ptr[16] = ':'; + payload_ptr[17] = ':'; + payload_ptr[18] = ']'; + payload_ptr[19] = ':'; + payload_ptr[20] = '3'; + sn_coap_protocol_stub.expectedHeader->payload_len = 21; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + + retCounter = 1; + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + free( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr ); //Investigate why would leak if removed? + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '0'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = (uint8_t*)malloc(3); + + payload_ptr[0] = '/'; + payload_ptr[1] = '/'; + payload_ptr[2] = '['; + payload_ptr[3] = ':'; + payload_ptr[4] = ':'; + payload_ptr[5] = 'A'; + payload_ptr[6] = '7'; + payload_ptr[7] = ':'; + payload_ptr[8] = 'd'; + payload_ptr[9] = '7'; + payload_ptr[10] = '7'; + payload_ptr[11] = ':'; + payload_ptr[12] = 'd'; + payload_ptr[13] = 'E'; + payload_ptr[14] = '7'; + payload_ptr[15] = '7'; + payload_ptr[16] = ':'; + payload_ptr[17] = '1'; + payload_ptr[18] = ']'; + payload_ptr[19] = ':'; + payload_ptr[20] = '3'; + payload_ptr[21] = '/'; + sn_coap_protocol_stub.expectedHeader->payload_len = 22; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + + retCounter = 1; + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + free( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr ); //Investigate why would leak if removed? + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '0'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = (uint8_t*)malloc(3); + + payload_ptr[0] = '/'; + payload_ptr[1] = '/'; + payload_ptr[2] = '['; + payload_ptr[3] = '2'; + payload_ptr[4] = ':'; + payload_ptr[5] = 'A'; + payload_ptr[6] = '7'; + payload_ptr[7] = ':'; + payload_ptr[8] = ':'; + payload_ptr[9] = '7'; + payload_ptr[10] = '7'; + payload_ptr[11] = ':'; + payload_ptr[12] = 'd'; + payload_ptr[13] = 'E'; + payload_ptr[14] = '7'; + payload_ptr[15] = '7'; + payload_ptr[16] = ':'; + payload_ptr[17] = '1'; + payload_ptr[18] = ']'; + payload_ptr[19] = ':'; + payload_ptr[20] = '3'; + payload_ptr[21] = '/'; + sn_coap_protocol_stub.expectedHeader->payload_len = 22; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + + retCounter = 1; + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + free( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr ); //Investigate why would leak if removed? + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '0'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + + payload_ptr[0] = '/'; + payload_ptr[1] = '/'; + payload_ptr[2] = '['; + payload_ptr[3] = ':'; + payload_ptr[4] = ':'; + payload_ptr[5] = ']'; + payload_ptr[6] = ':'; + payload_ptr[7] = '5'; + payload_ptr[8] = '/'; + sn_coap_protocol_stub.expectedHeader->payload_len = 9; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + + retCounter = 1; + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + free( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr ); //Investigate why would leak if removed? + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = NULL; + // <-- + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '0'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + + payload_ptr[0] = '/'; + payload_ptr[1] = '/'; + payload_ptr[2] = ':'; + sn_coap_protocol_stub.expectedHeader->payload_len = 3; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + handle->sn_nsdl_oma_bs_done_cb = myBootstrapCallback; + handle->sn_nsdl_oma_bs_done_cb_handle = myBootstrapCallbackHandle; + + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = (uint8_t*)malloc(3); + + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + + //Test IPv4 here --> + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '0'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + + payload_ptr[0] = '/'; + payload_ptr[1] = '/'; + payload_ptr[2] = '1'; + payload_ptr[3] = '.'; + payload_ptr[4] = '2'; + payload_ptr[5] = '.'; + payload_ptr[6] = '3'; + payload_ptr[7] = '.'; + payload_ptr[8] = '4'; + payload_ptr[9] = ':'; + payload_ptr[10] = '6'; + sn_coap_protocol_stub.expectedHeader->payload_len = 11; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + handle->sn_nsdl_oma_bs_done_cb = myBootstrapCallback; + handle->sn_nsdl_oma_bs_done_cb_handle = myBootstrapCallbackHandle; + + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '0'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + + payload_ptr[0] = '/'; + payload_ptr[1] = '/'; + payload_ptr[2] = '1'; + payload_ptr[3] = '.'; + payload_ptr[4] = '2'; + payload_ptr[5] = '.'; + payload_ptr[6] = '3'; + payload_ptr[7] = '.'; + payload_ptr[8] = '4'; + payload_ptr[9] = ':'; + payload_ptr[10] = '6'; + payload_ptr[11] = '6'; + sn_coap_protocol_stub.expectedHeader->payload_len = 12; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + handle->sn_nsdl_oma_bs_done_cb = myBootstrapCallback; + handle->sn_nsdl_oma_bs_done_cb_handle = myBootstrapCallbackHandle; + + + retCounter = 1; + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + free( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr ); //Investigate why would leak if removed? + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '0'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + + payload_ptr[0] = '/'; + payload_ptr[1] = '/'; + payload_ptr[2] = '1'; + payload_ptr[3] = '.'; + payload_ptr[4] = '2'; + payload_ptr[5] = '.'; + payload_ptr[6] = '3'; + payload_ptr[7] = '.'; + payload_ptr[8] = '4'; + payload_ptr[9] = ':'; + payload_ptr[10] = '6'; + payload_ptr[11] = '6'; + payload_ptr[12] = '/'; + sn_coap_protocol_stub.expectedHeader->payload_len = 13; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + handle->sn_nsdl_oma_bs_done_cb = myBootstrapCallback; + handle->sn_nsdl_oma_bs_done_cb_handle = myBootstrapCallbackHandle; + + retCounter = 1; + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + free( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr ); //Investigate why would leak if removed? + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '0'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + + payload_ptr[0] = '/'; + payload_ptr[1] = '/'; + payload_ptr[2] = 's'; + payload_ptr[3] = '.'; + payload_ptr[4] = 't'; + payload_ptr[5] = '.'; + payload_ptr[6] = 'u'; + payload_ptr[7] = '.'; + payload_ptr[8] = 'v'; + payload_ptr[9] = ':'; + payload_ptr[10] = '6'; + sn_coap_protocol_stub.expectedHeader->payload_len = 11; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + handle->sn_nsdl_oma_bs_done_cb = myBootstrapCallback; + handle->sn_nsdl_oma_bs_done_cb_handle = myBootstrapCallbackHandle; + + retCounter = 1; + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + free( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr ); //Investigate why would leak if removed? + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '0'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + + payload_ptr[0] = '/'; + payload_ptr[1] = '/'; + payload_ptr[2] = 's'; + payload_ptr[3] = '.'; + payload_ptr[4] = 't'; + payload_ptr[5] = '.'; + payload_ptr[6] = 'u'; + payload_ptr[7] = '.'; + payload_ptr[8] = 'v'; + payload_ptr[9] = ':'; + payload_ptr[10] = '6'; + sn_coap_protocol_stub.expectedHeader->payload_len = 11; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + handle->sn_nsdl_oma_bs_done_cb = myBootstrapCallback; + handle->sn_nsdl_oma_bs_done_cb_handle = myBootstrapCallbackHandle; + handle->handle_bootstrap_msg = false; + + retCounter = 1; + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + free( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr ); //Investigate why would leak if removed? + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = NULL; + handle->handle_bootstrap_msg = true; + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '0'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + + payload_ptr[0] = '/'; + payload_ptr[1] = '/'; + payload_ptr[2] = 's'; + payload_ptr[3] = '.'; + payload_ptr[4] = 't'; + payload_ptr[5] = '.'; + payload_ptr[6] = 'u'; + payload_ptr[7] = '.'; + payload_ptr[8] = 'v'; + payload_ptr[9] = '.'; + payload_ptr[10] = 'w'; + payload_ptr[11] = ':'; + payload_ptr[12] = '6'; + payload_ptr[13] = '/'; + sn_coap_protocol_stub.expectedHeader->payload_len = 14; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + handle->sn_nsdl_oma_bs_done_cb = myBootstrapCallback; + handle->sn_nsdl_oma_bs_done_cb_handle = myBootstrapCallbackHandle; + + retCounter = 1; + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + free( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr ); //Investigate why would leak if removed? + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '0'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + + payload_ptr[0] = '/'; + payload_ptr[1] = '/'; + payload_ptr[2] = 's'; + payload_ptr[3] = '.'; + payload_ptr[4] = 't'; + payload_ptr[5] = '.'; + payload_ptr[6] = 'u'; + payload_ptr[7] = '.'; + payload_ptr[8] = 'v'; + payload_ptr[9] = '.'; + payload_ptr[10] = 'w'; + payload_ptr[11] = ':'; + payload_ptr[12] = '6'; + sn_coap_protocol_stub.expectedHeader->payload_len = 13; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + handle->sn_nsdl_oma_bs_done_cb = myBootstrapCallback; + handle->sn_nsdl_oma_bs_done_cb_handle = myBootstrapCallbackHandle; + + retCounter = 1; + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + free( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr ); //Investigate why would leak if removed? + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = NULL; + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '0'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + + free( payload_ptr ); + payload_ptr = malloc(276); + memset(payload_ptr, 1, 276); + payload_ptr[0] = '/'; + payload_ptr[1] = '/'; + payload_ptr[2] = 's'; + payload_ptr[3] = '.'; + payload_ptr[4] = 't'; + payload_ptr[5] = '.'; + payload_ptr[6] = 'u'; + payload_ptr[7] = '.'; + payload_ptr[8] = 'v'; + payload_ptr[9] = '.'; + payload_ptr[10] = 'w'; + payload_ptr[11] = ':'; + payload_ptr[12] = '6'; + sn_coap_protocol_stub.expectedHeader->payload_len = 276; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + handle->sn_nsdl_oma_bs_done_cb = myBootstrapCallback; + handle->sn_nsdl_oma_bs_done_cb_handle = myBootstrapCallbackHandle; + + retCounter = 1; + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + free( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr ); //Investigate why would leak if removed? + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = NULL; + // <-- + + sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s)); + sn_coap_protocol_stub.expectedHeader->coap_status = 6; + sn_coap_protocol_stub.expectedHeader->msg_code = 0; + sn_coap_protocol_stub.expectedHeader->content_type_len = 1; + sn_coap_protocol_stub.expectedHeader->content_type_ptr = (uint8_t*)malloc(1); + *sn_coap_protocol_stub.expectedHeader->content_type_ptr = 97; + sn_coap_protocol_stub.expectedHeader->uri_path_ptr = (uint8_t*)malloc(1); + sn_coap_protocol_stub.expectedHeader->uri_path_ptr[0] = '0'; + sn_coap_protocol_stub.expectedHeader->uri_path_len = 1; + + payload_ptr[0] = '/'; + payload_ptr[1] = '/'; + payload_ptr[2] = ':'; + payload_ptr[3] = ':'; + sn_coap_protocol_stub.expectedHeader->payload_len = 4; + sn_coap_protocol_stub.expectedHeader->payload_ptr = payload_ptr; + + if( SN_NSDL_SUCCESS != sn_nsdl_process_coap(handle, NULL, 0, addr) ){ + return false; + } + free(sn_grs_stub.expectedGrs->coap); + free(payload_ptr); + free(addr); + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_exec() +{ + if( -1 != sn_nsdl_exec(NULL, NULL) ){ + return false; + } + + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + sn_coap_protocol_stub.expectedInt8 = 0; + + if( 0 != sn_nsdl_exec(handle,0) ){ + return false; + } + + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_get_resource() +{ + if( NULL != sn_nsdl_get_resource(NULL, 0, NULL) ){ + return false; + } + sn_grs_stub.retNull = false; + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + + sn_nsdl_get_resource(handle, 0, NULL); + + sn_nsdl_destroy(handle); + return true; +} + +bool test_set_NSP_address() +{ + if( SN_NSDL_FAILURE != set_NSP_address(NULL, NULL, 0, SN_NSDL_ADDRESS_TYPE_IPV4) ){ + return false; + } + sn_grs_stub.retNull = false; + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = (uint8_t*)malloc(2); + memset( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr, 0, 2 ); + + uint8_t* addr = (uint8_t*)malloc(2); + memset(addr, 0, 2); + + if( SN_NSDL_FAILURE != set_NSP_address(handle, addr, 0, SN_NSDL_ADDRESS_TYPE_IPV4) ){ + return false; + } + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = NULL; + + retCounter = 1; + if( SN_NSDL_SUCCESS != set_NSP_address(handle, addr, 0, SN_NSDL_ADDRESS_TYPE_IPV4) ){ + return false; + } + free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr); + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = NULL; + + if( SN_NSDL_FAILURE != set_NSP_address(handle, addr, 0, SN_NSDL_ADDRESS_TYPE_IPV6) ){ + return false; + } + + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = NULL; + handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = (uint8_t*)malloc(2); + memset( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr, 0, 2 ); + + retCounter = 1; + if( SN_NSDL_SUCCESS != set_NSP_address(handle, addr, 0, SN_NSDL_ADDRESS_TYPE_IPV6) ){ + return false; + } + + free(addr); + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_list_resource() +{ + if( NULL != sn_nsdl_list_resource(NULL, 0, NULL) ){ + return false; + } + sn_grs_stub.retNull = false; + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + + if( NULL != sn_nsdl_list_resource(handle, 0, NULL) ){ + return false; + } + + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_free_resource_list() +{ + sn_nsdl_free_resource_list(NULL, NULL); + + sn_grs_stub.retNull = false; + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + + sn_grs_resource_list_s* list = (sn_grs_resource_list_s*)malloc(sizeof(sn_grs_resource_list_s)); + sn_nsdl_free_resource_list(handle, list); //mem leak or pass + + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_update_resource() +{ + if( SN_NSDL_FAILURE != sn_nsdl_update_resource(NULL, NULL) ){ + return false; + } + sn_grs_stub.retNull = false; + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + + if( 0 != sn_nsdl_update_resource(handle, NULL) ){ + return false; + } + + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_send_coap_message() +{ + if( SN_NSDL_FAILURE != sn_nsdl_send_coap_message(NULL, NULL, NULL) ){ + return false; + } + sn_grs_stub.retNull = false; + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + + if( 0 != sn_nsdl_send_coap_message(handle, NULL, NULL) ){ + return false; + } + + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_create_resource() +{ + if( SN_NSDL_FAILURE != sn_nsdl_create_resource(NULL, NULL) ){ + return false; + } + sn_grs_stub.retNull = false; + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + + if( 0 != sn_nsdl_create_resource(handle, NULL) ){ + return false; + } + + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_delete_resource() +{ + if( SN_NSDL_FAILURE != sn_nsdl_delete_resource(NULL, 0, NULL) ){ + return false; + } + sn_grs_stub.retNull = false; + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + + if( 0 != sn_nsdl_delete_resource(handle, 0, NULL) ){ + return false; + } + + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_get_first_resource() +{ + if( NULL != sn_nsdl_get_first_resource(NULL) ){ + return false; + } + sn_grs_stub.retNull = false; + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + + if( NULL != sn_nsdl_get_first_resource(handle) ){ + return false; + } + + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_get_next_resource() +{ + if( NULL != sn_nsdl_get_next_resource(NULL, NULL) ){ + return false; + } + sn_grs_stub.retNull = false; + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + + if( NULL != sn_nsdl_get_next_resource(handle, NULL) ){ + return false; + } + + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_build_response() +{ + if( NULL != sn_nsdl_build_response(NULL, NULL, 0) ){ + return false; + } + sn_grs_stub.retNull = false; + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + + if( NULL != sn_nsdl_build_response(handle, NULL, 0) ){ + return false; + } + + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_release_allocated_coap_msg_mem() +{ + sn_nsdl_release_allocated_coap_msg_mem(NULL, NULL); + sn_grs_stub.retNull = false; + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + + sn_coap_hdr_s* list = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s)); + + sn_nsdl_release_allocated_coap_msg_mem(handle, list); //mem leak or pass + + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_set_retransmission_parameters() +{ + struct nsdl_s* handle = NULL; + if (sn_nsdl_set_retransmission_parameters(handle, 10, 10) == 0){ + return false; + } + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + sn_coap_protocol_stub.expectedInt8 = 0; + + if (sn_nsdl_set_retransmission_parameters(handle, 10, 10) != 0){ + return false; + } + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_set_retransmission_buffer() +{ + struct nsdl_s* handle = NULL; + if (sn_nsdl_set_retransmission_buffer(handle,3,3 ) == 0){ + return false; + } + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + sn_coap_protocol_stub.expectedInt8 = 0; + + if (sn_nsdl_set_retransmission_buffer(handle,3,3 ) != 0){ + return false; + } + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_set_block_size() +{ + struct nsdl_s* handle = NULL; + if (sn_nsdl_set_block_size(handle,16) == 0){ + return false; + } + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + sn_coap_protocol_stub.expectedInt8 = 0; + + if (sn_nsdl_set_block_size(handle,16) != 0){ + return false; + } + sn_nsdl_destroy(handle); + return true; +} + +bool test_sn_nsdl_set_duplicate_buffer_size() +{ + struct nsdl_s* handle = NULL; + if (sn_nsdl_set_duplicate_buffer_size(handle,999) == 0){ + return false; + } + retCounter = 4; + sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s)); + memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s)); + handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree); + sn_coap_protocol_stub.expectedInt8 = 0; + + if (sn_nsdl_set_duplicate_buffer_size(handle,999) != 0){ + return false; + } + sn_nsdl_destroy(handle); + return true; +} diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_nsdl/test_sn_nsdl.h b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_nsdl/test_sn_nsdl.h new file mode 100644 index 0000000000..df6cbe097f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/sn_nsdl/test_sn_nsdl.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ +#ifndef TEST_SN_NSDL_H +#define TEST_SN_NSDL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +bool test_sn_nsdl_destroy(); + +bool test_sn_nsdl_init(); + +bool test_sn_nsdl_register_endpoint(); + +bool test_sn_nsdl_unregister_endpoint(); + +bool test_sn_nsdl_update_registration(); + +bool test_sn_nsdl_set_endpoint_location(); + +bool test_sn_nsdl_nsp_lost(); + +bool test_sn_nsdl_is_ep_registered(); + +bool test_sn_nsdl_send_observation_notification(); + +bool test_sn_nsdl_send_observation_notification_with_uri_path(); + +bool test_sn_nsdl_oma_bootstrap(); + +bool test_sn_nsdl_get_certificates(); + +bool test_sn_nsdl_update_certificates(); + +bool test_sn_nsdl_create_oma_device_object(); + +bool test_sn_nsdl_get_version(); + +bool test_sn_nsdl_process_coap(); + +bool test_sn_nsdl_exec(); + +bool test_sn_nsdl_get_resource(); + +bool test_set_NSP_address(); + +bool test_sn_nsdl_list_resource(); + +bool test_sn_nsdl_free_resource_list(); + +bool test_sn_nsdl_update_resource(); + +bool test_sn_nsdl_send_coap_message(); + +bool test_sn_nsdl_create_resource(); + +bool test_sn_nsdl_delete_resource(); + +bool test_sn_nsdl_get_first_resource(); + +bool test_sn_nsdl_get_next_resource(); + +bool test_sn_nsdl_build_response(); + +bool test_sn_nsdl_release_allocated_coap_msg_mem(); + +bool test_sn_nsdl_set_retransmission_parameters(); + +bool test_sn_nsdl_set_retransmission_buffer(); + +bool test_sn_nsdl_set_block_size(); + +bool test_sn_nsdl_set_duplicate_buffer_size(); + +#ifdef __cplusplus +} +#endif + +#endif // TEST_SN_NSDL_H + diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/ns_list_stub.c b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/ns_list_stub.c new file mode 100644 index 0000000000..a48d3a5371 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/ns_list_stub.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 NS_LIST_FN extern +#include "ns_list.h" + diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_builder_stub.c b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_builder_stub.c new file mode 100644 index 0000000000..b240ae2a46 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_builder_stub.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2011-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 sn_coap_builder.c + * + * \brief CoAP Message builder + * + * Functionality: Builds CoAP message + * + */ + +/* * * * * * * * * * * * * * */ +/* * * * INCLUDE FILES * * * */ +/* * * * * * * * * * * * * * */ + +#include "ns_types.h" +#include "sn_coap_header.h" +#include "sn_coap_builder_stub.h" + + +sn_coap_builder_stub_def sn_coap_builder_stub; + +sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code) +{ + return sn_coap_builder_stub.expectedHeader; +} + +int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_size) +{ + return sn_coap_builder_stub.expectedInt16; +} + +int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr) +{ + return sn_coap_builder_stub.expectedInt16; +} + +uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_size) +{ + return sn_coap_builder_stub.expectedUint16; +} + +uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_coap_msg_ptr) +{ + return sn_coap_builder_stub.expectedUint16; +} + +int16_t sn_coap_builder_options_build_add_zero_length_option(uint8_t **dst_packet_data_pptr, uint8_t option_length, uint8_t option_exist, sn_coap_option_numbers_e option_number) +{ + return sn_coap_builder_stub.expectedInt16; +} diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_builder_stub.h b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_builder_stub.h new file mode 100644 index 0000000000..55b1c35d89 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_builder_stub.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 __SN_COAP_BUILDER_STUB_H__ +#define __SN_COAP_BUILDER_STUB_H__ + +typedef struct { + int16_t expectedInt16; + uint16_t expectedUint16; + sn_coap_hdr_s *expectedHeader; +} sn_coap_builder_stub_def; + +extern sn_coap_builder_stub_def sn_coap_builder_stub; + +#endif //__SN_COAP_BUILDER_STUB_H__ diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_header_check_stub.c b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_header_check_stub.c new file mode 100644 index 0000000000..9229bebcda --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_header_check_stub.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 sn_coap_header_check.c + * + * \brief CoAP Header validity checker + * + * Functionality: Checks validity of CoAP Header + * + */ + +#include "ns_types.h" +#include "sn_coap_header.h" + +#include "sn_coap_header_check_stub.h" + +sn_coap_header_check_stub_def sn_coap_header_check_stub; + +int8_t sn_coap_header_validity_check(sn_coap_hdr_s *src_coap_msg_ptr, coap_version_e coap_version) +{ + return sn_coap_header_check_stub.expectedInt8; +} diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_header_check_stub.h b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_header_check_stub.h new file mode 100644 index 0000000000..268c42b298 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_header_check_stub.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 __SN_COAP_HEADER_CHECK_STUB_H__ +#define __SN_COAP_HEADER_CHECK_STUB_H__ + +#include + +typedef struct { + int8_t expectedInt8; +} sn_coap_header_check_stub_def; + +extern sn_coap_header_check_stub_def sn_coap_header_check_stub; + +#endif //__SN_COAP_HEADER_CHECK_STUB_H__ diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_parser_stub.c b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_parser_stub.c new file mode 100644 index 0000000000..cbd9023601 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_parser_stub.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 sn_coap_parser.c + * + * \brief CoAP Header parser + * + * Functionality: Parses CoAP Header + * + */ + +#include "ns_types.h" +#include "sn_nsdl.h" +#include "sn_coap_header.h" +#include "sn_coap_protocol_internal.h" +#include "sn_coap_parser_stub.h" + +sn_coap_parser_def sn_coap_parser_stub; + +sn_coap_hdr_s *sn_coap_parser(struct coap_s *handle, uint16_t packet_data_len, uint8_t *packet_data_ptr, coap_version_e *coap_version_ptr) +{ + return sn_coap_parser_stub.expectedHeader; +} + +void sn_coap_parser_release_allocated_coap_msg_mem(struct coap_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr) +{ + if (freed_coap_msg_ptr != NULL) { + if (freed_coap_msg_ptr->uri_path_ptr != NULL) { + free(freed_coap_msg_ptr->uri_path_ptr); + } + + if (freed_coap_msg_ptr->token_ptr != NULL) { + free(freed_coap_msg_ptr->token_ptr); + } + + if (freed_coap_msg_ptr->content_type_ptr != NULL) { + free(freed_coap_msg_ptr->content_type_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr != NULL) { + if (freed_coap_msg_ptr->options_list_ptr->max_age_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->max_age_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->proxy_uri_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->proxy_uri_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->etag_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->etag_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->uri_host_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->uri_host_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->location_path_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->location_path_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->uri_port_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->uri_port_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->location_query_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->location_query_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->observe_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->observe_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->uri_query_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->uri_query_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->block2_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->block2_ptr); + } + + if (freed_coap_msg_ptr->options_list_ptr->block1_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->block1_ptr); + } + if (freed_coap_msg_ptr->options_list_ptr->accept_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->accept_ptr); + } + if (freed_coap_msg_ptr->options_list_ptr->size1_ptr != NULL) { + free(freed_coap_msg_ptr->options_list_ptr->size1_ptr); + } + free(freed_coap_msg_ptr->options_list_ptr); + } + + free(freed_coap_msg_ptr); + freed_coap_msg_ptr = NULL; + } +} + +sn_coap_hdr_s *sn_coap_parser_init_message(sn_coap_hdr_s *coap_msg_ptr) +{ + /* * * * Check given pointer * * * */ + if (coap_msg_ptr == NULL) { + return NULL; + } + + /* XXX not technically legal to memset pointers to 0 */ + memset(coap_msg_ptr, 0x00, sizeof(sn_coap_hdr_s)); + + return coap_msg_ptr; +} + +sn_coap_hdr_s *sn_coap_parser_alloc_message(struct coap_s *handle) +{ + sn_coap_hdr_s *returned_coap_msg_ptr; + + /* * * * Check given pointer * * * */ + if (handle == NULL) { + return NULL; + } + + /* * * * Allocate memory for returned CoAP message and initialize allocated memory with with default values * * * */ + returned_coap_msg_ptr = handle->sn_coap_protocol_malloc(sizeof(sn_coap_hdr_s)); + + return sn_coap_parser_init_message(returned_coap_msg_ptr); +} + +sn_coap_options_list_s *sn_coap_parser_alloc_options(struct coap_s *handle, sn_coap_hdr_s *coap_msg_ptr) +{ + /* * * * Check given pointers * * * */ + if (handle == NULL || coap_msg_ptr == NULL) { + return NULL; + } + + /* * * * If the message already has options, return them * * * */ + if (coap_msg_ptr->options_list_ptr) { + return coap_msg_ptr->options_list_ptr; + } + + /* * * * Allocate memory for options and initialize allocated memory with with default values * * * */ + coap_msg_ptr->options_list_ptr = handle->sn_coap_protocol_malloc(sizeof(sn_coap_options_list_s)); + + if (coap_msg_ptr->options_list_ptr == NULL) { + return NULL; + } + + /* XXX not technically legal to memset pointers to 0 */ + memset(coap_msg_ptr->options_list_ptr, 0x00, sizeof(sn_coap_options_list_s)); + + return coap_msg_ptr->options_list_ptr; +} diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_parser_stub.h b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_parser_stub.h new file mode 100644 index 0000000000..c24339c0e6 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_parser_stub.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 __SN_COAP_PARSER_STUB_H__ +#define __SN_COAP_PARSER_STUB_H__ + +typedef struct { + sn_coap_hdr_s *expectedHeader; +} sn_coap_parser_def; + +extern sn_coap_parser_def sn_coap_parser_stub; + +#endif //__SN_COAP_PARSER_STUB_H__ diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_protocol_stub.c b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_protocol_stub.c new file mode 100644 index 0000000000..b5acd3272e --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_protocol_stub.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 /* For libary malloc() */ +#include /* For memset() and memcpy() */ +#ifdef __linux__ +#include +#endif + +#include "ns_types.h" +#include "sn_nsdl.h" +#include "sn_coap_protocol.h" +#include "sn_coap_header_internal.h" +#include "sn_coap_protocol_internal.h" +#include "sn_coap_protocol_stub.h" + +uint16_t sn_coap_block_data_size = 0; + +uint8_t sn_coap_resending_queue_msgs = 0; +uint8_t sn_coap_resending_queue_bytes = 0; +uint8_t sn_coap_resending_count = 0; +uint8_t sn_coap_resending_intervall = 0; + +uint8_t sn_coap_duplication_buffer_size = 0; + +sn_coap_protocol_stub_def sn_coap_protocol_stub; + +int8_t sn_coap_protocol_destroy(struct coap_s *handle) +{ + return sn_coap_protocol_stub.expectedInt8; +} + +struct coap_s *sn_coap_protocol_init(void *(*used_malloc_func_ptr)(uint16_t), void (*used_free_func_ptr)(void *), + uint8_t (*used_tx_callback_ptr)(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *), + int8_t (*used_rx_callback_ptr)(sn_coap_hdr_s *, sn_nsdl_addr_s *, void *param)) +{ + if( sn_coap_protocol_stub.expectedCoap ){ + sn_coap_protocol_stub.expectedCoap->sn_coap_protocol_free = used_free_func_ptr; + sn_coap_protocol_stub.expectedCoap->sn_coap_protocol_malloc = used_malloc_func_ptr; + sn_coap_protocol_stub.expectedCoap->sn_coap_rx_callback = used_rx_callback_ptr; + sn_coap_protocol_stub.expectedCoap->sn_coap_tx_callback = used_tx_callback_ptr; + //sn_coap_protocol_stub.expectedCoap->linked_list_resent_msgs = + } + return sn_coap_protocol_stub.expectedCoap; +} + +int8_t sn_coap_protocol_set_block_size(struct coap_s *handle, uint16_t block_size) +{ + return sn_coap_protocol_stub.expectedInt8; +} + +int8_t sn_coap_protocol_set_duplicate_buffer_size(struct coap_s *handle, uint8_t message_count) +{ + return sn_coap_protocol_stub.expectedInt8; +} + +int8_t sn_coap_protocol_set_retransmission_parameters(struct coap_s *handle, uint8_t resending_count, uint8_t resending_intervall) +{ + return sn_coap_protocol_stub.expectedInt8; +} + +int8_t sn_coap_protocol_set_retransmission_buffer(struct coap_s *handle, uint8_t buffer_size_messages, uint16_t buffer_size_bytes) +{ + return sn_coap_protocol_stub.expectedInt8; +} + +void sn_coap_protocol_clear_retransmission_buffer(struct coap_s *handle) +{ +} + + +int16_t sn_coap_protocol_build(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, + uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, void *param) +{ + return sn_coap_protocol_stub.expectedInt16; +} + +sn_coap_hdr_s *sn_coap_protocol_parse(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t packet_data_len, uint8_t *packet_data_ptr, void *param) +{ + return sn_coap_protocol_stub.expectedHeader; +} + +int8_t sn_coap_protocol_exec(struct coap_s *handle, uint32_t current_time) +{ + return sn_coap_protocol_stub.expectedInt8; +} + +coap_send_msg_s *sn_coap_protocol_allocate_mem_for_msg(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint16_t packet_data_len) +{ + return sn_coap_protocol_stub.expectedSendMsg; +} + + + diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_protocol_stub.h b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_protocol_stub.h new file mode 100644 index 0000000000..e003780442 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_coap_protocol_stub.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 __SN_COAP_PROTOCOL_STUB_H__ +#define __SN_COAP_PROTOCOL_STUB_H__ + +#include "sn_coap_header_internal.h" +#include "sn_coap_protocol_internal.h" + +typedef struct { + int8_t expectedInt8; + int16_t expectedInt16; + struct coap_s *expectedCoap; + sn_coap_hdr_s *expectedHeader; + coap_send_msg_s *expectedSendMsg; +} sn_coap_protocol_stub_def; + +extern sn_coap_protocol_stub_def sn_coap_protocol_stub; + +#endif //__SN_COAP_PROTOCOL_STUB_H__ diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_grs_stub.c b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_grs_stub.c new file mode 100755 index 0000000000..0009a60c65 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_grs_stub.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 sn_grs.c + * + * \brief General resource server. + * + */ +#include +#include + +#include "ns_list.h" +#include "ns_types.h" +#include "sn_nsdl.h" +#include "sn_coap_header.h" +#include "sn_coap_protocol.h" +#include "sn_nsdl_lib.h" +#include "sn_grs.h" + +#include "sn_grs_stub.h" + +sn_grs_stub_def sn_grs_stub; + +/* Extern function prototypes */ +extern int8_t sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration); + + +extern int8_t sn_grs_destroy(struct grs_s *handle) +{ + if( handle ){ + free(handle); + } + return sn_grs_stub.expectedInt8; +} + +extern struct grs_s *sn_grs_init(uint8_t (*sn_grs_tx_callback_ptr)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, + sn_nsdl_addr_s *), int8_t (*sn_grs_rx_callback_ptr)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *), + void *(*sn_grs_alloc)(uint16_t), void (*sn_grs_free)(void *)) +{ + if( sn_grs_stub.retNull ){ + return NULL; + } + return sn_grs_stub.expectedGrs; +} + + + +extern sn_grs_resource_list_s *sn_grs_list_resource(struct grs_s *handle, uint16_t pathlen, uint8_t *path) +{ + if( sn_grs_stub.retNull ){ + return NULL; + } + return sn_grs_stub.expectedList; +} + + +extern void sn_grs_free_resource_list(struct grs_s *handle, sn_grs_resource_list_s *list) +{ + if( list ){ + free(list); + list = NULL; + } +} + + +extern const sn_nsdl_resource_info_s *sn_grs_get_first_resource(struct grs_s *handle) +{ + if( sn_grs_stub.retNull ){ + return NULL; + } + if( sn_grs_stub.infoRetCounter == -1 && sn_grs_stub.info2ndRetCounter > 0 ){ + sn_grs_stub.info2ndRetCounter--; + return sn_grs_stub.expectedInfo; + } + if( sn_grs_stub.infoRetCounter > 0){ + sn_grs_stub.infoRetCounter--; + return sn_grs_stub.expectedInfo; + } + sn_grs_stub.infoRetCounter = -1; + return NULL; +} + + +extern const sn_nsdl_resource_info_s *sn_grs_get_next_resource(struct grs_s *handle, const sn_nsdl_resource_info_s *sn_grs_current_resource) +{ + if( sn_grs_stub.retNull ){ + return NULL; + } + if( sn_grs_stub.infoRetCounter == -1 && sn_grs_stub.info2ndRetCounter > 0 ){ + sn_grs_stub.info2ndRetCounter--; + return sn_grs_stub.expectedInfo; + } + if( sn_grs_stub.infoRetCounter > 0){ + sn_grs_stub.infoRetCounter--; + return sn_grs_stub.expectedInfo; + } + sn_grs_stub.infoRetCounter = -1; + return NULL; +} + + +extern int8_t sn_grs_delete_resource(struct grs_s *handle, uint16_t pathlen, uint8_t *path) +{ + return sn_grs_stub.expectedInt8; +} + + +extern int8_t sn_grs_update_resource(struct grs_s *handle, sn_nsdl_resource_info_s *res) +{ + return sn_grs_stub.expectedInt8; +} + + +extern int8_t sn_grs_create_resource(struct grs_s *handle, sn_nsdl_resource_info_s *res) +{ + if( sn_grs_stub.int8SuccessCounter > 0 ){ + sn_grs_stub.int8SuccessCounter--; + return SN_NSDL_SUCCESS; + } + return sn_grs_stub.expectedInt8; +} + + +extern int8_t sn_grs_process_coap(struct nsdl_s *nsdl_handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *src_addr_ptr) +{ + return sn_grs_stub.expectedInt8; +} + +extern int8_t sn_grs_send_coap_message(struct nsdl_s *handle, sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr) +{ + return sn_grs_stub.expectedInt8; +} + +sn_nsdl_resource_info_s *sn_grs_search_resource(struct grs_s *handle, uint16_t pathlen, uint8_t *path, uint8_t search_method) +{ + if(sn_grs_stub.useMockedPath){ + memcpy(path, &sn_grs_stub.mockedPath, sn_grs_stub.mockedPathLen); + } + if( sn_grs_stub.retNull ){ + return NULL; + } + if( sn_grs_stub.infoRetCounter == -1 && sn_grs_stub.info2ndRetCounter > 0 ){ + sn_grs_stub.info2ndRetCounter--; + return sn_grs_stub.expectedInfo; + } + if( sn_grs_stub.infoRetCounter > 0){ + sn_grs_stub.infoRetCounter--; + return sn_grs_stub.expectedInfo; + } + sn_grs_stub.infoRetCounter = -1; + return NULL; +} + +void sn_grs_mark_resources_as_registered(struct nsdl_s *handle) +{ +} + diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_grs_stub.h b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_grs_stub.h new file mode 100644 index 0000000000..bf4774560c --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_grs_stub.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 __SN_GRS_STUB_H__ +#define __SN_GRS_STUB_H__ + +#include "sn_nsdl_lib.h" +#include "sn_grs.h" + +typedef struct { + bool retNull; + int8_t infoRetCounter; + int8_t info2ndRetCounter; + int8_t expectedInt8; + int8_t int8SuccessCounter; + struct grs_s *expectedGrs; + sn_nsdl_resource_info_s *expectedInfo; + sn_grs_resource_list_s *expectedList; + + bool useMockedPath; + uint8_t mockedPath[8]; + uint8_t mockedPathLen; +}sn_grs_stub_def; + +extern sn_grs_stub_def sn_grs_stub; + +#endif //__SN_GRS_STUB_H__ diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_nsdl_stub.c b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_nsdl_stub.c new file mode 100755 index 0000000000..47d1badcd4 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_nsdl_stub.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "ns_types.h" +#include "sn_nsdl.h" +#include "sn_coap_header.h" +#include "sn_coap_protocol.h" +#include "sn_nsdl_lib.h" +#include "sn_grs.h" + +/* Defines */ +#define RESOURCE_DIR_LEN 2 +#define EP_NAME_PARAMETERS_LEN 3 +#define ET_PARAMETER_LEN 3 +#define LT_PARAMETER_LEN 3 +#define DOMAIN_PARAMETER_LEN 2 +#define RT_PARAMETER_LEN 3 +#define IF_PARAMETER_LEN 3 +#define OBS_PARAMETER_LEN 3 +#define AOBS_PARAMETER_LEN 8 +#define COAP_CON_PARAMETER_LEN 3 +#define BS_EP_PARAMETER_LEN 3 +#define BS_QUEUE_MODE_PARAMATER_LEN 2 + +#define SN_NSDL_EP_REGISTER_MESSAGE 1 +#define SN_NSDL_EP_UPDATE_MESSAGE 2 + +#define SN_NSDL_MSG_UNDEFINED 0 +#define SN_NSDL_MSG_REGISTER 1 +#define SN_NSDL_MSG_UNREGISTER 2 +#define SN_NSDL_MSG_UPDATE 3 + +#include "sn_nsdl_stub.h" + +sn_nsdl_stub_def sn_nsdl_stub; + +int8_t sn_nsdl_destroy(struct nsdl_s *handle) +{ + return sn_nsdl_stub.expectedInt8; +} + +struct nsdl_s *sn_nsdl_init(uint8_t (*sn_nsdl_tx_cb)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *), + uint8_t (*sn_nsdl_rx_cb)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *), + void *(*sn_nsdl_alloc)(uint16_t), void (*sn_nsdl_free)(void *)) +{ + return NULL; +} + +uint16_t sn_nsdl_register_endpoint(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr) +{ + return sn_nsdl_stub.expectedUint16; +} + +uint16_t sn_nsdl_unregister_endpoint(struct nsdl_s *handle) +{ + return sn_nsdl_stub.expectedUint16; +} + +uint16_t sn_nsdl_update_registration(struct nsdl_s *handle, uint8_t *lt_ptr, uint8_t lt_len) +{ + return sn_nsdl_stub.expectedUint16; +} + +int8_t sn_nsdl_set_endpoint_location(struct nsdl_s *handle, uint8_t *loc_ptr, uint8_t loc_len) +{ + return sn_nsdl_stub.expectedInt8; +} + +void sn_nsdl_nsp_lost(struct nsdl_s *handle) +{ +} + +int8_t sn_nsdl_is_ep_registered(struct nsdl_s *handle) +{ + return sn_nsdl_stub.expectedInt8; +} + +uint16_t sn_nsdl_send_observation_notification_with_uri_path(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len, + uint8_t *payload_ptr, uint16_t payload_len, + uint8_t *observe_ptr, uint8_t observe_len, + sn_coap_msg_type_e message_type, + uint8_t content_type, + uint8_t *uri_path_ptr, + uint16_t uri_path_len) +{ + return sn_nsdl_stub.expectedUint16; +} + +uint16_t sn_nsdl_send_observation_notification(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len, + uint8_t *payload_ptr, uint16_t payload_len, + uint8_t *observe_ptr, uint8_t observe_len, + sn_coap_msg_type_e message_type, + uint8_t content_type) +{ + return sn_nsdl_stub.expectedUint16; +} + +/* * * * * * * * * * */ +/* ~ OMA functions ~ */ +/* * * * * * * * * * */ + +uint16_t sn_nsdl_oma_bootstrap(struct nsdl_s *handle, sn_nsdl_addr_s *bootstrap_address_ptr, sn_nsdl_ep_parameters_s *endpoint_info_ptr, sn_nsdl_bs_ep_info_t *bootstrap_endpoint_info_ptr) +{ + return sn_nsdl_stub.expectedUint16; +} + +omalw_certificate_list_t *sn_nsdl_get_certificates(struct nsdl_s *handle) +{ + return NULL; +} + +int8_t sn_nsdl_update_certificates(struct nsdl_s *handle, omalw_certificate_list_t *certificate_ptr, uint8_t certificate_chain) +{ + return sn_nsdl_stub.expectedInt8; +} + +int8_t sn_nsdl_create_oma_device_object(struct nsdl_s *handle, sn_nsdl_oma_device_t *device_object_ptr) +{ + return sn_nsdl_stub.expectedInt8; +} + +char *sn_nsdl_get_version(void) +{ + return NULL; +} + + +int8_t sn_nsdl_process_coap(struct nsdl_s *handle, uint8_t *packet_ptr, uint16_t packet_len, sn_nsdl_addr_s *src_ptr) +{ + return sn_nsdl_stub.expectedInt8; +} + +int8_t sn_nsdl_exec(struct nsdl_s *handle, uint32_t time) +{ + return sn_nsdl_stub.expectedInt8; +} + +sn_nsdl_resource_info_s *sn_nsdl_get_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path_ptr) +{ + return NULL; +} + +int8_t sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration) +{ + if( sn_nsdl_stub.allocatePayloadPtr && message_ptr && handle){ + message_ptr->payload_ptr = handle->sn_nsdl_alloc(2); + message_ptr->payload_len = 2; + } + return sn_nsdl_stub.expectedInt8; +} + +int8_t set_NSP_address(struct nsdl_s *handle, uint8_t *NSP_address, uint16_t port, sn_nsdl_addr_type_e address_type) +{ + return sn_nsdl_stub.expectedInt8; +} + +int8_t sn_nsdl_process_oma_tlv(struct nsdl_s *handle, uint8_t *data_ptr, uint16_t data_len) +{ + return sn_nsdl_stub.expectedInt8; +} + +/* Wrapper */ +sn_grs_resource_list_s *sn_nsdl_list_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path) +{ + return NULL; +} + +void sn_nsdl_free_resource_list(struct nsdl_s *handle, sn_grs_resource_list_s *list) +{ +} + +extern int8_t sn_nsdl_update_resource(struct nsdl_s *handle, sn_nsdl_resource_info_s *res) +{ + return sn_nsdl_stub.expectedInt8; +} + +extern int8_t sn_nsdl_send_coap_message(struct nsdl_s *handle, sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr) +{ + return sn_nsdl_stub.expectedInt8; +} + +extern int8_t sn_nsdl_create_resource(struct nsdl_s *handle, sn_nsdl_resource_info_s *res) +{ + return sn_nsdl_stub.expectedInt8; +} + +extern int8_t sn_nsdl_delete_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path) +{ + return sn_nsdl_stub.expectedInt8; +} + +extern const sn_nsdl_resource_info_s *sn_nsdl_get_first_resource(struct nsdl_s *handle) +{ + return NULL; +} + +extern const sn_nsdl_resource_info_s *sn_nsdl_get_next_resource(struct nsdl_s *handle, const sn_nsdl_resource_info_s *resource) +{ + return NULL; +} + +extern sn_coap_hdr_s *sn_nsdl_build_response(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code) +{ + return NULL; +} + +extern void sn_nsdl_release_allocated_coap_msg_mem(struct nsdl_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr) +{ +} diff --git a/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_nsdl_stub.h b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_nsdl_stub.h new file mode 100644 index 0000000000..33bedeee21 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/test/nsdl-c/unittest/stubs/sn_nsdl_stub.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 __SN_NSDL_STUB_H__ +#define __SN_NSDL_STUB_H__ + +typedef struct { + int8_t expectedInt8; + uint16_t expectedUint16; + bool allocatePayloadPtr; +}sn_nsdl_stub_def; + +extern sn_nsdl_stub_def sn_nsdl_stub; + +#endif //__SN_NSDL_STUB_H__ diff --git a/features/FEATURE_CLIENT/mbed-client-c/unittest/test_libCoap/Test.c b/features/FEATURE_CLIENT/mbed-client-c/unittest/test_libCoap/Test.c new file mode 100644 index 0000000000..74bc6898ca --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/unittest/test_libCoap/Test.c @@ -0,0 +1,622 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 \test_libCoap\Test.c + * + * \brief Unit tests for libCoap + */ +#include "ns_types.h" +#include "sn_nsdl.h" +#include "sn_coap_header.h" +#include "sn_coap_protocol.h" +#include "sn_coap_header_internal.h" + +#include "unity.h" +#include "string.h" +#include "stdlib.h" + +static uint8_t *message_ptr = 0; +static uint16_t message_len = 0; +static sn_coap_hdr_s coap_header; +sn_nsdl_addr_s coap_address; +static uint8_t address[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; + +/* CoAP parameters to be used */ +static uint8_t option_short[3] = {0x61, 0x62, 0x63}; +static uint8_t option_path[5] = {0x62, 0x63, 0x2f, 0x61, 0x62}; +static uint8_t option_30[30]; +static uint8_t option_300[300]; +static uint8_t option_600[600]; +static uint8_t option_800[800]; + +/* Resultat sju rätt är: */ +static uint8_t coap_message_no_options[4] = {0x60, 0x44, 0x12, 0x34}; +static uint8_t coap_message_token_payload[11] = {0x63, 0x44, 0x12, 0x34, 0x61, 0x62, 0x63, 0xff, 0x61, 0x62, 0x63}; +static uint8_t coap_message_wrong_version[4] = {0xe0, 0x44, 0x12, 0x34}; +static uint8_t coap_message_malformed[4] = {0x60, 0xae, 0x43, 0x11}; +static uint8_t coap_message_option_short[9] = {0x60, 0x44, 0x12, 0x34, 0xd3, 0x16, 0x61, 0x62, 0x63}; // option number 35 +static uint8_t coap_message_option_30[7] = {0x60, 0x44, 0x12, 0x34, 0xdd, 0x16, 0x11}; // option number 35, length 30 +static uint8_t coap_message_option_300[8] = {0x60, 0x44, 0x12, 0x34, 0xde, 0x16, 0x00, 0x1f}; // option number 35, length 300 +static uint8_t coap_message_option_600[8] = {0x60, 0x44, 0x12, 0x34, 0xde, 0x16, 0x01, 0x4b}; // option number 35, length 600 +static uint8_t coap_message_option_800[8] = {0x60, 0x44, 0x12, 0x34, 0xde, 0x16, 0x02, 0x13}; // option number 35, length 800 +/* Options = Token - 3 bytes, max age - 14 - 3 bytes, Uri path - 11 - 2 x 2 bytes, Uri host - 3 - 3 bytes */ +static uint8_t coap_message_multiple_options[21] = {0x63, 0x44, 0x12, 0x34, 0x61, 0x62, 0x63, 0x33, 0x61, 0x62, 0x63, 0x82, 0x62, 0x63, 0x02, 0x61, 0x62, 0x33, 0x61, 0x62, 0x63}; + +static uint8_t coap_message_empty_con[4] = {0x40, 0x00, 0x12, 0x34}; +static uint8_t coap_message_wrong_code_1[4] = {0x40, 0x24, 0x12, 0x34}; +static uint8_t coap_message_wrong_code_6[4] = {0x40, 0xc4, 0x12, 0x34}; +static uint8_t coap_message_wrong_code_7[4] = {0x40, 0xe4, 0x12, 0x34}; + + +void *own_alloc(uint16_t size); +void own_free(void *ptr); + +struct coap_s *handle; + +uint8_t tx_function(uint8_t *data_ptr, uint16_t data_len, sn_nsdl_addr_s *address_ptr, void *param); +int8_t rx_callback(sn_coap_hdr_s *coap_header_ptr, sn_nsdl_addr_s *address_ptr, void *param); + +/* non-test function declarations */ +void fill_with_random(uint8_t *ptr, uint16_t len); + +/* Unity test code starts */ +void setUp(void) +{ + //This is run before EACH TEST + +} + +void tearDown(void) +{ + +} + +void test_libcoap_init(void) +{ + handle = sn_coap_protocol_init(&own_alloc, &own_free, &tx_function, &rx_callback); + + TEST_ASSERT_NOT_NULL(handle); +} + + +/** + * \fn test_libcoap_builder_no_options(void) + * + * \brief Build CoAP message - ACK - Changed + * + */ +void test_libcoap_builder_no_options(void) +{ + memset(&coap_header, 0, sizeof(sn_coap_hdr_s)); + coap_header.msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + coap_header.msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; + coap_header.msg_id = 0x1234; + + coap_header.options_list_ptr = malloc(sizeof(sn_coap_options_list_s)); + memset(coap_header.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + + message_len = sn_coap_builder_calc_needed_packet_data_size(&coap_header); + message_ptr = malloc(message_len); + sn_coap_builder(message_ptr, &coap_header); + + TEST_ASSERT_EQUAL(sizeof(coap_message_no_options), message_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(coap_message_no_options, message_ptr, sizeof(coap_message_no_options)); + + free(message_ptr); + message_ptr = 0; +} + +/** + * \fn test_libcoap_builder_token_and_payload(void) + * + * \brief Build CoAP message - ACK - changed - token - payload + * + */ +void test_libcoap_builder_token_and_payload(void) +{ + memset(&coap_header, 0, sizeof(sn_coap_hdr_s)); + coap_header.msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + coap_header.msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; + coap_header.msg_id = 0x1234; + coap_header.token_len = sizeof(option_short); + coap_header.token_ptr = option_short; + coap_header.payload_len = sizeof(option_short); + coap_header.payload_ptr = option_short; + + coap_header.options_list_ptr = malloc(sizeof(sn_coap_options_list_s)); + memset(coap_header.options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + + message_len = sn_coap_builder_calc_needed_packet_data_size(&coap_header); + message_ptr = malloc(message_len); + sn_coap_builder(message_ptr, &coap_header); + + TEST_ASSERT_EQUAL(sizeof(coap_message_token_payload), message_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(coap_message_token_payload, message_ptr, sizeof(coap_message_token_payload)); + + free(message_ptr); + message_ptr = 0; +} + +/** + * \fn test_libcoap_builder_short_option(void) + * + * \brief Build CoAP message - ACK - changed - short proxy URI option + * + */ +void test_libcoap_builder_short_option(void) +{ + coap_header.token_len = 0; + coap_header.token_ptr = 0; + coap_header.payload_len = 0; + coap_header.payload_ptr = 0; + + coap_header.options_list_ptr->proxy_uri_len = sizeof(option_short); + coap_header.options_list_ptr->proxy_uri_ptr = option_short; + + message_len = sn_coap_builder_calc_needed_packet_data_size(&coap_header); + message_ptr = malloc(message_len); + sn_coap_builder(message_ptr, &coap_header); + + TEST_ASSERT_EQUAL(sizeof(coap_message_option_short), message_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(coap_message_option_short, message_ptr, sizeof(coap_message_option_short)); + + free(message_ptr); + message_ptr = 0; +} + +/** + * \fn test_libcoap_builder_option_30(void) + * + * \brief Build CoAP message - ACK - changed - proxy URI option, length 30 bytes + * + */ +void test_libcoap_builder_option_30(void) +{ + fill_with_random(option_30, sizeof(option_30)); + coap_header.options_list_ptr->proxy_uri_len = sizeof(option_30); + coap_header.options_list_ptr->proxy_uri_ptr = option_30; + + message_len = sn_coap_builder_calc_needed_packet_data_size(&coap_header); + message_ptr = malloc(message_len); + sn_coap_builder(message_ptr, &coap_header); + + TEST_ASSERT_EQUAL((sizeof(coap_message_option_30) + sizeof(option_30)), message_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(coap_message_option_30, message_ptr, sizeof(coap_message_option_30)); + + free(message_ptr); + message_ptr = 0; + +} + +/** + * \fn test_libcoap_builder_option_300(void) + * + * \brief Build CoAP message - ACK - changed - proxy URI option, length 300 bytes + * + */ +void test_libcoap_builder_option_300(void) +{ + fill_with_random(option_300, sizeof(option_300)); + coap_header.options_list_ptr->proxy_uri_len = sizeof(option_300); + coap_header.options_list_ptr->proxy_uri_ptr = option_300; + + message_len = sn_coap_builder_calc_needed_packet_data_size(&coap_header); + message_ptr = malloc(message_len); + sn_coap_builder(message_ptr, &coap_header); + + TEST_ASSERT_EQUAL(sizeof(coap_message_option_300) + sizeof(option_300), message_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(coap_message_option_300, message_ptr, sizeof(coap_message_option_300)); + + free(message_ptr); + message_ptr = 0; +} + +/** + * \fn test_libcoap_builder_option_600(void) + * + * \brief Build CoAP message - ACK - changed - proxy URI option, length 600 bytes + * + */ + +void test_libcoap_builder_option_600(void) +{ + fill_with_random(option_600, sizeof(option_600)); + coap_header.options_list_ptr->proxy_uri_len = sizeof(option_600); + coap_header.options_list_ptr->proxy_uri_ptr = option_600; + + message_len = sn_coap_builder_calc_needed_packet_data_size(&coap_header); + message_ptr = malloc(message_len); + sn_coap_builder(message_ptr, &coap_header); + + TEST_ASSERT_EQUAL(sizeof(coap_message_option_600) + sizeof(option_600), message_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(coap_message_option_600, message_ptr, sizeof(coap_message_option_600)); + + free(message_ptr); + message_ptr = 0; +} + +/** + * \fn test_libcoap_builder_option_800(void) + * + * \brief Build CoAP message - ACK - changed - proxy URI option, length 800 bytes + * + */ +void test_libcoap_builder_option_800(void) +{ + fill_with_random(option_800, sizeof(option_800)); + coap_header.options_list_ptr->proxy_uri_len = sizeof(option_800); + coap_header.options_list_ptr->proxy_uri_ptr = option_800; + + message_len = sn_coap_builder_calc_needed_packet_data_size(&coap_header); + message_ptr = malloc(message_len); + sn_coap_builder(message_ptr, &coap_header); + + TEST_ASSERT_EQUAL(sizeof(coap_message_option_800) + sizeof(option_800), message_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(coap_message_option_800, message_ptr, sizeof(coap_message_option_800)); + + free(message_ptr); + message_ptr = 0; +} + +/** + * \fn test_libcoap_builder_message_with_multiple_options(void) + * + * \brief Build CoAP message - ACK - changed - URI host - URI path - max age - token + * + */ +void test_libcoap_builder_message_with_multiple_options(void) +{ + coap_header.options_list_ptr->proxy_uri_len = 0; + coap_header.options_list_ptr->proxy_uri_ptr = 0; + + coap_header.options_list_ptr->uri_host_len = sizeof(option_short); + coap_header.options_list_ptr->uri_host_ptr = option_short; + + coap_header.uri_path_len = sizeof(option_path); + coap_header.uri_path_ptr = option_path; + + coap_header.options_list_ptr->max_age_len = sizeof(option_short); + coap_header.options_list_ptr->max_age_ptr = option_short; + + coap_header.token_len = sizeof(option_short); + coap_header.token_ptr = option_short; + + message_len = sn_coap_builder_calc_needed_packet_data_size(&coap_header); + message_ptr = malloc(message_len); + sn_coap_builder(message_ptr, &coap_header); + + TEST_ASSERT_EQUAL(sizeof(coap_message_multiple_options), message_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(coap_message_multiple_options, message_ptr, sizeof(coap_message_multiple_options)); + + free(message_ptr); + message_ptr = 0; +} + +/*******************************************************************************/ +/*** CoAP PARSER TEST ***/ +/*******************************************************************************/ + +/** + * \fn test_libcoap_parser_parse_message_without_options(void) + * + * \brief call coap protocol parser with message without options (ACK - changed) + * + */ +void test_libcoap_parser_parse_message_without_options(void) +{ + coap_address.addr_ptr = address; + + sn_coap_hdr_s *coap_header_ptr = sn_coap_protocol_parse(handle, &coap_address, sizeof(coap_message_no_options), coap_message_no_options, NULL); + + TEST_ASSERT_NOT_NULL(coap_header_ptr); + + TEST_ASSERT_EQUAL(COAP_MSG_TYPE_ACKNOWLEDGEMENT, coap_header_ptr->msg_type); + TEST_ASSERT_EQUAL(COAP_MSG_CODE_RESPONSE_CHANGED, coap_header_ptr->msg_code); + TEST_ASSERT_EQUAL(0x1234, coap_header_ptr->msg_id); + + sn_coap_parser_release_allocated_coap_msg_mem(handle, coap_header_ptr); +} + +/** + * \fn test_libcoap_parser_parse_message_with_payload_and_token(void) + * + * \brief call coap protocol parser with message with token option and small payload (ACK - changed) + * + */ +void test_libcoap_parser_parse_message_with_payload_and_token(void) +{ + coap_address.addr_ptr = address; + + sn_coap_hdr_s *coap_header_ptr = sn_coap_protocol_parse(handle, &coap_address, sizeof(coap_message_token_payload), coap_message_token_payload, NULL); + + TEST_ASSERT_NOT_NULL(coap_header_ptr); + + TEST_ASSERT_EQUAL(COAP_MSG_TYPE_ACKNOWLEDGEMENT, coap_header_ptr->msg_type); + TEST_ASSERT_EQUAL(COAP_MSG_CODE_RESPONSE_CHANGED, coap_header_ptr->msg_code); + TEST_ASSERT_EQUAL(0x1234, coap_header_ptr->msg_id); + + TEST_ASSERT_EQUAL(3, coap_header_ptr->token_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(option_short, coap_header_ptr->token_ptr, sizeof(option_short)); + + TEST_ASSERT_EQUAL(3, coap_header_ptr->payload_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(option_short, coap_header_ptr->payload_ptr, sizeof(option_short)); + + sn_coap_parser_release_allocated_coap_msg_mem(handle, coap_header_ptr); +} + +/** + * \fn test_libcoap_parser_parse_message_with_small_option(void) + * + * \brief call coap protocol parser with message with small option (ACK - changed - URI query) + * + */ +void test_libcoap_parser_parse_message_with_small_option(void) +{ + coap_address.addr_ptr = address; + + sn_coap_hdr_s *coap_header_ptr = sn_coap_protocol_parse(handle, &coap_address, sizeof(coap_message_option_short), coap_message_option_short, NULL); + + TEST_ASSERT_NOT_NULL(coap_header_ptr); + TEST_ASSERT_NOT_NULL(coap_header_ptr->options_list_ptr); + + TEST_ASSERT_EQUAL(COAP_MSG_TYPE_ACKNOWLEDGEMENT, coap_header_ptr->msg_type); + TEST_ASSERT_EQUAL(COAP_MSG_CODE_RESPONSE_CHANGED, coap_header_ptr->msg_code); + TEST_ASSERT_EQUAL(0x1234, coap_header_ptr->msg_id); + + TEST_ASSERT_EQUAL(sizeof(option_short), coap_header_ptr->options_list_ptr->proxy_uri_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(option_short, coap_header_ptr->options_list_ptr->proxy_uri_ptr, sizeof(option_short)); + + sn_coap_parser_release_allocated_coap_msg_mem(handle, coap_header_ptr); +} + + +/** + * \fn test_libcoap_parser_parse_message_with_multiple_options(void) + * + * \brief call coap protocol parser with message with multiple options (ACK - changed - token - max age - URI path - URI host) + * + */ +void test_libcoap_parser_parse_message_with_multiple_options(void) +{ + coap_address.addr_ptr = address; + + sn_coap_hdr_s *coap_header_ptr = sn_coap_protocol_parse(handle, &coap_address, sizeof(coap_message_multiple_options), coap_message_multiple_options, NULL); + + TEST_ASSERT_NOT_NULL(coap_header_ptr); + TEST_ASSERT_NOT_NULL(coap_header_ptr->options_list_ptr); + + TEST_ASSERT_EQUAL(COAP_MSG_TYPE_ACKNOWLEDGEMENT, coap_header_ptr->msg_type); + TEST_ASSERT_EQUAL(COAP_MSG_CODE_RESPONSE_CHANGED, coap_header_ptr->msg_code); + TEST_ASSERT_EQUAL(0x1234, coap_header_ptr->msg_id); + + + TEST_ASSERT_EQUAL(sizeof(option_short), coap_header_ptr->options_list_ptr->uri_host_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(option_short, coap_header_ptr->options_list_ptr->uri_host_ptr, sizeof(option_short)); + + TEST_ASSERT_EQUAL(sizeof(option_path), coap_header_ptr->uri_path_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(option_path, coap_header_ptr->uri_path_ptr, sizeof(option_path)); + + TEST_ASSERT_EQUAL(sizeof(option_short), coap_header_ptr->options_list_ptr->max_age_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(option_short, coap_header_ptr->options_list_ptr->max_age_ptr, sizeof(option_short)); + + TEST_ASSERT_EQUAL(sizeof(option_short), coap_header_ptr->token_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(option_short, coap_header_ptr->token_ptr, sizeof(option_short)); + + + sn_coap_parser_release_allocated_coap_msg_mem(handle, coap_header_ptr); +} + +/*******************************************************************************/ +/*** NEGATIVE TEST CASES ***/ +/*******************************************************************************/ + +/** + * \fn test_libcoap_negative_build_with_null_pointer(void) + * + * \brief - Call sn_coap_builder_calc_needed_packet_data_size with null pointer parameter + * - Call sn_coap_builder with null pointer parameter + * + */ +void test_libcoap_negative_build_with_null_pointer(void) +{ + int16_t ret_val_1 = 0; + int16_t ret_val_2 = 0; + + message_len = sn_coap_builder_calc_needed_packet_data_size(NULL); + ret_val_1 = sn_coap_builder(message_ptr, NULL); + ret_val_2 = sn_coap_builder(NULL, &coap_header); + + TEST_ASSERT_EQUAL(0, message_len); + TEST_ASSERT_EQUAL(-2, ret_val_1); + TEST_ASSERT_EQUAL(-2, ret_val_2); +} + +/** + * \fn test_libcoap_negative_parse_with_null_pointer(void) + * + * \brief - Call sn_coap_protocol_parse with null pointer parameter + * + */ +void test_libcoap_negative_parse_with_null_pointer(void) +{ + coap_address.addr_ptr = address; + + sn_coap_hdr_s *coap_header_ptr = sn_coap_protocol_parse(handle, NULL, sizeof(coap_message_no_options), coap_message_no_options, NULL); + TEST_ASSERT_NULL(coap_header_ptr); + + coap_header_ptr = sn_coap_protocol_parse(NULL, &coap_address, sizeof(coap_message_no_options), coap_message_no_options, NULL); + TEST_ASSERT_NULL(coap_header_ptr); + + coap_header_ptr = sn_coap_protocol_parse(handle, &coap_address, sizeof(coap_message_no_options), NULL, NULL); + TEST_ASSERT_NULL(coap_header_ptr); +} + +/** + * \fn test_libcoap_negative_parse_with_coap_packet_len_null(void) + * + * \brief - Call sn_coap_protocol_parse with parameter length = 0 + * + */ +void test_libcoap_negative_parse_with_coap_packet_len_null(void) +{ + coap_address.addr_ptr = address; + + sn_coap_hdr_s *coap_header_ptr = sn_coap_protocol_parse(handle, &coap_address, 0, coap_message_no_options, NULL); + TEST_ASSERT_NULL(coap_header_ptr); +} + +/** + * \fn test_libcoap_negative_parse_with_wrong_coap_packet_len(void) + * + * \brief - Call sn_coap_protocol_parse with wrong packet length + * + */ +void test_libcoap_negative_parse_with_wrong_coap_packet_len(void) +{ + coap_address.addr_ptr = address; + + sn_coap_hdr_s *coap_header_ptr = sn_coap_protocol_parse(handle, &coap_address, (sizeof(coap_message_multiple_options) - 1), coap_message_multiple_options, NULL); + TEST_ASSERT_NULL(coap_header_ptr); +} + +/** + * \fn test_libcoap_negative_parse_with_wrong_coap_version(void) + * + * \brief - Call sn_coap_protocol_parse with wrong CoAP version + * + */ +void test_libcoap_negative_parse_with_wrong_coap_version(void) +{ + coap_address.addr_ptr = address; + + sn_coap_hdr_s *coap_header_ptr = sn_coap_protocol_parse(handle, &coap_address, sizeof(coap_message_wrong_version), coap_message_wrong_version, NULL); + TEST_ASSERT_NULL(coap_header_ptr); +} + +/** + * \fn test_libcoap_negative_parse_malformed_coap(void) + * + * \brief - Call sn_coap_protocol_parse with malformed CoAP message + * + */ +void test_libcoap_negative_parse_malformed_coap(void) +{ + coap_address.addr_ptr = address; + + sn_coap_hdr_s *coap_header_ptr = sn_coap_protocol_parse(handle, &coap_address, sizeof(coap_message_malformed), coap_message_malformed, NULL); + TEST_ASSERT_NULL(coap_header_ptr); +} + +/** + * \fn test_libcoap_negative_parse_empty_con(void) + * + * \brief - Call sn_coap_protocol_parse with "CoAP ping" message. Should return RST + * + */ +void test_libcoap_negative_parse_empty_con(void) +{ + coap_address.addr_ptr = address; + + sn_coap_hdr_s *coap_header_ptr = sn_coap_protocol_parse(handle, &coap_address, sizeof(coap_message_empty_con), coap_message_empty_con, NULL); + TEST_ASSERT_NULL(coap_header_ptr); + +} + +/** + * \fn test_libcoap_negative_parse_wrong_code_1(void) + * + * \brief - Call sn_coap_protocol_parse with wrong message code. Should return RST + * + */ +void test_libcoap_negative_parse_wrong_code_1(void) +{ + coap_address.addr_ptr = address; + + sn_coap_hdr_s *coap_header_ptr = sn_coap_protocol_parse(handle, &coap_address, sizeof(coap_message_wrong_code_1), coap_message_wrong_code_1, NULL); + TEST_ASSERT_NULL(coap_header_ptr); + +} + +/** + * \fn test_libcoap_negative_parse_wrong_code_6(void) + * + * \brief - Call sn_coap_protocol_parse with wrong message code. Should return RST + * + */ +void test_libcoap_negative_parse_wrong_code_6(void) +{ + coap_address.addr_ptr = address; + + sn_coap_hdr_s *coap_header_ptr = sn_coap_protocol_parse(handle, &coap_address, sizeof(coap_message_wrong_code_6), coap_message_wrong_code_6, NULL); + TEST_ASSERT_NULL(coap_header_ptr); + +} + +/** + * \fn test_libcoap_negative_parse_wrong_code_7(void) + * + * \brief - Call sn_coap_protocol_parse with wrong message code. Should return RST + * + */ +void test_libcoap_negative_parse_wrong_code_7(void) +{ + coap_address.addr_ptr = address; + + sn_coap_hdr_s *coap_header_ptr = sn_coap_protocol_parse(handle, &coap_address, sizeof(coap_message_wrong_code_7), coap_message_wrong_code_7, NULL); + TEST_ASSERT_NULL(coap_header_ptr); + +} + + +/*******************************/ +/*** non-test functions ***/ +/*******************************/ + +void fill_with_random(uint8_t *ptr, uint16_t len) +{ + while (len--) { + *(ptr + len) = 'a'; + } +} + +void *own_alloc(uint16_t size) +{ + return malloc(size); +} + +void own_free(void *ptr) +{ + free(ptr); +} + +uint8_t tx_function(uint8_t *data_ptr, uint16_t data_len, sn_nsdl_addr_s *address_ptr, void *param) +{ + return 0; +} + +int8_t rx_callback(sn_coap_hdr_s *coap_header_ptr, sn_nsdl_addr_s *address_ptr, void *param) +{ + return 0; +} + + + + + + + + + diff --git a/features/FEATURE_CLIENT/mbed-client-c/unittest/test_libCoap/makefile b/features/FEATURE_CLIENT/mbed-client-c/unittest/test_libCoap/makefile new file mode 100644 index 0000000000..f762fc6992 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/unittest/test_libCoap/makefile @@ -0,0 +1,31 @@ +# ========================================== +# Unity Project - A Test Framework for C +# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +# [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +C_COMPILER=gcc +TARGET_BASE=test_libCoap +TARGET_EXTENSION=.out +TARGET = $(TARGET_BASE)$(TARGET_EXTENSION) + +SRC_FILES=../../../unittest/src/unity.c ../../source/libCoap/src/sn_coap_protocol.c ../../source/libCoap/src/sn_coap_parser.c \ +../../source/libCoap/src/sn_coap_header_check.c ../../source/libCoap/src/sn_coap_builder.c ../../../libService/source/libList/ns_list.c \ +Test.c Test_Runner.c + +INC_DIRS=-I../../../unittest/src -I../../nsdl-c/ -I../../source/libCoap/src/include -I../../../libService/libService + +SYMBOLS=-DTEST -std=gnu99 -DUNITY_EXCLUDE_STDINT_H + +CLEANUP = rm -f build/*.o ; rm -f $(TARGET) + +all: clean default + +default: + ruby ../../../unittest/auto/generate_test_runner.rb Test.c Test_Runner.c + $(C_COMPILER) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES) -o $(TARGET) + ./$(TARGET) + +clean: + $(CLEANUP) + diff --git a/features/FEATURE_CLIENT/mbed-client-c/unittest/test_libNsdl/Test.c b/features/FEATURE_CLIENT/mbed-client-c/unittest/test_libNsdl/Test.c new file mode 100644 index 0000000000..135ba69f39 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/unittest/test_libNsdl/Test.c @@ -0,0 +1,676 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 \test_libNsdl\Test.c + * + * \brief Unit tests for libNsdl + * NOTE!! Needs libCoap.a from ../../nsdl-c/libCoap/x86_gcc + * + * */ + +#include "ns_types.h" + +#include "sn_nsdl.h" +#include "sn_coap_header.h" +#include "sn_coap_protocol.h" +#include "sn_nsdl_lib.h" + +#include "unity.h" +#include "string.h" +#include "stdlib.h" + +/* non-test function declarations */ +void fill_with_random(uint8_t *ptr, uint16_t len); +void *own_alloc(uint16_t size); +void own_free(void *ptr); +uint8_t nsdl_tx_dummy(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *); +uint8_t nsdl_rx_dummy(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *); +uint8_t dynamic_callback(struct nsdl_s *handle, sn_coap_hdr_s *coap_header_ptr, sn_nsdl_addr_s *address_ptr, sn_nsdl_capab_e protocol); +static void init_temp_variables(void); + +static uint8_t res1_path[] = {"test/res1"}; +static uint8_t res1_content[] = {"res1 content"}; + +static uint8_t res2_path[] = {"test/res2"}; +static uint8_t res2_content[] = {"res2 content"}; + +static uint8_t res3_path[] = {"test/res3"}; +static uint8_t res3_content[] = {"res3 content"}; + +static uint8_t res4_path[] = {"test/res4"}; +static uint8_t res4_content[] = {"res4 content"}; + +static uint8_t res5_path[] = {"test/res5"}; +static uint8_t res5_content[] = {"res5 content"}; + +static uint8_t res_negative_path[] = {"test/negative"}; +static uint8_t res_negative_content[] = {"negative_test content"}; + +static uint8_t address[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; + +/* Change byte 13 to differend resources */ +static uint8_t get_message[14] = {0x40, 0x01, 0x12, 0x34, 0xb4, 0x74, 0x65, 0x73, 0x74, 0x04, 0x72, 0x65, 0x73, 0x31}; +static uint8_t put_message[18] = {0x40, 0x03, 0x12, 0x34, 0xb4, 0x74, 0x65, 0x73, 0x74, 0x04, 0x72, 0x65, 0x73, 0x32, 0xff, 0x61, 0x62, 0x63}; +static uint8_t post_message[18] = {0x40, 0x02, 0x12, 0x34, 0xb4, 0x74, 0x65, 0x73, 0x74, 0x04, 0x72, 0x65, 0x73, 0x33, 0xff, 0x61, 0x62, 0x63}; +static uint8_t delete_message[14] = {0x40, 0x04, 0x12, 0x34, 0xb4, 0x74, 0x65, 0x73, 0x74, 0x04, 0x72, 0x65, 0x73, 0x34}; + +static uint8_t message_payload[3] = {0x61, 0x62, 0x63}; + +static uint8_t get_response[17] = {0x60, 0x45, 0x12, 0x34, 0xff, 0x72, 0x65, 0x73, 0x31, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74}; +static uint8_t response_not_allowed[4] = {0x60, 0x85, 0x12, 0x34}; +static uint8_t response_changed[4] = {0x60, 0x44, 0x12, 0x34}; +static uint8_t response_created[4] = {0x60, 0x41, 0x12, 0x34}; +static uint8_t response_deleted[4] = {0x60, 0x42, 0x12, 0x34}; + +#define NSP_PORT 5683 + +#define NSP_REGISTRATION_MESSAGE_LEN 72 +static uint8_t registration_message[NSP_REGISTRATION_MESSAGE_LEN] = { + 0x40, 0x02, 0x01, 0x47, 0xb2, 0x72, 0x64, 0xff, 0x3c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x72, + 0x65, 0x73, 0x35, 0x3e, 0x2c, 0x3c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x72, 0x65, 0x73, 0x34, + 0x3e, 0x2c, 0x3c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x72, 0x65, 0x73, 0x33, 0x3e, 0x2c, 0x3c, + 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x72, 0x65, 0x73, 0x32, 0x3e, 0x2c, 0x3c, 0x2f, 0x74, 0x65, + 0x73, 0x74, 0x2f, 0x72, 0x65, 0x73, 0x31, 0x3e +}; + +static uint16_t message_temp_len = 0; +static uint8_t *message_temp_ptr = 0; +static sn_nsdl_addr_s *address_temp_ptr = 0; + +struct nsdl_s *handle; + +/* Unity test code starts */ +void setUp(void) +{ + //This is run before EACH TEST + +} + +void tearDown(void) +{ + +} + +/** + * \fn void test_libnsdl_init(void) + * + * \brief Tests sn_nsdl_init - function. Function must return failure (-1) if initialization fails. + * + * Negative test cases: + * - Memory structure contains null pointer(s) + * - One of the parameter is null + * + */ +void test_libnsdl_init(void) +{ + /* Memory struct contains null */ + handle = sn_nsdl_init(&nsdl_tx_dummy, &nsdl_rx_dummy, NULL, NULL); + TEST_ASSERT_NULL(handle); + + handle = sn_nsdl_init(&nsdl_tx_dummy, &nsdl_rx_dummy, &own_alloc, NULL); + TEST_ASSERT_NULL(handle); + + handle = sn_nsdl_init(&nsdl_tx_dummy, &nsdl_rx_dummy, NULL, &own_free); + TEST_ASSERT_NULL(handle); + + /* One of parameters is null */ + handle = sn_nsdl_init(NULL, &nsdl_rx_dummy, &own_alloc, &own_free); + TEST_ASSERT_NULL(handle); + + handle = sn_nsdl_init(&nsdl_tx_dummy, NULL, &own_alloc, &own_free); + TEST_ASSERT_NULL(handle); + + /* OK case */ + handle = sn_nsdl_init(&nsdl_tx_dummy, &nsdl_rx_dummy, &own_alloc, &own_free); + TEST_ASSERT_NOT_NULL(handle); +} + +/** + * \fn void test_libnsdl_create_resource(void) + * + * \brief Tests sn_nsdl_create_resource - function. Creates five resources. + * + * STATIC RESOURCES: + * - Resource 1 + * * Get allowed + * - Resource 2 + * * Put allowed + * - Resource 3 + * * Post allowed + * - Resource 4 + * * Delete allowed + * + * DYNAMIC RESOURCES: + * - Resource 5 + * * All allowed + * + * Negative test cases: + * - Resource already exists + * - Null pointer as a parameter + * + */ +void test_libnsdl_create_resource(void) +{ + sn_nsdl_resource_info_s resource; + sn_nsdl_resource_parameters_s resource_parameters; + int8_t ret_val; + + memset(&resource, 0, sizeof(sn_nsdl_resource_info_s)); + memset(&resource_parameters, 0, sizeof(sn_nsdl_resource_parameters_s)); + + + /* Resource 1*/ + resource.access = SN_GRS_GET_ALLOWED; + resource.mode = SN_GRS_STATIC; + resource.path = res1_path; + resource.pathlen = sizeof(res1_path) - 1; + resource.resource = res1_content; + resource.resourcelen = sizeof(res1_content) - 1; + resource.resource_parameters_ptr = &resource_parameters; + + ret_val = sn_nsdl_create_resource(handle, &resource); + TEST_ASSERT_EQUAL(0, ret_val); + + + /* Resource 2 */ + resource.access = SN_GRS_PUT_ALLOWED; + resource.path = res2_path; + resource.pathlen = sizeof(res2_path) - 1; + resource.resource = res2_content; + resource.resourcelen = sizeof(res2_content) - 1; + + ret_val = sn_nsdl_create_resource(handle, &resource); + TEST_ASSERT_EQUAL(0, ret_val); + + + /* Resource 3 */ + resource.access = SN_GRS_POST_ALLOWED; + resource.path = res3_path; + resource.pathlen = sizeof(res3_path) - 1; + resource.resource = res3_content; + resource.resourcelen = sizeof(res3_content) - 1; + + ret_val = sn_nsdl_create_resource(handle, &resource); + TEST_ASSERT_EQUAL(0, ret_val); + + + /* Resource 4 */ + resource.access = SN_GRS_DELETE_ALLOWED; + resource.path = res4_path; + resource.pathlen = sizeof(res4_path) - 1; + resource.resource = res4_content; + resource.resourcelen = sizeof(res4_content) - 1; + + ret_val = sn_nsdl_create_resource(handle, &resource); + TEST_ASSERT_EQUAL(0, ret_val); + + + /* Resource 5 - Dynamic*/ + resource.mode = SN_GRS_DYNAMIC; + + resource.access = 0xFF; + resource.path = res5_path; + resource.pathlen = sizeof(res5_path) - 1; + resource.resource = res5_content; + resource.resourcelen = sizeof(res5_content) - 1; + resource.sn_grs_dyn_res_callback = &dynamic_callback; + + ret_val = sn_nsdl_create_resource(handle, &resource); + TEST_ASSERT_EQUAL(0, ret_val); + + /*** Negative test cases ***/ + + /* Already exists */ + ret_val = sn_nsdl_create_resource(handle, &resource); + TEST_ASSERT_EQUAL(-2, ret_val); + + /* Null pointer */ + ret_val = sn_nsdl_create_resource(handle, NULL); + TEST_ASSERT_EQUAL(-1, ret_val); + + ret_val = sn_nsdl_create_resource(NULL, &resource); + TEST_ASSERT_EQUAL(-1, ret_val); + + resource.path = NULL; + resource.pathlen = sizeof(res_negative_path) - 1; + resource.resource = res_negative_content; + resource.resourcelen = sizeof(res_negative_content) - 1; + + ret_val = sn_nsdl_create_resource(handle, &resource); + TEST_ASSERT_EQUAL(-3, ret_val); + + resource.path = res_negative_path; + resource.pathlen = 0; + + ret_val = sn_nsdl_create_resource(handle, &resource); + TEST_ASSERT_EQUAL(-3, ret_val); + +} + +/** + * \fn test_libnsdl_list_resources(void) + * + * \brief Calls sn_nsdl_list_resource - function + * Function must return list of early created resources + */ + +void test_libnsdl_list_resources(void) +{ + sn_grs_resource_list_s *resource_list_ptr; + + resource_list_ptr = sn_nsdl_list_resource(handle, 0, 0); + + TEST_ASSERT_EQUAL(5, resource_list_ptr->res_count); + + TEST_ASSERT_EQUAL_INT8_ARRAY(resource_list_ptr->res[4].path, res1_path, resource_list_ptr->res[4].pathlen); + TEST_ASSERT_EQUAL_INT8_ARRAY(resource_list_ptr->res[3].path, res2_path, resource_list_ptr->res[3].pathlen); + TEST_ASSERT_EQUAL_INT8_ARRAY(resource_list_ptr->res[2].path, res3_path, resource_list_ptr->res[2].pathlen); + TEST_ASSERT_EQUAL_INT8_ARRAY(resource_list_ptr->res[1].path, res4_path, resource_list_ptr->res[1].pathlen); + TEST_ASSERT_EQUAL_INT8_ARRAY(resource_list_ptr->res[0].path, res5_path, resource_list_ptr->res[0].pathlen); + +} + +/** + * \fn test_libnsdl_get_resource(void) + * + * \brief Calls sn_nsdl_get_resource - function + * Function must return pointer to created resource + * + * Negative test cases: + * - call function with null parameter + * + */ + +void test_libnsdl_get_resource(void) +{ + sn_nsdl_resource_info_s *res_ptr; + + /* With null pointer */ + res_ptr = sn_nsdl_get_resource(handle, 0, res1_path); + TEST_ASSERT_NULL(res_ptr); + + res_ptr = sn_nsdl_get_resource(handle, sizeof(res1_path) - 1, NULL); + TEST_ASSERT_NULL(res_ptr); + + res_ptr = sn_nsdl_get_resource(NULL, sizeof(res1_path) - 1, res1_path); + TEST_ASSERT_NULL(res_ptr); + + /* Ok case, gets resource 1 and checks that path and content are ok */ + res_ptr = sn_nsdl_get_resource(handle, sizeof(res1_path) - 1, res1_path); + TEST_ASSERT_NOT_NULL(res_ptr); + + TEST_ASSERT_EQUAL_INT8_ARRAY(res_ptr->path, res1_path, sizeof(res1_path) - 1); + TEST_ASSERT_EQUAL_INT8_ARRAY(res_ptr->resource, res1_content, sizeof(res1_content) - 1); +} + +/** + * \fn test_libnsdl_set_nsp_address(void) + * + * \brief Sets NSP address to nsdl-library + * + * Negative test cases: + * - call function with null parameter + */ +void test_libnsdl_set_nsp_address(void) +{ + int8_t ret_val = 0; + + /* with null pointer */ + ret_val = set_NSP_address(handle, NULL, NSP_PORT, SN_NSDL_ADDRESS_TYPE_IPV4); + TEST_ASSERT_EQUAL(-1, ret_val); + + ret_val = set_NSP_address(NULL, address, NSP_PORT, SN_NSDL_ADDRESS_TYPE_IPV4); + TEST_ASSERT_EQUAL(-1, ret_val); + + /* OK case */ + ret_val = set_NSP_address(handle, address, NSP_PORT, SN_NSDL_ADDRESS_TYPE_IPV4); + TEST_ASSERT_EQUAL(0, ret_val); +} + +/** + * \fn test_libnsdl_register(void) + * + * \brief Calls sn_nsdl_get_resource - function + * + * Negative test cases: + * - call function with null parameter + * + */ + +void test_libnsdl_register(void) +{ + int8_t ret_val = 0; + sn_nsdl_ep_parameters_s endpoint_info; + + memset(&endpoint_info, 0, sizeof(sn_nsdl_ep_parameters_s)); + + /* With null pointer */ + ret_val = sn_nsdl_register_endpoint(handle, NULL); + TEST_ASSERT_EQUAL(0, ret_val); + + ret_val = sn_nsdl_register_endpoint(NULL, &endpoint_info); + TEST_ASSERT_EQUAL(0, ret_val); + + /* OK case */ + ret_val = sn_nsdl_register_endpoint(handle, &endpoint_info); + TEST_ASSERT_NOT_EQUAL(0, ret_val); + + /* Check address */ + TEST_ASSERT_EQUAL(NSP_PORT, address_temp_ptr->port); + TEST_ASSERT_EQUAL_INT8_ARRAY(address, address_temp_ptr->addr_ptr, address_temp_ptr->addr_len); + + /* Check registration message !Note, message ID [bytes 2-3] is random in every message! */ + TEST_ASSERT_EQUAL(NSP_REGISTRATION_MESSAGE_LEN, message_temp_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(message_temp_ptr, registration_message, 2); //message header + TEST_ASSERT_EQUAL_INT8_ARRAY(message_temp_ptr + 4, registration_message + 4, message_temp_len - 4); //Rest of the message + + init_temp_variables(); +} + +/** + * \fn void test_libnsdl_get_requests_to_resources(void) + * + * \brief Process CoAP message "GET" + * + * - GET to resource that is allowed + * - GET to resource that is not allowed + * + */ + +void test_libnsdl_get_requests_to_resources(void) +{ + sn_nsdl_addr_s address_struct; + int8_t ret_val = 0; + + address_struct.addr_ptr = address; + address_struct.addr_len = 16; + address_struct.port = NSP_PORT; + + /* Get to resource that is allowed */ + ret_val = sn_nsdl_process_coap(handle, get_message, sizeof(get_message), &address_struct); + + TEST_ASSERT_EQUAL(0, ret_val); + TEST_ASSERT_EQUAL(sizeof(get_response), message_temp_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(message_temp_ptr, get_response, message_temp_len); + + init_temp_variables(); + + /* Get to resource that is not allowed */ + get_message[13] = 0x32; + ret_val = sn_nsdl_process_coap(handle, get_message, sizeof(get_message), &address_struct); + get_message[13] = 0x31; + + TEST_ASSERT_EQUAL(0, ret_val); + + TEST_ASSERT_EQUAL(sizeof(response_not_allowed), message_temp_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(message_temp_ptr, response_not_allowed, message_temp_len); + + init_temp_variables(); +} + +/** + * \fn void test_libnsdl_put_requests_to_resources(void) + * + * \brief Process CoAP message "PUT" + * + * - PUT to resource that is allowed + * - PUT to resource that is not allowed + */ +void test_libnsdl_put_requests_to_resources(void) +{ + sn_nsdl_addr_s address_struct; + int8_t ret_val = 0; + sn_nsdl_resource_info_s *res_ptr; + + address_struct.addr_ptr = address; + address_struct.addr_len = 16; + address_struct.port = NSP_PORT; + + /* Put to resource that is allowed */ + ret_val = sn_nsdl_process_coap(handle, put_message, sizeof(put_message), &address_struct); + + TEST_ASSERT_EQUAL(0, ret_val); + TEST_ASSERT_EQUAL(sizeof(response_changed), message_temp_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(response_changed, message_temp_ptr, message_temp_len); + + //get resource and read res value + res_ptr = sn_nsdl_get_resource(handle, sizeof(res2_path) - 1, res2_path); + TEST_ASSERT_EQUAL_INT8_ARRAY(message_payload, res_ptr->resource, sizeof(message_payload)); + + init_temp_variables(); + + /* Put to resource that is not allowed */ + put_message[13] = 0x31; + ret_val = sn_nsdl_process_coap(handle, put_message, sizeof(put_message), &address_struct); + put_message[13] = 0x32; + + TEST_ASSERT_EQUAL(0, ret_val); + TEST_ASSERT_EQUAL(sizeof(response_not_allowed), message_temp_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(response_not_allowed, message_temp_ptr, message_temp_len); + + init_temp_variables(); +} + +/** + * \fn void test_libnsdl_post_requests_to_resources(void) + * + * \brief Process CoAP message "POST" + * + * - POST to resource that is allowed + * - POST to resource that is not allowed + * + */ +void test_libnsdl_post_requests_to_resources(void) +{ + sn_nsdl_addr_s address_struct; + int8_t ret_val = 0; + sn_nsdl_resource_info_s *res_ptr; + + address_struct.addr_ptr = address; + address_struct.addr_len = 16; + address_struct.port = NSP_PORT; + + /* Post to resource that is allowed */ + ret_val = sn_nsdl_process_coap(handle, post_message, sizeof(post_message), &address_struct); + + TEST_ASSERT_EQUAL(0, ret_val); + TEST_ASSERT_EQUAL(sizeof(response_changed), message_temp_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(response_changed, message_temp_ptr, message_temp_len); + + //get resource and read res value + res_ptr = sn_nsdl_get_resource(handle, sizeof(res3_path) - 1, res3_path); + TEST_ASSERT_EQUAL_INT8_ARRAY(message_payload, res_ptr->resource, sizeof(message_payload)); + + init_temp_variables(); + + /* Post to resource that is not allowed */ + post_message[13] = 0x32; + ret_val = sn_nsdl_process_coap(handle, post_message, sizeof(post_message), &address_struct); + post_message[13] = 0x33; + + TEST_ASSERT_EQUAL(0, ret_val); + TEST_ASSERT_EQUAL(sizeof(response_not_allowed), message_temp_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(response_not_allowed, message_temp_ptr, message_temp_len); + + init_temp_variables(); +} + +/** + * \fn void test_libnsdl_delete_requests_to_resources(void) + * + * \brief Process CoAP message "DELETE" + * + * - DELETE to resource that is allowed + * - DELETE to resource that is not allowed + * + */ +void test_libnsdl_delete_requests_to_resources(void) +{ + sn_nsdl_addr_s address_struct; + int8_t ret_val = 0; + sn_nsdl_resource_info_s *res_ptr; + + address_struct.addr_ptr = address; + address_struct.addr_len = 16; + address_struct.port = NSP_PORT; + + /* Delete to resource that is not allowed */ + delete_message[13] = 0x33; + ret_val = sn_nsdl_process_coap(handle, delete_message, sizeof(delete_message), &address_struct); + delete_message[13] = 0x34; + + TEST_ASSERT_EQUAL(0, ret_val); + TEST_ASSERT_EQUAL(sizeof(response_not_allowed), message_temp_len); + TEST_ASSERT_EQUAL_INT8_ARRAY(response_not_allowed, message_temp_ptr, message_temp_len); + + init_temp_variables(); +} + +/** + * \fn void test_libnsdl_update_resource_value(void) + * + * \brief Updates resource value from application + * + */ +void test_libnsdl_update_resource_value(void) +{ + sn_nsdl_resource_info_s resource; + sn_nsdl_resource_info_s *res_ptr; + sn_nsdl_resource_parameters_s resource_parameters; + int8_t ret_val; + + memset(&resource, 0, sizeof(sn_nsdl_resource_info_s)); + memset(&resource_parameters, 0, sizeof(sn_nsdl_resource_parameters_s)); + + /* Resource 1*/ + resource.access = SN_GRS_GET_ALLOWED; + resource.mode = SN_GRS_STATIC; + resource.path = res1_path; + resource.pathlen = sizeof(res1_path) - 1; + resource.resource = message_payload; + resource.resourcelen = sizeof(message_payload); + resource.resource_parameters_ptr = &resource_parameters; + + ret_val = sn_nsdl_update_resource(handle, &resource); + + TEST_ASSERT_EQUAL(0, ret_val); + + //get resource and read res value + res_ptr = sn_nsdl_get_resource(handle, sizeof(res1_path) - 1, res1_path); + TEST_ASSERT_NOT_NULL(res_ptr); + TEST_ASSERT_EQUAL_INT8_ARRAY(message_payload, res_ptr->resource, sizeof(message_payload)); + +} + +/** + * \fn void test_libnsdl_delete_resource(void) + * + * \brief Delete resource from application + * + */ +void test_libnsdl_delete_resource(void) +{ + sn_nsdl_resource_info_s *res_ptr; + int8_t ret_val; + + ret_val = sn_nsdl_delete_resource(handle, sizeof(res4_path) - 1, res4_path); + + TEST_ASSERT_EQUAL(0, ret_val); + + //get resource and read res value + res_ptr = sn_nsdl_get_resource(handle, sizeof(res4_path) - 1, res4_path); + TEST_ASSERT_NULL(res_ptr); +} + + +/*******************************/ +/*** non-test functions ***/ +/*******************************/ + +void fill_with_random(uint8_t *ptr, uint16_t len) +{ + while (len--) { + *(ptr + len) = 'a'; + } +} + +void *own_alloc(uint16_t size) +{ + return malloc(size); +} + +void own_free(void *ptr) +{ + free(ptr); +} + +uint8_t nsdl_tx_dummy(struct nsdl_s *handle, sn_nsdl_capab_e protocol, uint8_t *data_ptr, uint16_t data_len, sn_nsdl_addr_s *address_ptr) +{ + message_temp_ptr = malloc(data_len); + memcpy(message_temp_ptr, data_ptr, data_len); + + message_temp_len = data_len; + + address_temp_ptr = malloc(sizeof(sn_nsdl_addr_s)); + memcpy(address_temp_ptr, address_ptr, sizeof(sn_nsdl_addr_s)); + +#if 0 + uint8_t i; + printf("\nlength = %d\n", data_len); + for (i = 0; i < data_len; i++) { + printf("0x"); + if (*(data_ptr + i) <= 0x0F) { + printf("0"); + } + printf("%x, ", *(data_ptr + i)); + if (!((i + 1) % 16)) { + printf("\n"); + } + } + printf("\n"); +#endif +} + +uint8_t nsdl_rx_dummy(struct nsdl_s *handle, sn_coap_hdr_s *coap_header_ptr, sn_nsdl_addr_s *address_ptr) +{ + +} + +uint8_t dynamic_callback(struct nsdl_s *handle, sn_coap_hdr_s *coap_header_ptr, sn_nsdl_addr_s *address_ptr, sn_nsdl_capab_e protocol) +{ + +} + +static void init_temp_variables(void) +{ + if (message_temp_ptr) { + free(message_temp_ptr); + message_temp_ptr = 0; + } + if (address_temp_ptr) { + free(address_temp_ptr); + address_temp_ptr = 0; + } + message_temp_len = 0; +} + + + + + + + + diff --git a/features/FEATURE_CLIENT/mbed-client-c/unittest/test_libNsdl/makefile b/features/FEATURE_CLIENT/mbed-client-c/unittest/test_libNsdl/makefile new file mode 100644 index 0000000000..8037c3cadd --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/unittest/test_libNsdl/makefile @@ -0,0 +1,33 @@ +# ========================================== +# Unity Project - A Test Framework for C +# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams +# [Released under MIT License. Please refer to license.txt for details] +# ========================================== + +C_COMPILER=gcc +TARGET_BASE=test_libNsdl +TARGET_EXTENSION=.out + +TARGET = $(TARGET_BASE)$(TARGET_EXTENSION) + +SRC_FILES=../../../unittest/src/unity.c ../../source/libNsdl/src/sn_grs.c ../../source/libNsdl/src/sn_nsdl.c \ +../../../libService/source/libList/ns_list.c Test.c Test_Runner.c + +INC_DIRS=-I../../../unittest/src -I../../nsdl-c/ -I../../source/libNsdl/src/include -I../../../libService/libService + +SYMBOLS= -std=c99 -DTEST -DUNITY_EXCLUDE_STDINT_H + +LDFLAGS = -L../../ -lnsdl_gcc + +CLEANUP = rm -f build/*.o ; rm -f $(TARGET) + +all: clean default + +default: + ruby ../../../unittest/auto/generate_test_runner.rb Test.c Test_Runner.c + $(C_COMPILER) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES) -o $(TARGET) $(LDFLAGS) + ./$(TARGET) + +clean: + $(CLEANUP) + diff --git a/features/FEATURE_CLIENT/mbed-client-c/xsl_script.sh b/features/FEATURE_CLIENT/mbed-client-c/xsl_script.sh new file mode 100755 index 0000000000..d5320b42b8 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-c/xsl_script.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# Copyright (c) 2015 ARM Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# * http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +echo +echo "Creating report" +echo + +echo ' + +' >> lcov/index.xml + +for f in lcov/results/*.xml +do +name=${f##*/} +echo ''>> lcov/index.xml +done + +echo '' >> lcov/index.xml + +echo +echo "Report created to lcov/index.xml (outputs html)" +echo \ No newline at end of file diff --git a/features/FEATURE_CLIENT/mbed-client-classic/LICENSE b/features/FEATURE_CLIENT/mbed-client-classic/LICENSE new file mode 100644 index 0000000000..8dada3edaf --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-classic/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/features/FEATURE_CLIENT/mbed-client-classic/mbed-client-classic/m2mconnectionhandlerpimpl.h b/features/FEATURE_CLIENT/mbed-client-classic/mbed-client-classic/m2mconnectionhandlerpimpl.h new file mode 100644 index 0000000000..c3db88f6d4 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-classic/mbed-client-classic/m2mconnectionhandlerpimpl.h @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_CONNECTION_HANDLER_PIMPL_H__ +#define M2M_CONNECTION_HANDLER_PIMPL_H__ + +#include "ns_types.h" +#include "mbed-client/m2mconfig.h" +#include "mbed-client/m2mconstants.h" +#include "mbed-client/m2minterface.h" +#include "mbed-client/m2mconnectionobserver.h" +#include "mbed-client/m2mconnectionsecurity.h" +#include "nsdl-c/sn_nsdl.h" + +#include "Socket.h" + + +class M2MConnectionSecurity; +class M2MConnectionHandler; +class M2MSecurity; + +/** + * @brief M2MConnectionHandlerPimpl. + * This class handles the socket connection for LWM2M Client + */ + + +class M2MConnectionHandlerPimpl { +public: + + enum SocketEvent { + ESocketIdle = 0x00, + ESocketReadytoRead = 0x02, + ESocketDnsHandler = 0x04, + ESocketSend = 0x08 + }; + + struct TaskIdentifier { + M2MConnectionHandlerPimpl *pimpl; + void *data_ptr; + }; + + /** + * @brief Constructor + */ + M2MConnectionHandlerPimpl(M2MConnectionHandler* base, M2MConnectionObserver &observer, + M2MConnectionSecurity* sec, + M2MInterface::BindingMode mode, + M2MInterface::NetworkStack stack); + + /** + * @brief Destructor + */ + ~M2MConnectionHandlerPimpl(); + + /** + * @brief This binds the socket connection. + * @param listen_port Port to listen for incoming connection. + * @return true if successful else false. + */ + bool bind_connection(const uint16_t listen_port); + + /** + * @brief This resolves the server address. Output is + * returned through callback + * @param String server address. + * @param uint16_t Server port. + * @param ServerType, Server Type to be resolved. + * @return true if address is valid else false. + */ + bool resolve_server_address(const String& server_address, + const uint16_t server_port, + M2MConnectionObserver::ServerType server_type, + const M2MSecurity* security); + + /** + * @brief Sends data, to the connected sent to server. + * @param data, Data to be sent. + */ + bool send_data(uint8_t *data_ptr, + uint16_t data_len, + sn_nsdl_addr_s *address_ptr); + + /** + * @brief Listens for incoming data from remote server + * @return true if successful else false. + */ + bool start_listening_for_data(); + + /** + * @brief Stops listening for incoming data + */ + void stop_listening(); + + /** + * @brief send_to_socket Sends directly to socket. This is used by + * security classes to send after data has been encrypted. + * @param buf Buffer to send + * @param len Length of a buffer + * @return Number of bytes sent or -1 if failed + */ + int send_to_socket(const unsigned char *buf, size_t len); + + /** + * \brief Receives directly from the socket. This + * is used by the security classes to receive raw data to be decrypted. + * \param buf Buffer to send. + * \param len The length of the buffer. + * \param timeout Timeout defined from DTLS to wait for blocking receive calls + * before timing out, by default value is 0. + * \return Number of bytes read or negative number if failed. + */ + int receive_from_socket(unsigned char *buf, size_t len); + + /** + * @brief Error handling for DTLS connectivity. + * @param error, Error code from TLS library + */ + void handle_connection_error(int error); + + /** + * \brief Sets the network interface handler that is used by client to connect + * to a network over IP.. + * \param handler A network interface handler that is used by client to connect. + * This API is optional but provides a mechanism for different platforms to + * manage usage of underlying network interface by client. + */ + void set_platform_network_handler(void *handler = NULL); + + /** + * \brief Claims mutex to prevent thread clashes + * in multithreaded environment. + */ + void claim_mutex(); + + /** + * \brief Releases mutex to prevent thread clashes + * in multithreaded environment. + */ + void release_mutex(); + + /** + * @brief Callback handler for sending data over socket. + */ + void send_handler(); + + /** + * @brief Callback handler for receiving data over socket. + */ + void receive_handler(); + + /** + * @brief Callback handler for receiving data for secured connection. + */ + void receive_handshake_handler(); + + /** + * @brief Returns true if DTLS handshake is still ongoing. + */ + bool is_handshake_ongoing(); + + /** + * @brief Returns connection handler tasklet ID. + */ + int8_t connection_tasklet_handler(); + + /** + * @brief Handles DNS resolving through event loop. + */ + void dns_handler(); + + /** + * @brief Sends data to socket through event loop. + */ + void send_socket_data(uint8_t *data, uint16_t data_len); + + +private: + + /** + * @brief Callback handler for socket events. + */ + void socket_event(); + + /** + * @brief Initialize mbed OS socket + */ + void init_socket(); + + /** + * @brief Check socket type + * @return True if TCP connection otherwise false + */ + bool is_tcp_connection(); + + /** + * @brief Close and delete socket + */ + void close_socket(); + + /** + * @brief Enables keepalive for TCP connections. + */ + void enable_keepalive(); + +private: + M2MConnectionHandler *_base; + M2MConnectionObserver &_observer; + M2MConnectionSecurity *_security_impl; //owned + const M2MSecurity *_security; //non-owned + bool _use_secure_connection; + M2MInterface::BindingMode _binding_mode; + M2MInterface::NetworkStack _network_stack; + M2MConnectionObserver::SocketAddress _address; + unsigned char _address_buffer[NSAPI_IP_SIZE]; + Socket *_socket; + bool _is_handshaking; + bool _listening; + M2MConnectionObserver::ServerType _server_type; + uint16_t _server_port; + uint16_t _listen_port; + bool _running; + unsigned char _recv_buffer[BUFFER_LENGTH]; + NetworkInterface *_net_iface; //doesn't own + SocketAddress *_socket_address; + static int8_t _tasklet_id; + String _server_address; + +friend class Test_M2MConnectionHandlerPimpl; +friend class Test_M2MConnectionHandlerPimpl_mbed; +friend class M2MConnection_TestObserver; +}; + +#endif //M2M_CONNECTION_HANDLER_PIMPL_H__ diff --git a/features/FEATURE_CLIENT/mbed-client-classic/mbed-client-classic/m2mtimerpimpl.h b/features/FEATURE_CLIENT/mbed-client-classic/mbed-client-classic/m2mtimerpimpl.h new file mode 100644 index 0000000000..0de6ffb6c9 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-classic/mbed-client-classic/m2mtimerpimpl.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_TIMER_PIMPL_H__ +#define M2M_TIMER_PIMPL_H__ + +#include "ns_types.h" + +#include "mbed-client/m2mtimerobserver.h" + +class M2MTimerPimpl { +private: + + // Prevents the use of assignment operator + M2MTimerPimpl& operator=(const M2MTimerPimpl& other); + + // Prevents the use of copy constructor + M2MTimerPimpl(const M2MTimerPimpl& other); +public: + + /** + * Constructor. + */ + M2MTimerPimpl(M2MTimerObserver& _observer); + + /** + * Destructor. + */ + virtual ~M2MTimerPimpl(); + + /** + * Starts timer + * @param interval Timer's interval in milliseconds + * @param single_shot defines if timer is ticked + * once or is it restarted everytime timer is expired. + */ + void start_timer(uint64_t interval, M2MTimerObserver::Type type, bool single_shot = true); + + /** + * @brief Starts timer in DTLS manner + * @param intermediate_interval Intermediate interval to use, must be smaller than tiotal (usually 1/4 of total) + * @param total_interval Total interval to use; This is the timeout value of a DTLS packet + * @param type Type of the timer + */ + void start_dtls_timer(uint64_t intermediate_interval, uint64_t total_interval, M2MTimerObserver::Type type); + + /** + * Stops timer. + * This cancels the ongoing timer. + */ + void stop_timer(); + + /** + * Callback function for timer completion. + */ + void timer_expired(); + + /** + * @brief Checks if the intermediate interval has passed + * @return true if interval has passed, false otherwise + */ + bool is_intermediate_interval_passed(); + + /** + * @brief Checks if the total interval has passed + * @return true if interval has passed, false otherwise + */ + bool is_total_interval_passed(); + + inline int8_t get_timer_id() const; + +private: + + void start(); + void cancel(); + +private: + M2MTimerObserver& _observer; + bool _single_shot; + uint64_t _interval; + M2MTimerObserver::Type _type; + + uint64_t _intermediate_interval; + uint64_t _total_interval; + uint8_t _status; + bool _dtls_type; + + // this is the timer-id of this object, used to map the + // timer event callback to the correct object. + int8_t _timer_id; + + static int8_t _tasklet_id; + static int8_t _next_timer_id; + + friend class M2MTimer; +}; + +inline int8_t M2MTimerPimpl::get_timer_id() const +{ + return _timer_id; +} + +#endif //M2M_TIMER_PIMPL_H__ diff --git a/features/FEATURE_CLIENT/mbed-client-classic/source/m2mconnectionhandler.cpp b/features/FEATURE_CLIENT/mbed-client-classic/source/m2mconnectionhandler.cpp new file mode 100644 index 0000000000..2c51012dc8 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-classic/source/m2mconnectionhandler.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client-classic/m2mconnectionhandlerpimpl.h" +#include "mbed-client/m2mconnectionobserver.h" +#include "mbed-client/m2mconnectionhandler.h" +#include "mbed-client/m2mconstants.h" + +M2MConnectionHandler::M2MConnectionHandler(M2MConnectionObserver &observer, + M2MConnectionSecurity* sec, + M2MInterface::BindingMode mode, + M2MInterface::NetworkStack stack) +:_observer(observer) +{ + _private_impl = new M2MConnectionHandlerPimpl(this, observer, sec, mode, stack); +} + +M2MConnectionHandler::~M2MConnectionHandler() +{ + delete _private_impl; +} + +bool M2MConnectionHandler::bind_connection(const uint16_t listen_port) +{ + + return _private_impl->bind_connection(listen_port); +} + +bool M2MConnectionHandler::resolve_server_address(const String& server_address, + const uint16_t server_port, + M2MConnectionObserver::ServerType server_type, + const M2MSecurity* security) +{ + return _private_impl->resolve_server_address(server_address, server_port, + server_type, security); +} + +bool M2MConnectionHandler::start_listening_for_data() +{ + return _private_impl->start_listening_for_data(); +} + +void M2MConnectionHandler::stop_listening() +{ + _private_impl->stop_listening(); +} + +int M2MConnectionHandler::send_to_socket(const unsigned char *buf, size_t len) +{ + return _private_impl->send_to_socket(buf, len); +} + +int M2MConnectionHandler::receive_from_socket(unsigned char *buf, size_t len) +{ + return _private_impl->receive_from_socket(buf, len); +} + +bool M2MConnectionHandler::send_data(uint8_t *data, + uint16_t data_len, + sn_nsdl_addr_s *address) +{ + return _private_impl->send_data(data, data_len, address); +} + +void M2MConnectionHandler::handle_connection_error(int error) +{ + _private_impl->handle_connection_error(error); +} + +void M2MConnectionHandler::set_platform_network_handler(void *handler) +{ + _private_impl->set_platform_network_handler(handler); +} + +void M2MConnectionHandler::claim_mutex() +{ + _private_impl->claim_mutex(); +} + +void M2MConnectionHandler::release_mutex() +{ + _private_impl->release_mutex(); +} diff --git a/features/FEATURE_CLIENT/mbed-client-classic/source/m2mconnectionhandlerpimpl.cpp b/features/FEATURE_CLIENT/mbed-client-classic/source/m2mconnectionhandlerpimpl.cpp new file mode 100644 index 0000000000..5703d82701 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-classic/source/m2mconnectionhandlerpimpl.cpp @@ -0,0 +1,574 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client-classic/m2mconnectionhandlerpimpl.h" +#include "mbed-client/m2mconnectionobserver.h" +#include "mbed-client/m2mconstants.h" +#include "mbed-client/m2msecurity.h" +#include "mbed-client/m2mconnectionhandler.h" + +#include "NetworkInterface.h" +#include "UDPSocket.h" +#include "TCPSocket.h" + +#include "eventOS_event.h" +#include "eventOS_scheduler.h" + +#include "mbed-trace/mbed_trace.h" + +#define TRACE_GROUP "mClt" + +int8_t M2MConnectionHandlerPimpl::_tasklet_id = -1; + +extern "C" void connection_tasklet_event_handler(arm_event_s *event) +{ + tr_debug("M2MConnectionHandlerPimpl::connection_tasklet_event_handler"); + M2MConnectionHandlerPimpl::TaskIdentifier *task_id = (M2MConnectionHandlerPimpl::TaskIdentifier*)event->data_ptr; + M2MConnectionHandlerPimpl* pimpl = (M2MConnectionHandlerPimpl*)task_id->pimpl; + if(pimpl) { + eventOS_scheduler_set_active_tasklet(pimpl->connection_tasklet_handler()); + } + switch (event->event_type) { + case M2MConnectionHandlerPimpl::ESocketIdle: + tr_debug("Connection Tasklet Generated"); + break; + case M2MConnectionHandlerPimpl::ESocketReadytoRead: + tr_debug("connection_tasklet_event_handler - ESocketReadytoRead"); + if(pimpl) { + if(pimpl->is_handshake_ongoing()) { + pimpl->receive_handshake_handler(); + } else { + pimpl->receive_handler(); + } + } + break; + case M2MConnectionHandlerPimpl::ESocketDnsHandler: + tr_debug("connection_tasklet_event_handler - ESocketDnsHandler"); + if(pimpl) { + pimpl->dns_handler(); + } + break; + case M2MConnectionHandlerPimpl::ESocketSend: + tr_debug("connection_tasklet_event_handler - ESocketSend"); + if(pimpl) { + pimpl->send_socket_data((uint8_t*)task_id->data_ptr,(uint16_t)event->event_data); + if (task_id->data_ptr) { + free(task_id->data_ptr); + } + } + break; + default: + break; + } + if (task_id) { + free(task_id); + } +} + +M2MConnectionHandlerPimpl::M2MConnectionHandlerPimpl(M2MConnectionHandler* base, M2MConnectionObserver &observer, + M2MConnectionSecurity* sec, + M2MInterface::BindingMode mode, + M2MInterface::NetworkStack stack) +:_base(base), + _observer(observer), + _security_impl(sec), + _use_secure_connection(false), + _binding_mode(mode), + _network_stack(stack), + _socket(0), + _is_handshaking(false), + _listening(true), + _server_type(M2MConnectionObserver::LWM2MServer), + _server_port(0), + _listen_port(0), + _running(false), + _net_iface(0), + _socket_address(0) +{ + memset(&_address_buffer, 0, sizeof _address_buffer); + memset(&_address, 0, sizeof _address); + _address._address = _address_buffer; + + if (_network_stack != M2MInterface::LwIP_IPv4) { + error("ConnectionHandler: Unsupported network stack, only IPv4 is currently supported"); + } + _running = true; + tr_debug("M2MConnectionHandlerPimpl::M2MConnectionHandlerPimpl() - Initializing thread"); + eventOS_scheduler_mutex_wait(); + if (M2MConnectionHandlerPimpl::_tasklet_id == -1) { + M2MConnectionHandlerPimpl::_tasklet_id = eventOS_event_handler_create(&connection_tasklet_event_handler, ESocketIdle); + } + eventOS_scheduler_mutex_release(); +} + +M2MConnectionHandlerPimpl::~M2MConnectionHandlerPimpl() +{ + tr_debug("M2MConnectionHandlerPimpl::~M2MConnectionHandlerPimpl()"); + if (_socket) { + delete _socket; + _socket = 0; + } + _net_iface = 0; + delete _security_impl; + tr_debug("M2MConnectionHandlerPimpl::~M2MConnectionHandlerPimpl() - OUT"); +} + +bool M2MConnectionHandlerPimpl::bind_connection(const uint16_t listen_port) +{ + _listen_port = listen_port; + return true; +} + +bool M2MConnectionHandlerPimpl::resolve_server_address(const String& server_address, + const uint16_t server_port, + M2MConnectionObserver::ServerType server_type, + const M2MSecurity* security) +{ + tr_debug("M2MConnectionHandlerPimpl::resolve_server_address()"); + if (!_net_iface) { + return false; + } + _security = security; + _server_port = server_port; + _server_type = server_type; + _server_address = server_address; + TaskIdentifier* task = (TaskIdentifier*)malloc(sizeof(TaskIdentifier)); + if (!task) { + return false; + } + task->pimpl = this; + + arm_event_s event; + event.receiver = M2MConnectionHandlerPimpl::_tasklet_id; + event.sender = 0; + event.event_type = ESocketDnsHandler; + event.data_ptr = task; + event.priority = ARM_LIB_HIGH_PRIORITY_EVENT; + return eventOS_event_send(&event) == 0 ? true : false; +} + +void M2MConnectionHandlerPimpl::dns_handler() +{ + tr_debug("M2MConnectionHandlerPimpl::dns_handler()"); + _socket_address = new SocketAddress(_net_iface,_server_address.c_str(), _server_port); + if(*_socket_address) { + _address._address = (void*)_socket_address->get_ip_address(); + tr_debug("IP Address %s",_socket_address->get_ip_address()); + tr_debug("Port %d",_socket_address->get_port()); + _address._length = strlen((char*)_address._address); + _address._port = _socket_address->get_port(); + _address._stack = _network_stack; + } else { + _observer.socket_error(M2MConnectionHandler::DNS_RESOLVING_ERROR, true); + close_socket(); + return; + } + + close_socket(); + init_socket(); + + if(is_tcp_connection()) { + tr_debug("M2MConnectionHandlerPimpl::resolve_server_address - Using TCP"); + if (((TCPSocket*)_socket)->connect(*_socket_address) < 0) { + _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT); + return; + } + } + + _running = true; + + if (_security) { + if (_security->resource_value_int(M2MSecurity::SecurityMode) == M2MSecurity::Certificate || + _security->resource_value_int(M2MSecurity::SecurityMode) == M2MSecurity::Psk) { + + if( _security_impl != NULL ){ + _security_impl->reset(); + if (_security_impl->init(_security) == 0) { + _is_handshaking = true; + tr_debug("M2MConnectionHandlerPimpl::resolve_server_address - connect DTLS"); + if(_security_impl->start_connecting_non_blocking(_base) < 0 ){ + tr_debug("M2MConnectionHandlerPimpl::dns_handler - handshake failed"); + _is_handshaking = false; + _observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR); + close_socket(); + return; + } + } else { + tr_error("M2MConnectionHandlerPimpl::resolve_server_address - init failed"); + _observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR, false); + close_socket(); + return; + } + } else { + tr_error("M2MConnectionHandlerPimpl::dns_handler - sec is null"); + _observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR, false); + close_socket(); + return; + } + } + } + if(!_is_handshaking) { + enable_keepalive(); + _observer.address_ready(_address, + _server_type, + _address._port); + } +} + +void M2MConnectionHandlerPimpl::send_handler() +{ + tr_debug("M2MConnectionHandlerPimpl::send_handler()"); + _observer.data_sent(); +} + +bool M2MConnectionHandlerPimpl::send_data(uint8_t *data, + uint16_t data_len, + sn_nsdl_addr_s *address) +{ + tr_debug("M2MConnectionHandlerPimpl::send_data()"); + if (address == NULL || data == NULL) { + return false; + } + + uint8_t *buffer = (uint8_t*)malloc(data_len); + if(!buffer) { + return false; + } + + TaskIdentifier* task = (TaskIdentifier*)malloc(sizeof(TaskIdentifier)); + if (!task) { + free(buffer); + return false; + } + task->pimpl = this; + memcpy(buffer, data, data_len); + task->data_ptr = buffer; + arm_event_s event; + event.receiver = M2MConnectionHandlerPimpl::_tasklet_id; + event.sender = 0; + event.event_type = ESocketSend; + event.data_ptr = task; + event.event_data = data_len; + event.priority = ARM_LIB_HIGH_PRIORITY_EVENT; + + return eventOS_event_send(&event) == 0 ? true : false; +} + +void M2MConnectionHandlerPimpl::send_socket_data(uint8_t *data, + uint16_t data_len) +{ + bool success = false; + if( _use_secure_connection ){ + if( _security_impl->send_message(data, data_len) > 0){ + success = true; + } + } else { + int32_t ret = -1; + if(is_tcp_connection()){ + //We need to "shim" the length in front + uint16_t d_len = data_len+4; + uint8_t* d = (uint8_t*)malloc(data_len+4); + + d[0] = (data_len >> 24 )& 0xff; + d[1] = (data_len >> 16 )& 0xff; + d[2] = (data_len >> 8 )& 0xff; + d[3] = data_len & 0xff; + memmove(d+4, data, data_len); + ret = ((TCPSocket*)_socket)->send(d,d_len); + free(d); + }else { + ret = ((UDPSocket*)_socket)->sendto(*_socket_address,data, data_len); + } + if (ret > 0) { + success = true; + } + } + + if (!success) { + _observer.socket_error(M2MConnectionHandler::SOCKET_SEND_ERROR, true); + close_socket(); + } +} + +int8_t M2MConnectionHandlerPimpl::connection_tasklet_handler() +{ + return M2MConnectionHandlerPimpl::_tasklet_id; +} + +void M2MConnectionHandlerPimpl::socket_event() +{ + tr_debug("M2MConnectionHandlerPimpl::socket_event()"); + + TaskIdentifier* task = (TaskIdentifier*)malloc(sizeof(TaskIdentifier)); + if (!task) { + _observer.socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, true); + return; + } + task->pimpl = this; + + arm_event_s event; + event.receiver = M2MConnectionHandlerPimpl::_tasklet_id; + event.sender = 0; + event.event_type = ESocketReadytoRead; + event.data_ptr = task; + event.priority = ARM_LIB_HIGH_PRIORITY_EVENT; + int8_t error = eventOS_event_send(&event); + if(error != 0) { + _observer.socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, true); + } +} + +bool M2MConnectionHandlerPimpl::start_listening_for_data() +{ + tr_debug("M2MConnectionHandlerPimpl::start_listening_for_data()"); + // Boolean return required for other platforms, + // not needed in mbed OS Socket. + _listening = true; + _running = true; + return _listening; +} + +void M2MConnectionHandlerPimpl::stop_listening() +{ + tr_debug("M2MConnectionHandlerPimpl::stop_listening()"); + _listening = false; + if(_security_impl) { + _security_impl->reset(); + } +} + +int M2MConnectionHandlerPimpl::send_to_socket(const unsigned char *buf, size_t len) +{ + tr_debug("M2MConnectionHandlerPimpl::send_to_socket len - %d", len); + int size = -1; + if(is_tcp_connection()) { + size = ((TCPSocket*)_socket)->send(buf,len); + } else { + size = ((UDPSocket*)_socket)->sendto(*_socket_address,buf,len); + } + tr_debug("M2MConnectionHandlerPimpl::send_to_socket size - %d", size); + if(NSAPI_ERROR_WOULD_BLOCK == size){ + if(_is_handshaking) { + return M2MConnectionHandler::CONNECTION_ERROR_WANTS_WRITE; + } else { + return len; + } + }else if(size < 0){ + return -1; + }else{ + if(!_is_handshaking) { + _observer.data_sent(); + } + return size; + } +} + +int M2MConnectionHandlerPimpl::receive_from_socket(unsigned char *buf, size_t len) +{ + tr_debug("M2MConnectionHandlerPimpl::receive_from_socket"); + int recv = -1; + if(is_tcp_connection()) { + recv = ((TCPSocket*)_socket)->recv(buf, len); + } else { + recv = ((UDPSocket*)_socket)->recvfrom(NULL,buf, len); + } + tr_debug("M2MConnectionHandlerPimpl::receive_from_socket recv size %d", recv); + if(NSAPI_ERROR_WOULD_BLOCK == recv){ + return M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ; + }else if(recv < 0){ + return -1; + }else{ + return recv; + } +} + +void M2MConnectionHandlerPimpl::handle_connection_error(int error) +{ + tr_debug("M2MConnectionHandlerPimpl::handle_connection_error"); + _observer.socket_error(error); +} + +void M2MConnectionHandlerPimpl::set_platform_network_handler(void *handler) +{ + tr_debug("M2MConnectionHandlerPimpl::set_platform_network_handler"); + _net_iface = (NetworkInterface*)handler; +} + +void M2MConnectionHandlerPimpl::receive_handshake_handler() +{ + tr_debug("M2MConnectionHandlerPimpl::receive_handshake_handler()"); + if( _is_handshaking ){ + int ret = _security_impl->continue_connecting(); + tr_debug("M2MConnectionHandlerPimpl::receive_handshake_handler() - ret %d", ret); + if( ret == M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ ){ //We wait for next readable event + tr_debug("M2MConnectionHandlerPimpl::receive_handshake_handler() - We wait for next readable event"); + return; + } else if( ret == 0 ){ + _is_handshaking = false; + _use_secure_connection = true; + enable_keepalive(); + _observer.address_ready(_address, + _server_type, + _server_port); + }else if( ret < 0 ){ + _is_handshaking = false; + _observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR, true); + close_socket(); + } + } +} + +bool M2MConnectionHandlerPimpl::is_handshake_ongoing() +{ + return _is_handshaking; +} + +void M2MConnectionHandlerPimpl::receive_handler() +{ + tr_debug("M2MConnectionHandlerPimpl::receive_handler()"); + memset(_recv_buffer, 0, 1024); + size_t receive_length = sizeof(_recv_buffer); + + if(_listening) { + if( _use_secure_connection ){ + int rcv_size = _security_impl->read(_recv_buffer, receive_length); + + if(rcv_size >= 0){ + _observer.data_available((uint8_t*)_recv_buffer, + rcv_size, _address); + } else if (M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ != rcv_size) { + _observer.socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, true); + close_socket(); + return; + } + }else{ + int recv = -1; + if(is_tcp_connection()){ + recv = ((TCPSocket*)_socket)->recv(_recv_buffer, receive_length); + + }else{ + recv = ((UDPSocket*)_socket)->recvfrom(NULL,_recv_buffer, receive_length); + } + if (recv > 0) { + // Send data for processing. + if(is_tcp_connection()){ + //We need to "shim" out the length from the front + if( receive_length > 4 ){ + uint64_t len = (_recv_buffer[0] << 24 & 0xFF000000) + (_recv_buffer[1] << 16 & 0xFF0000); + len += (_recv_buffer[2] << 8 & 0xFF00) + (_recv_buffer[3] & 0xFF); + if(len > 0) { + uint8_t* buf = (uint8_t*)malloc(len); + if(buf) { + memmove(buf, _recv_buffer+4, len); + // Observer for TCP plain mode + _observer.data_available(buf,len,_address); + free(buf); + } + } + }else{ + _observer.socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, true); + close_socket(); + } + } else { // Observer for UDP plain mode + tr_debug("M2MConnectionHandlerPimpl::receive_handler - data received %d", recv); + _observer.data_available((uint8_t*)_recv_buffer, + recv, _address); + } + } else if(NSAPI_ERROR_WOULD_BLOCK != recv) { + // Socket error in receiving + _observer.socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, true); + close_socket(); + } + } + } +} + +void M2MConnectionHandlerPimpl::claim_mutex() +{ + eventOS_scheduler_mutex_wait(); +} + +void M2MConnectionHandlerPimpl::release_mutex() +{ + eventOS_scheduler_mutex_release(); +} + +void M2MConnectionHandlerPimpl::init_socket() +{ + tr_debug("M2MConnectionHandlerPimpl::init_socket - IN"); + _is_handshaking = false; + _running = true; + + if(is_tcp_connection()) { + tr_debug("M2MConnectionHandlerPimpl::init_socket - Using TCP"); + _socket = new TCPSocket(_net_iface); + if(_socket) { + _socket->attach(this, &M2MConnectionHandlerPimpl::socket_event); + } else { + _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT); + return; + } + } else { + tr_debug("M2MConnectionHandlerPimpl::init_socket - Using UDP - port %d", _listen_port); + _socket = new UDPSocket(_net_iface); + if(_socket) { + _socket->bind(_listen_port); + _socket->attach(this, &M2MConnectionHandlerPimpl::socket_event); + } else { + _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT); + return; + } + } + _socket->set_blocking(false); + tr_debug("M2MConnectionHandlerPimpl::init_socket - OUT"); +} + +bool M2MConnectionHandlerPimpl::is_tcp_connection() +{ + return _binding_mode == M2MInterface::TCP || + _binding_mode == M2MInterface::TCP_QUEUE ? true : false; +} + +void M2MConnectionHandlerPimpl::close_socket() +{ + tr_debug("M2MConnectionHandlerPimpl::close_socket() - IN"); + if(_socket) { + _running = false; + _socket->close(); + delete _socket; + _socket = NULL; + } + tr_debug("M2MConnectionHandlerPimpl::close_socket() - OUT"); +} + +void M2MConnectionHandlerPimpl::enable_keepalive() +{ +#if MBED_CLIENT_TCP_KEEPALIVE_TIME + if(is_tcp_connection()) { + int keepalive = MBED_CLIENT_TCP_KEEPALIVE_TIME; + int enable = 1; + tr_debug("M2MConnectionHandlerPimpl::resolve_hostname - keepalive %d s\n", keepalive); + if(_socket->setsockopt(1,NSAPI_KEEPALIVE,&enable,sizeof(enable)) != 0) { + tr_error("M2MConnectionHandlerPimpl::enable_keepalive - setsockopt fail to Set Keepalive\n"); + } + if(_socket->setsockopt(1,NSAPI_KEEPINTVL,&keepalive,sizeof(keepalive)) != 0) { + tr_error("M2MConnectionHandlerPimpl::enable_keepalive - setsockopt fail to Set Keepalive TimeInterval\n"); + } + if(_socket->setsockopt(1,NSAPI_KEEPIDLE,&keepalive,sizeof(keepalive)) != 0) { + tr_error("M2MConnectionHandlerPimpl::enable_keepalive - setsockopt fail to Set Keepalive Time\n"); + } + } +#endif +} diff --git a/features/FEATURE_CLIENT/mbed-client-classic/source/m2mtimer.cpp b/features/FEATURE_CLIENT/mbed-client-classic/source/m2mtimer.cpp new file mode 100644 index 0000000000..12d81fced0 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-classic/source/m2mtimer.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client/m2mtimer.h" +#include "mbed-client/m2mtimerobserver.h" +#include "mbed-client-classic/m2mtimerpimpl.h" + + +M2MTimer::M2MTimer(M2MTimerObserver& observer) +: _observer(observer) +{ + _private_impl = new M2MTimerPimpl(observer); +} + +M2MTimer::~M2MTimer() +{ + delete _private_impl; + //_private_impl = NULL; +} + +void M2MTimer::start_timer( uint64_t interval, + M2MTimerObserver::Type type, + bool single_shot) +{ + _private_impl->start_timer(interval, + type, + single_shot); +} + +void M2MTimer::start_dtls_timer(uint64_t intermediate_interval, uint64_t total_interval, M2MTimerObserver::Type type){ + _private_impl->start_dtls_timer(intermediate_interval, total_interval, type); +} + +void M2MTimer::stop_timer() +{ + _private_impl->stop_timer(); +} + +bool M2MTimer::is_intermediate_interval_passed(){ + return _private_impl->is_intermediate_interval_passed(); +} + +bool M2MTimer::is_total_interval_passed(){ + return _private_impl->is_total_interval_passed(); +} diff --git a/features/FEATURE_CLIENT/mbed-client-classic/source/m2mtimerpimpl.cpp b/features/FEATURE_CLIENT/mbed-client-classic/source/m2mtimerpimpl.cpp new file mode 100644 index 0000000000..be8100a8d7 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-classic/source/m2mtimerpimpl.cpp @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2015-2016 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client-classic/m2mtimerpimpl.h" +#include "mbed-client/m2mtimerobserver.h" +#include "mbed-client/m2mvector.h" + +#include "eventOS_event.h" +#include "eventOS_event_timer.h" +#include "eventOS_scheduler.h" +#include "ns_hal_init.h" +#include "mbed-trace/mbed_trace.h" + +#define TRACE_GROUP "mClt" + +#define MBED_CLIENT_TIMER_EVENT 10 + +#ifdef MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE +#define MBED_CLIENT_EVENT_LOOP_SIZE MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE +#else +#define MBED_CLIENT_EVENT_LOOP_SIZE 1024 +#endif + +int8_t M2MTimerPimpl::_tasklet_id = -1; + +int8_t M2MTimerPimpl::_next_timer_id = 1; + +static m2m::Vector timer_impl_list; + +extern "C" void tasklet_func(arm_event_s *event) +{ + // skip the init event as there will be a timer event after + if (event->event_type == MBED_CLIENT_TIMER_EVENT) { + + bool timer_found = false; + eventOS_scheduler_mutex_wait(); + int timer_count = timer_impl_list.size(); + for (int index = 0; index < timer_count; index++) { + M2MTimerPimpl* timer = timer_impl_list[index]; + if (timer->get_timer_id() == event->event_id) { + eventOS_scheduler_mutex_release(); + timer_found = true; + timer->timer_expired(); + break; + } + } + if(!timer_found) { + eventOS_scheduler_mutex_release(); + } + } +} + +M2MTimerPimpl::M2MTimerPimpl(M2MTimerObserver& observer) +: _observer(observer), + _single_shot(true), + _interval(0), + _type(M2MTimerObserver::Notdefined), + _intermediate_interval(0), + _total_interval(0), + _status(0), + _dtls_type(false) +{ + ns_hal_init(NULL, MBED_CLIENT_EVENT_LOOP_SIZE, NULL, NULL); + eventOS_scheduler_mutex_wait(); + if (_tasklet_id < 0) { + _tasklet_id = eventOS_event_handler_create(tasklet_func, MBED_CLIENT_TIMER_EVENT); + assert(_tasklet_id >= 0); + } + + // XXX: this wraps over quite soon + _timer_id = M2MTimerPimpl::_next_timer_id++; + + timer_impl_list.push_back(this); + eventOS_scheduler_mutex_release(); +} + +M2MTimerPimpl::~M2MTimerPimpl() +{ + // cancel the timer request, if any is pending + cancel(); + + // there is no turning back, event os does not have eventOS_event_handler_delete() or similar, + // so the tasklet is lost forever. Same goes with timer_impl_list, which leaks now memory. + + // remove the timer from object list + eventOS_scheduler_mutex_wait(); + int timer_count = timer_impl_list.size(); + for (int index = 0; index < timer_count; index++) { + + const M2MTimerPimpl* timer = timer_impl_list[index]; + if (timer->get_timer_id() == _timer_id) { + + timer_impl_list.erase(index); + break; + } + } + eventOS_scheduler_mutex_release(); +} + +void M2MTimerPimpl::start_timer( uint64_t interval, + M2MTimerObserver::Type type, + bool single_shot) +{ + assert(interval <= INT32_MAX); + + _dtls_type = false; + _intermediate_interval = 0; + _total_interval = 0; + _status = 0; + _single_shot = single_shot; + _interval = interval; + _type = type; + start(); +} + +void M2MTimerPimpl::start_dtls_timer(uint64_t intermediate_interval, uint64_t total_interval, M2MTimerObserver::Type type) +{ + assert(intermediate_interval <= INT32_MAX); + assert(intermediate_interval <= total_interval); + + _dtls_type = true; + _intermediate_interval = intermediate_interval; + _total_interval = total_interval; + _interval = _intermediate_interval; + _status = 0; + _single_shot = false; + _type = type; + start(); +} + +void M2MTimerPimpl::start() +{ + int status; + + status = eventOS_event_timer_request(_timer_id, MBED_CLIENT_TIMER_EVENT, + M2MTimerPimpl::_tasklet_id, + _interval); + assert(status == 0); +} + +void M2MTimerPimpl::cancel() +{ + eventOS_event_timer_cancel(_timer_id, M2MTimerPimpl::_tasklet_id); +} + +void M2MTimerPimpl::stop_timer() +{ + _interval = 0; + _single_shot = true; + cancel(); +} + +void M2MTimerPimpl::timer_expired() +{ + _status++; + _observer.timer_expired(_type); + + if ((!_dtls_type) && (!_single_shot)) { + // start next round of periodic timer + start(); + } else if ((_dtls_type) && (!is_total_interval_passed())) { + // if only the intermediate time has passed, we need still wait up to total time + _interval = _total_interval - _intermediate_interval; + start(); + } +} + +bool M2MTimerPimpl::is_intermediate_interval_passed() +{ + if (_status > 0) { + return true; + } + return false; +} + +bool M2MTimerPimpl::is_total_interval_passed() +{ + if (_status > 1) { + return true; + } + return false; +} diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/.gitignore b/features/FEATURE_CLIENT/mbed-client-mbed-tls/.gitignore new file mode 100644 index 0000000000..3b689afb8c --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/.gitignore @@ -0,0 +1,7 @@ +.yotta.json +coverage/ +lcov/ +yotta_modules/ +yotta_targets/ +upload.tar.gz +build/ diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/.mbedignore b/features/FEATURE_CLIENT/mbed-client-mbed-tls/.mbedignore new file mode 100644 index 0000000000..ab1cfb4ef2 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/.mbedignore @@ -0,0 +1 @@ +test/* diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/LICENSE b/features/FEATURE_CLIENT/mbed-client-mbed-tls/LICENSE new file mode 100644 index 0000000000..97df0e645d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/LICENSE @@ -0,0 +1,2 @@ +Unless specifically indicated otherwise in a file, files are licensed +under the Apache 2.0 license, as can be found in: apache-2.0.txt \ No newline at end of file diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/README.md b/features/FEATURE_CLIENT/mbed-client-mbed-tls/README.md new file mode 100644 index 0000000000..74c4cf0fef --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/README.md @@ -0,0 +1,2 @@ +# mbed-client-mbedtls +Mbedtls specific implementation, which can be used by mbed clients diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/apache-2.0.txt b/features/FEATURE_CLIENT/mbed-client-mbed-tls/apache-2.0.txt new file mode 100644 index 0000000000..0e4cf3ee99 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/apache-2.0.txt @@ -0,0 +1,56 @@ + + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + You must give any other recipients of the Work or Derivative Works a copy of this License; and + You must cause any modified files to carry prominent notices stating that You changed the files; and + You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/include_dirs.mk b/features/FEATURE_CLIENT/mbed-client-mbed-tls/include_dirs.mk new file mode 100644 index 0000000000..3c5aef4d28 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/include_dirs.mk @@ -0,0 +1,15 @@ +INCLUDE_DIRS := \ + ../ \ + . \ + ../../nsdl-c \ + ../../libService/libService \ + ../../libService/exported-libs/mbed-client-libservice \ + ../../libService \ + ../../mbedtls/include \ + ../lwm2m-client \ + ../lwm2m-client/mbed-client \ + ../lwm2m-client-linux/source \ + ../lwm2m-client-mbedtls \ + source \ + + diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/junit_xsl.xslt b/features/FEATURE_CLIENT/mbed-client-mbed-tls/junit_xsl.xslt new file mode 100644 index 0000000000..7376b27f26 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/junit_xsl.xslt @@ -0,0 +1,101 @@ + + + + + + + + + +

+ Unittest report +

+ +

+ + Total tests run + , failures: + + + + + +

+
+ + +

+ +

+ + + + + + + + + + + +
Tests runTests failedOther errors
+
+ + + + + + + + +
Tests namePASS/FAILFailing caseReason
+
+ + + + + + + + + + + PASS + + + + + + + FAIL + + + + + + + + + + + + + + + + FAIL + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/mbed-client-mbedtls/m2mconnectionsecuritypimpl.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/mbed-client-mbedtls/m2mconnectionsecuritypimpl.h new file mode 100644 index 0000000000..bb13af4ecb --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/mbed-client-mbedtls/m2mconnectionsecuritypimpl.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 __M2M_CONNECTION_SECURITY_PIMPL_H__ +#define __M2M_CONNECTION_SECURITY_PIMPL_H__ + +#include "mbed-client/m2mconnectionsecurity.h" +#include "mbed-client/m2mtimerobserver.h" +#include "mbed-client/m2mconstants.h" +#include "mbed-client/m2msecurity.h" + +#include "mbedtls/config.h" +#include "mbedtls/platform.h" +#include "mbedtls/debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" +#include "mbedtls/certs.h" +#include "mbedtls/entropy_poll.h" + +class M2MTimer; + +//TODO: Should we let application to select these or not?? +const static int PSK_SUITES[] = { + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, + MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, + 0 +}; + + +/** + * @brief The M2MConnectionSecurityPimpl class + */ +class M2MConnectionSecurityPimpl : public M2MTimerObserver { + +private: + + // Prevents the use of assignment operator by accident. + M2MConnectionSecurityPimpl& operator=( const M2MConnectionSecurityPimpl& /*other*/ ); + // Prevents the use of copy constructor by accident + M2MConnectionSecurityPimpl( const M2MConnectionSecurityPimpl& /*other*/ ); + +public: + + /** + * @brief Constructor + */ + M2MConnectionSecurityPimpl(M2MConnectionSecurity::SecurityMode mode); + + /** + * @brief Destructor + */ + virtual ~M2MConnectionSecurityPimpl(); + + /** + * \brief Resets the socket connection states. + */ + void reset(); + + /** + * \brief Initiatlizes the socket connection states. + */ + int init(const M2MSecurity *security); + + /** + * \brief Starts the connection in non-blocking mode. + * \param connHandler The ConnectionHandler object that maintains the socket. + * \return Returns the state of the connection. Successful or not. + */ + int start_connecting_non_blocking(M2MConnectionHandler* connHandler); + + /** + * \brief Continues connectivity logic for secure connection. + * \return Returns an error code if any while continuing the connection sequence. + */ + int continue_connecting(); + + /** + * \brief Connects the client to the server. + * \param connHandler The ConnectionHandler object that maintains the socket. + * \return Returns the state of the connection. Successful or not. + */ + int connect(M2MConnectionHandler* connHandler); + + /** + * \brief Sends data to the server. + * \param message The data to be sent. + * \param len The length of the data. + * @return Indicates whether the data is sent successfully or not. + */ + int send_message(unsigned char *message, int len); + + /** + * \brief Reads the data received from the server. + * \param message The data to be read. + * \param len The length of the data. + * \return Indicates whether the data is read successfully or not. + */ + int read(unsigned char* buffer, uint16_t len); + + /** + * \brief Sets the function callback that will be called by mbed-client for + * fetching random number from application for ensuring strong entropy. + * \param random_callback A function pointer that will be called by mbed-client + * while performing secure handshake. + * Function signature should be uint32_t (*random_number_callback)(void); + */ + void set_random_number_callback(random_number_cb callback); + + /** + * \brief Sets the function callback that will be called by mbed-client for + * providing entropy source from application for ensuring strong entropy. + * \param entropy_callback A function pointer that will be called by mbed-client + * while performing secure handshake. + * Function signature , if using mbed-client-mbedtls should be + * int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, + * size_t len, size_t *olen); + */ + void set_entropy_callback(entropy_cb callback); + +protected: //From M2MTimerObserver + + virtual void timer_expired(M2MTimerObserver::Type type); + +private: + + int start_handshake(); + +private: + + bool _init_done; + mbedtls_ssl_config _conf; + mbedtls_ssl_context _ssl; + mbedtls_x509_crt _cacert; + mbedtls_x509_crt _owncert; + mbedtls_pk_context _pkey; + mbedtls_ctr_drbg_context _ctr_drbg; + mbedtls_entropy_context _entropy; + uint32_t _flags; + M2MTimer *_timer; + M2MConnectionSecurity::SecurityMode _sec_mode; + + friend class Test_M2MConnectionSecurityPimpl; +}; + +#endif //__M2M_CONNECTION_SECURITY_PIMPL_H__ diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/module.json b/features/FEATURE_CLIENT/mbed-client-mbed-tls/module.json new file mode 100644 index 0000000000..8403c7f149 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/module.json @@ -0,0 +1,19 @@ +{ + "name": "mbed-client-mbedtls", + "version": "3.0.3", + "description": "Mbedtls specific implementation, which can be used by mbed client", + "keywords": [ + "mbed-client-mbedtls" + ], + "author": "Antti Kauppila", + "repository": { + "url": "git@github.com:ARMmbed/mbed-client-mbedtls.git", + "type": "git" + }, + "homepage": "https://github.com/ARMmbed/mbed-client-mbedtls", + "license": "Apache-2.0", + "dependencies": { + "mbedtls": "^2.0.0" + }, + "targetDependencies": {} +} diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/run_unit_tests_with_valgrind.sh b/features/FEATURE_CLIENT/mbed-client-mbed-tls/run_unit_tests_with_valgrind.sh new file mode 100755 index 0000000000..f02fd71470 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/run_unit_tests_with_valgrind.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# Execute script with root path where to find binaries. +# For example ./run_unit_tests_with_valgrind.sh ./build/x86-linux-native-coverage/test/mbedclient/ + +input="binaries.txt" +valgrind_logs="valgrind_logs" +rm -rf $valgrind_logs +mkdir $valgrind_logs +find $1 -type f -executable -exec sh -c "file -i '{}' | grep -q 'x-executable; charset=binary'" \; -print > $input +while file= read -r binary +do + valgrind --track-origins=yes --xml=yes --xml-file="${valgrind_logs}/valgrind_$(basename $binary).xml" "$binary" + +done < "$input" diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/source/m2mconnectionsecurity.cpp b/features/FEATURE_CLIENT/mbed-client-mbed-tls/source/m2mconnectionsecurity.cpp new file mode 100644 index 0000000000..b76f15cb0e --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/source/m2mconnectionsecurity.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client/m2mconnectionhandler.h" +#include "mbed-client/m2mconnectionsecurity.h" +#include "mbed-client/m2mtimer.h" +#include "mbed-client/m2msecurity.h" +#include "mbed-client-mbedtls/m2mconnectionsecuritypimpl.h" + +M2MConnectionSecurity::M2MConnectionSecurity(SecurityMode mode) +{ + _private_impl = new M2MConnectionSecurityPimpl(mode); +} + +M2MConnectionSecurity::~M2MConnectionSecurity(){ + delete _private_impl; +} + +void M2MConnectionSecurity::reset(){ + _private_impl->reset(); +} + +int M2MConnectionSecurity::init(const M2MSecurity *security){ + return _private_impl->init(security); +} + +int M2MConnectionSecurity::start_connecting_non_blocking(M2MConnectionHandler* connHandler) +{ + return _private_impl->start_connecting_non_blocking(connHandler); +} + +int M2MConnectionSecurity::continue_connecting() +{ + return _private_impl->continue_connecting(); +} + +int M2MConnectionSecurity::connect(M2MConnectionHandler* connHandler){ + return _private_impl->connect(connHandler); +} + +int M2MConnectionSecurity::send_message(unsigned char *message, int len){ + return _private_impl->send_message(message, len); +} + +int M2MConnectionSecurity::read(unsigned char* buffer, uint16_t len){ + return _private_impl->read(buffer, len); +} + +void M2MConnectionSecurity::set_random_number_callback(random_number_cb callback) +{ + _private_impl->set_random_number_callback(callback); +} + +void M2MConnectionSecurity::set_entropy_callback(entropy_cb callback) +{ + _private_impl->set_entropy_callback(callback); +} diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/source/m2mconnectionsecuritypimpl.cpp b/features/FEATURE_CLIENT/mbed-client-mbed-tls/source/m2mconnectionsecuritypimpl.cpp new file mode 100644 index 0000000000..1da7435883 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/source/m2mconnectionsecuritypimpl.cpp @@ -0,0 +1,454 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client/m2mconnectionhandler.h" +#include "mbed-client-mbedtls/m2mconnectionsecuritypimpl.h" +#include "mbed-client/m2mtimer.h" +#include "mbed-client/m2msecurity.h" +#include "mbed-trace/mbed_trace.h" +#include "mbedtls/debug.h" +#include + +#define TRACE_GROUP "mClt" + +void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ); +int mbedtls_timing_get_delay( void *data ); +int entropy_poll( void *data, unsigned char *output, size_t len, size_t *olen ); +//Point these back to M2MConnectionHandler!!! +int f_send( void *ctx, const unsigned char *buf, size_t len ); +int f_recv(void *ctx, unsigned char *buf, size_t len); +int f_recv_timeout(void *ctx, unsigned char *buf, size_t len, uint32_t some); + +bool cancelled; +random_number_cb __random_number_callback; +entropy_cb __entropy_callback; + +//Comment out following define to enable tracing from mbedtls +//#define ENABLE_MBED_CLIENT_MBED_TLS_DEBUGS +#ifdef ENABLE_MBED_CLIENT_MBED_TLS_DEBUGS +static void mbedtls_debug( void *ctx, int level, + const char *file, int line, const char *str ) +{ + ((void) level); + tr_debug("%s", str); +} + +static int verify_cert_chains(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) +{ + char buf[1024]; + (void) data; + + printf("\nVerifying certificate at depth %d:\n", depth); + mbedtls_x509_crt_info(buf, sizeof (buf) - 1, " ", crt); + printf("%s", buf); + + if (*flags == 0) + printf("No verification issue for this certificate\n"); + else + { + mbedtls_x509_crt_verify_info(buf, sizeof (buf), " ! ", *flags); + printf("%s\n", buf); + } + + return 0; +} +#endif + +M2MConnectionSecurityPimpl::M2MConnectionSecurityPimpl(M2MConnectionSecurity::SecurityMode mode) + : _flags(0), + _sec_mode(mode) +{ + _init_done = false; + cancelled = true; + _timer = new M2MTimer(*this); + mbedtls_ssl_init( &_ssl ); + mbedtls_ssl_config_init( &_conf ); + mbedtls_x509_crt_init( &_cacert ); + mbedtls_x509_crt_init(&_owncert); + mbedtls_pk_init(&_pkey); + mbedtls_ctr_drbg_init( &_ctr_drbg ); + mbedtls_entropy_init( &_entropy ); +} + +M2MConnectionSecurityPimpl::~M2MConnectionSecurityPimpl(){ + mbedtls_ssl_config_free(&_conf); + mbedtls_ssl_free(&_ssl); + mbedtls_x509_crt_free(&_cacert); + mbedtls_x509_crt_free(&_owncert); + mbedtls_pk_free(&_pkey); + mbedtls_ctr_drbg_free( &_ctr_drbg ); + mbedtls_entropy_free( &_entropy ); + delete _timer; +} + +void M2MConnectionSecurityPimpl::timer_expired(M2MTimerObserver::Type type){ + tr_debug("M2MConnectionSecurityPimpl::timer_expired"); + if(type == M2MTimerObserver::Dtls && !cancelled){ + int error = continue_connecting(); + if(MBEDTLS_ERR_SSL_TIMEOUT == error || error == -1) { + tr_error("M2MConnectionSecurityPimpl::timer_expired - handshake timeout"); + if(_ssl.p_bio) { + M2MConnectionHandler* ptr = (M2MConnectionHandler*)_ssl.p_bio; + ptr->handle_connection_error(M2MConnectionHandler::SSL_HANDSHAKE_ERROR); + } + reset(); + } + } +} + +void M2MConnectionSecurityPimpl::reset(){ + _init_done = false; + cancelled = true; + mbedtls_ssl_config_free(&_conf); + mbedtls_ssl_free(&_ssl); + mbedtls_x509_crt_free(&_cacert); + mbedtls_x509_crt_free(&_owncert); + mbedtls_pk_free(&_pkey); + mbedtls_ctr_drbg_free( &_ctr_drbg ); + mbedtls_entropy_free( &_entropy ); + _timer->stop_timer(); +} + +int M2MConnectionSecurityPimpl::init(const M2MSecurity *security) +{ + tr_debug("M2MConnectionSecurityPimpl::init"); + int ret = -1; + if (security != NULL) { + const char *pers = "dtls_client"; + mbedtls_ssl_init( &_ssl ); + mbedtls_ssl_config_init( &_conf ); + mbedtls_x509_crt_init( &_cacert ); + mbedtls_x509_crt_init(&_owncert); + mbedtls_pk_init(&_pkey); + mbedtls_ctr_drbg_init( &_ctr_drbg ); + mbedtls_entropy_init( &_entropy ); + + int mode = MBEDTLS_SSL_TRANSPORT_DATAGRAM; + if( _sec_mode == M2MConnectionSecurity::TLS ){ + mode = MBEDTLS_SSL_TRANSPORT_STREAM; + } + + if( mbedtls_entropy_add_source( &_entropy, entropy_poll, NULL, + 128, 0 ) < 0 ){ + return -1; + } + if(__entropy_callback.entropy_source_ptr) { + if( mbedtls_entropy_add_source( &_entropy, __entropy_callback.entropy_source_ptr, + __entropy_callback.p_source,__entropy_callback.threshold, + __entropy_callback.strong ) < 0 ){ + return -1; + } + } + + if( mbedtls_ctr_drbg_seed( &_ctr_drbg, mbedtls_entropy_func, &_entropy, + (const unsigned char *) pers, + strlen( pers ) ) != 0 ) { + return -1; + } + + if( mbedtls_ssl_config_defaults( &_conf, + MBEDTLS_SSL_IS_CLIENT, + mode, 0 ) != 0 ) { + return -1; + } + + M2MSecurity::SecurityModeType cert_mode = + (M2MSecurity::SecurityModeType)security->resource_value_int(M2MSecurity::SecurityMode); + + // Note: these are relatively large buffers, no point to make copy of them here as mbedtls will make a copy of them. + const uint8_t *srv_public_key = NULL; + const uint8_t *public_key = NULL; + const uint8_t *sec_key = NULL; + + uint32_t srv_public_key_size = security->resource_value_buffer(M2MSecurity::ServerPublicKey, srv_public_key); + uint32_t public_key_size = security->resource_value_buffer(M2MSecurity::PublicKey, public_key); + uint32_t sec_key_size = security->resource_value_buffer(M2MSecurity::Secretkey, sec_key); + if( srv_public_key == NULL || public_key == NULL || sec_key == NULL || + srv_public_key_size == 0 || public_key_size == 0 || sec_key_size == 0 ){ + return -1; + } + + if( cert_mode == M2MSecurity::Certificate ){ + if ( mbedtls_x509_crt_parse( &_cacert, (const unsigned char *) srv_public_key, + srv_public_key_size + 1) < 0 || + mbedtls_x509_crt_parse( &_owncert, (const unsigned char *) public_key, + public_key_size + 1) < 0 || + mbedtls_pk_parse_key(&_pkey, (const unsigned char *) sec_key, + sec_key_size + 1, NULL, 0 ) < 0 ) { + ret = -1; + } else { + ret = 0; + } + + if ( ret == 0 ) { + mbedtls_ssl_conf_own_cert(&_conf, &_owncert, &_pkey); + mbedtls_ssl_conf_authmode( &_conf, MBEDTLS_SSL_VERIFY_REQUIRED ); + mbedtls_ssl_conf_ca_chain( &_conf, &_cacert, NULL ); + } + + } else if ( cert_mode == M2MSecurity::Psk ){ + if (mbedtls_ssl_conf_psk(&_conf, sec_key, sec_key_size, public_key, public_key_size) == 0) { + ret = 0; + } + mbedtls_ssl_conf_ciphersuites(&_conf, PSK_SUITES); + } else { + ret = -1; + } + +#ifdef ENABLE_MBED_CLIENT_MBED_TLS_DEBUGS + mbedtls_ssl_conf_dbg( &_conf, mbedtls_debug, stdout ); + mbedtls_debug_set_threshold(5); + mbedtls_ssl_conf_verify(&_conf, verify_cert_chains, NULL); +#endif + } + + if( ret == 0 ){ + _init_done = true; + } + tr_debug("M2MConnectionSecurityPimpl::init - ret %d", ret); + return ret; +} + + +int M2MConnectionSecurityPimpl::start_handshake(){ + tr_debug("M2MConnectionSecurityPimpl::start_handshake"); + int ret = -1; + do + { + ret = mbedtls_ssl_handshake( &_ssl ); + } + while( ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE); + + if( ret != 0 ) { + ret = -1; + }else { + if( ( _flags = mbedtls_ssl_get_verify_result( &_ssl ) ) != 0 ) { + ret = -1; + } + } + tr_debug("M2MConnectionSecurityPimpl::start_handshake - OUT"); + return ret; +} + +int M2MConnectionSecurityPimpl::connect(M2MConnectionHandler* connHandler){ + + tr_debug("M2MConnectionSecurityPimpl::connect"); + int ret=-1; + if(!_init_done){ + return ret; + } + + mbedtls_ssl_conf_rng( &_conf, mbedtls_ctr_drbg_random, &_ctr_drbg ); + + if( ( ret = mbedtls_ssl_setup( &_ssl, &_conf ) ) != 0 ) { + return -1; + } + + mbedtls_ssl_set_bio( &_ssl, connHandler, + f_send, f_recv, f_recv_timeout ); + + mbedtls_ssl_set_timer_cb( &_ssl, _timer, mbedtls_timing_set_delay, + mbedtls_timing_get_delay ); + + ret = start_handshake(); + _timer->stop_timer(); + tr_debug("M2MConnectionSecurityPimpl::connect - handshake ret: %d, ssl state: %d", ret, _ssl.state); + return ret; +} + +int M2MConnectionSecurityPimpl::start_connecting_non_blocking(M2MConnectionHandler* connHandler) +{ + tr_debug("M2MConnectionSecurityPimpl::start_connecting_non_blocking"); + int ret=-1; + if(!_init_done){ + return ret; + } + + int mode = MBEDTLS_SSL_TRANSPORT_DATAGRAM; + if( _sec_mode == M2MConnectionSecurity::TLS ){ + mode = MBEDTLS_SSL_TRANSPORT_STREAM; + } + + if( ( ret = mbedtls_ssl_config_defaults( &_conf, + MBEDTLS_SSL_IS_CLIENT, + mode, 0 ) ) != 0 ) + { + return -1; + } + + // This is for non-blocking sockets total timeout is 1+2+4+8+16+29=60 seconds + mbedtls_ssl_conf_handshake_timeout( &_conf, 10000, 29000 ); + mbedtls_ssl_conf_rng( &_conf, mbedtls_ctr_drbg_random, &_ctr_drbg ); + + if( ( ret = mbedtls_ssl_setup( &_ssl, &_conf ) ) != 0 ) + { + return -1; + } + + mbedtls_ssl_set_bio( &_ssl, connHandler, + f_send, f_recv, f_recv_timeout ); + + mbedtls_ssl_set_timer_cb( &_ssl, _timer, mbedtls_timing_set_delay, + mbedtls_timing_get_delay ); + + ret = mbedtls_ssl_handshake_step( &_ssl ); + if( ret == 0 ){ + ret = mbedtls_ssl_handshake_step( &_ssl ); + } + + if( ret >= 0){ + ret = 1; + } else { + ret = -1; + } + tr_debug("M2MConnectionSecurityPimpl::start_connecting_non_blocking - handshake ret: %d, ssl state: %d", ret, _ssl.state); + return ret; +} + +int M2MConnectionSecurityPimpl::continue_connecting() +{ + tr_debug("M2MConnectionSecurityPimpl::continue_connecting"); + int ret=-1; + while( ret != M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ ){ + ret = mbedtls_ssl_handshake_step( &_ssl ); + if( MBEDTLS_ERR_SSL_WANT_READ == ret ){ + ret = M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ; + } + else if (ret != 0) { + break; + } + + if( _ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER ){ + return 0; + } + } + tr_debug("M2MConnectionSecurityPimpl::continue_connecting, ret: %d", ret); + return ret; +} + +int M2MConnectionSecurityPimpl::send_message(unsigned char *message, int len){ + tr_debug("M2MConnectionSecurityPimpl::send_message"); + int ret=-1; + if(!_init_done){ + return ret; + } + + do ret = mbedtls_ssl_write( &_ssl, (unsigned char *) message, len ); + while( ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + + tr_debug("M2MConnectionSecurityPimpl::send_message - ret: %d", ret); + return ret; //bytes written +} + +int M2MConnectionSecurityPimpl::read(unsigned char* buffer, uint16_t len){ + int ret=-1; + if(!_init_done){ + tr_error("M2MConnectionSecurityPimpl::read - init not done!"); + return ret; + } + + memset( buffer, 0, len ); + do ret = mbedtls_ssl_read( &_ssl, buffer, len-1 ); + while( ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + + return ret; //bytes read +} + +int f_send( void *ctx, const unsigned char *buf, size_t len){ + M2MConnectionHandler* handler = ((M2MConnectionHandler *) ctx); + return handler->send_to_socket(buf, len); +} + +int f_recv(void *ctx, unsigned char *buf, size_t len){ + M2MConnectionHandler* handler = ((M2MConnectionHandler *) ctx); + return handler->receive_from_socket(buf, len); +} + +int f_recv_timeout(void *ctx, unsigned char *buf, size_t len, uint32_t /*some*/){ + return f_recv(ctx, buf, len); +} + +int entropy_poll( void *, unsigned char *output, size_t len, + size_t *olen ) +{ + uint32_t rdm = 0; + if(__random_number_callback) { + rdm = __random_number_callback(); + } else { + rdm = time(NULL); + } + for(uint16_t i=0; i < len; i++){ + srand(rdm); + output[i] = rand() % 256; + } + *olen = len; + + return( 0 ); +} + +void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ){ + tr_debug("mbedtls_timing_set_delay - intermediate: %d", int_ms); + tr_debug("mbedtls_timing_set_delay - final: %d", fin_ms); + M2MTimer* timer = static_cast (data); + if(!timer) { + return; + } + if( int_ms > 0 && fin_ms > 0 ){ + tr_debug("mbedtls_timing_set_delay - start"); + cancelled = false; + timer->stop_timer(); + timer->start_dtls_timer(int_ms, fin_ms); + }else{ + tr_debug("mbedtls_timing_set_delay - stop"); + cancelled = true; + timer->stop_timer(); + } +} + +int mbedtls_timing_get_delay( void *data ){ + tr_debug("mbedtls_timing_get_delay"); + M2MTimer* timer = static_cast (data); + if(!timer){ + return 0; + } + if(true == cancelled) { + tr_debug("mbedtls_timing_get_delay - ret -1"); + return -1; + } else if( timer->is_total_interval_passed() ){ + tr_debug("mbedtls_timing_get_delay - ret 2"); + return 2; + }else if( timer->is_intermediate_interval_passed() ){ + tr_debug("mbedtls_timing_get_delay - ret 1"); + return 1; + }else{ + tr_debug("mbedtls_timing_get_delay - ret 0"); + return 0; + } +} + +void M2MConnectionSecurityPimpl::set_random_number_callback(random_number_cb callback) +{ + __random_number_callback = callback; +} + +void M2MConnectionSecurityPimpl::set_entropy_callback(entropy_cb callback) +{ + __entropy_callback = callback; +} + diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/sources.mk b/features/FEATURE_CLIENT/mbed-client-mbed-tls/sources.mk new file mode 100644 index 0000000000..49747ba558 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/sources.mk @@ -0,0 +1,7 @@ +SRCS += \ + source/m2mconnectionsecurity.cpp \ + source/m2mconnectionsecuritypimpl.cpp \ + + + + diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/MakefileWorker.mk b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/MakefileWorker.mk new file mode 100755 index 0000000000..2096ced036 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/MakefileWorker.mk @@ -0,0 +1,562 @@ +#--------- +# +# MakefileWorker.mk +# +# Include this helper file in your makefile +# It makes +# A static library +# A test executable +# +# See this example for parameter settings +# examples/Makefile +# +#---------- +# Inputs - these variables describe what to build +# +# INCLUDE_DIRS - Directories used to search for include files. +# This generates a -I for each directory +# SRC_DIRS - Directories containing source file to built into the library +# SRC_FILES - Specific source files to build into library. Helpful when not all code +# in a directory can be built for test (hopefully a temporary situation) +# TEST_SRC_DIRS - Directories containing unit test code build into the unit test runner +# These do not go in a library. They are explicitly included in the test runner +# TEST_SRC_FILES - Specific source files to build into the unit test runner +# These do not go in a library. They are explicitly included in the test runner +# MOCKS_SRC_DIRS - Directories containing mock source files to build into the test runner +# These do not go in a library. They are explicitly included in the test runner +#---------- +# You can adjust these variables to influence how to build the test target +# and where to put and name outputs +# See below to determine defaults +# COMPONENT_NAME - the name of the thing being built +# TEST_TARGET - name the test executable. By default it is +# $(COMPONENT_NAME)_tests +# Helpful if you want 1 > make files in the same directory with different +# executables as output. +# CPPUTEST_HOME - where CppUTest home dir found +# TARGET_PLATFORM - Influences how the outputs are generated by modifying the +# CPPUTEST_OBJS_DIR and CPPUTEST_LIB_DIR to use a sub-directory under the +# normal objs and lib directories. Also modifies where to search for the +# CPPUTEST_LIB to link against. +# CPPUTEST_OBJS_DIR - a directory where o and d files go +# CPPUTEST_LIB_DIR - a directory where libs go +# CPPUTEST_ENABLE_DEBUG - build for debug +# CPPUTEST_USE_MEM_LEAK_DETECTION - Links with overridden new and delete +# CPPUTEST_USE_STD_CPP_LIB - Set to N to keep the standard C++ library out +# of the test harness +# CPPUTEST_USE_GCOV - Turn on coverage analysis +# Clean then build with this flag set to Y, then 'make gcov' +# CPPUTEST_MAPFILE - generate a map file +# CPPUTEST_WARNINGFLAGS - overly picky by default +# OTHER_MAKEFILE_TO_INCLUDE - a hook to use this makefile to make +# other targets. Like CSlim, which is part of fitnesse +# CPPUTEST_USE_VPATH - Use Make's VPATH functionality to support user +# specification of source files and directories that aren't below +# the user's Makefile in the directory tree, like: +# SRC_DIRS += ../../lib/foo +# It defaults to N, and shouldn't be necessary except in the above case. +#---------- +# +# Other flags users can initialize to sneak in their settings +# CPPUTEST_CXXFLAGS - flags for the C++ compiler +# CPPUTEST_CPPFLAGS - flags for the C++ AND C preprocessor +# CPPUTEST_CFLAGS - flags for the C complier +# CPPUTEST_LDFLAGS - Linker flags +#---------- + +# Some behavior is weird on some platforms. Need to discover the platform. + +# Platforms +UNAME_OUTPUT = "$(shell uname -a)" +MACOSX_STR = Darwin +MINGW_STR = MINGW +CYGWIN_STR = CYGWIN +LINUX_STR = Linux +SUNOS_STR = SunOS +UNKNWOWN_OS_STR = Unknown + +# Compilers +CC_VERSION_OUTPUT ="$(shell $(CXX) -v 2>&1)" +CLANG_STR = clang +SUNSTUDIO_CXX_STR = SunStudio + +UNAME_OS = $(UNKNWOWN_OS_STR) + +ifeq ($(findstring $(MINGW_STR),$(UNAME_OUTPUT)),$(MINGW_STR)) + UNAME_OS = $(MINGW_STR) +endif + +ifeq ($(findstring $(CYGWIN_STR),$(UNAME_OUTPUT)),$(CYGWIN_STR)) + UNAME_OS = $(CYGWIN_STR) +endif + +ifeq ($(findstring $(LINUX_STR),$(UNAME_OUTPUT)),$(LINUX_STR)) + UNAME_OS = $(LINUX_STR) +endif + +ifeq ($(findstring $(MACOSX_STR),$(UNAME_OUTPUT)),$(MACOSX_STR)) + UNAME_OS = $(MACOSX_STR) +#lion has a problem with the 'v' part of -a + UNAME_OUTPUT = "$(shell uname -pmnrs)" +endif + +ifeq ($(findstring $(SUNOS_STR),$(UNAME_OUTPUT)),$(SUNOS_STR)) + UNAME_OS = $(SUNOS_STR) + + SUNSTUDIO_CXX_ERR_STR = CC -flags +ifeq ($(findstring $(SUNSTUDIO_CXX_ERR_STR),$(CC_VERSION_OUTPUT)),$(SUNSTUDIO_CXX_ERR_STR)) + CC_VERSION_OUTPUT ="$(shell $(CXX) -V 2>&1)" + COMPILER_NAME = $(SUNSTUDIO_CXX_STR) +endif +endif + +ifeq ($(findstring $(CLANG_STR),$(CC_VERSION_OUTPUT)),$(CLANG_STR)) + COMPILER_NAME = $(CLANG_STR) +endif + +#Kludge for mingw, it does not have cc.exe, but gcc.exe will do +ifeq ($(UNAME_OS),$(MINGW_STR)) + CC := gcc +endif + +#And another kludge. Exception handling in gcc 4.6.2 is broken when linking the +# Standard C++ library as a shared library. Unbelievable. +ifeq ($(UNAME_OS),$(MINGW_STR)) + CPPUTEST_LDFLAGS += -static +endif +ifeq ($(UNAME_OS),$(CYGWIN_STR)) + CPPUTEST_LDFLAGS += -static +endif + + +#Kludge for MacOsX gcc compiler on Darwin9 who can't handle pendantic +ifeq ($(UNAME_OS),$(MACOSX_STR)) +ifeq ($(findstring Version 9,$(UNAME_OUTPUT)),Version 9) + CPPUTEST_PEDANTIC_ERRORS = N +endif +endif + +ifndef COMPONENT_NAME + COMPONENT_NAME = name_this_in_the_makefile +endif + +# Debug on by default +ifndef CPPUTEST_ENABLE_DEBUG + CPPUTEST_ENABLE_DEBUG = Y +endif + +# new and delete for memory leak detection on by default +ifndef CPPUTEST_USE_MEM_LEAK_DETECTION + CPPUTEST_USE_MEM_LEAK_DETECTION = Y +endif + +# Use the standard C library +ifndef CPPUTEST_USE_STD_C_LIB + CPPUTEST_USE_STD_C_LIB = Y +endif + +# Use the standard C++ library +ifndef CPPUTEST_USE_STD_CPP_LIB + CPPUTEST_USE_STD_CPP_LIB = Y +endif + +# Use gcov, off by default +ifndef CPPUTEST_USE_GCOV + CPPUTEST_USE_GCOV = N +endif + +ifndef CPPUTEST_PEDANTIC_ERRORS + CPPUTEST_PEDANTIC_ERRORS = Y +endif + +# Default warnings +ifndef CPPUTEST_WARNINGFLAGS + CPPUTEST_WARNINGFLAGS = -Wall -Wextra -Wshadow -Wswitch-default -Wswitch-enum -Wconversion +ifeq ($(CPPUTEST_PEDANTIC_ERRORS), Y) +# CPPUTEST_WARNINGFLAGS += -pedantic-errors + CPPUTEST_WARNINGFLAGS += -pedantic +endif +ifeq ($(UNAME_OS),$(LINUX_STR)) + CPPUTEST_WARNINGFLAGS += -Wsign-conversion +endif + CPPUTEST_CXX_WARNINGFLAGS = -Woverloaded-virtual + CPPUTEST_C_WARNINGFLAGS = -Wstrict-prototypes +endif + +#Wonderful extra compiler warnings with clang +ifeq ($(COMPILER_NAME),$(CLANG_STR)) +# -Wno-disabled-macro-expansion -> Have to disable the macro expansion warning as the operator new overload warns on that. +# -Wno-padded -> I sort-of like this warning but if there is a bool at the end of the class, it seems impossible to remove it! (except by making padding explicit) +# -Wno-global-constructors Wno-exit-time-destructors -> Great warnings, but in CppUTest it is impossible to avoid as the automatic test registration depends on the global ctor and dtor +# -Wno-weak-vtables -> The TEST_GROUP macro declares a class and will automatically inline its methods. Thats ok as they are only in one translation unit. Unfortunately, the warning can't detect that, so it must be disabled. + CPPUTEST_CXX_WARNINGFLAGS += -Weverything -Wno-disabled-macro-expansion -Wno-padded -Wno-global-constructors -Wno-exit-time-destructors -Wno-weak-vtables + CPPUTEST_C_WARNINGFLAGS += -Weverything -Wno-padded +endif + +# Uhm. Maybe put some warning flags for SunStudio here? +ifeq ($(COMPILER_NAME),$(SUNSTUDIO_CXX_STR)) + CPPUTEST_CXX_WARNINGFLAGS = + CPPUTEST_C_WARNINGFLAGS = +endif + +# Default dir for temporary files (d, o) +ifndef CPPUTEST_OBJS_DIR +ifndef TARGET_PLATFORM + CPPUTEST_OBJS_DIR = objs +else + CPPUTEST_OBJS_DIR = objs/$(TARGET_PLATFORM) +endif +endif + +# Default dir for the outout library +ifndef CPPUTEST_LIB_DIR +ifndef TARGET_PLATFORM + CPPUTEST_LIB_DIR = lib +else + CPPUTEST_LIB_DIR = lib/$(TARGET_PLATFORM) +endif +endif + +# No map by default +ifndef CPPUTEST_MAP_FILE + CPPUTEST_MAP_FILE = N +endif + +# No extentions is default +ifndef CPPUTEST_USE_EXTENSIONS + CPPUTEST_USE_EXTENSIONS = N +endif + +# No VPATH is default +ifndef CPPUTEST_USE_VPATH + CPPUTEST_USE_VPATH := N +endif +# Make empty, instead of 'N', for usage in $(if ) conditionals +ifneq ($(CPPUTEST_USE_VPATH), Y) + CPPUTEST_USE_VPATH := +endif + +ifndef TARGET_PLATFORM +#CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_HOME)/lib +CPPUTEST_LIB_LINK_DIR = /usr/lib/x86_64-linux-gnu +else +CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_HOME)/lib/$(TARGET_PLATFORM) +endif + +# -------------------------------------- +# derived flags in the following area +# -------------------------------------- + +# Without the C library, we'll need to disable the C++ library and ... +ifeq ($(CPPUTEST_USE_STD_C_LIB), N) + CPPUTEST_USE_STD_CPP_LIB = N + CPPUTEST_USE_MEM_LEAK_DETECTION = N + CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_C_LIB_DISABLED + CPPUTEST_CPPFLAGS += -nostdinc +endif + +CPPUTEST_CPPFLAGS += -DCPPUTEST_COMPILATION + +ifeq ($(CPPUTEST_USE_MEM_LEAK_DETECTION), N) + CPPUTEST_CPPFLAGS += -DCPPUTEST_MEM_LEAK_DETECTION_DISABLED +else + ifndef CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE + CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE = -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorNewMacros.h + endif + ifndef CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE + CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE = -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorMallocMacros.h + endif +endif + +ifeq ($(CPPUTEST_ENABLE_DEBUG), Y) + CPPUTEST_CXXFLAGS += -g + CPPUTEST_CFLAGS += -g + CPPUTEST_LDFLAGS += -g +endif + +ifeq ($(CPPUTEST_USE_STD_CPP_LIB), N) + CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_CPP_LIB_DISABLED +ifeq ($(CPPUTEST_USE_STD_C_LIB), Y) + CPPUTEST_CXXFLAGS += -nostdinc++ +endif +endif + +ifdef $(GMOCK_HOME) + GTEST_HOME = $(GMOCK_HOME)/gtest + CPPUTEST_CPPFLAGS += -I$(GMOCK_HOME)/include + GMOCK_LIBRARY = $(GMOCK_HOME)/lib/.libs/libgmock.a + LD_LIBRARIES += $(GMOCK_LIBRARY) + CPPUTEST_CPPFLAGS += -DINCLUDE_GTEST_TESTS + CPPUTEST_WARNINGFLAGS = + CPPUTEST_CPPFLAGS += -I$(GTEST_HOME)/include -I$(GTEST_HOME) + GTEST_LIBRARY = $(GTEST_HOME)/lib/.libs/libgtest.a + LD_LIBRARIES += $(GTEST_LIBRARY) +endif + + +ifeq ($(CPPUTEST_USE_GCOV), Y) + CPPUTEST_CXXFLAGS += -fprofile-arcs -ftest-coverage + CPPUTEST_CFLAGS += -fprofile-arcs -ftest-coverage +endif + +CPPUTEST_CXXFLAGS += $(CPPUTEST_WARNINGFLAGS) $(CPPUTEST_CXX_WARNINGFLAGS) +CPPUTEST_CPPFLAGS += $(CPPUTEST_WARNINGFLAGS) +CPPUTEST_CXXFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE) +CPPUTEST_CPPFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE) +CPPUTEST_CFLAGS += $(CPPUTEST_C_WARNINGFLAGS) + +TARGET_MAP = $(COMPONENT_NAME).map.txt +ifeq ($(CPPUTEST_MAP_FILE), Y) + CPPUTEST_LDFLAGS += -Wl,-map,$(TARGET_MAP) +endif + +# Link with CppUTest lib +CPPUTEST_LIB = $(CPPUTEST_LIB_LINK_DIR)/libCppUTest.a + +ifeq ($(CPPUTEST_USE_EXTENSIONS), Y) +CPPUTEST_LIB += $(CPPUTEST_LIB_LINK_DIR)/libCppUTestExt.a +endif + +ifdef CPPUTEST_STATIC_REALTIME + LD_LIBRARIES += -lrt +endif + +TARGET_LIB = \ + $(CPPUTEST_LIB_DIR)/lib$(COMPONENT_NAME).a + +ifndef TEST_TARGET + ifndef TARGET_PLATFORM + TEST_TARGET = $(COMPONENT_NAME)_tests + else + TEST_TARGET = $(COMPONENT_NAME)_$(TARGET_PLATFORM)_tests + endif +endif + +#Helper Functions +get_src_from_dir = $(wildcard $1/*.cpp) $(wildcard $1/*.cc) $(wildcard $1/*.c) +get_dirs_from_dirspec = $(wildcard $1) +get_src_from_dir_list = $(foreach dir, $1, $(call get_src_from_dir,$(dir))) +__src_to = $(subst .c,$1, $(subst .cc,$1, $(subst .cpp,$1,$(if $(CPPUTEST_USE_VPATH),$(notdir $2),$2)))) +src_to = $(addprefix $(CPPUTEST_OBJS_DIR)/,$(call __src_to,$1,$2)) +src_to_o = $(call src_to,.o,$1) +src_to_d = $(call src_to,.d,$1) +src_to_gcda = $(call src_to,.gcda,$1) +src_to_gcno = $(call src_to,.gcno,$1) +time = $(shell date +%s) +delta_t = $(eval minus, $1, $2) +debug_print_list = $(foreach word,$1,echo " $(word)";) echo; + +#Derived +STUFF_TO_CLEAN += $(TEST_TARGET) $(TEST_TARGET).exe $(TARGET_LIB) $(TARGET_MAP) + +SRC += $(call get_src_from_dir_list, $(SRC_DIRS)) $(SRC_FILES) +OBJ = $(call src_to_o,$(SRC)) + +STUFF_TO_CLEAN += $(OBJ) + +TEST_SRC += $(call get_src_from_dir_list, $(TEST_SRC_DIRS)) $(TEST_SRC_FILES) +TEST_OBJS = $(call src_to_o,$(TEST_SRC)) +STUFF_TO_CLEAN += $(TEST_OBJS) + + +MOCKS_SRC += $(call get_src_from_dir_list, $(MOCKS_SRC_DIRS)) +MOCKS_OBJS = $(call src_to_o,$(MOCKS_SRC)) +STUFF_TO_CLEAN += $(MOCKS_OBJS) + +ALL_SRC = $(SRC) $(TEST_SRC) $(MOCKS_SRC) + +# If we're using VPATH +ifeq ($(CPPUTEST_USE_VPATH), Y) +# gather all the source directories and add them + VPATH += $(sort $(dir $(ALL_SRC))) +# Add the component name to the objs dir path, to differentiate between same-name objects + CPPUTEST_OBJS_DIR := $(addsuffix /$(COMPONENT_NAME),$(CPPUTEST_OBJS_DIR)) +endif + +#Test coverage with gcov +GCOV_OUTPUT = gcov_output.txt +GCOV_REPORT = gcov_report.txt +GCOV_ERROR = gcov_error.txt +GCOV_GCDA_FILES = $(call src_to_gcda, $(ALL_SRC)) +GCOV_GCNO_FILES = $(call src_to_gcno, $(ALL_SRC)) +TEST_OUTPUT = $(TEST_TARGET).txt +STUFF_TO_CLEAN += \ + $(GCOV_OUTPUT)\ + $(GCOV_REPORT)\ + $(GCOV_REPORT).html\ + $(GCOV_ERROR)\ + $(GCOV_GCDA_FILES)\ + $(GCOV_GCNO_FILES)\ + $(TEST_OUTPUT) + +#The gcda files for gcov need to be deleted before each run +#To avoid annoying messages. +GCOV_CLEAN = $(SILENCE)rm -f $(GCOV_GCDA_FILES) $(GCOV_OUTPUT) $(GCOV_REPORT) $(GCOV_ERROR) +RUN_TEST_TARGET = $(SILENCE) $(GCOV_CLEAN) ; echo "Running $(TEST_TARGET)"; ./$(TEST_TARGET) $(CPPUTEST_EXE_FLAGS) -ojunit + +ifeq ($(CPPUTEST_USE_GCOV), Y) + + ifeq ($(COMPILER_NAME),$(CLANG_STR)) + LD_LIBRARIES += --coverage + else + LD_LIBRARIES += -lgcov + endif +endif + + +INCLUDES_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(INCLUDE_DIRS)) +INCLUDES += $(foreach dir, $(INCLUDES_DIRS_EXPANDED), -I$(dir)) +MOCK_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(MOCKS_SRC_DIRS)) +INCLUDES += $(foreach dir, $(MOCK_DIRS_EXPANDED), -I$(dir)) + +CPPUTEST_CPPFLAGS += $(INCLUDES) $(CPPUTESTFLAGS) + +DEP_FILES = $(call src_to_d, $(ALL_SRC)) +STUFF_TO_CLEAN += $(DEP_FILES) $(PRODUCTION_CODE_START) $(PRODUCTION_CODE_END) +STUFF_TO_CLEAN += $(STDLIB_CODE_START) $(MAP_FILE) cpputest_*.xml junit_run_output + +# We'll use the CPPUTEST_CFLAGS etc so that you can override AND add to the CppUTest flags +CFLAGS = $(CPPUTEST_CFLAGS) $(CPPUTEST_ADDITIONAL_CFLAGS) +CPPFLAGS = $(CPPUTEST_CPPFLAGS) $(CPPUTEST_ADDITIONAL_CPPFLAGS) +CXXFLAGS = $(CPPUTEST_CXXFLAGS) $(CPPUTEST_ADDITIONAL_CXXFLAGS) +LDFLAGS = $(CPPUTEST_LDFLAGS) $(CPPUTEST_ADDITIONAL_LDFLAGS) + +# Don't consider creating the archive a warning condition that does STDERR output +ARFLAGS := $(ARFLAGS)c + +DEP_FLAGS=-MMD -MP + +# Some macros for programs to be overridden. For some reason, these are not in Make defaults +RANLIB = ranlib + +# Targets + +.PHONY: all +all: start $(TEST_TARGET) + $(RUN_TEST_TARGET) + +.PHONY: start +start: $(TEST_TARGET) + $(SILENCE)START_TIME=$(call time) + +.PHONY: all_no_tests +all_no_tests: $(TEST_TARGET) + +.PHONY: flags +flags: + @echo + @echo "OS ${UNAME_OS}" + @echo "Compile C and C++ source with CPPFLAGS:" + @$(call debug_print_list,$(CPPFLAGS)) + @echo "Compile C++ source with CXXFLAGS:" + @$(call debug_print_list,$(CXXFLAGS)) + @echo "Compile C source with CFLAGS:" + @$(call debug_print_list,$(CFLAGS)) + @echo "Link with LDFLAGS:" + @$(call debug_print_list,$(LDFLAGS)) + @echo "Link with LD_LIBRARIES:" + @$(call debug_print_list,$(LD_LIBRARIES)) + @echo "Create libraries with ARFLAGS:" + @$(call debug_print_list,$(ARFLAGS)) + +TEST_DEPS = $(TEST_OBJS) $(MOCKS_OBJS) $(PRODUCTION_CODE_START) $(TARGET_LIB) $(USER_LIBS) $(PRODUCTION_CODE_END) $(CPPUTEST_LIB) $(STDLIB_CODE_START) +test-deps: $(TEST_DEPS) + +$(TEST_TARGET): $(TEST_DEPS) + @echo Linking $@ + $(SILENCE)$(CXX) -o $@ $^ $(LD_LIBRARIES) $(LDFLAGS) + +$(TARGET_LIB): $(OBJ) + @echo Building archive $@ + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(AR) $(ARFLAGS) $@ $^ + $(SILENCE)$(RANLIB) $@ + +test: $(TEST_TARGET) + $(RUN_TEST_TARGET) | tee $(TEST_OUTPUT) + +vtest: $(TEST_TARGET) + $(RUN_TEST_TARGET) -v | tee $(TEST_OUTPUT) + +$(CPPUTEST_OBJS_DIR)/%.o: %.cc + @echo compiling $(notdir $<) + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $< + +$(CPPUTEST_OBJS_DIR)/%.o: %.cpp + @echo compiling $(notdir $<) + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $< + +$(CPPUTEST_OBJS_DIR)/%.o: %.c + @echo compiling $(notdir $<) + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(COMPILE.c) $(DEP_FLAGS) $(OUTPUT_OPTION) $< + +ifneq "$(MAKECMDGOALS)" "clean" +-include $(DEP_FILES) +endif + +.PHONY: clean +clean: + @echo Making clean + $(SILENCE)$(RM) $(STUFF_TO_CLEAN) + $(SILENCE)rm -rf gcov objs #$(CPPUTEST_OBJS_DIR) + $(SILENCE)rm -rf $(CPPUTEST_LIB_DIR) + $(SILENCE)find . -name "*.gcno" | xargs rm -f + $(SILENCE)find . -name "*.gcda" | xargs rm -f + +#realclean gets rid of all gcov, o and d files in the directory tree +#not just the ones made by this makefile +.PHONY: realclean +realclean: clean + $(SILENCE)rm -rf gcov + $(SILENCE)find . -name "*.gdcno" | xargs rm -f + $(SILENCE)find . -name "*.[do]" | xargs rm -f + +gcov: test +ifeq ($(CPPUTEST_USE_VPATH), Y) + $(SILENCE)gcov --object-directory $(CPPUTEST_OBJS_DIR) $(SRC) >> $(GCOV_OUTPUT) 2>> $(GCOV_ERROR) +else + $(SILENCE)for d in $(SRC_DIRS) ; do \ + gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$d $$d/*.c $$d/*.cpp >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \ + done + $(SILENCE)for f in $(SRC_FILES) ; do \ + gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$f $$f >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \ + done +endif +# $(CPPUTEST_HOME)/scripts/filterGcov.sh $(GCOV_OUTPUT) $(GCOV_ERROR) $(GCOV_REPORT) $(TEST_OUTPUT) + /usr/share/cpputest/scripts/filterGcov.sh $(GCOV_OUTPUT) $(GCOV_ERROR) $(GCOV_REPORT) $(TEST_OUTPUT) + $(SILENCE)cat $(GCOV_REPORT) + $(SILENCE)mkdir -p gcov + $(SILENCE)mv *.gcov gcov + $(SILENCE)mv gcov_* gcov + @echo "See gcov directory for details" + +.PHONEY: format +format: + $(CPPUTEST_HOME)/scripts/reformat.sh $(PROJECT_HOME_DIR) + +.PHONEY: debug +debug: + @echo + @echo "Target Source files:" + @$(call debug_print_list,$(SRC)) + @echo "Target Object files:" + @$(call debug_print_list,$(OBJ)) + @echo "Test Source files:" + @$(call debug_print_list,$(TEST_SRC)) + @echo "Test Object files:" + @$(call debug_print_list,$(TEST_OBJS)) + @echo "Mock Source files:" + @$(call debug_print_list,$(MOCKS_SRC)) + @echo "Mock Object files:" + @$(call debug_print_list,$(MOCKS_OBJS)) + @echo "All Input Dependency files:" + @$(call debug_print_list,$(DEP_FILES)) + @echo Stuff to clean: + @$(call debug_print_list,$(STUFF_TO_CLEAN)) + @echo Includes: + @$(call debug_print_list,$(INCLUDES)) + +-include $(OTHER_MAKEFILE_TO_INCLUDE) diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/CThunk.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/CThunk.h new file mode 100644 index 0000000000..4fd91033e0 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/CThunk.h @@ -0,0 +1,202 @@ +/* General C++ Object Thunking class + * + * - allows direct callbacks to non-static C++ class functions + * - keeps track for the corresponding class instance + * - supports an optional context parameter for the called function + * - ideally suited for class object receiving interrupts (NVIC_SetVector) + * + * Copyright (c) 2014-2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __CTHUNK_H__ +#define __CTHUNK_H__ + +#define CTHUNK_ADDRESS 1 + +#if defined(__CORTEX_M3) || defined(__CORTEX_M4) || defined(__thumb2__) +#define CTHUNK_VARIABLES volatile uint32_t code[1] +/** +* CTHUNK disassembly for Cortex-M3/M4 (thumb2): +* * ldm.w pc,{r0,r1,r2,pc} +* +* This instruction loads the arguments for the static thunking function to r0-r2, and +* branches to that function by loading its address into PC. +* +* This is safe for both regular calling and interrupt calling, since it only touches scratch registers +* which should be saved by the caller, and are automatically saved as part of the IRQ context switch. +*/ +#define CTHUNK_ASSIGMENT m_thunk.code[0] = 0x8007E89F + +#elif defined(__CORTEX_M0PLUS) || defined(__CORTEX_M0) +/* +* CTHUNK disassembly for Cortex M0 (thumb): +* * push {r0,r1,r2,r3,r4,lr} save touched registers and return address +* * movs r4,#4 set up address to load arguments from (immediately following this code block) (1) +* * add r4,pc set up address to load arguments from (immediately following this code block) (2) +* * ldm r4!,{r0,r1,r2,r3} load arguments for static thunk function +* * blx r3 call static thunk function +* * pop {r0,r1,r2,r3,r4,pc} restore scratch registers and return from function +*/ +#define CTHUNK_VARIABLES volatile uint32_t code[3] +#define CTHUNK_ASSIGMENT do { \ + m_thunk.code[0] = 0x2404B51F; \ + m_thunk.code[1] = 0xCC0F447C; \ + m_thunk.code[2] = 0xBD1F4798; \ + } while (0) + +#else +#error "Target is not currently suported." +#endif + +/* IRQ/Exception compatible thunk entry function */ +typedef void (*CThunkEntry)(void); + +template +class CThunk +{ + public: + typedef void (T::*CCallbackSimple)(void); + typedef void (T::*CCallback)(void* context); + + inline CThunk(T *instance) + { + init(instance, NULL, NULL); + } + + inline CThunk(T *instance, CCallback cb) + { + init(instance, cb, NULL); + } + + ~CThunk() { + + } + + inline CThunk(T *instance, CCallbackSimple cb) + { + init(instance, (CCallback)cb, NULL); + } + + inline CThunk(T &instance, CCallback cb) + { + init(instance, cb, NULL); + } + + inline CThunk(T &instance, CCallbackSimple cb) + { + init(instance, (CCallback)cb, NULL); + } + + inline CThunk(T &instance, CCallback cb, void* ctx) + { + init(instance, cb, ctx); + } + + inline void callback(CCallback cb) + { + m_callback = cb; + } + + inline void callback(CCallbackSimple cb) + { + m_callback = (CCallback)cb; + } + + inline void context(void* ctx) + { + m_thunk.context = (uint32_t)ctx; + } + + inline void context(uint32_t ctx) + { + m_thunk.context = ctx; + } + + inline uint32_t entry(void) + { + return (((uint32_t)&m_thunk)|CTHUNK_ADDRESS); + } + + /* get thunk entry point for connecting rhunk to an IRQ table */ + inline operator CThunkEntry(void) + { + return (CThunkEntry)entry(); + } + + /* get thunk entry point for connecting rhunk to an IRQ table */ + inline operator uint32_t(void) + { + return entry(); + } + + /* simple test function */ + inline void call(void) + { + (((CThunkEntry)(entry()))()); + } + + private: + T* m_instance; + volatile CCallback m_callback; + +// TODO: this needs proper fix, to refactor toolchain header file and all its use +// PACKED there is not defined properly for IAR +#if defined (__ICCARM__) + typedef __packed struct + { + CTHUNK_VARIABLES; + volatile uint32_t instance; + volatile uint32_t context; + volatile uint32_t callback; + volatile uint32_t trampoline; + } CThunkTrampoline; +#else + typedef struct + { + CTHUNK_VARIABLES; + volatile uint32_t instance; + volatile uint32_t context; + volatile uint32_t callback; + volatile uint32_t trampoline; + } __attribute__((__packed__)) CThunkTrampoline; +#endif + + static void trampoline(T* instance, void* ctx, CCallback* cb) + { + if(instance && *cb) { + (static_cast(instance)->**cb)(ctx); + } + } + + volatile CThunkTrampoline m_thunk; + + inline void init(T *instance, CCallback cb, void* ctx) + { + /* remember callback - need to add this level of redirection + as pointer size for member functions differs between platforms */ + m_callback = cb; + + /* populate thunking trampoline */ +// CTHUNK_ASSIGMENT; +// m_thunk.context = (uint32_t)ctx; +// m_thunk.instance = (uint32_t)instance; +// m_thunk.callback = (uint32_t)&m_callback; +// m_thunk.trampoline = (uint32_t)&trampoline; + +// __ISB(); +// __DSB(); + } +}; + +#endif/*__CTHUNK_H__*/ diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/FunctionPointer.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/FunctionPointer.h new file mode 100644 index 0000000000..b8a7e89448 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/FunctionPointer.h @@ -0,0 +1,604 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 MBED_FUNCTIONPOINTER_H +#define MBED_FUNCTIONPOINTER_H + +#include +#include +#include +#include +#include +#include "FunctionPointerBase.h" +#include "FunctionPointerBind.h" + +namespace mbed { +/** A class for storing and calling a pointer to a static or member void function without arguments + */ +template +class FunctionPointer0 : public FunctionPointerBase{ +public: + typedef R(*static_fp)(void); + typedef struct arg_struct{ + } ArgStruct; + /** Create a FunctionPointer, attaching a static function + * + * @param function The void static function to attach (default is none) + */ + FunctionPointer0(static_fp function = 0): + FunctionPointerBase() + { + attach(function); + } + + /** Create a FunctionPointer, attaching a member function + * + * @param object The object pointer to invoke the member function on (i.e. the this pointer) + * @param function The address of the void member function to attach + */ + template + FunctionPointer0(T *object, R (T::*member)(void)): + FunctionPointerBase() + { + attach(object, member); + } + + /** Attach a static function + * + * @param function The void static function to attach (default is none) + */ + void attach(static_fp function) { + FunctionPointerBase::_object = reinterpret_cast(function); + FunctionPointerBase::_membercaller = &FunctionPointer0::staticcaller; + } + + /** Attach a member function + * + * @param object The object pointer to invoke the member function on (i.e. the this pointer) + * @param function The address of the void member function to attach + */ + template + void attach(T *object, R (T::*member)(void)) { + FunctionPointerBase::_object = static_cast(object); + *reinterpret_cast(FunctionPointerBase::_member) = member; + FunctionPointerBase::_membercaller = &FunctionPointer0::membercaller; + } + + /** Call the attached static or member function + */ + R call(){ + return FunctionPointerBase::call(NULL); + } + + FunctionPointerBind bind() { + FunctionPointerBind fp; + fp.bind(&FunctionPointerBase::_nullops, (ArgStruct *) NULL, this); + return fp; + } + + static_fp get_function()const { + return reinterpret_cast(FunctionPointerBase::_object); + } + + R operator ()(void) { + return call(); + } + +private: + template + static R membercaller(void *object, uintptr_t *member, void *arg) { + (void) arg; + T* o = static_cast(object); + R (T::**m)(void) = reinterpret_cast(member); + return (o->**m)(); + } + static R staticcaller(void *object, uintptr_t *member, void *arg) { + (void) arg; + (void) member; + static_fp f = reinterpret_cast(object); + return f(); + } +}; + +/* If we had variaditic templates, this wouldn't be a problem, but until C++11 is enabled, we are stuck with multiple classes... */ + +/** A class for storing and calling a pointer to a static or member void function with one argument + */ +template +class FunctionPointer1 : public FunctionPointerBase { +protected: + typedef struct arg_struct{ + A1 a1; + arg_struct(const A1 *b1) { + a1 = *b1; + } + } ArgStruct; + +public: + typedef R(*static_fp)(A1); + /** Create a FunctionPointer, attaching a static function + * + * @param function The void static function to attach (default is none) + */ + FunctionPointer1(static_fp function = 0) { + attach(function); + } + + /** Create a FunctionPointer, attaching a member function + * + * @param object The object pointer to invoke the member function on (i.e. the this pointer) + * @param function The address of the void member function to attach + */ + template + FunctionPointer1(T *object, R (T::*member)(A1)) { + attach(object, member); + } + + /** Attach a static function + * + * @param function The void static function to attach (default is none) + */ + void attach(static_fp function) { + FunctionPointerBase::_object = reinterpret_cast(function); + FunctionPointerBase::_membercaller = &FunctionPointer1::staticcaller; + } + + /** Attach a member function + * + * @param object The object pointer to invoke the member function on (i.e. the this pointer) + * @param function The address of the void member function to attach + */ + template + void attach(T *object, R (T::*member)(A1)) + { + FunctionPointerBase::_object = static_cast(object); + *reinterpret_cast(FunctionPointerBase::_member) = member; + FunctionPointerBase::_membercaller = &FunctionPointer1::membercaller; + } + + FunctionPointerBind bind(const A1 &a1) { + FunctionPointerBind fp; + fp.bind(&_fp1_ops, (ArgStruct *) NULL, this, &a1); + return fp; + } + + + /** Call the attached static or member function + */ + R call(A1 a1) + { + ArgStruct Args(&a1); + return FunctionPointerBase::call(&Args); + } + + static_fp get_function()const + { + return reinterpret_cast(FunctionPointerBase::_object); + } + + R operator ()(A1 a) { + return call(a); + } + +private: + template + static R membercaller(void *object, uintptr_t *member, void *arg) { + ArgStruct *Args = static_cast(arg); + T* o = static_cast(object); + R (T::**m)(A1) = reinterpret_cast(member); + return (o->**m)(Args->a1); + } + static R staticcaller(void *object, uintptr_t *member, void *arg) { + ArgStruct *Args = static_cast(arg); + (void) member; + static_fp f = reinterpret_cast(object); + return f(Args->a1); + } +/* static void constructor(void * dest, va_list args) { + new(dest) ArgStruct(va_arg(args,A1*)); + } + static void copy_constructor(void *dest , void* src) { + ArgStruct *src_args = static_cast(src); + new(dest) ArgStruct(&(src_args->a1)); + } + static void destructor(void *args) { + ArgStruct *argstruct = static_cast(args); + argstruct->~arg_struct(); + } +*/ +protected: + static const struct FunctionPointerBase::ArgOps _fp1_ops; +}; + +template +const struct FunctionPointerBase::ArgOps FunctionPointer1::_fp1_ops = { + FunctionPointer1::constructor, + FunctionPointer1::copy_constructor, + FunctionPointer1::destructor +}; + + +/** A class for storing and calling a pointer to a static or member void function with two arguments + */ +template +class FunctionPointer2 : public FunctionPointerBase { +protected: + typedef struct arg_struct{ + A1 a1; + A2 a2; + arg_struct(const A1 *b1, const A2 *b2) { + a1 = *b1; + a2 = *b2; + } + } ArgStruct; + +public: + typedef R(*static_fp)(A1, A2); + /** Create a FunctionPointer, attaching a static function + * + * @param function The void static function to attach (default is none) + */ + FunctionPointer2(static_fp function = 0) { + attach(function); + } + + /** Create a FunctionPointer, attaching a member function + * + * @param object The object pointer to invoke the member function on (i.e. the this pointer) + * @param function The address of the void member function to attach + */ + template + FunctionPointer2(T *object, R (T::*member)(A1, A2)) { + attach(object, member); + } + + /** Attach a static function + * + * @param function The void static function to attach (default is none) + */ + void attach(static_fp function) { + FunctionPointerBase::_object = reinterpret_cast(function); + FunctionPointerBase::_membercaller = &FunctionPointer2::staticcaller; + } + + /** Attach a member function + * + * @param object The object pointer to invoke the member function on (i.e. the this pointer) + * @param function The address of the void member function to attach + */ + template + void attach(T *object, R (T::*member)(A1, A2)) + { + FunctionPointerBase::_object = static_cast(object); + *reinterpret_cast(FunctionPointerBase::_member) = member; + FunctionPointerBase::_membercaller = &FunctionPointer2::membercaller; + } + + FunctionPointerBind bind(const A1 &a1, const A2 &a2) { + FunctionPointerBind fp; + fp.bind(&_fp2_ops, (ArgStruct *) NULL, this, &a1, &a2); + return fp; + } + + + /** Call the attached static or member function + */ + R call(A1 a1, A2 a2) + { + ArgStruct Args(&a1, &a2); + return FunctionPointerBase::call(&Args); + } + + static_fp get_function()const + { + return reinterpret_cast(FunctionPointerBase::_object); + } + + R operator ()(A1 a1, A2 a2) { + return call(a1, a2); + } + +private: + template + static R membercaller(void *object, uintptr_t *member, void *arg) { + ArgStruct *Args = static_cast(arg); + T* o = static_cast(object); + R (T::**m)(A1, A2) = reinterpret_cast(member); + return (o->**m)(Args->a1, Args->a2); + } + static R staticcaller(void *object, uintptr_t *member, void *arg) { + ArgStruct *Args = static_cast(arg); + (void) member; + static_fp f = reinterpret_cast(object); + return f(Args->a1, Args->a2); + } +/* static void constructor(void * dest, va_list args) { + A1 *a1 = va_arg(args, A1*); + A2 *a2 = va_arg(args, A2*); + new(dest) ArgStruct(a1, a2); + } + static void copy_constructor(void *dest , void* src) { + ArgStruct *src_args = static_cast(src); + new(dest) ArgStruct(&(src_args->a1), &(src_args->a2)); + } + static void destructor(void *args) { + ArgStruct *argstruct = static_cast(args); + argstruct->~arg_struct(); + } +*/ +protected: + static const struct FunctionPointerBase::ArgOps _fp2_ops; +}; + +template +const struct FunctionPointerBase::ArgOps FunctionPointer2::_fp2_ops = { + FunctionPointer2::constructor, + FunctionPointer2::copy_constructor, + FunctionPointer2::destructor +}; + +/** A class for storing and calling a pointer to a static or member void function with three arguments + */ +template +class FunctionPointer3 : public FunctionPointerBase { +protected: + typedef struct arg_struct{ + A1 a1; + A2 a2; + A3 a3; + arg_struct(const A1 *b1, const A2 *b2, const A3* b3) { + a1 = *b1; + a2 = *b2; + a3 = *b3; + } + } ArgStruct; + +public: + typedef R(*static_fp)(A1, A2, A3); + /** Create a FunctionPointer, attaching a static function + * + * @param function The void static function to attach (default is none) + */ + FunctionPointer3(static_fp function = 0) { + attach(function); + } + + /** Create a FunctionPointer, attaching a member function + * + * @param object The object pointer to invoke the member function on (i.e. the this pointer) + * @param function The address of the void member function to attach + */ + template + FunctionPointer3(T *object, R (T::*member)(A1, A2, A3)) { + attach(object, member); + } + + /** Attach a static function + * + * @param function The void static function to attach (default is none) + */ + void attach(static_fp function) { + FunctionPointerBase::_object = reinterpret_cast(function); + FunctionPointerBase::_membercaller = &FunctionPointer3::staticcaller; + } + + /** Attach a member function + * + * @param object The object pointer to invoke the member function on (i.e. the this pointer) + * @param function The address of the void member function to attach + */ + template + void attach(T *object, R (T::*member)(A1, A2, A3)) + { + FunctionPointerBase::_object = static_cast(object); + *reinterpret_cast(FunctionPointerBase::_member) = member; + FunctionPointerBase::_membercaller = &FunctionPointer3::membercaller; + } + + FunctionPointerBind bind(const A1 &a1, const A2 &a2, const A3 &a3) { + FunctionPointerBind fp; + fp.bind(&_fp3_ops, (ArgStruct *) NULL, this, &a1, &a2, &a3); + return fp; + } + + + /** Call the attached static or member function + */ + R call(A1 a1, A2 a2, A3 a3) + { + ArgStruct Args(&a1, &a2, &a3); + return FunctionPointerBase::call(&Args); + } + + static_fp get_function()const + { + return reinterpret_cast(FunctionPointerBase::_object); + } + + R operator ()(A1 a1, A2 a2, A3 a3) { + return call(a1, a2, a3); + } + +private: + template + static R membercaller(void *object, uintptr_t *member, void *arg) { + ArgStruct *Args = static_cast(arg); + T* o = static_cast(object); + R (T::**m)(A1, A2, A3) = reinterpret_cast(member); + return (o->**m)(Args->a1, Args->a2, Args->a3); + } + static R staticcaller(void *object, uintptr_t *member, void *arg) { + ArgStruct *Args = static_cast(arg); + (void) member; + static_fp f = reinterpret_cast(object); + return f(Args->a1, Args->a2, Args->a3); + } +/* static void constructor(void * dest, va_list args) { + A1 *a1 = va_arg(args, A1*); + A2 *a2 = va_arg(args, A2*); + A3 *a3 = va_arg(args, A3*); + new(dest) ArgStruct(a1, a2, a3); + } + static void copy_constructor(void *dest , void* src) { + ArgStruct *src_args = static_cast(src); + new(dest) ArgStruct(&(src_args->a1), &(src_args->a2), &(src_args->a3)); + } + static void destructor(void *args) { + ArgStruct *argstruct = static_cast(args); + argstruct->~arg_struct(); + } +*/ +protected: + static const struct FunctionPointerBase::ArgOps _fp3_ops; +}; + +template +const struct FunctionPointerBase::ArgOps FunctionPointer3::_fp3_ops = { + FunctionPointer3::constructor, + FunctionPointer3::copy_constructor, + FunctionPointer3::destructor +}; + +/** A class for storing and calling a pointer to a static or member void function with four arguments + */ +template +class FunctionPointer4 : public FunctionPointerBase { +protected: + typedef struct arg_struct{ + A1 a1; + A2 a2; + A3 a3; + A4 a4; + arg_struct(const A1 *b1, const A2 *b2, const A3* b3, const A4* b4) { + a1 = *b1; + a2 = *b2; + a3 = *b3; + a4 = *b4; + } + } ArgStruct; + +public: + typedef R(*static_fp)(A1, A2, A3, A4); + /** Create a FunctionPointer, attaching a static function + * + * @param function The void static function to attach (default is none) + */ + FunctionPointer4(static_fp function = 0) { + attach(function); + } + + /** Create a FunctionPointer, attaching a member function + * + * @param object The object pointer to invoke the member function on (i.e. the this pointer) + * @param function The address of the void member function to attach + */ + template + FunctionPointer4(T *object, R (T::*member)(A1, A2, A3, A4)) { + attach(object, member); + } + + /** Attach a static function + * + * @param function The void static function to attach (default is none) + */ + void attach(static_fp function) { + FunctionPointerBase::_object = reinterpret_cast(function); + FunctionPointerBase::_membercaller = &FunctionPointer4::staticcaller; + } + + /** Attach a member function + * + * @param object The object pointer to invoke the member function on (i.e. the this pointer) + * @param function The address of the void member function to attach + */ + template + void attach(T *object, R (T::*member)(A1, A2, A3, A4)) + { + FunctionPointerBase::_object = static_cast(object); + *reinterpret_cast(FunctionPointerBase::_member) = member; + FunctionPointerBase::_membercaller = &FunctionPointer4::membercaller; + } + + FunctionPointerBind bind(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) { + FunctionPointerBind fp; + fp.bind(&_fp4_ops, (ArgStruct *) NULL, this, &a1, &a2, &a3, &a4); + return fp; + } + + + /** Call the attached static or member function + */ + R call(A1 a1, A2 a2, A3 a3, A4 a4) + { + ArgStruct Args(&a1, &a2, &a3, &a4); + return FunctionPointerBase::call(&Args); + } + + static_fp get_function()const + { + return reinterpret_cast(FunctionPointerBase::_object); + } + + R operator ()(A1 a1, A2 a2, A3 a3, A4 a4) { + return call(a1, a2, a3, a4); + } + +private: + template + static R membercaller(void *object, uintptr_t *member, void *arg) { + ArgStruct *Args = static_cast(arg); + T* o = static_cast(object); + R (T::**m)(A1, A2, A3, A4) = reinterpret_cast(member); + return (o->**m)(Args->a1, Args->a2, Args->a3, Args->a4); + } + static R staticcaller(void *object, uintptr_t *member, void *arg) { + ArgStruct *Args = static_cast(arg); + (void) member; + static_fp f = reinterpret_cast(object); + return f(Args->a1, Args->a2, Args->a3, Args->a4); + } +/* static void constructor(void * dest, va_list args) { + A1 *a1 = va_arg(args, A1*); + A2 *a2 = va_arg(args, A2*); + A3 *a3 = va_arg(args, A3*); + A4 *a4 = va_arg(args, A4*); + new(dest) ArgStruct(a1, a2, a3, a4); + } + static void copy_constructor(void *dest , void* src) { + ArgStruct *src_args = static_cast(src); + new(dest) ArgStruct(&(src_args->a1), &(src_args->a2), &(src_args->a3), &(src_args->a4)); + } + static void destructor(void *args) { + ArgStruct *argstruct = static_cast(args); + argstruct->~arg_struct(); + } +*/ +protected: + static const struct FunctionPointerBase::ArgOps _fp4_ops; +}; + +template +const struct FunctionPointerBase::ArgOps FunctionPointer4::_fp4_ops = { + FunctionPointer4::constructor, + FunctionPointer4::copy_constructor, + FunctionPointer4::destructor +}; + +typedef FunctionPointer0 FunctionPointer; +//typedef FunctionPointer1 event_callback_t; + +} // namespace mbed + +#endif diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/FunctionPointerBase.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/FunctionPointerBase.h new file mode 100644 index 0000000000..02a6dbd30f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/FunctionPointerBase.h @@ -0,0 +1,89 @@ +/* mbed Microcontroller Library + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 MBED_FUNCTIONPOINTERBASE_H +#define MBED_FUNCTIONPOINTERBASE_H + +#include +#include +#include +#include +namespace mbed { + +template +class FunctionPointerBase { +public: + operator bool(void) const { + return (_membercaller != NULL) && (_object != NULL); + } + + /** + * Clears the current function pointer assignment + * After clear(), this instance will point to nothing (NULL) + */ + virtual void clear() { + _membercaller = NULL; + _object = NULL; + } + +protected: + struct ArgOps { + void (*constructor)(void *, va_list); + void (*copy_args)(void *, void *); + void (*destructor)(void *); + }; + void * _object; // object Pointer/function pointer + R (*_membercaller)(void *, uintptr_t *, void *); + // aligned raw member function pointer storage - converted back by registered _membercaller + uintptr_t _member[4]; + static const struct ArgOps _nullops; + +protected: + FunctionPointerBase():_object(NULL), _membercaller(NULL) {} + FunctionPointerBase(const FunctionPointerBase & fp) { + copy(&fp); + } + virtual ~FunctionPointerBase() { + } + + /** + * Calls the member pointed to by object::member or (function)object + * @param arg + * @return + */ + inline R call(void* arg) { + return _membercaller(_object, _member, arg); + } + + void copy(const FunctionPointerBase * fp) { + _object = fp->_object; + memcpy (_member, fp->_member, sizeof(_member)); + _membercaller = fp->_membercaller; + } +private: + static void _null_constructor(void * dest, va_list args) {(void) dest;(void) args;} + static void _null_copy_args(void *dest , void* src) {(void) dest; (void) src;} + static void _null_destructor(void *args) {(void) args;} + +}; +template +const struct FunctionPointerBase::ArgOps FunctionPointerBase::_nullops = { + FunctionPointerBase::_null_constructor, + FunctionPointerBase::_null_copy_args, + FunctionPointerBase::_null_destructor +}; + +} +#endif diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/FunctionPointerBind.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/FunctionPointerBind.h new file mode 100644 index 0000000000..f90f187f4c --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/FunctionPointerBind.h @@ -0,0 +1,112 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 MBED_FUNCTIONPOINTERBIND_H__ +#define MBED_FUNCTIONPOINTERBIND_H__ + +#include +#include +#include +#include +#include +#include "FunctionPointerBase.h" + +#ifndef EVENT_STORAGE_SIZE +#define EVENT_STORAGE_SIZE 32 +#endif + +#define MBED_STATIC_ASSERT(MBED_STATIC_ASSERT_FAILED,MSG)\ + switch(0){\ + case 0:case (MBED_STATIC_ASSERT_FAILED): \ + break;} + +namespace mbed{ + +template +class FunctionPointerBind : public FunctionPointerBase { +public: + // Call the Event + inline R call() { + return FunctionPointerBase::call(static_cast(_storage)); + } + FunctionPointerBind(): + FunctionPointerBase(), + _ops(&FunctionPointerBase::_nullops) + {} + + FunctionPointerBind(const FunctionPointerBind & fp): + FunctionPointerBase(), + _ops(&FunctionPointerBase::_nullops) { + *this = fp; + } + + virtual ~FunctionPointerBind() { + _ops->destructor(_storage); + } + + FunctionPointerBind & operator=(const FunctionPointerBind& rhs) { + if (_ops != &FunctionPointerBase::_nullops) { + _ops->destructor(_storage); + } + FunctionPointerBase::copy(&rhs); + _ops = rhs._ops; + _ops->copy_args(_storage, (void *)rhs._storage); + return *this; + } + + /** + * Clears the current binding, making this instance unbound + */ + virtual void clear() { + if (_ops != &FunctionPointerBase::_nullops) { + _ops->destructor(_storage); + } + _ops = &FunctionPointerBase::_nullops; + FunctionPointerBase::clear(); + } + + template + FunctionPointerBind & bind(const struct FunctionPointerBase::ArgOps * ops , S * argStruct, FunctionPointerBase *fp, ...) { + MBED_STATIC_ASSERT(sizeof(S) <= sizeof(_storage), ERROR: Arguments too large for FunctionPointerBind internal storage) + if (_ops != &FunctionPointerBase::_nullops) { + _ops->destructor(_storage); + } + _ops = ops; + FunctionPointerBase::copy(fp); + assert(this->_ops != NULL); + assert(this->_ops->constructor != NULL); + if (argStruct) { + this->_ops->copy_args(this->_storage, (void *)argStruct); + } else { + va_list args; + va_start(args, fp); + this->_ops->constructor(_storage, args); + va_end(args); + } + return *this; + } + + R operator()() { + return call(); + } + +protected: + const struct FunctionPointerBase::ArgOps * _ops; + uint32_t _storage[(EVENT_STORAGE_SIZE+sizeof(uint32_t)-1)/sizeof(uint32_t)]; +}; +} + +#endif // MBED_FUNCTIONPOINTERBIND_H__ diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/Ticker.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/Ticker.h new file mode 100644 index 0000000000..54611a3c32 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/Ticker.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TICKER_H +#define TICKER_H + +namespace mbed +{ +typedef uint64_t timestamp_t; + + class Ticker{ + public : + Ticker() {} + ~Ticker(){} + + // Ticker + template + void attach_us(T* tptr, void (T::*mptr)(void), timestamp_t){} + + void detach(); + }; +} + +#endif // TICKER_H diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/alltests.cpp b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/alltests.cpp new file mode 100644 index 0000000000..853034e8ca --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/alltests.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +//#include "../m2mbase/m2mbasetest.h" +#include "../m2mobject/m2mobjecttest.h" diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/ip6string.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/ip6string.h new file mode 100644 index 0000000000..dc0c0e6bfc --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/ip6string.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 IP6STRING_H +#define IP6STRING_H +#ifdef __cplusplus +extern "C" { +#endif +/** + * Print binary IPv6 address to a string. + * String must contain enough room for full address, 40 bytes exact. + * IPv4 tunneling addresses are not covered. + * \param ip6addr IPv6 address. + * \p buffer to write string to. + */ +uint_fast8_t ip6tos(const void *ip6addr, char *p); + +/** + * Convert numeric IPv6 address string to a binary. + * IPv4 tunneling addresses are not covered. + * \param ip6addr IPv6 address in string format. + * \param len Lenght of ipv6 string, maximum of 41. + * \param dest buffer for address. MUST be 16 bytes. + */ +void stoip6(const char *ip6addr, size_t len, void *dest); +/** + * Find out numeric IPv6 address prefix length + * \param ip6addr IPv6 address in string format + * \return prefix length or 0 if it not given + */ +unsigned char sipv6_prefixlength(const char *ip6addr); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/mbed.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/mbed.h new file mode 100644 index 0000000000..9a1b1fbce9 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/mbed.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 MBED_H +#define MBED_H + +#include +#include + +#endif // MBED_H diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/ns_list.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/ns_list.h new file mode 100644 index 0000000000..e17f55facd --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/ns_list.h @@ -0,0 +1,736 @@ +/* + * Copyright (c) 2014-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 NS_LIST_H_ +#define NS_LIST_H_ + +#include "ns_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file + * \brief Linked list support library + * + * The ns_list.h file provides a doubly-linked list/queue, providing O(1) + * performance for all insertion/removal operations, and access to either + * end of the list. + * + * Memory footprint is two pointers for the list head, and two pointers in each + * list entry. It is similar in concept to BSD's TAILQ. + * + * Although the API is symmetrical and O(1) in both directions, due to internal + * pointer design, it is *slightly* more efficient to insert at the end when + * used as a queue, and to iterate forwards rather than backwards. + * + * Example of an entry type that can be stored to this list. + * ~~~ + * typedef struct example_entry + * { + * uint8_t *data; + * uint32_t data_count; + * ns_list_link_t link; + * } + * example_entry_t; + * + * static NS_LIST_HEAD(example_entry_t, link) my_list; + * ns_list_init(&my_list); + * ~~~ + * OR + * ~~~ + * NS_LIST_HEAD(example_entry_t, link) my_list = NS_LIST_INIT(my_list); + * ~~~ + * OR + * ~~~ + * static NS_LIST_DEFINE(my_list, example_entry_t, link); + * ~~~ + * OR + * ~~~ + * typedef NS_LIST_HEAD(example_entry_t, link) example_list_t; + * example_list_t NS_LIST_NAME_INIT(my_list); + * ~~~ + * NOTE: the link field SHALL NOT be accessed by the user. + * + * An entry can exist on multiple lists by having multiple link fields. + * + * All the list operations are implemented as macros, most of which are backed + * by optionally-inline functions. The macros do not evaluate any arguments more + * than once, unless documented. + * + * In macro documentation, `list_t` refers to a list type defined using + * NS_LIST_HEAD(), and `entry_t` to the entry type that was passed to it. + */ + +/** \brief Underlying generic linked list head. + * + * Users should not use this type directly, but use the NS_LIST_HEAD() macro. + */ +typedef struct ns_list +{ + void *first_entry; ///< Pointer to first entry, or NULL if list is empty + void **last_nextptr; ///< Pointer to last entry's `next` pointer, or + ///< to head's `first_entry` pointer if list is empty +} ns_list_t; + +/** \brief Declare a list head type + * + * This union stores the real list head, and also encodes as compile-time type + * information the offset of the link pointer, and the type of the entry. + * + * Note that type information is compiler-dependent; this means + * ns_list_get_first() could return either `void *`, or a pointer to the actual + * entry type. So `ns_list_get_first()->data` is not a portable construct - + * always assign returned entry pointers to a properly typed pointer variable. + * This assignment will be then type-checked where the compiler supports it, and + * will dereference correctly on compilers that don't support this extension. + * ~~~ + * NS_LIST_HEAD(example_entry_t, link) my_list; + * + * example_entry_t *entry = ns_list_get_first(&my_list); + * do_something(entry->data); + * ~~~ + * Each use of this macro generates a new anonymous union, so these two lists + * have different types: + * ~~~ + * NS_LIST_HEAD(example_entry_t, link) my_list1; + * NS_LIST_HEAD(example_entry_t, link) my_list2; + * ~~~ + * If you need to use a list type in multiple places, eg as a function + * parameter, use typedef: + * ~~~ + * typedef NS_LIST_HEAD(example_entry_t, link) example_list_t; + * + * void example_function(example_list_t *); + * ~~~ + */ +#define NS_LIST_HEAD(entry_type, field) \ +union \ +{ \ + ns_list_t slist; \ + NS_STATIC_ASSERT(offsetof(entry_type, field) <= UINT_FAST8_MAX, "link offset too large") \ + char (*offset)[offsetof(entry_type, field)]; \ + entry_type *type; \ +} + +/// \privatesection +/** \brief Get offset of link field in entry. + * \return `(ns_list_offset_t)` The offset of the link field for entries on the specified list + */ +#define NS_LIST_OFFSET_(list) ((ns_list_offset_t) sizeof *(list)->offset) + +/** \brief Get the entry type. + * \def NS_LIST_TYPE_ + * + * \return The type of entry on the specified list. + * + * Only available if the compiler provides a "typeof" operator. + */ +#if defined __cplusplus && __cplusplus >= 201103L +#define NS_LIST_TYPE_(list) decltype(*(list)->type) +#elif defined __GNUC__ +#define NS_LIST_TYPE_(list) __typeof__(*(list)->type) +#endif + +/** \brief Check for compatible pointer types + * + * Although this can be done portably, the GCC custom version is provided to + * produce a clearer diagnostic, and it produces an error rather than a warning. + * + * The portable version will produce a diagnostic about a pointer mismatch on + * the == inside the sizeof operator. For example ARM/Norcroft C gives the error: + * + * operand types are incompatible ("entry_t *" and "other_t *") + */ +#ifdef CPPCHECK +#define NS_PTR_MATCH_(a, b, str) ((void) 0) +#elif defined __GNUC__ +#define NS_PTR_MATCH_(a, b, str) __extension__ \ + ({ NS_STATIC_ASSERT(__builtin_types_compatible_p(__typeof__ (*(a)), __typeof__ (*(b))), \ + str) }) +#else +#define NS_PTR_MATCH_(a, b, str) ((void) sizeof ((a) == (b))) +#endif + +/** \brief Internal macro to cast returned entry pointers to correct type. + * + * Not portable in C, alas. With GCC or C++11, the "get entry" macros return + * correctly-typed pointers. Otherwise, the macros return `void *`. + * + * The attempt at a portable version would work if the C `?:` operator wasn't + * broken - `x ? (t *) : (void *)` should really have type `(t *)` in C, but + * it has type `(void *)`, which only makes sense for C++. The `?:` is left in, + * in case some day it works. Some compilers may still warn if this is + * assigned to a different type. + */ +#ifdef NS_LIST_TYPE_ +#define NS_LIST_TYPECAST_(list, val) ((NS_LIST_TYPE_(list) *) (val)) +#else +#define NS_LIST_TYPECAST_(list, val) (0 ? (list)->type : (val)) +#endif + +/** \brief Internal macro to check types of input entry pointer. */ +#define NS_LIST_TYPECHECK_(list, entry) \ + (NS_PTR_MATCH_((list)->type, (entry), "incorrect entry type for list"), (entry)) + +/** \brief Type used to pass link offset to underlying functions + * + * We could use size_t, but it would be unnecessarily large on 8-bit systems, + * where we can be (pretty) confident we won't have next pointers more than + * 256 bytes into a structure. + */ +typedef uint_fast8_t ns_list_offset_t; + +/// \publicsection +/** \brief The type for the link member in the user's entry structure. + * + * Users should not access this member directly - just pass its name to the + * list head macros. The funny prev pointer simplifies common operations + * (eg insertion, removal), at the expense of complicating rare reverse iteration. + * + * NB - the list implementation relies on next being the first member. + */ +typedef struct ns_list_link +{ + void *next; ///< Pointer to next entry, or NULL if none + void **prev; ///< Pointer to previous entry's (or head's) next pointer +} ns_list_link_t; + +/** \brief "Poison" value placed in unattached entries' link pointers. + * \internal What are good values for this? Platform dependent, maybe just NULL + */ +#define NS_LIST_POISON ((void *) 0xDEADBEEF) + +/** \brief Initialiser for an entry's link member + * + * This initialiser is not required by the library, but a user may want an + * initialiser to include in their own entry initialiser. See + * ns_list_link_init() for more discussion. + */ +#define NS_LIST_LINK_INIT(name) \ + NS_FUNNY_INTPTR_OK \ + { NS_LIST_POISON, NS_LIST_POISON } \ + NS_FUNNY_INTPTR_RESTORE + +/** \hideinitializer \brief Initialise an entry's list link + * + * This "initialises" an unattached entry's link by filling the fields with + * poison. This is optional, as unattached entries field pointers are not + * meaningful, and it is not valid to call ns_list_get_next or similar on + * an unattached entry. + * + * \param entry Pointer to an entry + * \param field The name of the link member to initialise + */ +#define ns_list_link_init(entry, field) ns_list_link_init_(&(entry)->field) + +/** \hideinitializer \brief Initialise a list + * + * Initialise a list head before use. A list head must be initialised using this + * function or one of the NS_LIST_INIT()-type macros before use. A zero-initialised + * list head is *not* valid. + * + * If used on a list containing existing entries, those entries will + * become detached. (They are not modified, but their links are now effectively + * undefined). + * + * \param list Pointer to a NS_LIST_HEAD() structure. + */ +#define ns_list_init(list) ns_list_init_(&(list)->slist) + +/** \brief Initialiser for an empty list + * + * Usage in an enclosing initialiser: + * ~~~ + * static my_type_including_list_t x = { + * "Something", + * 23, + * NS_LIST_INIT(x), + * }; + * ~~~ + * NS_LIST_DEFINE() or NS_LIST_NAME_INIT() may provide a shorter alternative + * in simpler cases. + */ +#define NS_LIST_INIT(name) { { NULL, &(name).slist.first_entry } } + +/** \brief Name and initialiser for an empty list + * + * Usage: + * ~~~ + * list_t NS_LIST_NAME_INIT(foo); + * ~~~ + * acts as + * ~~~ + * list_t foo = { empty list }; + * ~~~ + * Also useful with designated initialisers: + * ~~~ + * .NS_LIST_NAME_INIT(foo), + * ~~~ + * acts as + * ~~~ + * .foo = { empty list }, + * ~~~ + */ +#define NS_LIST_NAME_INIT(name) name = NS_LIST_INIT(name) + +/** \brief Define a list, and initialise to empty. + * + * Usage: + * ~~~ + * static NS_LIST_DEFINE(my_list, entry_t, link); + * ~~~ + * acts as + * ~~~ + * static list_type my_list = { empty list }; + * ~~~ + */ +#define NS_LIST_DEFINE(name, type, field) \ + NS_LIST_HEAD(type, field) NS_LIST_NAME_INIT(name) + +/** \hideinitializer \brief Add an entry to the start of the linked list. + * + * ns_list_add_to_end() is *slightly* more efficient than ns_list_add_to_start(). + * + * \param list `(list_t *)` Pointer to list. + * \param entry `(entry_t * restrict)` Pointer to new entry to add. + */ +#define ns_list_add_to_start(list, entry) \ + ns_list_add_to_start_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, entry)) + +/** \hideinitializer \brief Add an entry to the end of the linked list. + * + * \param list `(list_t *)` Pointer to list. + * \param entry `(entry_t * restrict)` Pointer to new entry to add. + */ +#define ns_list_add_to_end(list, entry) \ + ns_list_add_to_end_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, entry)) + +/** \hideinitializer \brief Add an entry before a specified entry. + * + * \param list `(list_t *)` Pointer to list. + * \param before `(entry_t *)` Existing entry before which to place the new entry. + * \param entry `(entry_t * restrict)` Pointer to new entry to add. + */ +#define ns_list_add_before(list, before, entry) \ + ns_list_add_before_(NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, before), NS_LIST_TYPECHECK_(list, entry)) + +/** \hideinitializer \brief Add an entry after a specified entry. + * + * ns_list_add_before() is *slightly* more efficient than ns_list_add_after(). + * + * \param list `(list_t *)` Pointer to list. + * \param after `(entry_t *)` Existing entry after which to place the new entry. + * \param entry `(entry_t * restrict)` Pointer to new entry to add. + */ +#define ns_list_add_after(list, after, entry) \ + ns_list_add_after_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, after), NS_LIST_TYPECHECK_(list, entry)) + +/** \brief Check if a list is empty. + * + * \param list `(const list_t *)` Pointer to list. + * + * \return `(bool)` true if the list is empty. + */ +#define ns_list_is_empty(list) ((bool) ((list)->slist.first_entry == NULL)) + +/** \brief Get the first entry. + * + * \param list `(const list_t *)` Pointer to list. + * + * \return `(entry_t *)` Pointer to first entry. + * \return NULL if list is empty. + */ +#define ns_list_get_first(list) NS_LIST_TYPECAST_(list, (list)->slist.first_entry) + +/** \hideinitializer \brief Get the previous entry. + * + * \param list `(const list_t *)` Pointer to list. + * \param current `(const entry_t *)` Pointer to current entry. + * + * \return `(entry_t *)` Pointer to previous entry. + * \return NULL if current entry is first. + */ +#define ns_list_get_previous(list, current) \ + NS_LIST_TYPECAST_(list, ns_list_get_previous_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, current))) + +/** \hideinitializer \brief Get the next entry. + * + * \param list `(const list_t *)` Pointer to list. + * \param current `(const entry_t *)` Pointer to current entry. + * + * \return `(entry_t *)` Pointer to next entry. + * \return NULL if current entry is last. + */ +#define ns_list_get_next(list, current) \ + NS_LIST_TYPECAST_(list, ns_list_get_next_(NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, current))) + +/** \hideinitializer \brief Get the last entry. + * + * \param list `(const list_t *)` Pointer to list. + * + * \return `(entry_t *)` Pointer to last entry. + * \return NULL if list is empty. + */ +#define ns_list_get_last(list) \ + NS_LIST_TYPECAST_(list, ns_list_get_last_(&(list)->slist, NS_LIST_OFFSET_(list))) + +/** \hideinitializer \brief Remove an entry. + * + * \param list `(list_t *)` Pointer to list. + * \param entry `(entry_t *)` Entry on list to be removed. + */ +#define ns_list_remove(list, entry) \ + ns_list_remove_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, entry)) + +/** \hideinitializer \brief Replace an entry. + * + * \param list `(list_t *)` Pointer to list. + * \param current `(entry_t *)` Existing entry on list to be replaced. + * \param replacement `(entry_t * restrict)` New entry to be the replacement. + */ +#define ns_list_replace(list, current, replacement) \ + ns_list_replace_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, current), NS_LIST_TYPECHECK_(list, replacement)) + +/** \hideinitializer \brief Concatenate two lists. + * + * Attach the entries on the source list to the end of the destination + * list, leaving the source list empty. + * + * \param dst `(list_t *)` Pointer to destination list. + * \param src `(list_t *)` Pointer to source list. + * + */ +#define ns_list_concatenate(dst, src) \ + (NS_PTR_MATCH_(dst, src, "concatenating different list types"), \ + ns_list_concatenate_(&(dst)->slist, &(src)->slist, NS_LIST_OFFSET_(src))) + +/** \brief Iterate forwards over a list. + * + * Example: + * ~~~ + * ns_list_foreach(const my_entry_t, cur, &my_list) + * { + * printf("%s\n", cur->name); + * } + * ~~~ + * Deletion of the current entry is not permitted as its next is checked after + * running user code. + * + * The iteration pointer is declared inside the loop, using C99/C++, so it + * is not accessible after the loop. This encourages good code style, and + * matches the semantics of C++11's "ranged for", which only provides the + * declaration form: + * ~~~ + * for (const my_entry_t cur : my_list) + * ~~~ + * If you need to see the value of the iteration pointer after a `break`, + * you will need to assign it to a variable declared outside the loop before + * breaking: + * ~~~ + * my_entry_t *match = NULL; + * ns_list_foreach(my_entry_t, cur, &my_list) + * { + * if (cur->id == id) + * { + * match = cur; + * break; + * } + * } + * ~~~ + * + * The user has to specify the entry type for the pointer definition, as type + * extraction from the list argument isn't portable. On the other hand, this + * also permits const qualifiers, as in the example above, and serves as + * documentation. The entry type will be checked against the list type where the + * compiler supports it. + * + * \param type Entry type `([const] entry_t)`. + * \param e Name for iteration pointer to be defined + * inside the loop. + * \param list `(const list_t *)` Pointer to list - evaluated multiple times. + */ +#define ns_list_foreach(type, e, list) \ + for (type *e = ns_list_get_first(list); e; e = ns_list_get_next(list, e)) + +/** \brief Iterate forwards over a list, where user may delete. + * + * As ns_list_foreach(), but deletion of current entry is permitted as its + * next pointer is recorded before running user code. + * + * Example: + * ~~~ + * ns_list_foreach_safe(my_entry_t, cur, &my_list) + * { + * ns_list_remove(cur); + * } + * ~~~ + * \param type Entry type `(entry_t)`. + * \param e Name for iteration pointer to be defined + * inside the loop. + * \param list `(list_t *)` Pointer to list - evaluated multiple times. + */ +#define ns_list_foreach_safe(type, e, list) \ + for (type *e = ns_list_get_first(list), *_next; \ + e && (_next = ns_list_get_next(list, e), true); e = _next) + +/** \brief Iterate backwards over a list. + * + * As ns_list_foreach(), but going backwards - see its documentation. + * Iterating forwards is *slightly* more efficient. + */ +#define ns_list_foreach_reverse(type, e, list) \ + for (type *e = ns_list_get_last(list); e; e = ns_list_get_previous(list, e)) + +/** \brief Iterate backwards over a list, where user may delete. + * + * As ns_list_foreach_safe(), but going backwards - see its documentation. + * Iterating forwards is *slightly* more efficient. + */ +#define ns_list_foreach_reverse_safe(type, e, list) \ + for (type *e = ns_list_get_last(list), *_next; \ + e && (_next = ns_list_get_previous(list, e), true); e = _next) + +/** \hideinitializer \brief Count entries on a list + * + * Unlike other operations, this is O(n). Note: if list might contain over + * 65535 entries, this function **must not** be used to get the entry count. + * + * \param list `(const list_t *)` Pointer to list. + + * \return `(uint_fast16_t)` Number of entries that are stored in list. + */ +#define ns_list_count(list) ns_list_count_(&(list)->slist, NS_LIST_OFFSET_(list)) + +/** \privatesection + * Internal functions - designed to be accessed using corresponding macros above + */ +NS_INLINE void ns_list_init_(ns_list_t *list); +NS_INLINE void ns_list_link_init_(ns_list_link_t *link); +NS_INLINE void ns_list_add_to_start_(ns_list_t *list, ns_list_offset_t link_offset, void * restrict entry); +NS_INLINE void ns_list_add_to_end_(ns_list_t *list, ns_list_offset_t link_offset, void * restrict entry); +NS_INLINE void ns_list_add_before_(ns_list_offset_t link_offset, void *before, void * restrict entry); +NS_INLINE void ns_list_add_after_(ns_list_t *list, ns_list_offset_t link_offset, void *after, void * restrict entry); +NS_INLINE void *ns_list_get_next_(ns_list_offset_t link_offset, const void *current); +NS_INLINE void *ns_list_get_previous_(const ns_list_t *list, ns_list_offset_t link_offset, const void *current); +NS_INLINE void *ns_list_get_last_(const ns_list_t *list, ns_list_offset_t offset); +NS_INLINE void ns_list_remove_(ns_list_t *list, ns_list_offset_t link_offset, void *entry); +NS_INLINE void ns_list_replace_(ns_list_t *list, ns_list_offset_t link_offset, void *current, void * restrict replacement); +NS_INLINE void ns_list_concatenate_(ns_list_t *dst, ns_list_t *src, ns_list_offset_t offset); +NS_INLINE uint_fast16_t ns_list_count_(const ns_list_t *list, ns_list_offset_t link_offset); + +/* Provide definitions, either for inlining, or for ns_list.c */ +#if defined NS_ALLOW_INLINING || defined NS_LIST_FN +#ifndef NS_LIST_FN +#define NS_LIST_FN NS_INLINE +#endif + +/* Pointer to the link member in entry e */ +#define NS_LIST_LINK_(e, offset) ((ns_list_link_t *)((char *)(e) + offset)) + +/* Lvalue of the next link pointer in entry e */ +#define NS_LIST_NEXT_(e, offset) (NS_LIST_LINK_(e, offset)->next) + +/* Lvalue of the prev link pointer in entry e */ +#define NS_LIST_PREV_(e, offset) (NS_LIST_LINK_(e, offset)->prev) + +/* Convert a pointer to a link member back to the entry; + * works for linkptr either being a ns_list_link_t pointer, or its next pointer, + * as the next pointer is first in the ns_list_link_t */ +#define NS_LIST_ENTRY_(linkptr, offset) ((void *)((char *)(linkptr) - offset)) + +NS_LIST_FN void ns_list_init_(ns_list_t *list) +{ + list->first_entry = NULL; + list->last_nextptr = &list->first_entry; +} + +NS_LIST_FN void ns_list_link_init_(ns_list_link_t *link) +{ + NS_FUNNY_INTPTR_OK + link->next = NS_LIST_POISON; + link->prev = NS_LIST_POISON; + NS_FUNNY_INTPTR_RESTORE +} + +NS_LIST_FN void ns_list_add_to_start_(ns_list_t *list, ns_list_offset_t offset, void * restrict entry) +{ + void *next; + + NS_LIST_PREV_(entry, offset) = &list->first_entry; + NS_LIST_NEXT_(entry, offset) = next = list->first_entry; + + if (next) + { + NS_LIST_PREV_(next, offset) = &NS_LIST_NEXT_(entry, offset); + } + else + { + list->last_nextptr = &NS_LIST_NEXT_(entry, offset); + } + + list->first_entry = entry; +} + +NS_LIST_FN void ns_list_add_after_(ns_list_t *list, ns_list_offset_t offset, void *current, void * restrict entry) +{ + void *next; + + NS_LIST_PREV_(entry, offset) = &NS_LIST_NEXT_(current, offset); + NS_LIST_NEXT_(entry, offset) = next = NS_LIST_NEXT_(current, offset); + + if (next) + { + NS_LIST_PREV_(next, offset) = &NS_LIST_NEXT_(entry, offset); + } + else + { + list->last_nextptr = &NS_LIST_NEXT_(entry, offset); + } + + NS_LIST_NEXT_(current, offset) = entry; +} + +NS_LIST_FN void ns_list_add_before_(ns_list_offset_t offset, void *current, void * restrict entry) +{ + void **prev_nextptr; + + NS_LIST_NEXT_(entry, offset) = current; + NS_LIST_PREV_(entry, offset) = prev_nextptr = NS_LIST_PREV_(current, offset); + *prev_nextptr = entry; + NS_LIST_PREV_(current, offset) = &NS_LIST_NEXT_(entry, offset); +} + +NS_LIST_FN void ns_list_add_to_end_(ns_list_t *list, ns_list_offset_t offset, void * restrict entry) +{ + void **prev_nextptr; + + NS_LIST_NEXT_(entry, offset) = NULL; + NS_LIST_PREV_(entry, offset) = prev_nextptr = list->last_nextptr; + *prev_nextptr = entry; + list->last_nextptr = &NS_LIST_NEXT_(entry, offset); +} + +NS_LIST_FN void *ns_list_get_next_(ns_list_offset_t offset, const void *current) +{ + return NS_LIST_NEXT_(current, offset); +} + +NS_LIST_FN void *ns_list_get_previous_(const ns_list_t *list, ns_list_offset_t offset, const void *current) +{ + if(current == list->first_entry) + { + return NULL; + } + + // Tricky. We don't have a direct previous pointer, but a pointer to the + // pointer that points to us - ie &head->first_entry OR &{prev}->next. + // This makes life easier on insertion and removal, but this is where we + // pay the price. + + // We have to check manually for being the first entry above, so we know it's + // a real link's next pointer. Then next is the first field of + // ns_list_link_t, so we can use the normal offset value. + + return NS_LIST_ENTRY_(NS_LIST_PREV_(current, offset), offset); +} + +NS_LIST_FN void *ns_list_get_last_(const ns_list_t *list, ns_list_offset_t offset) +{ + if(!list->first_entry) + { + return NULL; + } + + // See comments in ns_list_get_previous_() + return NS_LIST_ENTRY_(list->last_nextptr, offset); +} + +NS_LIST_FN void ns_list_remove_(ns_list_t *list, ns_list_offset_t offset, void *removed) +{ + void *next; + void **prev_nextptr; + + next = NS_LIST_NEXT_(removed, offset); + prev_nextptr = NS_LIST_PREV_(removed, offset); + if (next) + { + NS_LIST_PREV_(next, offset) = prev_nextptr; + } + else + { + list->last_nextptr = prev_nextptr; + } + *prev_nextptr = next; + + ns_list_link_init_(NS_LIST_LINK_(removed, offset)); +} + +NS_LIST_FN void ns_list_replace_(ns_list_t *list, ns_list_offset_t offset, void *current, void * restrict replacement) +{ + void *next; + void **prev_nextptr; + + NS_LIST_PREV_(replacement, offset) = prev_nextptr = NS_LIST_PREV_(current, offset); + NS_LIST_NEXT_(replacement, offset) = next = NS_LIST_NEXT_(current, offset); + + if (next) + { + NS_LIST_PREV_(next, offset) = &NS_LIST_NEXT_(replacement, offset); + } + else + { + list->last_nextptr = &NS_LIST_NEXT_(replacement, offset); + } + *prev_nextptr = replacement; + + ns_list_link_init_(NS_LIST_LINK_(current, offset)); +} + +NS_LIST_FN void ns_list_concatenate_(ns_list_t *dst, ns_list_t *src, ns_list_offset_t offset) +{ + ns_list_link_t *src_first; + + src_first = src->first_entry; + if (!src_first) + return; + + *dst->last_nextptr = src_first; + NS_LIST_PREV_(src_first, offset) = dst->last_nextptr; + dst->last_nextptr = src->last_nextptr; + + ns_list_init_(src); +} + +NS_LIST_FN uint_fast16_t ns_list_count_(const ns_list_t *list, ns_list_offset_t offset) +{ + uint_fast16_t count = 0; + + for (void *p = list->first_entry; p; p = NS_LIST_NEXT_(p, offset)) + { + count++; + } + + return count; +} +#endif /* defined NS_ALLOW_INLINING || defined NS_LIST_FN */ + +#ifdef __cplusplus +} +#endif + +#endif /* NS_LIST_H_ */ + diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/ns_types.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/ns_types.h new file mode 100644 index 0000000000..7c0389f20a --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/ns_types.h @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2014-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * ns_types.h - Basic compiler and type setup for Nanostack libraries. + */ +#ifndef NS_TYPES_H_ +#define NS_TYPES_H_ + +/** \file + * \brief Basic compiler and type setup + * + * We currently assume C99 or later. + * + * C99 features being relied on: + * + * - and + * - inline (with C99 semantics, not C++ as per default GCC); + * - designated initialisers; + * - compound literals; + * - restrict; + * - [static N] in array parameters; + * - declarations in for statements; + * - mixing declarations and statements + * + * Compilers should be set to C99 or later mode when building Nanomesh source. + * For GCC this means "-std=gnu99" (C99 with usual GNU extensions). + * + * Also, a little extra care is required for public header files that could be + * included from C++, especially as C++ lacks some C99 features. + * + * (TODO: as this is exposed to API users, do we need a predefine to distinguish + * internal and external use, for finer control? Not yet, but maybe...) + */ + +/* Make sure defines its macros if C++ */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_CONSTANT_MACROS +#define __STDC_CONSTANT_MACROS +#endif + +#include +#include // includes ; debugf() users need PRIu32 etc +#include + +#if defined __GNUC__ && defined __arm__ +/* arm-none-eabi-gcc 4.8-2014q3 has a problem in its : + * int_fast32_t is defined as int, but PRIFAST32 are defined as "l". + * Try to detect this situation and override it. + * Very hard to detect types in the preprocessor - this is best I could do. + * Expansion works by: + * NS_TEST_Y(INT_FAST32_MAX) -> NS_TEST_X(2147483647) -> __NS2147483647 -> 1 + * Nested macros are needed so we don't get __NSINT_FAST32_MAX. + */ +#define __NS2147483647 1 +#define __NS2147483647L 2 +#define NS_TEST_X(x) __NS##x +#define NS_TEST_Y(x) NS_TEST_X(x) + +#if NS_TEST_Y(INT_FAST32_MAX) == __NS2147483647 && \ + NS_TEST_Y(INT_LEAST32_MAX) == __NS2147483647L && \ + NS_TEST_Y(INT32_MAX) == __NS2147483647L + +// Fast 32-bit types are int, others are long - this is the problem case in +// arm-none-eabi-gcc. +#undef PRIoFAST32 +#undef PRIuFAST32 +#undef PRIxFAST32 +#undef PRIXFAST32 +#undef PRIdFAST32 +#undef PRIiFAST32 +#define PRIoFAST32 "o" +#define PRIuFAST32 "u" +#define PRIxFAST32 "x" +#define PRIXFAST32 "X" +#define PRIdFAST32 "d" +#define PRIiFAST32 "i" +#endif +#undef NS_TEST_X +#undef NS_TEST_Y +#undef __NS2147483647 +#undef __NS2147483647L +#endif + +/* + * Create the optional 24-bit types if they don't exist (worth trying + * to use them, as they could exist and be more efficient than 32-bit on 8-bit + * systems...) + */ +#ifndef UINT24_LEAST_MAX +typedef uint_least32_t uint_least24_t; +#define UINT_LEAST24_MAX UINT_LEAST32_MAX +#define UINT24_C(x) UINT32_C(x) +#define PRIoLEAST24 PRIoLEAST32 +#define PRIuLEAST24 PRIuLEAST32 +#define PRIxLEAST24 PRIxLEAST32 +#define PRIXLEAST24 PRIXLEAST32 +#endif + +#ifndef INT24_LEAST_MAX +typedef int_least32_t int_least24_t; +#define INT24_LEAST_MIN INT_LEAST32_MIN +#define INT24_LEAST_MAX INT_LEAST32_MAX +#define INT24_C(x) INT32_C(x) +#define PRIdLEAST24 PRIdLEAST32 +#define PRIiLEAST24 PRIiLEAST32 +#endif + +#ifndef UINT24_FAST_MAX +typedef uint_fast32_t uint_fast24_t; +#define UINT_FAST24_MAX UINT_FAST32_MAX +#define PRIoFAST24 PRIoFAST32 +#define PRIuFAST24 PRIuFAST32 +#define PRIxFAST24 PRIxFAST32 +#define PRIXFAST24 PRIXFAST32 +#endif + +#ifndef INT24_FAST_MAX +typedef int_fast32_t int_fast24_t; +#define INT_FAST24_MIN INT_FAST32_MIN +#define INT_FAST24_MAX INT_FAST32_MAX +#define PRIdFAST24 PRIdFAST32 +#define PRIiFAST24 PRIiFAST32 +#endif + +/* C11's "noreturn" macro, emulated if necessary */ +#ifndef noreturn +#if defined __cplusplus && __cplusplus >= 201103L +// noreturn is a C++11 keyword +#elif __STDC_VERSION__ >= 201112L +#include +#elif defined __GNUC__ +#define noreturn /*__attribute__((__noreturn__))*/ +#elif defined __CC_ARM +#define noreturn __declspec(noreturn) +#elif defined __IAR_SYSTEMS_ICC__ +#define noreturn __noreturn +#else +#define noreturn +#endif +#endif + +/* C11's "alignas" macro, emulated for integer expressions if necessary */ +#ifndef __alignas_is_defined +#if __STDC_VERSION__ >= 201112L || (defined __cplusplus && __cplusplus >= 201103L) +#include +#elif defined __GNUC__ +#define alignas(n) __attribute__((__aligned__(n))) +#define __alignas_is_defined 1 +#elif defined __CC_ARM || defined __TASKING__ +#define alignas(n) __align(n) +#define __alignas_is_defined 1 +#elif defined __IAR_SYSTEMS_ICC__ +/* Does this really just apply to the next variable? */ +#define alignas(n) __Alignas(data_alignment=n) +#define __Alignas(x) _Pragma(#x) +#define __alignas_is_defined 1 +#endif +#endif + +/** + * Marker for functions or objects that may be unused, suppressing warnings. + * Place after the identifier: + * ~~~ + * static int X MAYBE_UNUSED = 3; + * static int foo(void) MAYBE_UNUSED; + * ~~~ + */ +#if defined __CC_ARM || defined __GNUC__ +#define MAYBE_UNUSED __attribute__((unused)) +#else +#define MAYBE_UNUSED +#endif + +/* + * C++ (even C++11) doesn't provide restrict: define away or provide + * alternative. + */ +#ifdef __cplusplus +#ifdef __GNUC__ +#define restrict __restrict +#else +#define restrict +#endif +#endif /* __cplusplus */ + + +/** + * C++ doesn't allow "static" in function parameter types: ie + * ~~~ + * entry_t *find_entry(const uint8_t address[static 16]) + * ~~~ + * If a header file may be included from C++, use this __static define instead. + * + * (Syntax introduced in C99 - `uint8_t address[16]` in a prototype was always + * equivalent to `uint8_t *address`, but the C99 addition of static tells the + * compiler that address is never NULL, and always points to at least 16 + * elements. This adds no new type-checking, but the information could aid + * compiler optimisation, and it can serve as documentation). + */ +#ifdef __cplusplus +#define __static +#else +#define __static static +#endif + +#ifdef __GNUC__ +#define NS_GCC_VERSION (__GNUC__ * 10000 \ + + __GNUC_MINOR__ * 100 \ + + __GNUC_PATCHLEVEL__) +#endif + +/** \brief Compile-time assertion + * + * C11 provides _Static_assert, as does GCC even in C99 or C++ mode (and + * as a freestanding implementation, we can't rely on to get + * the static_assert macro). + * C++11 provides static_assert as a keyword. + * + * The assertion acts as a declaration that can be placed at file scope, in a + * code block (except after a label), or as a member of a struct/union. It + * produces a compiler error if "test" evaluates to 0. + * + * Note that this *includes* the required semicolon when defined, else it + * is totally empty, permitting use in structs. (If the user provided the `;`, + * it would leave an illegal stray `;` if unavailable). + */ +#if __STDC_VERSION__ >= 201112L +#define NS_STATIC_ASSERT(test, str) _Static_assert(test, str); +#elif defined __cplusplus && __cplusplus >= 201103L +#define NS_STATIC_ASSERT(test, str) static_assert(test, str); +#elif defined __GNUC__ && NS_GCC_VERSION >= 40600 +//#define NS_STATIC_ASSERT(test, str) __extension__ _Static_assert(test, str); +#define NS_STATIC_ASSERT(test, str) +#else +#define NS_STATIC_ASSERT(test, str) +#endif + +#define static_assert _Static_assert + +/** \brief Pragma to suppress warnings about unusual pointer values. + * + * Useful if using "poison" values. + */ +#ifdef __IAR_SYSTEMS_ICC__ +#define NS_FUNNY_INTPTR_OK _Pragma("diag_suppress=Pe1053") +#define NS_FUNNY_INTPTR_RESTORE _Pragma("diag_default=Pe1053") +#else +#define NS_FUNNY_INTPTR_OK +#define NS_FUNNY_INTPTR_RESTORE +#endif + +/** \brief Convert pointer to member to pointer to containing structure */ +#define NS_CONTAINER_OF(ptr, type, member) \ + ((type *) ((char *) (ptr) - offsetof(type, member))) + +/* + * Inlining could cause problems when mixing with C++; provide a mechanism to + * disable it. This could also be turned off for other reasons (although + * this can usually be done through a compiler flag, eg -O0 on gcc). + */ +#ifndef __cplusplus +#define NS_ALLOW_INLINING +#endif + +/* There is inlining problem in GCC version 4.1.x and we know it works in 4.6.3 */ +#if defined __GNUC__ && NS_GCC_VERSION < 40600 +#undef NS_ALLOW_INLINING +#endif + +/** \brief Mark a potentially-inlineable function. + * + * We follow C99 semantics, which requires precisely one external definition. + * To also allow inlining to be totally bypassed under control of + * NS_ALLOW_INLINING, code can be structured as per the example of ns_list: + * + * foo.h + * ----- + * ~~~ + * NS_INLINE int my_func(int); + * + * #if defined NS_ALLOW_INLINING || defined FOO_FN + * #ifndef FOO_FN + * #define FOO_FN NS_INLINE + * #endif + * FOO_FN int my_func(int a) + * { + * definition; + * } + * #endif + * ~~~ + * foo.c + * ----- + * ~~~ + * #define FOO_FN extern + * #include "foo.h" + * ~~~ + * Which generates: + * ~~~ + * NS_ALLOW_INLINING set NS_ALLOW_INLINING unset + * ===================== ======================= + * Include foo.h Include foo.h + * ------------- ------------- + * inline int my_func(int); int my_func(int); + * + * // inline definition + * inline int my_func(int a) + * { + * definition; + * } + * + * Compile foo.c Compile foo.c + * ------------- ------------- + * (from .h) inline int my_func(int); int my_func(int); + * + * // external definition + * // because of no "inline" // normal external definition + * extern int my_func(int a) extern int my_func(int a) + * { { + * definition; definition; + * } } + * ~~~ + * + * Note that even with inline keywords, whether the compiler inlines or not is + * up to it. For example, gcc at "-O0" will not inline at all, and will always + * call the real functions in foo.o, just as if NS_ALLOW_INLINING was unset. + * At "-O2", gcc could potentially inline everything, meaning that foo.o is not + * referenced at all. + * + * Alternatively, you could use "static inline", which gives every caller its + * own internal definition. This is compatible with C++ inlining (which expects + * the linker to eliminate duplicates), but in C it's less efficient if the code + * ends up non-inlined, and it's harder to breakpoint. I don't recommend it + * except for the most trivial functions (which could then probably be macros). + */ +#ifdef NS_ALLOW_INLINING +#define NS_INLINE inline +#else +#define NS_INLINE +#endif + +#if defined __SDCC_mcs51 || defined __ICC8051__ || defined __C51__ + +/* The 8051 environments: SDCC (historic), IAR (current), Keil (future?) */ + +#define NS_LARGE __xdata +#define NS_LARGE_PTR __xdata +#ifdef __ICC8051__ +#define NS_REENTRANT +#define NS_REENTRANT_PREFIX __idata_reentrant +#else +#define NS_REENTRANT __reentrant +#define NS_REENTRANT_PREFIX +#endif +#define NS_NEAR_FUNC __near_func + +#else + +/* "Normal" systems. Define it all away. */ +#define NS_LARGE +#define NS_LARGE_PTR +#define NS_REENTRANT +#define NS_REENTRANT_PREFIX +#define NS_NEAR_FUNC + +#endif + +/** \brief Scatter-gather descriptor + * + * Slightly optimised for small platforms - we assume we won't need any + * element bigger than 64K. + */ +typedef struct ns_iovec +{ + void *iov_base; + uint_fast16_t iov_len; +} ns_iovec_t; +#endif /* NS_TYPES_H */ diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sal/socket_api.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sal/socket_api.h new file mode 100644 index 0000000000..8c61d39eed --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sal/socket_api.h @@ -0,0 +1,164 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKET_ABSTRACT_SOCKET_API_H__ +#define __MBED_NET_SOCKET_ABSTRACT_SOCKET_API_H__ + +#include +#include "socket_types.h" +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef SOCKET_MAX_STACKS +#define SOCKET_MAX_STACKS 2 +#endif + +typedef socket_error_t (*socket_init)(); +typedef socket_error_t (*socket_create)(struct socket *socket, + const socket_address_family_t af, const socket_proto_family_t pf, + socket_api_handler_t const handler); +typedef socket_error_t (*socket_destroy)(struct socket *socket); +typedef socket_error_t (*socket_close)(struct socket *socket); +typedef socket_api_handler_t (*socket_periodic_task)(const struct socket * socket); +typedef uint32_t (*socket_periodic_interval)(const struct socket * socket); +typedef socket_error_t (*socket_resolve)(struct socket *socket, const char *address); +typedef socket_error_t (*socket_connect)(struct socket *sock, const struct socket_addr *address, const uint16_t port); +typedef socket_error_t (*socket_bind)(struct socket *socket, const struct socket_addr *address, const uint16_t port); +typedef socket_error_t (*socket_str2addr)(const struct socket *socket, struct socket_addr *addr, const char *address); +typedef socket_error_t (*socket_start_listen)(struct socket *socket, const uint32_t backlog); +typedef socket_error_t (*socket_stop_listen)(struct socket *socket); +typedef socket_error_t (*socket_accept)(struct socket *sock, socket_api_handler_t handler); +typedef socket_error_t (*socket_reject)(struct socket *sock); +typedef socket_error_t (*socket_send)(struct socket *socket, const void * buf, const size_t len); +typedef socket_error_t (*socket_send_to)(struct socket *socket, const void * buf, const size_t len, const struct socket_addr *addr, const uint16_t port); +typedef socket_error_t (*socket_recv)(struct socket *socket, void * buf, size_t *len); +typedef socket_error_t (*socket_recv_from)(struct socket *socket, void * buf, size_t *len, struct socket_addr *addr, uint16_t *port); + +typedef socket_error_t (*socket_get_local_addr)(const struct socket *socket, struct socket_addr *addr); +typedef socket_error_t (*socket_get_remote_addr)(const struct socket *socket, struct socket_addr *addr); +typedef socket_error_t (*socket_get_local_port)(const struct socket *socket, uint16_t *port); +typedef socket_error_t (*socket_get_remote_port)(const struct socket *socket, uint16_t *port); + +typedef uint8_t (*socket_is_connected)(const struct socket *socket); +typedef uint8_t (*socket_is_bound)(const struct socket *socket); + +struct socket_api { + socket_stack_t stack; + uint32_t version; + socket_init init; + socket_create create; + socket_destroy destroy; + socket_close close; + socket_periodic_task periodic_task; + socket_periodic_interval periodic_interval; + socket_resolve resolve; + socket_connect connect; + socket_str2addr str2addr; + socket_bind bind; + socket_start_listen start_listen; + socket_stop_listen stop_listen; + socket_accept accept; + socket_reject reject; + socket_send send; + socket_send_to send_to; + socket_recv recv; + socket_recv_from recv_from; + socket_is_connected is_connected; + socket_is_bound is_bound; + socket_get_local_addr get_local_addr; + socket_get_remote_addr get_remote_addr; + socket_get_local_port get_local_port; + socket_get_remote_port get_remote_port; +}; +#define SOCKET_API_FIRST_PTR init +#define SOCKET_API_LAST_PTR get_remote_port + +socket_error_t socket_register_stack(const struct socket_api * api); +const char * socket_strerror(const socket_error_t err); +const struct socket_api * socket_get_api(const socket_stack_t stack); + +static inline int socket_addr_is_ipv4(const struct socket_addr *addr) +{ + if ((addr->ipv6be[0] == 0) && + (addr->ipv6be[1] == 0) && + (addr->ipv6be[2] == 0)) { + return 1; + } else { + return 0; + } +} +static inline int socket_addr_is_any(const struct socket_addr *addr) +{ + if ((addr->ipv6be[0] == 0) && + (addr->ipv6be[1] == 0) && + (addr->ipv6be[2] == 0) && + (addr->ipv6be[3] == 0)) { + return 1; + } else { + return 0; + } +} +static inline void socket_addr_set_ipv4_addr(struct socket_addr *addr, uint32_t ipv4addr) +{ + addr->ipv6be[0] = 0; + addr->ipv6be[1] = 0; + addr->ipv6be[2] = 0; + addr->ipv6be[3] = ipv4addr; +} +static inline uint32_t socket_addr_get_ipv4_addr(const struct socket_addr *addr) +{ + if (!socket_addr_is_ipv4(addr)) { + return 0; + } + return addr->ipv6be[3]; +} +static inline const uint32_t * socket_addr_get_ipv4_addrp(const struct socket_addr *addr) +{ + if (!socket_addr_is_ipv4(addr)) { + return NULL; + } + return &addr->ipv6be[3]; +} +static inline void socket_addr_set_any(struct socket_addr *addr) +{ + addr->ipv6be[0] = 0; + addr->ipv6be[1] = 0; + addr->ipv6be[2] = 0; + addr->ipv6be[3] = 0; +} + +static inline void socket_addr_copy(struct socket_addr *dest, const struct socket_addr *src) +{ + (dest)->ipv6be[0] = (src)->ipv6be[0]; + (dest)->ipv6be[1] = (src)->ipv6be[1]; + (dest)->ipv6be[2] = (src)->ipv6be[2]; + (dest)->ipv6be[3] = (src)->ipv6be[3]; +} +static inline int socket_addr_cmp(const struct socket_addr *a, const struct socket_addr *b) +{ + return + a->ipv6be[0] != b->ipv6be[0] || + a->ipv6be[1] != b->ipv6be[1] || + a->ipv6be[2] != b->ipv6be[2] || + a->ipv6be[3] != b->ipv6be[3]; +} + +#ifdef __cplusplus +} +#endif + +#endif /* __MBED_NET_SOCKET_ABSTRACT_SOCKET_API_H__ */ diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sal/socket_types.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sal/socket_types.h new file mode 100644 index 0000000000..0ffb822d9b --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sal/socket_types.h @@ -0,0 +1,181 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKET_ABSTRACT_SOCKET_TYPES_H__ +#define __MBED_NET_SOCKET_ABSTRACT_SOCKET_TYPES_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MBED_NET_LWIP +#define MBED_NET_LWIP 1 +#endif + +typedef enum { + SOCKET_ERROR_NONE = 0, + SOCKET_ERROR_UNKNOWN, + SOCKET_ERROR_UNIMPLEMENTED, + SOCKET_ERROR_BUSY, + SOCKET_ERROR_NULL_PTR, + SOCKET_ERROR_BAD_FAMILY, + SOCKET_ERROR_TIMEOUT, + SOCKET_ERROR_BAD_ALLOC, + SOCKET_ERROR_NO_CONNECTION, + SOCKET_ERROR_SIZE, + SOCKET_ERROR_STACK_EXISTS, + SOCKET_ERROR_STACKS, + SOCKET_ERROR_BAD_STACK, + SOCKET_ERROR_BAD_ADDRESS, + SOCKET_ERROR_DNS_FAILED, + SOCKET_ERROR_WOULD_BLOCK, + SOCKET_ERROR_CLOSED, + SOCKET_ERROR_VALUE, + SOCKET_ERROR_ADDRESS_IN_USE, + SOCKET_ERROR_ALREADY_CONNECTED, + SOCKET_ERROR_ABORT, + SOCKET_ERROR_RESET, + SOCKET_ERROR_BAD_ARGUMENT, + SOCKET_ERROR_INTERFACE_ERROR, + SOCKET_ERROR_API_VERSION, + SOCKET_ERROR_NOT_BOUND, + +} socket_error_t; + +typedef enum { + SOCKET_ALLOC_HEAP = 0, + SOCKET_ALLOC_POOL_BEST, +} socket_alloc_pool_t; + +typedef enum { + SOCKET_AF_UNINIT, + SOCKET_AF_INET4, + SOCKET_AF_INET6, + SOCKET_AF_MAX, +} socket_address_family_t; + +typedef enum { + SOCKET_PROTO_UNINIT = 0, + SOCKET_DGRAM, + SOCKET_STREAM, + SOCKET_PROTO_MAX, +} socket_proto_family_t; + +typedef enum { + SOCKET_EVENT_NONE = 0, + SOCKET_EVENT_ERROR, + SOCKET_EVENT_RX_DONE, + SOCKET_EVENT_TX_DONE, + SOCKET_EVENT_RX_ERROR, + SOCKET_EVENT_TX_ERROR, + SOCKET_EVENT_CONNECT, + SOCKET_EVENT_DISCONNECT, + SOCKET_EVENT_DNS, + SOCKET_EVENT_ACCEPT, +} event_flag_t; + +typedef enum { + SOCKET_STATUS_IDLE = 0, + SOCKET_STATUS_RX_BUSY = 1 << 0, + SOCKET_STATUS_TX_BUSY = 1 << 1, + SOCKET_STATUS_CONNECTED = 1 << 2, + SOCKET_STATUS_BOUND = 1 << 3, +} socket_status_t; + +typedef enum { + SOCKET_STACK_UNINIT = 0, + SOCKET_STACK_LWIP_IPV4, + SOCKET_STACK_LWIP_IPV6, + SOCKET_STACK_RESERVED, + SOCKET_STACK_NANOSTACK_IPV6, + SOCKET_STACK_PICOTCP, + SOCKET_STACK_MAX, +} socket_stack_t; + +typedef enum { + SOCKET_BUFFER_UNINITIALISED = 0, + SOCKET_BUFFER_RAW, + SOCKET_BUFFER_LWIP_PBUF, + SOCKET_BUFFER_NANOSTACK_PBUF, +} socket_buffer_type_t; + +struct socket_addr { + uint32_t ipv6be[4]; +}; + +struct socket_buffer { + socket_buffer_type_t type; + const struct socket_buf_api *api; + void *impl; +}; + +struct socket_rawbuf { + void * buf; + size_t size; + size_t pos; +}; + +typedef void (*socket_api_handler_t)(void); +typedef struct { + void * (*alloc)(void *,const size_t); + void (*dealloc)(void *, void *); + void *context; +} socket_allocator_t; + +struct socket_tx_info { + uint16_t sentbytes; +}; + +struct socket_dns_info { + struct socket_addr addr; // A stack-specific socket address struct + const char *domain; +}; + +struct socket_accept_info { + void * newimpl; + uint8_t reject; +}; + +struct socket_event { + event_flag_t event; + struct socket *sock; + union { + struct socket_tx_info t; + socket_error_t e; + struct socket_dns_info d; + struct socket_accept_info a; + } i; +}; +typedef struct socket_event socket_event_t; + +struct socket { + socket_api_handler_t handler; + socket_event_t *event; // TODO: (CThunk upgrade/Alpha3) + const struct socket_api *api; + void *impl; + socket_status_t status; + uint8_t family; + socket_stack_t stack; + void *rxBufChain; // TODO: Only required in some stacks, which do not support BSD-style buffering +}; + +#ifdef __cplusplus +} +#endif +#endif /* __MBED_NET_SOCKET_ABSTRACT_SOCKET_TYPES_H__ */ diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/Socket.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/Socket.h new file mode 100644 index 0000000000..e4dfda504f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/Socket.h @@ -0,0 +1,32 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKETS_SOCKET_H__ +#define __MBED_NET_SOCKETS_SOCKET_H__ + +/* Include all versions of the API */ +#include "v0/Socket.h" + +/* Set the current namespace */ +namespace mbed { + namespace Sockets { + namespace current { + using namespace mbed::Sockets::v0; + } + } +} + +#endif // __MBED_NET_SOCKETS_SOCKET_H__ diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/SocketAddr.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/SocketAddr.h new file mode 100644 index 0000000000..99f2943e9d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/SocketAddr.h @@ -0,0 +1,32 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKETS_SOCKETADDR_H__ +#define __MBED_NET_SOCKETS_SOCKETADDR_H__ + +/* Include all versions of the API */ +#include "v0/SocketAddr.h" + +/* Set the current namespace */ +namespace mbed { + namespace Sockets { + namespace current { + using namespace mbed::Sockets::v0; + } + } +} + +#endif // __MBED_NET_SOCKETS_SOCKETADDR_H__ diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/UDPSocket.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/UDPSocket.h new file mode 100644 index 0000000000..d2d2046650 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/UDPSocket.h @@ -0,0 +1,32 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKETS_UDPSOCKET_H__ +#define __MBED_NET_SOCKETS_UDPSOCKET_H__ + +/* Include all versions of the API */ +#include "v0/UDPSocket.h" + +/* Set the current namespace */ +namespace mbed { + namespace Sockets { + namespace current { + using namespace mbed::Sockets::v0; + } + } +} + +#endif // __MBED_NET_SOCKETS_UDPSOCKET_H__ diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/Socket.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/Socket.h new file mode 100644 index 0000000000..443d8a3042 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/Socket.h @@ -0,0 +1,268 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKETS_V0_SOCKET_H__ +#define __MBED_NET_SOCKETS_V0_SOCKET_H__ + + +#include +#include +#include "mbed.h" +#include "FunctionPointer.h" +#include "CThunk.h" +#include "sal/socket_types.h" +#include "SocketAddr.h" + +namespace mbed { +namespace Sockets { +namespace v0 { + +/** + * \brief Socket implements most of the interfaces required for sockets. + * Socket is a pure virtual class; it should never be instantiated directly, but it provides + * common functionality for derived classes. + */ +class Socket { +public: + typedef FunctionPointer3 DNSHandler_t; + typedef FunctionPointer2 ErrorHandler_t; + typedef FunctionPointer1 ReadableHandler_t; + typedef FunctionPointer2 SentHandler_t; +protected: + /** + * Socket constructor + * Initializes the Socket object. Initializes the underlying struct socket. Does not instantiate + * an underlying network stack socket. + * Since it is somewhat awkward to provide the network stack, a future change will provide + * a way to pass the network interface to the socket constructor, which will extract the stack from + * the interface. + * @param[in] stack The network stack to use for this socket. + */ + Socket(const socket_stack_t stack); + /** + * Socket destructor + * Frees the underlying socket implementation. + */ + virtual ~Socket(); +public: + /** + * Start the process of resolving a domain name. + * If the input is a text IP address, an event is queued immediately; otherwise, onDNS is + * queued as soon as DNS is resolved. + * The socket must have been opened before resolve is called + * @param[in] address The domain name to resolve + * @param[in] onDNS The handler to call when the name is resolved + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + virtual socket_error_t resolve(const char* address, const DNSHandler_t &onDNS); + /** + * Open the socket. + * Instantiates and initializes the underlying socket. Receive is started immediately after + * the socket is opened. + * @param[in] af Address family (SOCKET_AF_INET4 or SOCKET_AF_INET6), currently only IPv4 is supported + * @param[in] pf Protocol family (SOCKET_DGRAM or SOCKET_STREAM) + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + virtual socket_error_t open(const socket_address_family_t af, const socket_proto_family_t pf); + /** + * Binds the socket's local address and IP. + * 0.0.0.0 is accepted as a local address if only the port is meant to be bound. + * The behaviour of bind("0.0.0.0",...) is undefined where two or more stacks are in use. + * + * @param[in] address The string representation of the address to bind + * @param[in] port The local port to bind + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + virtual socket_error_t bind(const char *address, const uint16_t port); + /** + * bind(const SocketAddr *, const uint16_t) is the same as bind(const char *, const uint16_t), + * except that the address passed in is a SocketAddr. + * @param[in] address The address to bind + * @param[in] port The local port to bind + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + virtual socket_error_t bind(const SocketAddr *address, const uint16_t port); + /** + * Set the error handler. + * Errors are ignored if onError is not set. + * @param[in] onError + */ + virtual void setOnError(const ErrorHandler_t &onError); + /** + * Set the received data handler + * Received data is queued until it is read using recv or recv_from. + * @param[in] onReadable the handler to use for receive events + */ + virtual void setOnReadable(const ReadableHandler_t &onReadable); + /** + * Receive a message + * @param[out] buf The buffer to fill + * @param[in,out] len A pointer to the size of the receive buffer. Sets the maximum number of bytes + * to read but is updated with the actual number of bytes copied on success. len is not changed on + * failure + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + virtual socket_error_t recv(void * buf, size_t *len); + /** + * Receive a message with the sender address and port + * This API is not valid for SOCK_STREAM + * @param[out] buf The buffer to fill + * @param[in,out] len A pointer to the size of the receive buffer. Sets the maximum number of bytes + * to read but is updated with the actual number of bytes copied on success. len is not changed on + * failure + * @param[out] remote_addr Pointer to an address structure to fill with the sender address + * @param[out] remote_port Pointer to a uint16_t to fill with the sender port + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + virtual socket_error_t recv_from(void * buf, size_t *len, SocketAddr *remote_addr, uint16_t *remote_port); + /** + * Set the onSent handler. + * The exact moment this handler is called varies from implementation to implementation. + * On LwIP, onSent is called when the remote host ACK's data in TCP sockets, or when the message enters + * the network stack in UDP sockets. + * @param[in] onSent The handler to call when a send completes + */ + virtual void setOnSent(const SentHandler_t &onSent); + /** + * Send a message + * Sends a message over an open connection. This call is valid for UDP sockets, provided that connect() + * has been called. + * @param[in] buf The payload to send + * @param[in] len The size of the payload + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + virtual socket_error_t send(const void * buf, const size_t len); + /** + * Send a message to a specific address and port + * This API is not valid for SOCK_STREAM + * @param[in] buf The payload to send + * @param[in] len The size of the payload + * @param[in] address The address to send to + * @param[in] port The remote port to send to + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + virtual socket_error_t send_to(const void * buf, const size_t len, const SocketAddr *remote_addr, uint16_t remote_port); + /** + * Shuts down a socket. + * Sending and receiving are no longer possible after close() is called. + * The socket is not deallocated on close. A socket must not be reopened, it should be + * destroyed (either with delete, or by going out of scope) after calling close. + * Calling open on a closed socket can result in a memory leak. + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + virtual socket_error_t close(); + /** + * Error checking utility + * Generates an event on error, does nothing on SOCKET_ERROR_NONE + * @param[in] err the error code to check + * @return false if err is SOCKET_ERROR_NONE, true otherwise + */ + virtual bool error_check(socket_error_t err); + + /** + * Checks the socket status to determine whether it is still connected. + * @return true if the socket is connected, false if it is not + */ + virtual bool isConnected() const; + + /** + * Get the local address of the socket if bound. + * There are several failing conditions for this method: + * 1. If the socket has not been opened, returns SOCKET_ERROR_NULL_PTR + * 2. If the socket has not been bound, returns SOCKET_ERROR_NOT_BOUND + * 3. If addr is NULL, returns SOCKET_ERROR_NULL_PTR + * + * Otherwise, populates the SocketAddr object with the local address + * + * @param[out] addr a pointer to a SocketAddr object + * @return SOCKET_ERROR_NONE on success, or an error code on failure (see description) + */ + virtual socket_error_t getLocalAddr(SocketAddr *addr) const; + + /** + * Get the local port of the socket if bound. + * There are several failing conditions for this method: + * 1. If the socket has not been opened, returns SOCKET_ERROR_NULL_PTR + * 2. If the socket has not been bound, returns SOCKET_ERROR_NOT_BOUND + * 3. If port is NULL, returns SOCKET_ERROR_NULL_PTR + * + * Otherwise, populates the uint16_t object with the local port + * + * @param[out] port a pointer to a uint16_t + * @return SOCKET_ERROR_NONE on success, or an error code on failure (see description) + */ + virtual socket_error_t getLocalPort(uint16_t *port) const; + + /** + * Get the remote address of the socket if connected. + * There are several failing conditions for this method: + * 1. If the socket has not been opened, returns SOCKET_ERROR_NULL_PTR + * 2. If the socket has not been connected, returns SOCKET_ERROR_NO_CONNECTION + * 3. If addr is NULL, returns SOCKET_ERROR_NULL_PTR + * + * Otherwise, populates the SocketAddr object with the remote address + * + * @param[out] addr a pointer to a SocketAddr object + * @return SOCKET_ERROR_NONE on success, or an error code on failure (see description) + */ + virtual socket_error_t getRemoteAddr(SocketAddr *addr) const; + /** + * Get the remote port of the socket if connected. + * There are several failing conditions for this method: + * 1. If the socket has not been opened, returns SOCKET_ERROR_NULL_PTR + * 2. If the socket has not been connected, returns SOCKET_ERROR_NO_CONNECTION + * 3. If port is NULL, returns SOCKET_ERROR_NULL_PTR + * + * Otherwise, populates the uint16_t object with the remote port + * + * @param[out] port a pointer to a uint16_t + * @return SOCKET_ERROR_NONE on success, or an error code on failure (see description) + */ + virtual socket_error_t getRemotePort(uint16_t *port) const; + +#if 0 // not implemented yet + static long ntohl(long); + static short ntohs(short); + static long long ntohll(long long); +#endif + +protected: + /** + * The internal event handler + * @param[in] ev The event to handle + */ + virtual void _eventHandler(struct socket_event *ev); + +protected: + DNSHandler_t _onDNS; + ErrorHandler_t _onError; + ReadableHandler_t _onReadable; + SentHandler_t _onSent; + + CThunk _irq; + struct socket _socket; +private: + socket_event_t *_event; + /** + * Internal event handler. + * @param[in] arg + */ + void _nvEventHandler(void * arg); +}; +} // namespace v0 +} // namespace Sockets +} // namespace mbed +#endif // __MBED_NET_SOCKETS_V0_SOCKET_H__ diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/SocketAddr.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/SocketAddr.h new file mode 100644 index 0000000000..bc0fa17d65 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/SocketAddr.h @@ -0,0 +1,43 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKETS_V0_SOCKETADDR_H__ +#define __MBED_NET_SOCKETS_V0_SOCKETADDR_H__ + +#include "sal/socket_types.h" + +namespace mbed { +namespace Sockets { +namespace v0 { + +class SocketAddr { +public: + struct socket_addr * getAddr() {return &_addr;} + const struct socket_addr * getAddr() const {return &_addr;} + void setAddr(const struct socket_addr *addr); + void setAddr(const SocketAddr *addr); + size_t getAddrSize() const {return sizeof(_addr.ipv6be);} + bool is_v4(); + + int fmtIPv4(char *buf, size_t size); + int fmtIPv6(char *buf, size_t size); +protected: + struct socket_addr _addr; +}; +} // namespace v0 +} // namespace Sockets +} // namespace mbed +#endif // __MBED_NET_SOCKETS_V0_SOCKETADDR_H__ diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/TCPAsynch.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/TCPAsynch.h new file mode 100644 index 0000000000..58a9bb214f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/TCPAsynch.h @@ -0,0 +1,47 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKETS_V0_TCP_ASYNCH__ +#define __MBED_NET_SOCKETS_V0_TCP_ASYNCH__ + +#include "Socket.h" +#include "sal/socket_api.h" + +#include "Ticker.h" + +namespace mbed { +namespace Sockets { +namespace v0 { +class TCPAsynch: public Socket { +protected: + TCPAsynch(const socket_stack_t stack); + ~TCPAsynch(); + +public: + virtual socket_error_t open(const socket_address_family_t af); +protected: + static Ticker _ticker; + static FunctionPointer0 _tick_handler; + // uintptr_t is used to guarantee that there will always be a large enough + // counter to avoid overflows. Memory allocation will always fail before + // counter overflow if the counter is the same size as the pointer type and + // sizeof(TCPAsynch) > 0 + static uintptr_t _TCPSockets; +}; +} // namespace v0 +} // namespace Sockets +} // namespace mbed +#endif // __MBED_NET_SOCKETS_V0_TCP_ASYNCH__ diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/TCPListener.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/TCPListener.h new file mode 100644 index 0000000000..98ab5cbfce --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/TCPListener.h @@ -0,0 +1,86 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKETS_V0_TCPLISTENER_H__ +#define __MBED_NET_SOCKETS_V0_TCPLISTENER_H__ + +#include +#include +#include "mbed/FunctionPointer.h" +#include "TCPAsynch.h" +#include "TCPStream.h" + +namespace mbed { +namespace Sockets { +namespace v0 { +/** \brief TCPListener: a TCP server socket + * The TCPListener listens for incoming connections. Prior to listening, the + * TCPListener must be bound to a port and, optionally, an address. + */ +class TCPListener: public TCPAsynch { +public: + typedef FunctionPointer2 IncomingHandler_t; + /** + * The TCP Listener constructor. + * @param[in] stack the network stack to use + */ + TCPListener(const socket_stack_t stack); + + /** + * The TCP Listener destructor + * This performs teardown of the listener + */ + ~TCPListener(); + + /** + * Begin listening for incoming connections. + * The supplied listenHandler will be called whenever an incoming connection arrives + * To reject a connection, the event handler needs to set the reject flag in the event. + * @param[in] listenHandler The event handler to call when an incoming connection arrives + * @param[in] backlog The number of connection requests to keep in the backlog + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + socket_error_t start_listening(IncomingHandler_t listenHandler, uint32_t backlog = 0); + /** + * Stop listening for incoming connections + * After this call, the server will reject incoming connections until start_listening is called again + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + socket_error_t stop_listening(); + + /** + * accept is a utility function for constructing a new TCPStream from an incoming connection + * The event passed to the listenHandler contains a pointer to a low level implementation of an + * already connected socket. This function + * @param new_impl + * @return + */ + virtual TCPStream * accept(void *new_impl); + virtual void reject(void *new_impl); + +protected: + /** + * Internal event handler + * @param[in] ev the event to handle + */ + void _eventHandler(struct socket_event *ev); + + IncomingHandler_t _onIncoming; +}; +} // namespace v0 +} // namespace Sockets +} // namespace mbed +#endif // __MBED_NET_SOCKETS_V0_TCPLISTENER_H__ diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/TCPStream.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/TCPStream.h new file mode 100644 index 0000000000..361d9c200f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/TCPStream.h @@ -0,0 +1,83 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKETS_V0_TCPSTREAM_H__ +#define __MBED_NET_SOCKETS_V0_TCPSTREAM_H__ +#include +#include +#include "Ticker.h" +#include "TCPAsynch.h" + +namespace mbed { +namespace Sockets { +namespace v0 { + +class TCPStream: public TCPAsynch { +public: + typedef FunctionPointer1 ConnectHandler_t; + typedef FunctionPointer1 DisconnectHandler_t; + /** + * TCP socket constructor. + * Does not allocate an underlying TCP Socket instance. + * @param[in] stack The network stack to use for this socket. + */ + TCPStream(const socket_stack_t stack); + /** + * TCP socket constructor. + * Does not allocate an underlying TCP Socket instance. This version is for use with + * TCPListener::accept(). The struct socket instance passed into this constructor should + * be a fully initialized socket, with an initialized impl field. TCPStream will copy + * the stack, API, protocol family, and impl pointer from sock. + * @param[in] sock The TCP socket instance to use for this TCP socket. + */ + TCPStream(const struct socket * sock); + /** + * TCP socket destructor + */ + ~TCPStream(); + /** + * Connect to a remote host. + * Initates the TCP Connection process. onConnect is called when the connection + * is acknowledged. + * @param[in] address The remote host to connect to + * @param[in] port The remote port to connect to + * @param[in] onConnect + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + virtual socket_error_t connect(const SocketAddr &address, const uint16_t port, + const ConnectHandler_t &onConnect); + /** + * Set a disconnect handler + * This handler only needs to be configured once onConnect has been called + * @param[in] h the handler to call when a connection is disconnected + */ + virtual void setOnDisconnect(const DisconnectHandler_t &h) { _onDisconnect = h; } + +protected: + /** + * Internal event handler + * @param[in] ev the event to handle + */ + void _eventHandler(struct socket_event *ev); + +protected: + ConnectHandler_t _onConnect; + DisconnectHandler_t _onDisconnect; +}; +} // namespace v0 +} // namespace Sockets +} // namespace mbed +#endif // __MBED_NET_SOCKETS_V0_TCPSTREAM_H__ diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/UDPSocket.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/UDPSocket.h new file mode 100644 index 0000000000..7b4ab1d3e8 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/common/sockets/v0/UDPSocket.h @@ -0,0 +1,64 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKETS_V0_UDPSOCKET_H__ +#define __MBED_NET_SOCKETS_V0_UDPSOCKET_H__ + +#include +#include +#include "Socket.h" + +namespace mbed { +namespace Sockets { +namespace v0 { + +/* UDP socket class */ +class UDPSocket: public Socket { +public: + /** + * UDP socket constructor. + * Does not allocate an underlying UDP Socket instance. + * @param[in] stack The network stack to use for this socket. + */ + UDPSocket(socket_stack_t stack); + /** + * UDP Socket destructor + */ + ~UDPSocket(); + /** + * Open a UDP socket + * Instantiates and initializes the underlying socket. Receive is started immediately after + * the socket is opened. + * @param[in] af Address family (SOCKET_AF_INET4 or SOCKET_AF_INET6), currently only IPv4 is supported + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + socket_error_t inline open(const socket_address_family_t af) + { + return Socket::open(af,SOCKET_DGRAM); + } + /** + * Connect to a remote host. + * This is an internal configuration API only. No network traffic is generated. + * @param[in] address The remote host to connect to + * @param[in] port The remote port to connect to + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + socket_error_t connect(const SocketAddr *address, const uint16_t port); +}; +} // namespace v0 +} // namespace Sockets +} // namespace mbed +#endif // __MBED_NET_SOCKETS_V0_UDPSOCKET_H__ diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecurity_mbedtls/CMakeLists.txt b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecurity_mbedtls/CMakeLists.txt new file mode 100644 index 0000000000..66d9c5eb59 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecurity_mbedtls/CMakeLists.txt @@ -0,0 +1,27 @@ +if(TARGET_LIKE_LINUX) +include("../includes.txt") +add_executable(m2mconnectionsecurity_mbedtls + "../../../../source/m2mconnectionsecurity.cpp" + "main.cpp" + "m2mconnectionsecurity_mbedtlstest.cpp" + "test_m2mconnectionsecurity_mbedtls.cpp" + "../stub/m2msecurity_stub.cpp" + "../stub/m2mstring_stub.cpp" + "../stub/m2mobject_stub.cpp" + "../stub/m2mbase_stub.cpp" + "../stub/m2mtimer_stub.cpp" + "../stub/mbedtls_stub.cpp" + "../stub/m2mconnectionhandler_stub.cpp" + "../stub/m2mconnectionsecuritypimpl_stub.cpp" +) +target_link_libraries(m2mconnectionsecurity_mbedtls + CppUTest + CppUTestExt +) +set_target_properties(m2mconnectionsecurity_mbedtls +PROPERTIES COMPILE_FLAGS "${UTEST_COMPILE_FLAGS}" + LINK_FLAGS "${UTEST_LINK_FLAGS}") +set(binary "m2mconnectionsecurity_mbedtls -ojunit") +add_test(m2mconnectionsecurity_mbedtls ${binary}) + +endif() diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecurity_mbedtls/m2mconnectionsecurity_mbedtlstest.cpp b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecurity_mbedtls/m2mconnectionsecurity_mbedtlstest.cpp new file mode 100644 index 0000000000..f81baf7fe8 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecurity_mbedtls/m2mconnectionsecurity_mbedtlstest.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//CppUTest includes should be after your and system includes +#include "CppUTest/TestHarness.h" +#include "test_m2mconnectionsecurity_mbedtls.h" + + +TEST_GROUP(M2MConnectionSecurity_mbedtls) +{ + Test_M2MConnectionSecurity* inst; + + void setup() + { + inst = new Test_M2MConnectionSecurity(); + } + void teardown() + { + delete inst; + } +}; + +TEST(M2MConnectionSecurity_mbedtls, Create) +{ + CHECK(inst != NULL); +} + +TEST(M2MConnectionSecurity_mbedtls, test_constructor) +{ + inst->test_constructor(); +} + +TEST(M2MConnectionSecurity_mbedtls, test_destructor) +{ + inst->test_destructor(); +} + +TEST(M2MConnectionSecurity_mbedtls, test_reset) +{ + inst->test_reset(); +} + +TEST(M2MConnectionSecurity_mbedtls, test_init) +{ + inst->test_init(); +} + +TEST(M2MConnectionSecurity_mbedtls, test_connect) +{ + inst->test_connect(); +} + +TEST(M2MConnectionSecurity_mbedtls, test_start_connecting_non_blocking) +{ + inst->test_start_connecting_non_blocking(); +} + +TEST(M2MConnectionSecurity_mbedtls, test_continue_connecting) +{ + inst->test_continue_connecting(); +} + +TEST(M2MConnectionSecurity_mbedtls, test_send_message) +{ + inst->test_send_message(); +} + +TEST(M2MConnectionSecurity_mbedtls, test_read) +{ + inst->test_read(); +} + +TEST(M2MConnectionSecurity_mbedtls, test_set_random_number_callback) +{ + inst->test_set_random_number_callback(); +} + +TEST(M2MConnectionSecurity_mbedtls, test_set_entropy_callback) +{ + inst->test_set_entropy_callback(); +} + diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecurity_mbedtls/main.cpp b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecurity_mbedtls/main.cpp new file mode 100644 index 0000000000..f7eeeb076c --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecurity_mbedtls/main.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP(M2MConnectionSecurity_mbedtls); diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecurity_mbedtls/test_m2mconnectionsecurity_mbedtls.cpp b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecurity_mbedtls/test_m2mconnectionsecurity_mbedtls.cpp new file mode 100755 index 0000000000..360cb1a7c7 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecurity_mbedtls/test_m2mconnectionsecurity_mbedtls.cpp @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include "test_m2mconnectionsecurity_mbedtls.h" +#include "m2mtimerobserver.h" +#include "m2msecurity.h" +#include "m2msecurity_stub.h" +#include "mbedtls_stub.h" +#include "m2mconnectionhandler.h" +#include "mbed-client-mbed-os/m2mconnectionhandlerpimpl.h" +#include "m2mconnectionsecuritypimpl_stub.h" + +entropy_cb ent_cb; + +class TestObserver : public M2MConnectionObserver { + +public: + TestObserver(){} + void data_available(uint8_t*, + uint16_t, + const M2MConnectionObserver::SocketAddress &){} + + void socket_error(uint8_t error_code){} + + void address_ready(const M2MConnectionObserver::SocketAddress &, + M2MConnectionObserver::ServerType, + const uint16_t){} + + void data_sent(){} +}; + +Test_M2MConnectionSecurity::Test_M2MConnectionSecurity() +{ + mbedtls_stub::clear(); + m2msecurity_stub::clear(); +} + +Test_M2MConnectionSecurity::~Test_M2MConnectionSecurity() +{ +} + +void Test_M2MConnectionSecurity::test_constructor() +{ + M2MConnectionSecurity impl = M2MConnectionSecurity(M2MConnectionSecurity::TLS); +} + +void Test_M2MConnectionSecurity::test_destructor() +{ + M2MConnectionSecurity* impl = new M2MConnectionSecurity(M2MConnectionSecurity::TLS); + delete impl; + //Memory leak detector will report an error if leaks +} + +void Test_M2MConnectionSecurity::test_reset() +{ + M2MConnectionSecurity impl = M2MConnectionSecurity(M2MConnectionSecurity::TLS); + impl.reset(); +} + +void Test_M2MConnectionSecurity::test_init() +{ + M2MConnectionSecurity impl = M2MConnectionSecurity(M2MConnectionSecurity::TLS); + m2mconnectionsecuritypimpl_stub::int_value = 7; + CHECK( 7 == impl.init(NULL) ); +} + +void Test_M2MConnectionSecurity::test_connect() +{ + M2MConnectionSecurity impl = M2MConnectionSecurity(M2MConnectionSecurity::TLS); + m2mconnectionsecuritypimpl_stub::int_value = 7; + CHECK( 7 == impl.connect(NULL)); +} + +void Test_M2MConnectionSecurity::test_start_connecting_non_blocking() +{ + M2MConnectionSecurity impl = M2MConnectionSecurity(M2MConnectionSecurity::TLS); + m2mconnectionsecuritypimpl_stub::int_value = 7; + CHECK( 7 == impl.start_connecting_non_blocking(NULL)); +} + +void Test_M2MConnectionSecurity::test_continue_connecting() +{ + M2MConnectionSecurity impl = M2MConnectionSecurity(M2MConnectionSecurity::TLS); + m2mconnectionsecuritypimpl_stub::int_value = 7; + CHECK( 7 == impl.continue_connecting()); +} + +void Test_M2MConnectionSecurity::test_send_message() +{ + M2MConnectionSecurity impl = M2MConnectionSecurity(M2MConnectionSecurity::TLS); + unsigned char msg[6] = "hello"; + m2mconnectionsecuritypimpl_stub::int_value = 7; + CHECK( 7 == impl.send_message(msg, 5) ); +} + +void Test_M2MConnectionSecurity::test_read() + +{ + M2MConnectionSecurity impl = M2MConnectionSecurity(M2MConnectionSecurity::TLS); + unsigned char msg[50]; + m2mconnectionsecuritypimpl_stub::int_value = 7; + CHECK( 7 == impl.read(msg, 49)); +} + +void Test_M2MConnectionSecurity::test_set_random_number_callback() +{ + M2MConnectionSecurity impl = M2MConnectionSecurity(M2MConnectionSecurity::TLS); + random_number_cb cb(&test_random_callback); + impl.set_random_number_callback(cb); + +} + +void Test_M2MConnectionSecurity::test_set_entropy_callback() +{ + M2MConnectionSecurity impl = M2MConnectionSecurity(M2MConnectionSecurity::TLS); + impl.set_entropy_callback(ent_cb); +} + +uint32_t test_random_callback(void) +{ + return 1; +} diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecurity_mbedtls/test_m2mconnectionsecurity_mbedtls.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecurity_mbedtls/test_m2mconnectionsecurity_mbedtls.h new file mode 100755 index 0000000000..11206c210c --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecurity_mbedtls/test_m2mconnectionsecurity_mbedtls.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TEST_M2M_CONNECTION_SECURITY_H +#define TEST_M2M_CONNECTION_SECURITY_H + +#include "m2mconnectionsecurity.h" + +uint32_t test_random_callback(void); + +class Test_M2MConnectionSecurity +{ +public: + Test_M2MConnectionSecurity(); + + virtual ~Test_M2MConnectionSecurity(); + + void test_constructor(); + + void test_destructor(); + + void test_reset(); + + void test_init(); + + void test_connect(); + + void test_start_connecting_non_blocking(); + + void test_continue_connecting(); + + void test_send_message(); + + void test_read(); + + void test_set_random_number_callback(); + + void test_set_entropy_callback(); +}; + + +#endif // TEST_M2M_CONNECTION_SECURITY_H diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecuritypimpl_mbedtls/CMakeLists.txt b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecuritypimpl_mbedtls/CMakeLists.txt new file mode 100644 index 0000000000..84168cbe03 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecuritypimpl_mbedtls/CMakeLists.txt @@ -0,0 +1,28 @@ +if(TARGET_LIKE_LINUX) +include("../includes.txt") +add_executable(m2mconnectionsecuritypimpl_mbedtls + "../../../../yotta_modules/mbed-client-mbedtls/source/m2mconnectionsecuritypimpl.cpp" + "main.cpp" + "m2mconnectionsecuritypimpl_mbedtlstest.cpp" + "test_m2mconnectionsecuritypimpl_mbedtls.cpp" + "../stub/m2msecurity_stub.cpp" + "../stub/m2mstring_stub.cpp" + "../stub/m2mobject_stub.cpp" + "../stub/m2mbase_stub.cpp" + "../stub/m2mtimer_stub.cpp" + "../stub/mbedtls_stub.cpp" + "../stub/m2mconnectionhandler_stub.cpp" + "../stub/m2mconnectionsecurity_stub.cpp" +) + +target_link_libraries(m2mconnectionsecuritypimpl_mbedtls + CppUTest + CppUTestExt +) +set_target_properties(m2mconnectionsecuritypimpl_mbedtls +PROPERTIES COMPILE_FLAGS "${UTEST_COMPILE_FLAGS}" + LINK_FLAGS "${UTEST_LINK_FLAGS}") +set(binary "m2mconnectionsecuritypimpl_mbedtls -ojunit") +add_test(m2mconnectionsecuritypimpl_mbedtls ${binary}) + +endif() diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecuritypimpl_mbedtls/m2mconnectionsecuritypimpl_mbedtlstest.cpp b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecuritypimpl_mbedtls/m2mconnectionsecuritypimpl_mbedtlstest.cpp new file mode 100644 index 0000000000..4ae5442d50 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecuritypimpl_mbedtls/m2mconnectionsecuritypimpl_mbedtlstest.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//CppUTest includes should be after your and system includes +#include "CppUTest/TestHarness.h" +#include "test_m2mconnectionsecuritypimpl_mbedtls.h" + + +TEST_GROUP(M2MConnectionSecurityPimpl_mbedtls) +{ + Test_M2MConnectionSecurityPimpl* inst; + + void setup() + { + inst = new Test_M2MConnectionSecurityPimpl(); + } + void teardown() + { + delete inst; + } +}; + +TEST(M2MConnectionSecurityPimpl_mbedtls, Create) +{ + CHECK(inst != NULL); +} + +TEST(M2MConnectionSecurityPimpl_mbedtls, test_constructor) +{ + inst->test_constructor(); +} + +TEST(M2MConnectionSecurityPimpl_mbedtls, test_destructor) +{ + inst->test_destructor(); +} + +TEST(M2MConnectionSecurityPimpl_mbedtls, test_reset) +{ + inst->test_reset(); +} + +TEST(M2MConnectionSecurityPimpl_mbedtls, test_init) +{ + inst->test_init(); +} + +TEST(M2MConnectionSecurityPimpl_mbedtls, test_connect) +{ + inst->test_connect(); +} + +TEST(M2MConnectionSecurityPimpl_mbedtls, test_start_connecting_non_blocking) +{ + inst->test_start_connecting_non_blocking(); +} + +TEST(M2MConnectionSecurityPimpl_mbedtls, test_continue_connecting) +{ + inst->test_continue_connecting(); +} + +TEST(M2MConnectionSecurityPimpl_mbedtls, test_send_message) +{ + inst->test_send_message(); +} + +TEST(M2MConnectionSecurityPimpl_mbedtls, test_read) +{ + inst->test_read(); +} + +TEST(M2MConnectionSecurityPimpl_mbedtls, test_timer_expired) +{ + inst->test_timer_expired(); +} + +TEST(M2MConnectionSecurityPimpl_mbedtls, test_set_random_number_callback) +{ + inst->test_set_random_number_callback(); +} + +TEST(M2MConnectionSecurityPimpl_mbedtls, test_set_entropy_callback) +{ + inst->test_set_entropy_callback(); +} + diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecuritypimpl_mbedtls/main.cpp b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecuritypimpl_mbedtls/main.cpp new file mode 100644 index 0000000000..dc6690458c --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecuritypimpl_mbedtls/main.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP(M2MConnectionSecurityPimpl_mbedtls); diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecuritypimpl_mbedtls/test_m2mconnectionsecuritypimpl_mbedtls.cpp b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecuritypimpl_mbedtls/test_m2mconnectionsecuritypimpl_mbedtls.cpp new file mode 100755 index 0000000000..6131c0630f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecuritypimpl_mbedtls/test_m2mconnectionsecuritypimpl_mbedtls.cpp @@ -0,0 +1,409 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include "test_m2mconnectionsecuritypimpl_mbedtls.h" +#include "m2mtimerobserver.h" +#include "m2msecurity.h" +#include "m2msecurity_stub.h" +#include "mbedtls_stub.h" +#include "mbed-client/m2mconnectionhandler.h" +#include "m2mtimer_stub.h" + +uint32_t get_random_number(void) +{ + return time(NULL); +} + +entropy_cb ent_cb; + +int ent_poll( void *, unsigned char *output, size_t len, + size_t *olen ) +{ + for(uint16_t i=0; i < len; i++){ + srand(time(NULL)); + output[i] = rand() % 256; + } + *olen = len; + + return( 0 ); +} + +class TestObserver : public M2MConnectionObserver { + +public: + TestObserver(){} + void data_available(uint8_t*, + uint16_t, + const M2MConnectionObserver::SocketAddress &){} + + void socket_error(uint8_t error_code, bool retry = true){} + + void address_ready(const M2MConnectionObserver::SocketAddress &, + M2MConnectionObserver::ServerType, + const uint16_t){} + + void data_sent(){} +}; + +Test_M2MConnectionSecurityPimpl::Test_M2MConnectionSecurityPimpl() +{ + mbedtls_stub::clear(); + m2msecurity_stub::clear(); +} + +Test_M2MConnectionSecurityPimpl::~Test_M2MConnectionSecurityPimpl() +{ +} + +void Test_M2MConnectionSecurityPimpl::test_constructor() +{ + M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS); + CHECK(impl._timer != NULL); +} + +void Test_M2MConnectionSecurityPimpl::test_destructor() +{ + M2MConnectionSecurityPimpl* impl = new M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS); + delete impl; + //Memory leak detector will report an error if leaks +} + +void Test_M2MConnectionSecurityPimpl::test_reset() +{ + M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS); + impl._init_done = true; + impl.reset(); + CHECK(impl._init_done == false); +} + +void Test_M2MConnectionSecurityPimpl::test_init() +{ + M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS); + CHECK( -1 == impl.init(NULL) ); + + m2msecurity_stub::int_value = 5; + M2MSecurity* sec = new M2MSecurity(M2MSecurity::Bootstrap); + CHECK( -1 == impl.init(sec) ); + + m2msecurity_stub::int_value = 5; + m2msecurity_stub::has_value = true; + mbedtls_stub::useCounter = true; + mbedtls_stub::counter = 0; + mbedtls_stub::retArray[0] = -1; + m2msecurity_stub::int_value = M2MSecurity::Psk; + CHECK( -1 == impl.init(sec) ); + + mbedtls_stub::useCounter = true; + mbedtls_stub::counter = 0; + mbedtls_stub::retArray[0] = 0; + m2msecurity_stub::int_value = 5; + m2msecurity_stub::has_value = true; + mbedtls_stub::expected_int = -1; + mbedtls_stub::crt_expected_int = -1; + CHECK( -1 == impl.init(sec) ); + + mbedtls_stub::crt_expected_int = 0; + mbedtls_stub::useCounter = true; + mbedtls_stub::counter = 0; + mbedtls_stub::retArray[0] = 0; + mbedtls_stub::retArray[1] = 0; + mbedtls_stub::retArray[2] = 0; + m2msecurity_stub::int_value = M2MSecurity::Psk; + CHECK( 0 == impl.init(sec) ); + + mbedtls_stub::useCounter = true; + mbedtls_stub::counter = 0; + mbedtls_stub::retArray[0] = 0; + mbedtls_stub::retArray[1] = -1; + mbedtls_stub::retArray[2] = -1; + m2msecurity_stub::int_value = M2MSecurity::Certificate; + CHECK( -1 == impl.init(sec) ); + + mbedtls_stub::useCounter = true; + mbedtls_stub::counter = 0; + mbedtls_stub::retArray[0] = 0; + mbedtls_stub::retArray[1] = 0; + m2msecurity_stub::int_value = M2MSecurity::Certificate; + CHECK( -1 == impl.init(sec) ); + + mbedtls_stub::useCounter = true; + mbedtls_stub::counter = 0; + mbedtls_stub::retArray[0] = 0; + mbedtls_stub::retArray[1] = 0; + mbedtls_stub::retArray[2] = 0; + m2msecurity_stub::int_value = M2MSecurity::Certificate; + CHECK( -1 == impl.init(sec) ); + + mbedtls_stub::useCounter = true; + mbedtls_stub::counter = 0; + mbedtls_stub::retArray[0] = 0; + mbedtls_stub::retArray[1] = 0; + mbedtls_stub::retArray[2] = 0; + mbedtls_stub::retArray[3] = 0; + mbedtls_stub::retArray[4] = -1; + m2msecurity_stub::int_value = M2MSecurity::Certificate; + CHECK( -1 == impl.init(sec) ); + + mbedtls_stub::useCounter = true; + mbedtls_stub::counter = 0; + mbedtls_stub::retArray[0] = 0; + mbedtls_stub::retArray[1] = 0; + mbedtls_stub::retArray[2] = 0; + mbedtls_stub::retArray[3] = 0; + mbedtls_stub::retArray[4] = 0; + m2msecurity_stub::int_value = M2MSecurity::Certificate; + CHECK( 0 == impl.init(sec) ); + + mbedtls_stub::useCounter = true; + mbedtls_stub::counter = 0; + mbedtls_stub::retArray[0] = 0; + mbedtls_stub::retArray[1] = 0; + mbedtls_stub::retArray[2] = 0; + m2msecurity_stub::int_value = 99; + CHECK( -1 == impl.init(sec) ); + + impl.set_random_number_callback(NULL); + + ent_cb.entropy_source_ptr = ent_poll; + ent_cb.p_source = NULL; + ent_cb.threshold = 128; + ent_cb.strong = 0; + + m2msecurity_stub::int_value = 5; + m2msecurity_stub::has_value = false; + mbedtls_stub::useCounter = false; + mbedtls_stub::expected_int = 0; + mbedtls_stub::crt_expected_int = 0; + mbedtls_stub::counter = 1; + m2msecurity_stub::int_value = M2MSecurity::Certificate; + CHECK( -1 == impl.init(sec) ); + + impl.set_entropy_callback(ent_cb); + m2msecurity_stub::int_value = 5; + m2msecurity_stub::has_value = false; + mbedtls_stub::useCounter = false; + mbedtls_stub::expected_int = -1; + mbedtls_stub::crt_expected_int = 0; + mbedtls_stub::counter = 1; + m2msecurity_stub::int_value = M2MSecurity::Certificate; + CHECK( -1 == impl.init(sec) ); + + delete sec; + mbedtls_stub::clear(); +} + +void Test_M2MConnectionSecurityPimpl::test_connect() +{ + mbedtls_stub::invalidate_timer = true; + M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS); + CHECK( -1 == impl.connect(NULL)); + + impl._init_done = true; + CHECK( -1 == impl.connect(NULL)); + + m2msecurity_stub::int_value = 5; + m2msecurity_stub::has_value = true; + + mbedtls_stub::useCounter = true; + mbedtls_stub::counter = 0; + mbedtls_stub::retArray[0] = 0; + CHECK( -1 == impl.connect(NULL)); + + mbedtls_stub::counter = 0; + mbedtls_stub::retArray[0] = 0; + CHECK( -1 == impl.connect(NULL)); + + m2mtimer_stub::bool_value = true; + + TestObserver obs; + M2MConnectionHandler* obj = new M2MConnectionHandler(obs, NULL, M2MInterface::NOT_SET,M2MInterface::LwIP_IPv4); + + mbedtls_stub::expected_uint32_value = 12; + mbedtls_stub::counter = 0; + mbedtls_stub::retArray[0] = 0; + mbedtls_stub::retArray[1] = 0; + mbedtls_stub::retArray[2] = MBEDTLS_ERR_SSL_WANT_READ; + mbedtls_stub::retArray[3] = MBEDTLS_ERR_SSL_WANT_WRITE; + mbedtls_stub::retArray[4] = 0; + CHECK( -1 == impl.connect(obj)); + + delete obj; + + mbedtls_stub::counter = 0; + mbedtls_stub::expected_uint32_value = 0; + CHECK( 0 == impl.connect(NULL)); + + //Tests mbedtls_timing_get_delay() for intermediate case + mbedtls_stub::counter = 0; + m2mtimer_stub::total_bool_value = false; + m2mtimer_stub::bool_value = true; + mbedtls_stub::expected_uint32_value = 1; + + CHECK( -1 == impl.connect(obj)); + + //Tests mbedtls_timing_get_delay() for cancelled case + mbedtls_stub::invalidate_timer = true; + + mbedtls_stub::counter = 0; + m2mtimer_stub::total_bool_value = true; + CHECK( -1 == impl.connect(obj)); + + //Tests mbedtls_timing_get_delay() for NULL case + mbedtls_stub::counter = 0; + delete(impl._timer); + impl._timer = NULL; + CHECK( -1 == impl.connect(obj)); +} + +void Test_M2MConnectionSecurityPimpl::test_start_connecting_non_blocking() +{ + M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS); + CHECK( -1 == impl.start_connecting_non_blocking(NULL)); + + m2mtimer_stub::total_bool_value = false; + impl._init_done = true; + impl._sec_mode = M2MConnectionSecurity::TLS; + CHECK( -1 == impl.start_connecting_non_blocking(NULL)); + + m2msecurity_stub::int_value = 5; + m2msecurity_stub::has_value = true; + + mbedtls_stub::useCounter = true; + mbedtls_stub::counter = 0; + mbedtls_stub::retArray[0] = 0; + CHECK( -1 == impl.start_connecting_non_blocking(NULL)); + + mbedtls_stub::counter = 0; + mbedtls_stub::retArray[0] = 0; + mbedtls_stub::retArray[1] = 0; + CHECK( -1 == impl.start_connecting_non_blocking(NULL)); + + TestObserver obs; + M2MConnectionHandler* obj = new M2MConnectionHandler(obs, NULL, M2MInterface::NOT_SET, M2MInterface::LwIP_IPv4); + + m2mtimer_stub::total_bool_value = true; + mbedtls_stub::expected_uint32_value = 12; + mbedtls_stub::counter = 0; + mbedtls_stub::retArray[0] = 0; + mbedtls_stub::retArray[1] = 0; + mbedtls_stub::retArray[2] = 0; + mbedtls_stub::retArray[3] = 0; + mbedtls_stub::retArray[4] = 0; + CHECK( 1 == impl.start_connecting_non_blocking(obj)); + + delete obj; + + mbedtls_stub::counter = 0; + mbedtls_stub::expected_uint32_value = 0; + mbedtls_stub::retArray[3] = -1; + CHECK( -1 == impl.start_connecting_non_blocking(NULL)); +} + +void Test_M2MConnectionSecurityPimpl::test_continue_connecting() +{ + M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS); + impl._ssl.state = MBEDTLS_SSL_HELLO_REQUEST; + mbedtls_stub::expected_int = MBEDTLS_ERR_SSL_WANT_READ; + CHECK( M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ == impl.continue_connecting()); + + mbedtls_stub::expected_int = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST; + impl._ssl.state = MBEDTLS_SSL_CLIENT_HELLO; + CHECK( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST == impl.continue_connecting()); + + mbedtls_stub::expected_int = -6; + impl._ssl.state = MBEDTLS_SSL_HANDSHAKE_OVER; + CHECK( -6 == impl.continue_connecting()); + + mbedtls_stub::expected_int = 0; + impl._ssl.state = MBEDTLS_SSL_HANDSHAKE_OVER; + CHECK( 0 == impl.continue_connecting()); +} + +void Test_M2MConnectionSecurityPimpl::test_send_message() +{ + M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS); + unsigned char msg[6] = "hello"; + CHECK( -1 == impl.send_message(msg, 5) ); + impl._init_done = true; + + mbedtls_stub::useCounter = true; + mbedtls_stub::counter = 0; + mbedtls_stub::retArray[0] = MBEDTLS_ERR_SSL_WANT_READ; + mbedtls_stub::retArray[1] = MBEDTLS_ERR_SSL_WANT_WRITE; + mbedtls_stub::retArray[2] = 65; + CHECK( 65 == impl.send_message(msg, 5) ); +} + +void Test_M2MConnectionSecurityPimpl::test_read() + +{ + M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS); + unsigned char msg[50]; + CHECK( -1 == impl.read(msg, 49)); + + impl._init_done = true; + mbedtls_stub::useCounter = true; + mbedtls_stub::counter = 0; + mbedtls_stub::retArray[0] = MBEDTLS_ERR_SSL_WANT_READ; + mbedtls_stub::retArray[1] = MBEDTLS_ERR_SSL_WANT_WRITE; + mbedtls_stub::retArray[2] = 25; + CHECK( 25 == impl.read(msg, 49)); +} + +void Test_M2MConnectionSecurityPimpl::test_timer_expired() +{ + //This uses static function so we need to prepare test using connect() function. + mbedtls_stub::invalidate_timer = false; + M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS); + impl._init_done = true; + m2msecurity_stub::int_value = 5; + m2msecurity_stub::has_value = true; + mbedtls_stub::useCounter = true; + mbedtls_stub::counter = 0; + mbedtls_stub::retArray[0] = 0; + mbedtls_stub::retArray[1] = 0; + mbedtls_stub::retArray[3] = M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ; + impl.connect(NULL); + + void *bio = malloc(1); + impl._ssl.p_bio = bio; + impl.timer_expired(M2MTimerObserver::Dtls); + + // For testing blocking mode use case + mbedtls_stub::useCounter = false; + mbedtls_stub::expected_int = MBEDTLS_ERR_SSL_TIMEOUT; + + impl.timer_expired(M2MTimerObserver::Dtls); + free(bio); +} + +void Test_M2MConnectionSecurityPimpl::test_set_random_number_callback() +{ + M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS); + random_number_cb cb(&test_random_callback); + impl.set_random_number_callback(cb); +} + +void Test_M2MConnectionSecurityPimpl::test_set_entropy_callback() +{ + M2MConnectionSecurityPimpl impl = M2MConnectionSecurityPimpl(M2MConnectionSecurity::TLS); + impl.set_entropy_callback(ent_cb); +} + +uint32_t test_random_callback(void) +{ + return 1; +} diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecuritypimpl_mbedtls/test_m2mconnectionsecuritypimpl_mbedtls.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecuritypimpl_mbedtls/test_m2mconnectionsecuritypimpl_mbedtls.h new file mode 100755 index 0000000000..2ee96cd1a2 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/m2mconnectionsecuritypimpl_mbedtls/test_m2mconnectionsecuritypimpl_mbedtls.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TEST_M2M_CONNECTION_SECURITY_PIMPL_H +#define TEST_M2M_CONNECTION_SECURITY_PIMPL_H + +#include "mbed-client-mbedtls/m2mconnectionsecuritypimpl.h" + +uint32_t test_random_callback(void); + +class Test_M2MConnectionSecurityPimpl +{ +public: + Test_M2MConnectionSecurityPimpl(); + + virtual ~Test_M2MConnectionSecurityPimpl(); + + void test_constructor(); + + void test_destructor(); + + void test_reset(); + + void test_init(); + + void test_connect(); + + void test_start_connecting_non_blocking(); + + void test_continue_connecting(); + + void test_send_message(); + + void test_read(); + + void test_timer_expired(); + + void test_set_random_number_callback(); + + void test_set_entropy_callback(); + +}; + + +#endif // TEST_M2M_CONNECTION_SECURITY_PIMPL_H diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/makefile_defines.txt b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/makefile_defines.txt new file mode 100755 index 0000000000..60af40b851 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/makefile_defines.txt @@ -0,0 +1,28 @@ +#--- Inputs ----# +CPPUTEST_HOME = /usr +CPPUTEST_USE_EXTENSIONS = Y +CPPUTEST_USE_VPATH = Y +CPPUTEST_USE_GCOV = Y +CPP_PLATFORM = gcc +INCLUDE_DIRS =\ + .\ + ../common\ + ../stub\ + ../../../../source/include\ + ../../../../source\ + ../../../../\ + ../../../../yotta_modules/mbed-client/mbed-client\ + ../../../../yotta_modules/mbed-client\ + ../../../../yotta_modules/mbed-client/source\ + ../../../../yotta_modules/mbed-client/source/include\ + ../../../../yotta_modules/mbed-client-c\ + ../../../../yotta_modules/mbed-client-c/source/libNsdl\ + ../../../../yotta_modules/mbed-client-c/source/libNsdl/src/include\ + ../../../../yotta_modules/mbedtls\ + ../../../../yotta_modules/mbed-client-mbed-os\ + ../../../../yotta_modules/nanostack-libservice\ + ../../../../yotta_modules/mbed-trace\ + /usr/include\ + $(CPPUTEST_HOME)/include\ + +CPPUTESTFLAGS = -D__thumb2__ -w diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/common_stub.cpp b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/common_stub.cpp new file mode 100644 index 0000000000..e0805d40d3 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/common_stub.cpp @@ -0,0 +1,436 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "common_stub.h" +#include "sn_grs.h" +#include + +socket_error_t common_stub::error; +socket_event_t * common_stub::event; +socket_addr * common_stub::addr; +void * common_stub::void_value; +bool common_stub::visited; +bool common_stub::bool_value; +int common_stub::int_value; +int common_stub::int2_value; +addrinfo* common_stub::addrinfo; +uint16_t common_stub::uint_value; +omalw_certificate_list_t *common_stub::cert; +sn_coap_hdr_s *common_stub::coap_header; +sn_nsdl_resource_info_s *common_stub::resource; +pthread_t common_stub::thread; +const char* common_stub::char_value; + +using namespace mbed; +using namespace mbed::Sockets::v0; + +void common_stub::clear() +{ + int_value = -1; + int2_value = -1; + uint_value = 0; + error = SOCKET_ERROR_NONE; + event = NULL; + addr = NULL; + void_value = NULL; + cert = NULL; + visited = false; + bool_value= false; + coap_header = NULL; + resource = NULL; + addrinfo = NULL; + char_value = NULL; +} + +UDPSocket::UDPSocket(socket_stack_t stack) :Socket(stack) +{ +} + +UDPSocket::~UDPSocket() +{ +} + +socket_error_t UDPSocket::connect(const SocketAddr *, const uint16_t ) +{ + return common_stub::error; +} + +//SocketAddr + +void SocketAddr::setAddr(const struct socket_addr *) +{ +} + +void SocketAddr::setAddr(const SocketAddr *) +{ +} + +bool SocketAddr::SocketAddr::is_v4() +{ + return common_stub::bool_value; +} + +void mbed::Ticker::detach() +{ + common_stub::visited = true; +} + + +// SN_NSDL_LIB + +struct nsdl_s *sn_nsdl_init (uint8_t (*sn_nsdl_tx_cb)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *), + uint8_t (*sn_nsdl_rx_cb)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *), + void *(*sn_nsdl_alloc)(uint16_t),void (*sn_nsdl_free)(void *)) +{ + return NULL; +} + +uint16_t sn_nsdl_register_endpoint(struct nsdl_s *, sn_nsdl_ep_parameters_s *) +{ + return common_stub::uint_value; +} + +uint16_t sn_nsdl_unregister_endpoint(struct nsdl_s *) +{ + return common_stub::uint_value; +} + +uint16_t sn_nsdl_update_registration(struct nsdl_s *,uint8_t *, uint8_t) +{ + return common_stub::uint_value; +} + +uint16_t sn_nsdl_send_observation_notification(struct nsdl_s *, uint8_t *, uint8_t, + uint8_t *, uint16_t, + uint8_t *, uint8_t, + sn_coap_msg_type_e , uint8_t) +{ + return common_stub::uint_value; +} + +int8_t sn_nsdl_destroy(struct nsdl_s *handle) +{ + return common_stub::int_value; +} + +sn_coap_hdr_s *sn_nsdl_build_response(struct nsdl_s *, sn_coap_hdr_s *, uint8_t ) +{ + return common_stub::coap_header; +} + +sn_nsdl_resource_info_s *sn_nsdl_get_resource(struct nsdl_s *, uint16_t, uint8_t *) +{ + return common_stub::resource; +} + +int8_t sn_nsdl_process_coap(struct nsdl_s *, uint8_t *, uint16_t , sn_nsdl_addr_s *) +{ + return common_stub::int_value; +} + +int8_t sn_nsdl_exec(struct nsdl_s *, uint32_t) +{ + return common_stub::int_value; +} + +void sn_nsdl_release_allocated_coap_msg_mem(struct nsdl_s *, sn_coap_hdr_s *header) +{ + if(header && header != common_stub::coap_header){ + if( header->content_type_ptr ){ + free(header->content_type_ptr); + header->content_type_ptr = NULL; + } + if( header->options_list_ptr){ + free(header->options_list_ptr); + header->options_list_ptr = NULL; + } + free(header); + header = NULL; + } +} + +int8_t sn_nsdl_create_resource(struct nsdl_s *, sn_nsdl_resource_info_s *) +{ + return common_stub::int_value; +} + +int8_t sn_nsdl_delete_resource(struct nsdl_s *, uint16_t , uint8_t *) +{ + return common_stub::int_value; +} + +int8_t sn_nsdl_send_coap_message(struct nsdl_s *, sn_nsdl_addr_s *, sn_coap_hdr_s *) +{ + return common_stub::int_value; +} + +int8_t sn_nsdl_update_resource(struct nsdl_s *, sn_nsdl_resource_info_s *) +{ + return common_stub::int_value; +} + +int8_t set_NSP_address(struct nsdl_s *, uint8_t *, uint16_t, sn_nsdl_addr_type_e) +{ + return common_stub::int_value; +} + +uint16_t sn_nsdl_oma_bootstrap(struct nsdl_s *, sn_nsdl_addr_s *, + sn_nsdl_ep_parameters_s *, + sn_nsdl_bs_ep_info_t *) +{ + return common_stub::uint_value; +} + +omalw_certificate_list_t *sn_nsdl_get_certificates(struct nsdl_s *) +{ + return common_stub::cert; +} + +int8_t sn_nsdl_update_certificates(struct nsdl_s *, omalw_certificate_list_t*, uint8_t) +{ + return common_stub::int_value; +} + +int8_t sn_nsdl_create_oma_device_object(struct nsdl_s *, sn_nsdl_oma_device_t *) +{ + return common_stub::int_value; +} + +//Coap Headers + +sn_coap_hdr_s *sn_coap_build_response(struct coap_s *, sn_coap_hdr_s *, uint8_t ) +{ + return common_stub::coap_header; +} + +void sn_coap_parser_release_allocated_coap_msg_mem(struct coap_s *, sn_coap_hdr_s *) +{ +} + +int8_t sn_coap_protocol_set_retransmission_parameters(uint8_t, uint8_t) +{ + return common_stub::int_value; +} + +// IP6String.h +uint_fast8_t ip6tos(const void *, char *) +{ +} + +//Socket +Socket::Socket(const socket_stack_t ) : _irq(this) +{ + _socket.api = NULL; +} + +Socket::~Socket() +{ +} + +socket_error_t Socket::open(const socket_address_family_t , const socket_proto_family_t ) +{ + return common_stub::error; +} + +bool Socket::error_check(socket_error_t ) +{ + return common_stub::bool_value; +} + +void Socket::_eventHandler(struct socket_event *) +{ +} + +void Socket::setOnError(const ErrorHandler_t &) +{ +} + +void Socket::setOnReadable(const ReadableHandler_t &) +{ +} + +void Socket::setOnSent(const SentHandler_t & ) +{ +} + +void Socket::_nvEventHandler(void * ) +{ +} + +socket_error_t Socket::getLocalAddr(SocketAddr *) const +{ + return common_stub::error; +} + +socket_error_t Socket::getLocalPort(uint16_t *) const +{ + return common_stub::error; +} + +socket_error_t Socket::getRemoteAddr(SocketAddr *) const +{ + return common_stub::error; +} + +socket_error_t Socket::getRemotePort(uint16_t *) const +{ + return common_stub::error; +} + +socket_error_t Socket::resolve(const char* , const DNSHandler_t & ) +{ + return common_stub::error; +} + +socket_error_t Socket::bind(const char * , const uint16_t ) +{ + return common_stub::error; +} +socket_error_t Socket::bind(const SocketAddr * , const uint16_t ) +{ + return common_stub::error; +} + +socket_error_t Socket::close() +{ + return common_stub::error; +} + +socket_error_t Socket::recv(void * , size_t *) +{ + return common_stub::error; +} +socket_error_t Socket::recv_from(void * , size_t *, SocketAddr *, uint16_t *) +{ + return common_stub::error; +} + +socket_error_t Socket::send(const void * , const size_t ) +{ + return common_stub::error; +} +socket_error_t Socket::send_to(const void * , const size_t , const SocketAddr *, uint16_t ) +{ + return common_stub::error; +} + +bool Socket::isConnected() const { + return common_stub::error; +} + +// pthread +int pthread_equal (pthread_t , pthread_t ) __THROW +{ + return common_stub::int2_value; +} + +pthread_t pthread_self (void) __THROW +{ + return common_stub::thread; +} + +int pthread_detach (pthread_t) __THROW +{ + return common_stub::int_value; +} + +int pthread_create (pthread_t * , + const pthread_attr_t *, + void *(*__start_routine) (void *), + void *) __THROWNL +{ + __start_routine(NULL); + return common_stub::int_value; +} + +int pthread_cancel (pthread_t) +{ + return common_stub::int_value; +} + +int pthread_join (pthread_t , void **) +{ + return common_stub::int_value; +} + +void pthread_exit (void *__retval)/* __attribute__ ((__noreturn__))*/ +{ + +} + +// sys/socket +#ifndef __SOCKADDR_ARG +# define __SOCKADDR_ARG struct sockaddr *__restrict +#endif + +#ifndef __CONST_SOCKADDR_ARG +# define __CONST_SOCKADDR_ARG const struct sockaddr * +#endif + +#ifndef __socklen_t_defined +typedef __socklen_t socklen_t; +# define __socklen_t_defined +#endif + +int bind (int , __CONST_SOCKADDR_ARG , socklen_t ) + __THROW +{ + return common_stub::int_value; +} + +ssize_t sendto (int , const void *, size_t , + int , __CONST_SOCKADDR_ARG , + socklen_t ) +{ + return common_stub::int_value; +} + +ssize_t recvfrom (int , void * , size_t , + int , __SOCKADDR_ARG , + socklen_t * ) +{ + return common_stub::int_value; +} + +int getaddrinfo (const char *__restrict, + const char *__restrict, + const struct addrinfo *__restrict, + struct addrinfo **__restrict addr) +{ + //*addr = (addrinfo*)malloc(sizeof(addrinfo)); + //(*addr)->ai_addr = (sockaddr*)malloc(sizeof(sockaddr)); + *addr = common_stub::addrinfo; + return common_stub::int_value; +} + +void freeaddrinfo (struct addrinfo * addr) +__THROW +{ +// free(addr->ai_addr); +// free(addr); +} + +const char *inet_ntop (int, const void *__restrict, + char *__restrict, socklen_t) + __THROW +{ + return common_stub::char_value; +} + +int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) +{ + return common_stub::int_value; +} + diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/common_stub.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/common_stub.h new file mode 100644 index 0000000000..0c754a792b --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/common_stub.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 COMMON_STUB_H +#define COMMON_STUB_H + +#include +#include +//#include "UDPSocket.h" +#include "sockets/UDPSocket.h" +#include "nsdlaccesshelper.h" +#include "ip6string.h" +#include "Ticker.h" + +//some internal test related stuff +namespace common_stub +{ + extern socket_error_t error; + extern socket_event_t* event; + extern socket_addr* addr; + extern bool visited; + extern bool bool_value; + extern void* void_value; + extern int int_value; + extern int int2_value; + extern uint16_t uint_value; + extern omalw_certificate_list_t *cert; + extern addrinfo* addrinfo; + extern sn_coap_hdr_s *coap_header; + extern sn_nsdl_resource_info_s *resource; + extern pthread_t thread; + extern const char *char_value; + void clear(); +} + +#endif // COMMON_STUB_H diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mbase_stub.cpp b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mbase_stub.cpp new file mode 100755 index 0000000000..5d3ba2ebf7 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mbase_stub.cpp @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mbase_stub.h" + +#include + +uint8_t m2mbase_stub::uint8_value; +uint16_t m2mbase_stub::uint16_value; +uint32_t m2mbase_stub::uint32_value; +uint16_t m2mbase_stub::int_value; +int32_t m2mbase_stub::name_id_value; + +bool m2mbase_stub::bool_value; +String *m2mbase_stub::string_value; + +M2MBase::BaseType m2mbase_stub::base_type; +M2MBase::Operation m2mbase_stub::operation; +M2MBase::Mode m2mbase_stub::mode_value; +M2MBase::Observation m2mbase_stub::observation_level_value; + +void *m2mbase_stub::void_value; +M2MObservationHandler *m2mbase_stub::observe; +M2MReportHandler *m2mbase_stub::report; +bool m2mbase_stub::is_value_updated_function_set; + + +void m2mbase_stub::clear() +{ + int_value = 0; + uint8_value = 0; + uint16_value = 0; + uint32_value = 0; + string_value = NULL; + name_id_value = -1; + mode_value = M2MBase::Static; + base_type = M2MBase::Object; + observation_level_value = M2MBase::None; + bool_value = false; + m2mbase_stub::operation = M2MBase::NOT_ALLOWED; + void_value = NULL; + observe = NULL; + report = NULL; + is_value_updated_function_set = false; +} + +M2MBase::M2MBase(const String &/*resource_name*/, + M2MBase::Mode /*mode*/) +{ +} + +M2MBase& M2MBase::operator=(const M2MBase& other) +{ + if (this != &other) { // protect against invalid self-assignment + } + return *this; +} + +M2MBase::M2MBase(const M2MBase& other) +{ + this->operator=(other); +} + +M2MBase::~M2MBase() +{ +} + +void M2MBase::set_operation(M2MBase::Operation opr) +{ + m2mbase_stub::operation = opr; +} + +void M2MBase::set_interface_description(const String &/*desc*/) +{ +} + +void M2MBase::set_resource_type(const String &/*res_type*/) +{ +} + +void M2MBase::set_coap_content_type(const uint8_t /*con_type*/) +{ +} + +void M2MBase::set_instance_id(const uint16_t /*inst_id*/) +{ +} + +void M2MBase::set_observation_number(const uint16_t /*observation_number*/) +{ +} + +void M2MBase::set_max_age(const uint32_t /*max_age*/) +{ +} + +M2MBase::Operation M2MBase::operation() const +{ + return m2mbase_stub::operation; +} + +const String& M2MBase::name() const +{ + return *m2mbase_stub::string_value; +} + +int32_t M2MBase::name_id() const +{ + return m2mbase_stub::name_id_value; +} + +uint16_t M2MBase::instance_id() const +{ + return m2mbase_stub::int_value; +} + +const String& M2MBase::interface_description() const +{ + return *m2mbase_stub::string_value; +} + +const String& M2MBase::resource_type() const +{ + return *m2mbase_stub::string_value; +} + +uint8_t M2MBase::coap_content_type() const +{ + return m2mbase_stub::uint8_value; +} + +uint32_t M2MBase::max_age() const +{ + return m2mbase_stub::uint32_value; +} + +void M2MBase::set_observable(bool /*observable*/) +{ +} + +void M2MBase::add_observation_level(M2MBase::Observation) +{ +} + +void M2MBase::remove_observation_level(M2MBase::Observation) +{ +} + +void M2MBase::set_under_observation(bool /*observed*/, + M2MObservationHandler */*handler*/) +{ +} + +void M2MBase::set_observation_token(const uint8_t */*token*/, + const uint8_t /*length*/) +{ +} + +bool M2MBase::is_observable() const +{ + return m2mbase_stub::bool_value; +} + +M2MBase::Observation M2MBase::observation_level() const +{ + return m2mbase_stub::observation_level_value; +} + +void M2MBase::get_observation_token(uint8_t *&/*token*/, + uint32_t &/*length*/) +{ +} + +void M2MBase::set_base_type(M2MBase::BaseType /*type*/) +{ +} + +M2MBase::BaseType M2MBase::base_type() const +{ + return m2mbase_stub::base_type; +} + +M2MBase::Mode M2MBase::mode() const +{ + return m2mbase_stub::mode_value; +} + +uint16_t M2MBase::observation_number() const +{ + return m2mbase_stub::uint16_value; +} + +void M2MBase::remove_resource_from_coap(const String &) +{ +} + +void M2MBase::remove_object_from_coap() +{ +} + +bool M2MBase::handle_observation_attribute(char *&query) +{ + return m2mbase_stub::bool_value; +} + +void M2MBase::observation_to_be_sent(m2m::Vector, bool) +{ +} + +void *M2MBase::memory_alloc(uint32_t size) +{ + if(size) + return malloc(size); + else + return 0; +} + +void M2MBase::memory_free(void *ptr) +{ + if(ptr) + free(ptr); +} + +uint8_t* M2MBase::alloc_string_copy(const uint8_t* source, uint32_t size) +{ + assert(source != NULL); + + uint8_t* result = (uint8_t*)memory_alloc(size + 1); + if (result) { + memcpy(result, source, size); + result[size] = '\0'; + } + return result; +} + +uint8_t* M2MBase::alloc_copy(const uint8_t* source, uint32_t size) +{ + assert(source != NULL); + + uint8_t* result = (uint8_t*)memory_alloc(size); + if (result) { + memcpy(result, source, size); + } + return result; +} + +M2MReportHandler* M2MBase::report_handler() +{ + return m2mbase_stub::report; +} + +M2MObservationHandler* M2MBase::observation_handler() +{ + return m2mbase_stub::observe; +} + +sn_coap_hdr_s* M2MBase::handle_get_request(nsdl_s */*nsdl*/, + sn_coap_hdr_s */*received_coap_header*/, + M2MObservationHandler */*observation_handler*/) +{ + //Handled in M2MResource, M2MObjectInstance and M2MObject classes + return NULL; +} + +sn_coap_hdr_s* M2MBase::handle_put_request(nsdl_s */*nsdl*/, + sn_coap_hdr_s */*received_coap_header*/, + M2MObservationHandler */*observation_handler*/, + bool &execute_value_updated) +{ + //Handled in M2MResource, M2MObjectInstance and M2MObject classes + return NULL; +} + +sn_coap_hdr_s* M2MBase::handle_post_request(nsdl_s */*nsdl*/, + sn_coap_hdr_s */*received_coap_header*/, + M2MObservationHandler */*observation_handler*/, + bool &) +{ + //Handled in M2MResource, M2MObjectInstance and M2MObject classes + return NULL; +} + +void M2MBase::set_register_uri( bool register_uri) +{ +} + +bool M2MBase::register_uri() +{ + return m2mbase_stub::bool_value; +} + +void M2MBase::set_uri_path(const String &uri_path) +{ +} + +const String& M2MBase::uri_path() const +{ + return *m2mbase_stub::string_value; +} + +bool M2MBase::is_under_observation() const +{ + return m2mbase_stub::bool_value; +} + +void M2MBase::set_value_updated_function(value_updated_callback callback) +{ + +} + +void M2MBase::set_value_updated_function(value_updated_callback2 callback) +{ + +} + +bool M2MBase::is_value_updated_function_set() +{ + return m2mbase_stub::is_value_updated_function_set; +} + +void M2MBase::execute_value_updated(const String& name) +{ + +} diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mbase_stub.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mbase_stub.h new file mode 100755 index 0000000000..8abe2db655 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mbase_stub.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_BASE_STUB_H +#define M2M_BASE_STUB_H + +#include "m2mbase.h" + +//some internal test related stuff +namespace m2mbase_stub +{ + extern uint8_t uint8_value; + extern uint16_t uint16_value; + extern uint32_t uint32_value; + extern uint16_t int_value; + extern int32_t name_id_value; + extern String *string_value; + extern bool bool_value; + extern M2MBase::BaseType base_type; + extern M2MBase::Mode mode_value; + extern M2MBase::Operation operation; + extern void *void_value; + extern M2MObservationHandler *observe; + extern M2MReportHandler *report; + extern M2MBase::Observation observation_level_value; + extern bool is_value_updated_function_set; + void clear(); +} + +#endif // M2M_BASE_STUB_H + diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionhandler_stub.cpp b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionhandler_stub.cpp new file mode 100755 index 0000000000..8f6822bafa --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionhandler_stub.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mconnectionhandler_stub.h" +#include "m2mconnectionsecurity.h" +#include "common_stub.h" + +int m2mconnectionhandler_stub::int_value; +uint16_t m2mconnectionhandler_stub::uint_value; +bool m2mconnectionhandler_stub::bool_value; + +void m2mconnectionhandler_stub::clear() +{ + int_value = -1; + uint_value = 0; + bool_value = false; +} + +M2MConnectionHandler::M2MConnectionHandler(M2MConnectionObserver &observer, + M2MConnectionSecurity* sec, + M2MInterface::BindingMode, + M2MInterface::NetworkStack) +:_observer(observer) +{ + if( sec ){ + delete sec; + sec = NULL; + } +} + +M2MConnectionHandler::~M2MConnectionHandler() +{ +} + +bool M2MConnectionHandler::bind_connection(const uint16_t) +{ + return m2mconnectionhandler_stub::bool_value; +} + +bool M2MConnectionHandler::resolve_server_address(const String&, + const uint16_t, + M2MConnectionObserver::ServerType, + const M2MSecurity* ) +{ + return m2mconnectionhandler_stub::bool_value; +} + +bool M2MConnectionHandler::start_listening_for_data() +{ + return m2mconnectionhandler_stub::bool_value; +} + +bool M2MConnectionHandler::send_data(uint8_t *, + uint16_t , + sn_nsdl_addr_s *) +{ + return m2mconnectionhandler_stub::bool_value; +} + +void M2MConnectionHandler::stop_listening() +{ +} + +int M2MConnectionHandler::send_to_socket(const unsigned char *, size_t ) +{ + return m2mconnectionhandler_stub::int_value; +} + +int M2MConnectionHandler::receive_from_socket(unsigned char *buf, size_t len) +{ + return m2mconnectionhandler_stub::int_value; +} + +void M2MConnectionHandler::handle_connection_error(int) +{ +} + +void M2MConnectionHandler::set_platform_network_handler(void *) +{ +} + +void M2MConnectionHandler::claim_mutex() +{ +} + +void M2MConnectionHandler::release_mutex() +{ +} diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionhandler_stub.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionhandler_stub.h new file mode 100755 index 0000000000..e0a4d278a2 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionhandler_stub.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_CONNECTION_HANDLER_IMPL_MBED_STUB_H +#define M2M_CONNECTION_HANDLER_IMPL_MBED_STUB_H + +#include "m2mconnectionhandler.h" + +//some internal test related stuff +namespace m2mconnectionhandler_stub +{ + extern int int_value; + extern uint16_t uint_value; + extern bool bool_value; + void clear(); +} + +#endif // M2M_CONNECTION_HANDLER_IMPL_STUB_H + diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionsecurity_stub.cpp b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionsecurity_stub.cpp new file mode 100644 index 0000000000..15161f836a --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionsecurity_stub.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mconnectionhandler.h" +#include "m2mconnectionsecurity.h" +#include "m2mtimer.h" +#include "m2msecurity.h" +#include +#include "m2mconnectionsecurity_stub.h" + +bool m2mconnectionsecurityimpl_stub::use_inc_int; +int m2mconnectionsecurityimpl_stub::inc_int_value; +int m2mconnectionsecurityimpl_stub::int_value; + +void m2mconnectionsecurityimpl_stub::clear() +{ + int_value = -1; + use_inc_int = false; + inc_int_value = 0; +} + +M2MConnectionSecurity::M2MConnectionSecurity(M2MConnectionSecurity::SecurityMode mode) +{ + +} + +M2MConnectionSecurity::~M2MConnectionSecurity(){ +} + +void M2MConnectionSecurity::reset(){ +} + +int M2MConnectionSecurity::init(const M2MSecurity *security){ + if(m2mconnectionsecurityimpl_stub::use_inc_int){ + return m2mconnectionsecurityimpl_stub::inc_int_value++; + } + return m2mconnectionsecurityimpl_stub::int_value; +} + +int M2MConnectionSecurity::connect(M2MConnectionHandler* connHandler){ + if(m2mconnectionsecurityimpl_stub::use_inc_int){ + return m2mconnectionsecurityimpl_stub::inc_int_value++; + } + return m2mconnectionsecurityimpl_stub::int_value; +} + +int M2MConnectionSecurity::start_connecting_non_blocking(M2MConnectionHandler* connHandler) +{ + if(m2mconnectionsecurityimpl_stub::use_inc_int){ + return m2mconnectionsecurityimpl_stub::inc_int_value++; + } + return m2mconnectionsecurityimpl_stub::int_value; +} + +int M2MConnectionSecurity::continue_connecting() +{ + if(m2mconnectionsecurityimpl_stub::use_inc_int){ + return m2mconnectionsecurityimpl_stub::inc_int_value++; + } + return m2mconnectionsecurityimpl_stub::int_value; +} + +int M2MConnectionSecurity::send_message(unsigned char *message, int len){ + if(m2mconnectionsecurityimpl_stub::use_inc_int){ + return m2mconnectionsecurityimpl_stub::inc_int_value++; + } + return m2mconnectionsecurityimpl_stub::int_value; +} + +int M2MConnectionSecurity::read(unsigned char* buffer, uint16_t len){ + if(m2mconnectionsecurityimpl_stub::use_inc_int){ + return m2mconnectionsecurityimpl_stub::inc_int_value++; + } + return m2mconnectionsecurityimpl_stub::int_value; +} diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionsecurity_stub.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionsecurity_stub.h new file mode 100644 index 0000000000..0e4eda024e --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionsecurity_stub.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_CONNECTION_SECURITY_IMPL_STUB_H +#define M2M_CONNECTION_SECURITY_IMPL_STUB_H + +//some internal test related stuff +namespace m2mconnectionsecurityimpl_stub +{ + extern int int_value; + extern bool use_inc_int; + extern int inc_int_value; + void clear(); +} + +#endif // M2M_CONNECTION_SECURITY_IMPL_STUB_H + + + + diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionsecuritypimpl_stub.cpp b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionsecuritypimpl_stub.cpp new file mode 100644 index 0000000000..57cc0af802 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionsecuritypimpl_stub.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mconnectionhandler.h" +#include "m2mconnectionsecurity.h" +#include "mbed-client-mbedtls/m2mconnectionsecuritypimpl.h" +#include "m2mtimer.h" +#include "m2msecurity.h" +#include +#include "m2mconnectionsecuritypimpl_stub.h" + +int m2mconnectionsecuritypimpl_stub::int_value; + +void m2mconnectionsecuritypimpl_stub::clear() +{ + int_value = -1; +} + +M2MConnectionSecurityPimpl::M2MConnectionSecurityPimpl(M2MConnectionSecurity::SecurityMode mode) +{ + +} + +M2MConnectionSecurityPimpl::~M2MConnectionSecurityPimpl(){ +} + +void M2MConnectionSecurityPimpl::reset(){ +} + +int M2MConnectionSecurityPimpl::init(const M2MSecurity *security){ + return m2mconnectionsecuritypimpl_stub::int_value; +} + +int M2MConnectionSecurityPimpl::connect(M2MConnectionHandler* connHandler){ + return m2mconnectionsecuritypimpl_stub::int_value; +} + +int M2MConnectionSecurityPimpl::start_connecting_non_blocking(M2MConnectionHandler* connHandler) +{ + return m2mconnectionsecuritypimpl_stub::int_value; +} + +int M2MConnectionSecurityPimpl::continue_connecting() +{ + return m2mconnectionsecuritypimpl_stub::int_value; +} + +int M2MConnectionSecurityPimpl::send_message(unsigned char *message, int len){ + return m2mconnectionsecuritypimpl_stub::int_value; +} + +int M2MConnectionSecurityPimpl::read(unsigned char* buffer, uint16_t len){ + return m2mconnectionsecuritypimpl_stub::int_value; +} + +void M2MConnectionSecurityPimpl::timer_expired(M2MTimerObserver::Type type){ +} + +void M2MConnectionSecurityPimpl::set_random_number_callback(random_number_cb){ +} + +void M2MConnectionSecurityPimpl::set_entropy_callback(entropy_cb){ +} diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionsecuritypimpl_stub.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionsecuritypimpl_stub.h new file mode 100644 index 0000000000..c7ac60e158 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mconnectionsecuritypimpl_stub.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_CONNECTION_SECURITY_PIMPL_STUB_H +#define M2M_CONNECTION_SECURITY_PIMPL_STUB_H + +//some internal test related stuff +namespace m2mconnectionsecuritypimpl_stub +{ + extern int int_value; + void clear(); +} + +#endif // M2M_CONNECTION_SECURITY_PIMPL_STUB_H + + + + diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mobject_stub.cpp b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mobject_stub.cpp new file mode 100755 index 0000000000..28d4185a79 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mobject_stub.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mobject_stub.h" + +u_int16_t m2mobject_stub::int_value; +bool m2mobject_stub::bool_value; +M2MObjectInstance* m2mobject_stub::inst; +M2MObjectInstanceList m2mobject_stub::instance_list; +M2MBase::BaseType m2mobject_stub::base_type; +sn_coap_hdr_s *m2mobject_stub::header; + +void m2mobject_stub::clear() +{ + int_value = 0; + bool_value = false; + m2mobject_stub::base_type = M2MBase::Object; + instance_list.clear(); + header = NULL; +} + +M2MObject::M2MObject(const String &object_name) +: M2MBase(object_name,M2MBase::Dynamic) +{ +} + +M2MObject::~M2MObject() +{ +} + +M2MObject& M2MObject::operator=(const M2MObject& ) +{ + return *this; +} + +M2MObject::M2MObject(const M2MObject& other) +: M2MBase(other) +{ + *this = other; +} + +M2MObjectInstance* M2MObject::create_object_instance(uint16_t instance_id) +{ + return m2mobject_stub::inst; +} + +bool M2MObject::remove_object_instance(uint16_t) +{ + return m2mobject_stub::bool_value; +} + +M2MObjectInstance* M2MObject::object_instance(uint16_t) const +{ + return m2mobject_stub::inst; +} + +const M2MObjectInstanceList& M2MObject::instances() const +{ + return m2mobject_stub::instance_list; +} + +uint16_t M2MObject::instance_count() const +{ + return m2mobject_stub::int_value; +} + +M2MBase::BaseType M2MObject::base_type() const +{ + return m2mobject_stub::base_type; +} + +void M2MObject::add_observation_level(M2MBase::Observation) +{ + +} + +void M2MObject::remove_observation_level(M2MBase::Observation) +{ + +} + +sn_coap_hdr_s* M2MObject::handle_get_request(nsdl_s *, + sn_coap_hdr_s *, + M2MObservationHandler *) +{ + return m2mobject_stub::header; +} + +sn_coap_hdr_s* M2MObject::handle_put_request(nsdl_s *, + sn_coap_hdr_s *, + M2MObservationHandler *, + bool &execute) +{ + execute = m2mobject_stub::bool_value; + return m2mobject_stub::header; +} + +sn_coap_hdr_s* M2MObject::handle_post_request(nsdl_s *, + sn_coap_hdr_s *, + M2MObservationHandler *, + bool &) +{ + return m2mobject_stub::header; +} + +void M2MObject::notification_update(uint16_t obj_instance_id) +{ +} diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mobject_stub.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mobject_stub.h new file mode 100755 index 0000000000..c89a0dcdbd --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mobject_stub.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_OBJECT_STUB_H +#define M2M_OBJECT_STUB_H + +#include "m2mobject.h" +#include "m2mobjectinstance.h" + +//some internal test related stuff +namespace m2mobject_stub +{ + extern u_int16_t int_value; + extern M2MObjectInstance* inst; + extern bool bool_value; + extern M2MObjectInstanceList instance_list; + extern M2MBase::BaseType base_type; + extern sn_coap_hdr_s *header; + void clear(); +} + +#endif // M2M_OBJECT_STUB_H + diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2msecurity_stub.cpp b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2msecurity_stub.cpp new file mode 100755 index 0000000000..9609414212 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2msecurity_stub.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2msecurity_stub.h" + +bool m2msecurity_stub::has_value; +uint32_t m2msecurity_stub::int_value; +bool m2msecurity_stub::bool_value; +String *m2msecurity_stub::string_value; +M2MResource* m2msecurity_stub::resource; + +void m2msecurity_stub::clear() +{ + has_value = false; + int_value = -1; + bool_value = false; + string_value = NULL; + resource = NULL; +} + +M2MSecurity::M2MSecurity(ServerType ser_type) +: M2MObject("0"), + _server_type(ser_type), + _server_instance(NULL) +{ +} + +M2MSecurity::~M2MSecurity() +{ +} + +M2MResource* M2MSecurity::create_resource(SecurityResource, uint32_t) +{ + return m2msecurity_stub::resource; +} + +bool M2MSecurity::delete_resource(SecurityResource) +{ + return m2msecurity_stub::bool_value; +} + +bool M2MSecurity::set_resource_value(SecurityResource, + const String &) +{ + return m2msecurity_stub::bool_value; +} + +bool M2MSecurity::set_resource_value(SecurityResource, + uint32_t) +{ + return m2msecurity_stub::bool_value; +} + +bool M2MSecurity::set_resource_value(SecurityResource, + const uint8_t *, + const uint16_t) +{ + return m2msecurity_stub::bool_value; +} + +String M2MSecurity::resource_value_string(SecurityResource) const +{ + return *m2msecurity_stub::string_value; +} + +uint32_t M2MSecurity::resource_value_buffer(SecurityResource, + uint8_t *&value) const +{ + if( m2msecurity_stub::has_value ){ + value = (uint8_t *)malloc(5); + return 5; + } + return m2msecurity_stub::int_value; +} + +uint32_t M2MSecurity::resource_value_buffer(SecurityResource, + const uint8_t *&value) const +{ + if( m2msecurity_stub::has_value ){ + value = (const uint8_t*)"dummy"; + return 6; + } + return m2msecurity_stub::int_value; +} + +uint32_t M2MSecurity::resource_value_int(SecurityResource) const +{ + return m2msecurity_stub::int_value; +} + +bool M2MSecurity::is_resource_present(SecurityResource) const +{ + return m2msecurity_stub::bool_value; +} + +uint16_t M2MSecurity::total_resource_count() const +{ + return (uint16_t)m2msecurity_stub::int_value; +} + +M2MSecurity::ServerType M2MSecurity::server_type() const +{ + return _server_type; +} diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2msecurity_stub.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2msecurity_stub.h new file mode 100755 index 0000000000..8409c39a0d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2msecurity_stub.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_SECURITY_STUB_H +#define M2M_SECURITY_STUB_H + +#include "m2msecurity.h" + +//some internal test related stuff +namespace m2msecurity_stub +{ + extern bool has_value; + extern uint32_t int_value; + extern bool bool_value; + extern String *string_value; + extern M2MResource* resource; + void clear(); +} + +#endif // M2M_SECURITY_STUB_H + diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mstring_stub.cpp b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mstring_stub.cpp new file mode 100755 index 0000000000..c163468999 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mstring_stub.cpp @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mstring.h" +#include // strlen +#include // malloc, realloc +#include +#include // min + +namespace m2m { + +const String::size_type String::npos = static_cast(-1); + +char* String::strdup(const char* s) +{ + const size_t len = strlen(s)+1; + char *p2 = static_cast(malloc(len)); + memcpy(p2, s, len); + allocated_ = len; + size_ = len-1; + return p2; +} + +String::String() + : p( strdup("") ) +{ +} + +String::~String() +{ + free(p); + p = 0; +} + +String::String(const String& s) + : p(0) +{ + if( &s != NULL ) { + p = static_cast(malloc(s.size_ + 1)); + + allocated_ = s.size_ + 1; + size_ = s.size_; + memcpy(p, s.p, size_ + 1); + } +} + +String::String(const char* s) + : p(strdup(s)) +{ +} + +String& String::operator=(const char* s) +{ + if ( p != s ) { + // s could point into our own string, so we have to allocate a new string + const size_t len = strlen(s); + char* copy = (char*) malloc( len + 1); + memmove(copy, s, len+1); // trailing 0 + free( p ); + p = copy; + size_ = len; + allocated_ = len+1; + } + return *this; +} + +String& String::operator=(const String& s) +{ + return operator=(s.p); +} + +String& String::operator+=(const String& s) +{ + if (s.size_ > 0) { + this->reserve(size_ + s.size_); + memmove(p+size_, s.p, s.size_+1); // trailing 0 + size_ += s.size_; + } + return *this; +} + +// since p and s may overlap, we have to copy our own string first +String& String::operator+=(const char* s) +{ + const size_type lens = strlen(s); + if (lens > 0) { + if (size_ + lens + 1 <= allocated_) { + memmove(p+size_, s, lens+1); // trailing 0 + size_ += lens; + } else { + String s2( *this ); // copy own data + s2.reserve(size_ + lens); + memmove(s2.p+size_, s, lens+1); // trailing 0 + s2.size_ = size_ + lens; + this->swap( s2 ); + } + } + return *this; +} + +String& String::operator+=(const char c) +{ + push_back(c); + return *this; +} + +void String::push_back(const char c) { + + if (size_ == allocated_ - 1) { + size_t more = (allocated_* 3) / 2; // factor 1.5 + if ( more < 4 ) more = 4; + reserve( size_ + more ); + } + + p[size_] = c; + size_++; + p[size_] = 0; +} + +bool String::operator==(const char* s) const +{ + if( s == NULL ) { + if( p == NULL ) { + return true; + } + return false; + } + bool ret = strcmp(p, s); + return !ret; +} + +bool String::operator==(const String& s) const +{ + bool ret = strcmp(p, s.p); + return !ret; +} + +void String::clear() +{ + size_ = 0; + p[0] = 0; +} + +String String::substr(const size_type pos, size_type length) const +{ + String s; + const size_type len = size_; + + if ( pos <= len ) { + + size_type remain = len - pos; + + if ( length > remain ) + length = remain; + + s.reserve( length ); + + memcpy(s.p, p + pos, length); + s.p[length] = '\0'; + s.size_ = length; + } + return s; +} + + +// checked access, accessing the NUL at end is allowed +char String::at(const size_type i) const +{ + if ( i <= strlen(p) ) { + return p[i]; + } else { + return '\0'; + } +} + +String& String::erase(size_type pos, size_type len) +{ + if (len > 0) { + + if ( pos < size_ ) { // user must not remove trailing 0 + + size_type s2 = size_; + size_type remain = s2 - pos - len; + + if (remain > 0) { + // erase by overwriting + memmove(p + pos, p + pos + len, remain); + } + + //if ( remain < 0 ) remain = 0; + + // remove unused space + this->resize( pos+remain ); + + } + } + return *this; +} + +String& String::append( const char* str, size_type n) { + if (str && n > 0) { + size_t lens = strlen(str); + if (n > lens) + n = lens; + size_t newlen = size_ + n; + this->reserve( newlen ); + memmove(p+size_, str, n); // p and s.p MAY overlap + p[newlen] = 0; // add NUL termination + size_ = newlen; + } + return *this; +} + +String& String::append_raw( const char* str, size_type n) { + if (str && n > 0) { + size_t newlen = size_ + n; + this->reserve( newlen ); + memmove(p+size_, str, n); // p and s.p MAY overlap + p[newlen] = 0; // add NUL termination + size_ = newlen; + } + return *this; +} + +void String::append_int(int param) { + + // max len of "-9223372036854775808" plus zero termination + char conv_buff[20+1]; + + int len = itoa_c(param, conv_buff); + append_raw(conv_buff, len); +} + +int String::compare( size_type pos, size_type len, const String& str ) const { + int r = -1; + if (pos <= size_) { + if ( len > size_ - pos) + len = size_ - pos; // limit len to available length + + const size_type osize = str.size(); + const size_type len2 = std::min(len, osize); + r = strncmp( p + pos, str.p, len2); + if (r==0) // equal so far, now compare sizes + r = len < osize ? -1 : ( len == osize ? 0 : +1 ); + } + return r; +} + +int String::compare( size_type pos, size_type len, const char* str ) const { + int r = -1; + if (pos <= size_) { + + if ( len > size_ - pos) + len = size_ - pos; // limit len to available length + + const size_type osize = strlen(str); + const size_type len2 = std::min(len, osize); + r = strncmp( p + pos, str, len2); + if (r==0) // equal so far, now compare sizes + r = len < osize ? -1 : ( len == osize ? 0 : +1 ); + } + return r; +} + +int String::find_last_of(char c) const { + int r = -1; + char *v; + v = strrchr(p,c); + if (v != NULL) { + r = 0; + char* i = p; + while (v != i) { + i++; + r++; + } + } + return r; +} + +void String::new_realloc( size_type n) { + if (n > 0 ) { + char* pnew = static_cast(realloc(p, n)); // could return NULL + if (pnew) + p = pnew; + } +} + +void String::reserve( const size_type n) { + if (n >= allocated_ ) { + this->new_realloc(n + 1); + allocated_ = n + 1; + } +} + +void String::resize( const size_type n) { + this->resize( n, 0 ); +} + +void String::resize( const size_type n, const char c) { + if (n < size_ ) { + p[n] = 0; + size_ = n; + } + else if (n > size_ ) { + this->reserve( n ); + for (size_type i=size_; i < n; ++i ) + p[i] = c; + p[n] = 0; + size_ = n; + } +} + +void String::swap( String& s ) { + std::swap( allocated_, s.allocated_ ); + std::swap( size_, s.size_ ); + std::swap( p, s.p ); +} + + +// Comparison +bool operator<( const String& s1, const String& s2 ) { + return strcmp( s1.c_str(), s2.c_str() ) < 0; +} + +void reverse(char s[], uint32_t length) +{ + uint32_t i, j; + char c; + + for (i = 0, j = length-1; i 0); + + if (sign < 0) + s[i++] = '-'; + + s[i] = '\0'; + + m2m::reverse(s, i); + return i; +} + +uint8_t* String::convert_integer_to_array(int64_t value, uint8_t &size, uint8_t *array, uint32_t array_size) +{ + uint8_t* buffer = NULL; + size = 0; + if (array) { + value = String::convert_array_to_integer(array, array_size); + } + + if(value < 0xFF) { + size = 1; + } else if(value < 0xFFFF) { + size = 2; + } else if(value < 0xFFFFFF) { + size = 3; + } else if(value < 0xFFFFFFFF) { + size = 4; + } else if(value < 0xFFFFFFFFFF) { + size = 5; + } else if(value < 0xFFFFFFFFFFFF) { + size = 6; + } else if(value < 0xFFFFFFFFFFFFFF) { + size = 7; + } else { + size = 8; + } + + buffer = (uint8_t*)malloc(size); + if (buffer) { + for (int i = 0; i < size; i++) { + buffer[i] = (value >> ((size - i - 1) * 8)); + } + } else { + size = 0; + } + return buffer; +} + +int64_t String::convert_array_to_integer(uint8_t *value, uint32_t size) +{ + int64_t temp_64 = 0; + for (int i = size - 1; i >= 0; i--) { + temp_64 += (uint64_t)(*value++) << i * 8; + } + return temp_64; +} + +} // namespace diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mtimer_stub.cpp b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mtimer_stub.cpp new file mode 100755 index 0000000000..0ef5e49e1a --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mtimer_stub.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mtimer_stub.h" + +bool m2mtimer_stub::bool_value; +bool m2mtimer_stub::total_bool_value; + +void m2mtimer_stub::clear() +{ + bool_value = false; + total_bool_value = false; +} + +// Prevents the use of assignment operator +M2MTimer& M2MTimer::operator=(const M2MTimer& /*other*/) +{ + return *this; +} + +// Prevents the use of copy constructor +M2MTimer::M2MTimer(const M2MTimer& other) +: _observer(other._observer) +{ + *this = other; +} + +M2MTimer::M2MTimer(M2MTimerObserver& observer) +: _observer(observer) +{ +} + +M2MTimer::~M2MTimer() +{ +} + +void M2MTimer::start_timer(uint64_t /*interval*/, + M2MTimerObserver::Type /*type*/, + bool /*single_shot*/) +{ +} + +void M2MTimer::start_dtls_timer(uint64_t , uint64_t , M2MTimerObserver::Type ) +{ +} + +void M2MTimer::stop_timer() +{ +} + + +bool M2MTimer::is_intermediate_interval_passed(){ + return m2mtimer_stub::bool_value; +} + +bool M2MTimer::is_total_interval_passed(){ + return m2mtimer_stub::total_bool_value; +} diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mtimer_stub.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mtimer_stub.h new file mode 100755 index 0000000000..451eb516e8 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/m2mtimer_stub.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_TIMER_STUB_H +#define M2M_TIMER_STUB_H + +#include "m2mtimer.h" + +//some internal test related stuff +namespace m2mtimer_stub +{ + extern bool bool_value; + extern bool total_bool_value; + void clear(); +} + +#endif // M2M_TIMER_STUB_H + diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/mbedtls_stub.cpp b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/mbedtls_stub.cpp new file mode 100644 index 0000000000..b50de1ac2b --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/mbedtls_stub.cpp @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbedtls_stub.h" + +bool mbedtls_stub::useCounter; +int mbedtls_stub::counter; +int mbedtls_stub::retArray[20]; +int mbedtls_stub::crt_expected_int; +int mbedtls_stub::expected_int; +uint32_t mbedtls_stub::expected_uint32_value; +bool mbedtls_stub::invalidate_timer; + +void mbedtls_stub::clear() +{ + mbedtls_stub::useCounter = false; + counter = 0; + expected_int = -1; + crt_expected_int = -1; + expected_uint32_value = 0; + for( int i=0; i < 20; i++ ){ + retArray[i] = -1; + } + invalidate_timer = false; +} + +//From ssl.h +int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ) +{ + if( mbedtls_stub::useCounter ){ + return mbedtls_stub::retArray[mbedtls_stub::counter++]; + } + return mbedtls_stub::expected_int; +} + +int mbedtls_ssl_close_notify( mbedtls_ssl_context * ) +{ + if( mbedtls_stub::useCounter ){ + return mbedtls_stub::retArray[mbedtls_stub::counter++]; + } + return mbedtls_stub::expected_int; +} + +void mbedtls_ssl_init( mbedtls_ssl_context * ){ + +} + +void mbedtls_ssl_config_init( mbedtls_ssl_config * ){ + +} + +void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *, uint32_t, uint32_t) +{ + +} + +void mbedtls_ssl_free( mbedtls_ssl_context * ){ + +} + +int mbedtls_ssl_session_reset( mbedtls_ssl_context * ){ + +} + +int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *, + mbedtls_x509_crt *, + mbedtls_pk_context * ){ + if( mbedtls_stub::useCounter ){ + return mbedtls_stub::retArray[mbedtls_stub::counter++]; + } + return mbedtls_stub::expected_int; +} + +void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *, int ){ + +} + +void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *, + mbedtls_x509_crt *, + mbedtls_x509_crl * ){ + +} + +int mbedtls_ssl_conf_psk( mbedtls_ssl_config *, + const unsigned char *, size_t , + const unsigned char *, size_t ){ + if( mbedtls_stub::useCounter ){ + return mbedtls_stub::retArray[mbedtls_stub::counter++]; + } + return mbedtls_stub::expected_int; +} + +int mbedtls_ssl_config_defaults( mbedtls_ssl_config *, + int , int, int ){ + if( mbedtls_stub::useCounter ){ + return mbedtls_stub::retArray[mbedtls_stub::counter++]; + } + return mbedtls_stub::expected_int; +} + +void mbedtls_ssl_conf_rng( mbedtls_ssl_config *, + int (*f_rng)(void *, unsigned char *, size_t), + void * ){ + +} + +void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *, + const int *) +{ + +} + +int mbedtls_ssl_setup( mbedtls_ssl_context *, + const mbedtls_ssl_config * ){ + if( mbedtls_stub::useCounter ){ + return mbedtls_stub::retArray[mbedtls_stub::counter++]; + } + return mbedtls_stub::expected_int; +} + +void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, + void *p_bio, + int (*f_send)(void *, const unsigned char *, size_t), + int (*f_recv)(void *, unsigned char *, size_t), + int (*f_recv_timeout)(void *, unsigned char *, size_t, uint32_t) ){ + if( p_bio != NULL ){ + f_send( p_bio, NULL, 0 ); + f_recv( p_bio, NULL, 0 ); + f_recv_timeout( p_bio, NULL, 0, 0 ); + } +} + +void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *, + void *ctx, + void (*f_set_timer)(void *, uint32_t int_ms, uint32_t fin_ms), + int (*f_get_timer)(void *) ){ + f_set_timer(ctx, 1, 2); + f_get_timer(ctx); + if(mbedtls_stub::invalidate_timer){ + f_set_timer(ctx, 0, 0); + } + f_get_timer(ctx); +} + +int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ){ + if( mbedtls_stub::useCounter ){ + return mbedtls_stub::retArray[mbedtls_stub::counter++]; + } + return mbedtls_stub::expected_int; +} + +uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context * ){ + return mbedtls_stub::expected_uint32_value; +} + +int mbedtls_ssl_read( mbedtls_ssl_context *, unsigned char *, size_t ){ + if( mbedtls_stub::useCounter ){ + return mbedtls_stub::retArray[mbedtls_stub::counter++]; + } + return mbedtls_stub::expected_int; +} + +int mbedtls_ssl_write( mbedtls_ssl_context *, const unsigned char *, size_t ){ + if( mbedtls_stub::useCounter ){ + return mbedtls_stub::retArray[mbedtls_stub::counter++]; + } + return mbedtls_stub::expected_int; +} + + + +//From crt_drbg.h +int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *, + int (*f_entropy)(void *, unsigned char *, size_t), + void *, + const unsigned char *, + size_t ){ + return mbedtls_stub::crt_expected_int; +} + +void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context * ){ + +} + +void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context * ){ + +} + +int mbedtls_ctr_drbg_random_with_add( void *, + unsigned char *, size_t , + const unsigned char *, size_t ){ + return mbedtls_stub::crt_expected_int; +} + +int mbedtls_ctr_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ){ + return mbedtls_stub::crt_expected_int; +} + +//From x509_crt.h +void mbedtls_x509_crt_init( mbedtls_x509_crt * ){ + +} + +void mbedtls_x509_crt_free( mbedtls_x509_crt * ){ + +} + +int mbedtls_x509_crt_parse( mbedtls_x509_crt *, const unsigned char *, size_t ){ + if( mbedtls_stub::useCounter ){ + return mbedtls_stub::retArray[mbedtls_stub::counter++]; + } + return mbedtls_stub::expected_int; +} + +//From entropy.h +void mbedtls_entropy_init( mbedtls_entropy_context * ){ + +} + +void mbedtls_entropy_free( mbedtls_entropy_context *ctx ){ + +} + +int mbedtls_entropy_func( void *, unsigned char *, size_t ){ + if( mbedtls_stub::useCounter ){ + return mbedtls_stub::retArray[mbedtls_stub::counter++]; + } + return mbedtls_stub::expected_int; +} + +int mbedtls_entropy_add_source( mbedtls_entropy_context *, + mbedtls_entropy_f_source_ptr f_source, void *, + size_t, int ){ + unsigned char buf[2]; + size_t len; + f_source(NULL, buf, 1, &len); + + if( mbedtls_stub::useCounter ){ + return mbedtls_stub::retArray[mbedtls_stub::counter++]; + } + if(mbedtls_stub::counter == 1){ + mbedtls_stub::counter--; + return 0; + } + return mbedtls_stub::expected_int; +} + +//From pk.h +int mbedtls_pk_parse_key( mbedtls_pk_context *, + const unsigned char *, size_t , + const unsigned char *, size_t ){ + if( mbedtls_stub::useCounter ){ + return mbedtls_stub::retArray[mbedtls_stub::counter++]; + } + return mbedtls_stub::expected_int; +} + +void mbedtls_pk_init( mbedtls_pk_context *ctx ) +{ + +} + +void mbedtls_pk_free( mbedtls_pk_context *ctx ) +{ + +} + +void mbedtls_ssl_config_free( mbedtls_ssl_config * ) +{ + +} + diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/mbedtls_stub.h b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/mbedtls_stub.h new file mode 100644 index 0000000000..a55b4718f2 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/test/mbed-client-mbed-tls/unittest/stub/mbedtls_stub.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 MBEDTLS_STUB_H +#define MBEDTLS_STUB_H + +#include "mbedtls/platform.h" +#include "mbedtls/ssl.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/x509_crt.h" +#include "mbedtls/entropy.h" +#include "mbedtls/pk.h" + +namespace mbedtls_stub +{ + extern int crt_expected_int; + extern bool useCounter; + extern int counter; + extern int retArray[20]; + extern int expected_int; + extern uint32_t expected_uint32_value; + extern bool invalidate_timer; + void clear(); +} + +#endif // MBEDTLS_STUB_H diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/toolchain_rules.mk b/features/FEATURE_CLIENT/mbed-client-mbed-tls/toolchain_rules.mk new file mode 100644 index 0000000000..3d185bc10c --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/toolchain_rules.mk @@ -0,0 +1,293 @@ +# +# Toolchain rules for building libraries +# +# Support multi-platform builds +# You may define PLATFORM=.. prefix for compiler +# if PLATFORM is defined it will owerride CC and AR +# You may also specify CC and AR separately. +# example: Compile with KEIL +# make CC=ArmCC AR=ArmAR +# +# example: Cross Compile with Gnu toolchain, for embedded Linux +# make PLATFORM=arm-linux-gnueabi- +# +# Special rules for IAR-ARM toolchains added, AR tool on that does not follow common arquements. +# make CC=iccarm uses iarchive.exe for creating a archive. +# +# Special rules for IAR-RL78 toolchain added, uses own AR and compiler requires specific flags +# make CC=iccrl78 +# +# When using ArmCC, Select CPU by defining one of following supported values +# CPU=Cortex-M0 +# CPU=Cortex-M3 +# CPU=Cortex-M4 +# +# example: +# make CC=armcc CPU=Cortex-M4 + +# +# If PLATFORM prefix is defined, +# generate CC and AR accordingly +# +ifneq ($(strip $(PLATFORM)),) +CC:=$(PLATFORM)gcc +AR:=$(PLATFORM)ar +endif + +# +# Windows specific tweaks for echo and mkdir to work +# +ifeq ($(OS),Windows_NT) +SHELL := cmd.exe +mkdir = if not exist $(1) md $(subst /,\,$(1)) +else +mkdir = mkdir -p $(1) +endif + +# +# Append CC and CPU to library names +# +LIB:=$(LIB:%.a=%_$(CC).a) +ifneq (,$(CPU)) + LIB:=$(LIB:%.a=%_$(CPU).a) +endif + +########################################################## +# TOOLCHAIN SPECIFIC RULES AND FLAGS # +########################################################## + +# +# GCC toolchains +# +ifneq (,$(findstring gcc,$(CC))) + # Flags for common toolchain, usually GCC or CC + AROPTS=-rsc $@ $^ + override CFLAGS += -Wall -pedantic-errors + # Dependency generation + override CFLAGS += -MMD -MP + ifneq (,$(CPU)) + # CPU must be lowercase on GCC + CPU_L:=$(shell echo $(CPU) | tr A-Z a-z) + override CFLAGS += -mcpu=$(CPU_L) + # Use THUMB instructions of Cortex-M cores + ifeq (cortex-m,$(findstring cortex-m,$(CPU_L))) + override CFLAGS += -mthumb + endif + endif + # Debug + ifeq ($(DEBUG),1) + override CFLAGS += -g -O0 + else + override CFLAGS += -O2 + endif + # Enable Coverage generation + ifeq ($(COVERAGE),1) + override CFLAGS += -ftest-coverage -fprofile-arcs + override LDFLAGS += -ftest-coverage -fprofile-arcs + endif + COMPILE = $(CC) -std=gnu99 -c -o $@ + CXXCOMPILE = $(CC) -std=c++11 -c -o $@ + +# +# IAR-ARM toolchain +# +else ifneq (,$(findstring iccarm,$(CC))) + AR:=iarchive + AROPTS=$^ --create -o $@ + DLIB_FILE=$(subst bin\iccarm.exe,inc\c\DLib_Config_Full.h,$(shell where iccarm)) + override CFLAGS += --dlib_config '$(DLIB_FILE)' --cpu Cortex-M4 --vla --diag_suppress Pa50 + # Dependency generation + override CFLAGS += --dependencies=m $(basename $@).d + # Debug + ifeq ($(DEBUG),1) + override CFLAGS += --debug -On + else + override CFLAGS += -Om + endif + COMPILE = $(CC) -c -o $@ + +# +# ArmCC toolchain (Used by Keil) +# +else ifneq (,$(findstring armcc,$(CC))) + AR:=armar + AROPTS=-rsc $@ $^ + override CFLAGS += --c99 --no_wrap_diagnostics + # Dependency generation + override CFLAGS += --depend $(basename $@).d --phony_targets + LIB:=$(LIB:%.a=%.lib) + ifneq (,$(CPU)) + override CFLAGS += --cpu=$(CPU) + endif + # Debug + ifeq ($(DEBUG),1) + override CFLAGS += -g -O0 + else + override CFLAGS += -O2 + endif + COMPILE = $(CC) -c -o $@ + +# +# IAR Renesas78 toolchain +# +else ifneq (,$(findstring iccrl78,$(CC))) + AR:=xar + AROPTS=$@ $^ + # Hack to get \lib include path which contains dlib config headers for compiler + DIR=$(subst iccrl78.exe,..\lib\,$(shell where iccrl78)) + override CFLAGS += --core rl78_1 --code_model far --data_model far --dlib_config full --vla --no_wrap_diagnostics -I'$(DIR)' + # Dependency generation + LIB:=$(LIB:%.a=%.lib) + override CFLAGS += --dependencies=m $(basename $@).d + # Debug + ifeq ($(DEBUG),1) + override CFLAGS += --debug -Oh + else + override CFLAGS += -Ohz + endif + COMPILE = $(CC) -o $@ + +# +# IAR MSP430 toolchain +# +else ifneq (,$(findstring icc430,$(CC))) + AR:=xar + AROPTS=$@ $^ + # Hack to get \lib include path which contains dlib config headers for compiler + DIR=$(subst bin\icc430.exe,lib,$(shell where icc430)) + DLIB_FILE=$(subst bin\icc430.exe,lib\dlib\dl430xllff.h,$(shell where icc430)) + override CFLAGS += --dlib_config '$(DLIB_FILE)' --vla --core 430X --data_model large --no_wrap_diagnostics -I'$(DIR)' + # Dependency generation + LIB:=$(LIB:%.a=%.lib) + override CFLAGS += --dependencies=m $(basename $@).d + # Debug + ifeq ($(DEBUG),1) + override CFLAGS += --debug -On + else + override CFLAGS += -Ohz + endif + COMPILE = $(CC) -o $@ + +# +# CppCheck toolchain +# This is used only for static testing the code. +# cppcheck is used in place of compiler and linker phase is ignored +else ifneq (,$(findstring cppcheck,$(CC))) + AR = cppcheck -q --enable=warning --enable=style --std=c99 --inline-suppr -DCPPCHECK $(CPPCHECK_OPTS) $(CFLAGS) $(SRCS) + COMPILE = true + CPPCHECK = 1 + LIB:= "ignored_with_cppcheck" + + +################################### +# End of toolchain specific rules # +################################### +endif + +# +# Generate VERSION tag +# +ifeq (,$(CPPCHECK)) +VERSION := $(shell git describe --tags --long --dirty --always) +CFLAGS += -DVERSION='"$(VERSION)"' +endif + +############################################################ +# AUTOMATICALLY GENERATE LIBRARY COMPILATION RULES # +# # +# Use: # +# $(eval $(call generate_rules,$(OUTPUT_LIB),$(SRCS))) # +# at the end of your Makefile # +# # +############################################################ + +define generate_rules + +DEST_LIB := $(1) +LIB_SRCS := $(2) +C_SRCS := $$(filter %.c,$$(LIB_SRCS)) +CXX_SRCS := $$(filter %.cpp,$$(LIB_SRCS)) +all: $$(DEST_LIB) + +# +# Define build dir outside from src folders +# +BUILD_DIR := output/$$(CC) +ifneq (,$$(CPU)) +BUILD_DIR := $$(BUILD_DIR)_$$(CPU) +endif +ifneq (generic,$$(CONFIG)) +BUILD_DIR := $$(BUILD_DIR)_$$(CONFIG) +endif +OBJS := $$(C_SRCS:%.c=$$(BUILD_DIR)/%.o) $$(CXX_SRCS:%.cpp=$$(BUILD_DIR)/%.o) + +# Include auto-dependencies +-include $$(OBJS:.o=.d) + +# Create list of output directories. +OBJ_DIRS := $$(sort $$(dir $$(OBJS))) + +# requires directories to be created before build. +# '|' means do not care about timestamps of requisities +$$(OBJS): | $$(OBJ_DIRS) + +# Need to redefine build rule to find the sources +# from correct folder. +$$(BUILD_DIR)/%.o: %.c +ifeq ($(V),1) + $$(COMPILE) $$(CFLAGS) $$< +else ifeq (1,$(CPPCHECK)) + @$$(COMPILE) $$(CFLAGS) $$< +else ifeq (1,$(UNITTEST)) + @echo Building unittest $$< +ifneq ($(OS),Windows_NT) + ruby $(UNIT_TEST_BASE)/../auto/generate_test_runner.rb Test.c Test_Runner.c +endif + @gcc $$(CFLAGS) $$(SRCS) -o $$(OUTPUT_LIB) +else + @echo Building $$< + @$$(COMPILE) $$(CFLAGS) $$< +endif + +# Same again for C++ +$$(BUILD_DIR)/%.o: %.cpp +ifeq ($(V),1) + $$(CXXCOMPILE) $$(CFLAGS) $$< +else ifeq (1,$(CPPCHECK)) + @$$(CXXCOMPILE) $$(CFLAGS) $$< +else + @echo Building $$< + @$$(CXXCOMPILE) $$(CFLAGS) $$< +endif + +# Rule to create a object directory +$$(OBJ_DIRS): + @-$$(call mkdir,$$@) + +$$(DEST_LIB): $$(OBJS) +ifeq ($(V),1) + -$$(addprefix $$(RM) ,$$(wildcard $$@)) + $$(AR) $$(AROPTS) +else ifeq (1,$(CPPCHECK)) + @$$(AR) $$(AROPTS) +else ifeq (1,$(UNITTEST)) +#ifneq ($(OS),Windows_NT) +# lcov -q --capture -i --directory $(CURDIR) --output-file lib_base.info +# ./$$@ +# lcov -q --capture --directory $(CURDIR) --output-file lib_test.info +# lcov -a lib_base.info -a lib_test.info -o coverage.info +#endif +else + @echo Linking $$(notdir $$@) + @-$$(addprefix $$(RM) ,$$(wildcard $$@)) + @$$(AR) $$(AROPTS) +endif + +clean: + @$(RM) -r $$(BUILD_DIR) + @$(RM) $$(DEST_LIB) + +clean-all: + @$(RM) -r output *.a + +endef diff --git a/features/FEATURE_CLIENT/mbed-client-mbed-tls/xsl_script.sh b/features/FEATURE_CLIENT/mbed-client-mbed-tls/xsl_script.sh new file mode 100755 index 0000000000..d5320b42b8 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-mbed-tls/xsl_script.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# Copyright (c) 2015 ARM Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# * http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +echo +echo "Creating report" +echo + +echo ' + +' >> lcov/index.xml + +for f in lcov/results/*.xml +do +name=${f##*/} +echo ''>> lcov/index.xml +done + +echo '' >> lcov/index.xml + +echo +echo "Report created to lcov/index.xml (outputs html)" +echo \ No newline at end of file diff --git a/features/FEATURE_CLIENT/mbed-client-randlib/.gitignore b/features/FEATURE_CLIENT/mbed-client-randlib/.gitignore new file mode 100644 index 0000000000..77320b339f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-randlib/.gitignore @@ -0,0 +1 @@ +output/* diff --git a/features/FEATURE_CLIENT/mbed-client-randlib/.mbedignore b/features/FEATURE_CLIENT/mbed-client-randlib/.mbedignore new file mode 100644 index 0000000000..ba4eb1b31d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-randlib/.mbedignore @@ -0,0 +1,2 @@ +linux/* +test/* diff --git a/features/FEATURE_CLIENT/mbed-client-randlib/LICENSE b/features/FEATURE_CLIENT/mbed-client-randlib/LICENSE new file mode 100644 index 0000000000..97df0e645d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-randlib/LICENSE @@ -0,0 +1,2 @@ +Unless specifically indicated otherwise in a file, files are licensed +under the Apache 2.0 license, as can be found in: apache-2.0.txt \ No newline at end of file diff --git a/features/FEATURE_CLIENT/mbed-client-randlib/apache-2.0.txt b/features/FEATURE_CLIENT/mbed-client-randlib/apache-2.0.txt new file mode 100644 index 0000000000..0e4cf3ee99 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-randlib/apache-2.0.txt @@ -0,0 +1,56 @@ + + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + You must give any other recipients of the Work or Derivative Works a copy of this License; and + You must cause any modified files to carry prominent notices stating that You changed the files; and + You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/features/FEATURE_CLIENT/mbed-client-randlib/linux/randLIB.c b/features/FEATURE_CLIENT/mbed-client-randlib/linux/randLIB.c new file mode 100644 index 0000000000..654d9e7f82 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-randlib/linux/randLIB.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2014-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "randLIB.h" + +/** + * \brief Init seed for Pseudo Random. + * On a Linux, this does nothing. + * + * \return None + * + */ +void randLIB_seed_random(void) +{ +} + +/** + * \brief Generate 8-bit random number. + * + * \param None + * \return 8-bit random number + * + */ +uint8_t randLIB_get_8bit(void) +{ + uint8_t ret_val; + randLIB_get_n_bytes_random(&ret_val, 1); + return ret_val; +} + +/** + * \brief Generate 16-bit random number. + * + * \param None + * \return 16-bit random number + * + */ +uint16_t randLIB_get_16bit(void) +{ + uint16_t ret_val; + + randLIB_get_n_bytes_random((uint8_t*)&ret_val, 2); + return ret_val; +} +/** + * \brief Generate 32-bit random number. + * + * \param None + * \return 32-bit random number + * + */ +uint32_t randLIB_get_32bit(void) +{ + uint32_t ret_val; + randLIB_get_n_bytes_random((uint8_t*)&ret_val, 4); + return ret_val; +} + + +/** + * \brief Generate n-bytes random numbers. + * + * \param data_ptr pointer where random will be stored + * \param eight_bit_boundary how many bytes need random + * \return 0 process valid + * \return -1 Unsupported Parameters or failed to get random data. + * + */ +int8_t randLIB_get_n_bytes_random(uint8_t *data_ptr, uint8_t eight_bit_boundary) +{ + if ((data_ptr == 0) || (eight_bit_boundary == 0)) { + return -1; + } + + int fd = open("/dev/urandom", O_RDONLY); + if (fd != -1) { + size_t len = read(fd, data_ptr, eight_bit_boundary); + close(fd); + if (len == eight_bit_boundary) + return 0; + } + + return -1; +} + +/** + * \brief Generate a random number within a range. + * + * The result is linearly distributed in the range [min..max], inclusive. + * + * \param min minimum value that can be generated + * \param max maximum value that can be generated + */ +uint16_t randLIB_get_random_in_range(uint16_t min, uint16_t max) +{ + /* This special case is potentially common, particularly in this routine's + * first user (Trickle), so worth catching immediately */ + if (min == max) { + return min; + } + + /* 16-bit arithmetic below fails in this extreme case; we can optimise it */ + if (max - min == 0xFFFF) { + return randLIB_get_16bit(); + } + + unsigned int values_needed = max + 1 - min; + unsigned int band_size = 0x10000u / values_needed; + unsigned int top_of_bands = band_size * values_needed; + unsigned int result; + do { + result = randLIB_get_16bit(); + } while (result >= top_of_bands); + + return min + (uint16_t)(result / band_size); +} + +/** + * \brief Randomise a base 32-bit number by a jitter factor + * + * The result is linearly distributed in the jitter range, which is expressed + * as fixed-point unsigned 1.15 values. For example, to produce a number in the + * range [0.75 * base, 1.25 * base], set min_factor to 0x6000 and max_factor to + * 0xA000. + * + * Result is clamped to 0xFFFFFFFF if it overflows. + * + * \param base The base 32-bit value + * \param min_factor The minimum value for the random factor + * \param max_factor The maximum value for the random factor + */ +uint32_t randLIB_randomise_base(uint32_t base, uint16_t min_factor, uint16_t max_factor) +{ + uint16_t random_factor = randLIB_get_random_in_range(min_factor, max_factor); + + /* 32x16-bit long multiplication, to get 48-bit result */ + uint32_t hi = (base >> 16) * random_factor; + uint32_t lo = (base & 0xFFFF) * random_factor; + /* Add halves, and take top 32 bits of 48-bit result */ + uint32_t res = hi + (lo >> 16); + + /* Randomisation factor is *2^15, so need to shift up 1 more bit, avoiding overflow */ + if (res & 0x80000000) { + res = 0xFFFFFFFF; + } else { + res = (res << 1) | ((lo >> 15) & 1); + } + + return res; +} diff --git a/features/FEATURE_CLIENT/mbed-client-randlib/mbed-client-randlib/platform/arm_hal_random.h b/features/FEATURE_CLIENT/mbed-client-randlib/mbed-client-randlib/platform/arm_hal_random.h new file mode 100644 index 0000000000..744245c3da --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-randlib/mbed-client-randlib/platform/arm_hal_random.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 ARM_HAL_RANDOM_H_ +#define ARM_HAL_RANDOM_H_ +#ifdef __cplusplus +extern "C" { +#endif +/** + * \brief This function performs Random number driver init. + */ +extern void arm_random_module_init(void); +/** + * \brief Get random library seed value. + */ +extern uint32_t arm_random_seed_get(void); +#ifdef __cplusplus +} +#endif +#endif /* ARM_HAL_RANDOM_H_ */ diff --git a/features/FEATURE_CLIENT/mbed-client-randlib/mbed-client-randlib/randLIB.h b/features/FEATURE_CLIENT/mbed-client-randlib/mbed-client-randlib/randLIB.h new file mode 100644 index 0000000000..665b3deaf0 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-randlib/mbed-client-randlib/randLIB.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2014-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 randLIB.h + * \brief Pseudo Random Library API: + * + * + * \section net-boot Network Bootstrap Control API: + * - randLIB_seed_random(), Set seed for pseudo random + * - randLIB_get_8bit(), Generate 8-bit random number + * - randLIB_get_16bit(),Generate 16-bit random number + * - randLIB_get_32bit(),Generate 32-bit random number + * - randLIB_get_n_bytes_random(), Generate n-bytes random numbers + * + */ + +#ifndef RANDLIB_H_ +#define RANDLIB_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This library is made for getting random numbers for Timing needs in protocols. + * + * **not safe to use for security or cryptographic operations.** + * + */ + + +/** + * \brief Init seed for Pseudo Random. + * + * \return None + * + */ +extern void randLIB_seed_random(void); + +/** + * \brief Generate 8-bit random number. + * + * \param None + * \return 8-bit random number + * + */ +extern uint8_t randLIB_get_8bit(void); + +/** + * \brief Generate 16-bit random number. + * + * \param None + * \return 16-bit random number + * + */ +extern uint16_t randLIB_get_16bit(void); + +/** + * \brief Generate 32-bit random number. + * + * \param None + * \return 16-bit random number + * + */ +extern uint32_t randLIB_get_32bit(void); + +/** + * \brief Generate n-bytes random numbers. + * + * \param data_ptr pointer where random will be stored + * \param eight_bit_boundary how many bytes need random + * \return 0 process valid + * \return -1 Unsupported Parameters + * + */ +extern int8_t randLIB_get_n_bytes_random(uint8_t *data_ptr, uint8_t eight_bit_boundary); + +/** + * \brief Generate a random number within a range. + * + * The result is linearly distributed in the range [min..max], inclusive. + * + * \param min minimum value that can be generated + * \param max maximum value that can be generated + */ +uint16_t randLIB_get_random_in_range(uint16_t min, uint16_t max); + +/** + * \brief Randomise a base 32-bit number by a jitter factor + * + * The result is linearly distributed in the jitter range, which is expressed + * as fixed-point unsigned 1.15 values. For example, to produce a number in the + * range [0.75 * base, 1.25 * base], set min_factor to 0x6000 and max_factor to + * 0xA000. + * + * Result is clamped to 0xFFFFFFFF if it overflows. + * + * \param base The base 32-bit value + * \param min_factor The minimum value for the random factor + * \param max_factor The maximum value for the random factor + */ +uint32_t randLIB_randomise_base(uint32_t base, uint16_t min_factor, uint16_t max_factor); + +#ifdef __cplusplus +} +#endif +#endif /* RANDLIB_H_ */ diff --git a/features/FEATURE_CLIENT/mbed-client-randlib/module.json b/features/FEATURE_CLIENT/mbed-client-randlib/module.json new file mode 100644 index 0000000000..9aa2146560 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-randlib/module.json @@ -0,0 +1,13 @@ +{ + "name": "nanostack-randlib", + "version": "1.1.0", + "description": "Pseudo random library used by mbed-client and 6LoWPAN stack.", + "keywords": [], + "homepage": "https://github.com/ARMmbed/mbed-client-randlib", + "license": "Apache-2.0", + "extraIncludes": [ + "mbed-client-randlib" + ], + "dependencies": {}, + "targetDependencies": {} +} diff --git a/features/FEATURE_CLIENT/mbed-client-randlib/source/randLIB.c b/features/FEATURE_CLIENT/mbed-client-randlib/source/randLIB.c new file mode 100644 index 0000000000..9767a8dae0 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-randlib/source/randLIB.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2014-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "randLIB.h" +#include "platform/arm_hal_random.h" + +#if ((RAND_MAX+1) & RAND_MAX) != 0 +#error "RAND_MAX isn't 2^n-1 :(" +#endif + +/** + * This library is made for getting random numbers for Timing needs in protocols. + * + * **not safe to use for security or cryptographic operations.** + * + */ + + +/** + * \brief Init seed for Pseudo Random. + * + * \return None + * + */ +void randLIB_seed_random(void) +{ + uint32_t rand_seed; + arm_random_module_init(); + rand_seed = arm_random_seed_get(); + srand(rand_seed); +} + +/** + * \brief Generate 8-bit random number. + * + * \param None + * \return 8-bit random number + * + */ +uint8_t randLIB_get_8bit(void) +{ + return rand(); +} + +/** + * \brief Generate 16-bit random number. + * + * \param None + * \return 16-bit random number + * + */ +uint16_t randLIB_get_16bit(void) +{ + uint16_t ret_val; + + ret_val = rand(); +#if RAND_MAX == 0x7FFF + ret_val |= (uint16_t) rand() << 15; +#endif + + return ret_val; +} +/** + * \brief Generate 32-bit random number. + * + * \param None + * \return 32-bit random number + * + */ +uint32_t randLIB_get_32bit(void) +{ + uint32_t ret_val; + + ret_val = rand(); +#if RAND_MAX == 0x7FFF + ret_val |= (uint32_t) rand() << 15; + ret_val |= (uint32_t) rand() << 30; +#elif RAND_MAX == 0x3FFFFFFF /* IAR */ + ret_val |= (uint32_t) rand() << 30; +#elif RAND_MAX == 0x7FFFFFFF + ret_val |= (uint32_t) rand() << 31; +#else +#error "randLIB_get_32bit - odd RAND_MAX" +#endif + + return ret_val; +} + + +/** + * \brief Generate n-bytes random numbers. + * + * \param data_ptr pointer where random will be stored + * \param eight_bit_boundary how many bytes need random + * \return 0 process valid + * \return -1 Unsupported Parameters + * + */ +int8_t randLIB_get_n_bytes_random(uint8_t *data_ptr, uint8_t eight_bit_boundary) +{ + if ((data_ptr == 0) || (eight_bit_boundary == 0)) { + return -1; + } + + while (eight_bit_boundary) { + *data_ptr++ = randLIB_get_8bit(); + eight_bit_boundary--; + } + return 0; +} + +/** + * \brief Generate a random number within a range. + * + * The result is linearly distributed in the range [min..max], inclusive. + * + * \param min minimum value that can be generated + * \param max maximum value that can be generated + */ +uint16_t randLIB_get_random_in_range(uint16_t min, uint16_t max) +{ + /* This special case is potentially common, particularly in this routine's + * first user (Trickle), so worth catching immediately */ + if (min == max) { + return min; + } + + /* 16-bit arithmetic below fails in this extreme case; we can optimise it */ + if (max - min == 0xFFFF) { + return randLIB_get_16bit(); + } + + /* We get RAND_MAX+1 values from rand() in the range [0..RAND_MAX], and + * need to divvy them up into the number of values we need. And reroll any + * odd values off the end as we insist every value having equal chance. + * + * Special handling for systems where RAND_MAX is 0x7FFF; we use our + * randLIB_get_16bit() and have to be a bit more careful about + * unsigned integer overflow. (On other systems rand() returns int, + * so we can't overflow if we use unsigned int). + * + * Eg, range(1,3), RAND_MAX = 0x7FFFFFFF: + * We have 3 bands of size 0x2AAAAAAA (0x80000000/3). + * + * We roll: 0x00000000..0x2AAAAAAA9 -> 1 + * 0x2AAAAAAA..0x555555553 -> 2 + * 0x55555554..0x7FFFFFFFD -> 3 + * 0x7FFFFFFE..0x7FFFFFFFF -> reroll + * + * (Bias problem clearly pretty insignificant there, but gets worse as + * range increases). + */ + unsigned int values_needed = max + 1 - min; +#if RAND_MAX > 0xFFFF + unsigned int band_size = (RAND_MAX + 1u) / values_needed; +#elif UINT_MAX > 0xFFFF + unsigned int band_size = 0x10000u / values_needed; +#else + /* Avoid the need for long division, at the expense of fractionally + * increasing reroll chance. */ + unsigned int band_size = 0xFFFFu / values_needed; +#endif + unsigned int top_of_bands = band_size * values_needed; + unsigned int result; + do { +#if RAND_MAX > 0xFFFF + result = rand(); +#else + result = randLIB_get_16bit(); +#endif + } while (result >= top_of_bands); + + return min + (uint16_t)(result / band_size); +} + +/** + * \brief Randomise a base 32-bit number by a jitter factor + * + * The result is linearly distributed in the jitter range, which is expressed + * as fixed-point unsigned 1.15 values. For example, to produce a number in the + * range [0.75 * base, 1.25 * base], set min_factor to 0x6000 and max_factor to + * 0xA000. + * + * Result is clamped to 0xFFFFFFFF if it overflows. + * + * \param base The base 32-bit value + * \param min_factor The minimum value for the random factor + * \param max_factor The maximum value for the random factor + */ +uint32_t randLIB_randomise_base(uint32_t base, uint16_t min_factor, uint16_t max_factor) +{ + uint16_t random_factor = randLIB_get_random_in_range(min_factor, max_factor); + + /* 32x16-bit long multiplication, to get 48-bit result */ + uint32_t hi = (base >> 16) * random_factor; + uint32_t lo = (base & 0xFFFF) * random_factor; + /* Add halves, and take top 32 bits of 48-bit result */ + uint32_t res = hi + (lo >> 16); + + /* Randomisation factor is *2^15, so need to shift up 1 more bit, avoiding overflow */ + if (res & 0x80000000) { + res = 0xFFFFFFFF; + } else { + res = (res << 1) | ((lo >> 15) & 1); + } + + return res; +} diff --git a/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/MakefileWorker.mk b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/MakefileWorker.mk new file mode 100644 index 0000000000..2096ced036 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/MakefileWorker.mk @@ -0,0 +1,562 @@ +#--------- +# +# MakefileWorker.mk +# +# Include this helper file in your makefile +# It makes +# A static library +# A test executable +# +# See this example for parameter settings +# examples/Makefile +# +#---------- +# Inputs - these variables describe what to build +# +# INCLUDE_DIRS - Directories used to search for include files. +# This generates a -I for each directory +# SRC_DIRS - Directories containing source file to built into the library +# SRC_FILES - Specific source files to build into library. Helpful when not all code +# in a directory can be built for test (hopefully a temporary situation) +# TEST_SRC_DIRS - Directories containing unit test code build into the unit test runner +# These do not go in a library. They are explicitly included in the test runner +# TEST_SRC_FILES - Specific source files to build into the unit test runner +# These do not go in a library. They are explicitly included in the test runner +# MOCKS_SRC_DIRS - Directories containing mock source files to build into the test runner +# These do not go in a library. They are explicitly included in the test runner +#---------- +# You can adjust these variables to influence how to build the test target +# and where to put and name outputs +# See below to determine defaults +# COMPONENT_NAME - the name of the thing being built +# TEST_TARGET - name the test executable. By default it is +# $(COMPONENT_NAME)_tests +# Helpful if you want 1 > make files in the same directory with different +# executables as output. +# CPPUTEST_HOME - where CppUTest home dir found +# TARGET_PLATFORM - Influences how the outputs are generated by modifying the +# CPPUTEST_OBJS_DIR and CPPUTEST_LIB_DIR to use a sub-directory under the +# normal objs and lib directories. Also modifies where to search for the +# CPPUTEST_LIB to link against. +# CPPUTEST_OBJS_DIR - a directory where o and d files go +# CPPUTEST_LIB_DIR - a directory where libs go +# CPPUTEST_ENABLE_DEBUG - build for debug +# CPPUTEST_USE_MEM_LEAK_DETECTION - Links with overridden new and delete +# CPPUTEST_USE_STD_CPP_LIB - Set to N to keep the standard C++ library out +# of the test harness +# CPPUTEST_USE_GCOV - Turn on coverage analysis +# Clean then build with this flag set to Y, then 'make gcov' +# CPPUTEST_MAPFILE - generate a map file +# CPPUTEST_WARNINGFLAGS - overly picky by default +# OTHER_MAKEFILE_TO_INCLUDE - a hook to use this makefile to make +# other targets. Like CSlim, which is part of fitnesse +# CPPUTEST_USE_VPATH - Use Make's VPATH functionality to support user +# specification of source files and directories that aren't below +# the user's Makefile in the directory tree, like: +# SRC_DIRS += ../../lib/foo +# It defaults to N, and shouldn't be necessary except in the above case. +#---------- +# +# Other flags users can initialize to sneak in their settings +# CPPUTEST_CXXFLAGS - flags for the C++ compiler +# CPPUTEST_CPPFLAGS - flags for the C++ AND C preprocessor +# CPPUTEST_CFLAGS - flags for the C complier +# CPPUTEST_LDFLAGS - Linker flags +#---------- + +# Some behavior is weird on some platforms. Need to discover the platform. + +# Platforms +UNAME_OUTPUT = "$(shell uname -a)" +MACOSX_STR = Darwin +MINGW_STR = MINGW +CYGWIN_STR = CYGWIN +LINUX_STR = Linux +SUNOS_STR = SunOS +UNKNWOWN_OS_STR = Unknown + +# Compilers +CC_VERSION_OUTPUT ="$(shell $(CXX) -v 2>&1)" +CLANG_STR = clang +SUNSTUDIO_CXX_STR = SunStudio + +UNAME_OS = $(UNKNWOWN_OS_STR) + +ifeq ($(findstring $(MINGW_STR),$(UNAME_OUTPUT)),$(MINGW_STR)) + UNAME_OS = $(MINGW_STR) +endif + +ifeq ($(findstring $(CYGWIN_STR),$(UNAME_OUTPUT)),$(CYGWIN_STR)) + UNAME_OS = $(CYGWIN_STR) +endif + +ifeq ($(findstring $(LINUX_STR),$(UNAME_OUTPUT)),$(LINUX_STR)) + UNAME_OS = $(LINUX_STR) +endif + +ifeq ($(findstring $(MACOSX_STR),$(UNAME_OUTPUT)),$(MACOSX_STR)) + UNAME_OS = $(MACOSX_STR) +#lion has a problem with the 'v' part of -a + UNAME_OUTPUT = "$(shell uname -pmnrs)" +endif + +ifeq ($(findstring $(SUNOS_STR),$(UNAME_OUTPUT)),$(SUNOS_STR)) + UNAME_OS = $(SUNOS_STR) + + SUNSTUDIO_CXX_ERR_STR = CC -flags +ifeq ($(findstring $(SUNSTUDIO_CXX_ERR_STR),$(CC_VERSION_OUTPUT)),$(SUNSTUDIO_CXX_ERR_STR)) + CC_VERSION_OUTPUT ="$(shell $(CXX) -V 2>&1)" + COMPILER_NAME = $(SUNSTUDIO_CXX_STR) +endif +endif + +ifeq ($(findstring $(CLANG_STR),$(CC_VERSION_OUTPUT)),$(CLANG_STR)) + COMPILER_NAME = $(CLANG_STR) +endif + +#Kludge for mingw, it does not have cc.exe, but gcc.exe will do +ifeq ($(UNAME_OS),$(MINGW_STR)) + CC := gcc +endif + +#And another kludge. Exception handling in gcc 4.6.2 is broken when linking the +# Standard C++ library as a shared library. Unbelievable. +ifeq ($(UNAME_OS),$(MINGW_STR)) + CPPUTEST_LDFLAGS += -static +endif +ifeq ($(UNAME_OS),$(CYGWIN_STR)) + CPPUTEST_LDFLAGS += -static +endif + + +#Kludge for MacOsX gcc compiler on Darwin9 who can't handle pendantic +ifeq ($(UNAME_OS),$(MACOSX_STR)) +ifeq ($(findstring Version 9,$(UNAME_OUTPUT)),Version 9) + CPPUTEST_PEDANTIC_ERRORS = N +endif +endif + +ifndef COMPONENT_NAME + COMPONENT_NAME = name_this_in_the_makefile +endif + +# Debug on by default +ifndef CPPUTEST_ENABLE_DEBUG + CPPUTEST_ENABLE_DEBUG = Y +endif + +# new and delete for memory leak detection on by default +ifndef CPPUTEST_USE_MEM_LEAK_DETECTION + CPPUTEST_USE_MEM_LEAK_DETECTION = Y +endif + +# Use the standard C library +ifndef CPPUTEST_USE_STD_C_LIB + CPPUTEST_USE_STD_C_LIB = Y +endif + +# Use the standard C++ library +ifndef CPPUTEST_USE_STD_CPP_LIB + CPPUTEST_USE_STD_CPP_LIB = Y +endif + +# Use gcov, off by default +ifndef CPPUTEST_USE_GCOV + CPPUTEST_USE_GCOV = N +endif + +ifndef CPPUTEST_PEDANTIC_ERRORS + CPPUTEST_PEDANTIC_ERRORS = Y +endif + +# Default warnings +ifndef CPPUTEST_WARNINGFLAGS + CPPUTEST_WARNINGFLAGS = -Wall -Wextra -Wshadow -Wswitch-default -Wswitch-enum -Wconversion +ifeq ($(CPPUTEST_PEDANTIC_ERRORS), Y) +# CPPUTEST_WARNINGFLAGS += -pedantic-errors + CPPUTEST_WARNINGFLAGS += -pedantic +endif +ifeq ($(UNAME_OS),$(LINUX_STR)) + CPPUTEST_WARNINGFLAGS += -Wsign-conversion +endif + CPPUTEST_CXX_WARNINGFLAGS = -Woverloaded-virtual + CPPUTEST_C_WARNINGFLAGS = -Wstrict-prototypes +endif + +#Wonderful extra compiler warnings with clang +ifeq ($(COMPILER_NAME),$(CLANG_STR)) +# -Wno-disabled-macro-expansion -> Have to disable the macro expansion warning as the operator new overload warns on that. +# -Wno-padded -> I sort-of like this warning but if there is a bool at the end of the class, it seems impossible to remove it! (except by making padding explicit) +# -Wno-global-constructors Wno-exit-time-destructors -> Great warnings, but in CppUTest it is impossible to avoid as the automatic test registration depends on the global ctor and dtor +# -Wno-weak-vtables -> The TEST_GROUP macro declares a class and will automatically inline its methods. Thats ok as they are only in one translation unit. Unfortunately, the warning can't detect that, so it must be disabled. + CPPUTEST_CXX_WARNINGFLAGS += -Weverything -Wno-disabled-macro-expansion -Wno-padded -Wno-global-constructors -Wno-exit-time-destructors -Wno-weak-vtables + CPPUTEST_C_WARNINGFLAGS += -Weverything -Wno-padded +endif + +# Uhm. Maybe put some warning flags for SunStudio here? +ifeq ($(COMPILER_NAME),$(SUNSTUDIO_CXX_STR)) + CPPUTEST_CXX_WARNINGFLAGS = + CPPUTEST_C_WARNINGFLAGS = +endif + +# Default dir for temporary files (d, o) +ifndef CPPUTEST_OBJS_DIR +ifndef TARGET_PLATFORM + CPPUTEST_OBJS_DIR = objs +else + CPPUTEST_OBJS_DIR = objs/$(TARGET_PLATFORM) +endif +endif + +# Default dir for the outout library +ifndef CPPUTEST_LIB_DIR +ifndef TARGET_PLATFORM + CPPUTEST_LIB_DIR = lib +else + CPPUTEST_LIB_DIR = lib/$(TARGET_PLATFORM) +endif +endif + +# No map by default +ifndef CPPUTEST_MAP_FILE + CPPUTEST_MAP_FILE = N +endif + +# No extentions is default +ifndef CPPUTEST_USE_EXTENSIONS + CPPUTEST_USE_EXTENSIONS = N +endif + +# No VPATH is default +ifndef CPPUTEST_USE_VPATH + CPPUTEST_USE_VPATH := N +endif +# Make empty, instead of 'N', for usage in $(if ) conditionals +ifneq ($(CPPUTEST_USE_VPATH), Y) + CPPUTEST_USE_VPATH := +endif + +ifndef TARGET_PLATFORM +#CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_HOME)/lib +CPPUTEST_LIB_LINK_DIR = /usr/lib/x86_64-linux-gnu +else +CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_HOME)/lib/$(TARGET_PLATFORM) +endif + +# -------------------------------------- +# derived flags in the following area +# -------------------------------------- + +# Without the C library, we'll need to disable the C++ library and ... +ifeq ($(CPPUTEST_USE_STD_C_LIB), N) + CPPUTEST_USE_STD_CPP_LIB = N + CPPUTEST_USE_MEM_LEAK_DETECTION = N + CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_C_LIB_DISABLED + CPPUTEST_CPPFLAGS += -nostdinc +endif + +CPPUTEST_CPPFLAGS += -DCPPUTEST_COMPILATION + +ifeq ($(CPPUTEST_USE_MEM_LEAK_DETECTION), N) + CPPUTEST_CPPFLAGS += -DCPPUTEST_MEM_LEAK_DETECTION_DISABLED +else + ifndef CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE + CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE = -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorNewMacros.h + endif + ifndef CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE + CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE = -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorMallocMacros.h + endif +endif + +ifeq ($(CPPUTEST_ENABLE_DEBUG), Y) + CPPUTEST_CXXFLAGS += -g + CPPUTEST_CFLAGS += -g + CPPUTEST_LDFLAGS += -g +endif + +ifeq ($(CPPUTEST_USE_STD_CPP_LIB), N) + CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_CPP_LIB_DISABLED +ifeq ($(CPPUTEST_USE_STD_C_LIB), Y) + CPPUTEST_CXXFLAGS += -nostdinc++ +endif +endif + +ifdef $(GMOCK_HOME) + GTEST_HOME = $(GMOCK_HOME)/gtest + CPPUTEST_CPPFLAGS += -I$(GMOCK_HOME)/include + GMOCK_LIBRARY = $(GMOCK_HOME)/lib/.libs/libgmock.a + LD_LIBRARIES += $(GMOCK_LIBRARY) + CPPUTEST_CPPFLAGS += -DINCLUDE_GTEST_TESTS + CPPUTEST_WARNINGFLAGS = + CPPUTEST_CPPFLAGS += -I$(GTEST_HOME)/include -I$(GTEST_HOME) + GTEST_LIBRARY = $(GTEST_HOME)/lib/.libs/libgtest.a + LD_LIBRARIES += $(GTEST_LIBRARY) +endif + + +ifeq ($(CPPUTEST_USE_GCOV), Y) + CPPUTEST_CXXFLAGS += -fprofile-arcs -ftest-coverage + CPPUTEST_CFLAGS += -fprofile-arcs -ftest-coverage +endif + +CPPUTEST_CXXFLAGS += $(CPPUTEST_WARNINGFLAGS) $(CPPUTEST_CXX_WARNINGFLAGS) +CPPUTEST_CPPFLAGS += $(CPPUTEST_WARNINGFLAGS) +CPPUTEST_CXXFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE) +CPPUTEST_CPPFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE) +CPPUTEST_CFLAGS += $(CPPUTEST_C_WARNINGFLAGS) + +TARGET_MAP = $(COMPONENT_NAME).map.txt +ifeq ($(CPPUTEST_MAP_FILE), Y) + CPPUTEST_LDFLAGS += -Wl,-map,$(TARGET_MAP) +endif + +# Link with CppUTest lib +CPPUTEST_LIB = $(CPPUTEST_LIB_LINK_DIR)/libCppUTest.a + +ifeq ($(CPPUTEST_USE_EXTENSIONS), Y) +CPPUTEST_LIB += $(CPPUTEST_LIB_LINK_DIR)/libCppUTestExt.a +endif + +ifdef CPPUTEST_STATIC_REALTIME + LD_LIBRARIES += -lrt +endif + +TARGET_LIB = \ + $(CPPUTEST_LIB_DIR)/lib$(COMPONENT_NAME).a + +ifndef TEST_TARGET + ifndef TARGET_PLATFORM + TEST_TARGET = $(COMPONENT_NAME)_tests + else + TEST_TARGET = $(COMPONENT_NAME)_$(TARGET_PLATFORM)_tests + endif +endif + +#Helper Functions +get_src_from_dir = $(wildcard $1/*.cpp) $(wildcard $1/*.cc) $(wildcard $1/*.c) +get_dirs_from_dirspec = $(wildcard $1) +get_src_from_dir_list = $(foreach dir, $1, $(call get_src_from_dir,$(dir))) +__src_to = $(subst .c,$1, $(subst .cc,$1, $(subst .cpp,$1,$(if $(CPPUTEST_USE_VPATH),$(notdir $2),$2)))) +src_to = $(addprefix $(CPPUTEST_OBJS_DIR)/,$(call __src_to,$1,$2)) +src_to_o = $(call src_to,.o,$1) +src_to_d = $(call src_to,.d,$1) +src_to_gcda = $(call src_to,.gcda,$1) +src_to_gcno = $(call src_to,.gcno,$1) +time = $(shell date +%s) +delta_t = $(eval minus, $1, $2) +debug_print_list = $(foreach word,$1,echo " $(word)";) echo; + +#Derived +STUFF_TO_CLEAN += $(TEST_TARGET) $(TEST_TARGET).exe $(TARGET_LIB) $(TARGET_MAP) + +SRC += $(call get_src_from_dir_list, $(SRC_DIRS)) $(SRC_FILES) +OBJ = $(call src_to_o,$(SRC)) + +STUFF_TO_CLEAN += $(OBJ) + +TEST_SRC += $(call get_src_from_dir_list, $(TEST_SRC_DIRS)) $(TEST_SRC_FILES) +TEST_OBJS = $(call src_to_o,$(TEST_SRC)) +STUFF_TO_CLEAN += $(TEST_OBJS) + + +MOCKS_SRC += $(call get_src_from_dir_list, $(MOCKS_SRC_DIRS)) +MOCKS_OBJS = $(call src_to_o,$(MOCKS_SRC)) +STUFF_TO_CLEAN += $(MOCKS_OBJS) + +ALL_SRC = $(SRC) $(TEST_SRC) $(MOCKS_SRC) + +# If we're using VPATH +ifeq ($(CPPUTEST_USE_VPATH), Y) +# gather all the source directories and add them + VPATH += $(sort $(dir $(ALL_SRC))) +# Add the component name to the objs dir path, to differentiate between same-name objects + CPPUTEST_OBJS_DIR := $(addsuffix /$(COMPONENT_NAME),$(CPPUTEST_OBJS_DIR)) +endif + +#Test coverage with gcov +GCOV_OUTPUT = gcov_output.txt +GCOV_REPORT = gcov_report.txt +GCOV_ERROR = gcov_error.txt +GCOV_GCDA_FILES = $(call src_to_gcda, $(ALL_SRC)) +GCOV_GCNO_FILES = $(call src_to_gcno, $(ALL_SRC)) +TEST_OUTPUT = $(TEST_TARGET).txt +STUFF_TO_CLEAN += \ + $(GCOV_OUTPUT)\ + $(GCOV_REPORT)\ + $(GCOV_REPORT).html\ + $(GCOV_ERROR)\ + $(GCOV_GCDA_FILES)\ + $(GCOV_GCNO_FILES)\ + $(TEST_OUTPUT) + +#The gcda files for gcov need to be deleted before each run +#To avoid annoying messages. +GCOV_CLEAN = $(SILENCE)rm -f $(GCOV_GCDA_FILES) $(GCOV_OUTPUT) $(GCOV_REPORT) $(GCOV_ERROR) +RUN_TEST_TARGET = $(SILENCE) $(GCOV_CLEAN) ; echo "Running $(TEST_TARGET)"; ./$(TEST_TARGET) $(CPPUTEST_EXE_FLAGS) -ojunit + +ifeq ($(CPPUTEST_USE_GCOV), Y) + + ifeq ($(COMPILER_NAME),$(CLANG_STR)) + LD_LIBRARIES += --coverage + else + LD_LIBRARIES += -lgcov + endif +endif + + +INCLUDES_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(INCLUDE_DIRS)) +INCLUDES += $(foreach dir, $(INCLUDES_DIRS_EXPANDED), -I$(dir)) +MOCK_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(MOCKS_SRC_DIRS)) +INCLUDES += $(foreach dir, $(MOCK_DIRS_EXPANDED), -I$(dir)) + +CPPUTEST_CPPFLAGS += $(INCLUDES) $(CPPUTESTFLAGS) + +DEP_FILES = $(call src_to_d, $(ALL_SRC)) +STUFF_TO_CLEAN += $(DEP_FILES) $(PRODUCTION_CODE_START) $(PRODUCTION_CODE_END) +STUFF_TO_CLEAN += $(STDLIB_CODE_START) $(MAP_FILE) cpputest_*.xml junit_run_output + +# We'll use the CPPUTEST_CFLAGS etc so that you can override AND add to the CppUTest flags +CFLAGS = $(CPPUTEST_CFLAGS) $(CPPUTEST_ADDITIONAL_CFLAGS) +CPPFLAGS = $(CPPUTEST_CPPFLAGS) $(CPPUTEST_ADDITIONAL_CPPFLAGS) +CXXFLAGS = $(CPPUTEST_CXXFLAGS) $(CPPUTEST_ADDITIONAL_CXXFLAGS) +LDFLAGS = $(CPPUTEST_LDFLAGS) $(CPPUTEST_ADDITIONAL_LDFLAGS) + +# Don't consider creating the archive a warning condition that does STDERR output +ARFLAGS := $(ARFLAGS)c + +DEP_FLAGS=-MMD -MP + +# Some macros for programs to be overridden. For some reason, these are not in Make defaults +RANLIB = ranlib + +# Targets + +.PHONY: all +all: start $(TEST_TARGET) + $(RUN_TEST_TARGET) + +.PHONY: start +start: $(TEST_TARGET) + $(SILENCE)START_TIME=$(call time) + +.PHONY: all_no_tests +all_no_tests: $(TEST_TARGET) + +.PHONY: flags +flags: + @echo + @echo "OS ${UNAME_OS}" + @echo "Compile C and C++ source with CPPFLAGS:" + @$(call debug_print_list,$(CPPFLAGS)) + @echo "Compile C++ source with CXXFLAGS:" + @$(call debug_print_list,$(CXXFLAGS)) + @echo "Compile C source with CFLAGS:" + @$(call debug_print_list,$(CFLAGS)) + @echo "Link with LDFLAGS:" + @$(call debug_print_list,$(LDFLAGS)) + @echo "Link with LD_LIBRARIES:" + @$(call debug_print_list,$(LD_LIBRARIES)) + @echo "Create libraries with ARFLAGS:" + @$(call debug_print_list,$(ARFLAGS)) + +TEST_DEPS = $(TEST_OBJS) $(MOCKS_OBJS) $(PRODUCTION_CODE_START) $(TARGET_LIB) $(USER_LIBS) $(PRODUCTION_CODE_END) $(CPPUTEST_LIB) $(STDLIB_CODE_START) +test-deps: $(TEST_DEPS) + +$(TEST_TARGET): $(TEST_DEPS) + @echo Linking $@ + $(SILENCE)$(CXX) -o $@ $^ $(LD_LIBRARIES) $(LDFLAGS) + +$(TARGET_LIB): $(OBJ) + @echo Building archive $@ + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(AR) $(ARFLAGS) $@ $^ + $(SILENCE)$(RANLIB) $@ + +test: $(TEST_TARGET) + $(RUN_TEST_TARGET) | tee $(TEST_OUTPUT) + +vtest: $(TEST_TARGET) + $(RUN_TEST_TARGET) -v | tee $(TEST_OUTPUT) + +$(CPPUTEST_OBJS_DIR)/%.o: %.cc + @echo compiling $(notdir $<) + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $< + +$(CPPUTEST_OBJS_DIR)/%.o: %.cpp + @echo compiling $(notdir $<) + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $< + +$(CPPUTEST_OBJS_DIR)/%.o: %.c + @echo compiling $(notdir $<) + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(COMPILE.c) $(DEP_FLAGS) $(OUTPUT_OPTION) $< + +ifneq "$(MAKECMDGOALS)" "clean" +-include $(DEP_FILES) +endif + +.PHONY: clean +clean: + @echo Making clean + $(SILENCE)$(RM) $(STUFF_TO_CLEAN) + $(SILENCE)rm -rf gcov objs #$(CPPUTEST_OBJS_DIR) + $(SILENCE)rm -rf $(CPPUTEST_LIB_DIR) + $(SILENCE)find . -name "*.gcno" | xargs rm -f + $(SILENCE)find . -name "*.gcda" | xargs rm -f + +#realclean gets rid of all gcov, o and d files in the directory tree +#not just the ones made by this makefile +.PHONY: realclean +realclean: clean + $(SILENCE)rm -rf gcov + $(SILENCE)find . -name "*.gdcno" | xargs rm -f + $(SILENCE)find . -name "*.[do]" | xargs rm -f + +gcov: test +ifeq ($(CPPUTEST_USE_VPATH), Y) + $(SILENCE)gcov --object-directory $(CPPUTEST_OBJS_DIR) $(SRC) >> $(GCOV_OUTPUT) 2>> $(GCOV_ERROR) +else + $(SILENCE)for d in $(SRC_DIRS) ; do \ + gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$d $$d/*.c $$d/*.cpp >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \ + done + $(SILENCE)for f in $(SRC_FILES) ; do \ + gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$f $$f >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \ + done +endif +# $(CPPUTEST_HOME)/scripts/filterGcov.sh $(GCOV_OUTPUT) $(GCOV_ERROR) $(GCOV_REPORT) $(TEST_OUTPUT) + /usr/share/cpputest/scripts/filterGcov.sh $(GCOV_OUTPUT) $(GCOV_ERROR) $(GCOV_REPORT) $(TEST_OUTPUT) + $(SILENCE)cat $(GCOV_REPORT) + $(SILENCE)mkdir -p gcov + $(SILENCE)mv *.gcov gcov + $(SILENCE)mv gcov_* gcov + @echo "See gcov directory for details" + +.PHONEY: format +format: + $(CPPUTEST_HOME)/scripts/reformat.sh $(PROJECT_HOME_DIR) + +.PHONEY: debug +debug: + @echo + @echo "Target Source files:" + @$(call debug_print_list,$(SRC)) + @echo "Target Object files:" + @$(call debug_print_list,$(OBJ)) + @echo "Test Source files:" + @$(call debug_print_list,$(TEST_SRC)) + @echo "Test Object files:" + @$(call debug_print_list,$(TEST_OBJS)) + @echo "Mock Source files:" + @$(call debug_print_list,$(MOCKS_SRC)) + @echo "Mock Object files:" + @$(call debug_print_list,$(MOCKS_OBJS)) + @echo "All Input Dependency files:" + @$(call debug_print_list,$(DEP_FILES)) + @echo Stuff to clean: + @$(call debug_print_list,$(STUFF_TO_CLEAN)) + @echo Includes: + @$(call debug_print_list,$(INCLUDES)) + +-include $(OTHER_MAKEFILE_TO_INCLUDE) diff --git a/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/makefile_defines.txt b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/makefile_defines.txt new file mode 100644 index 0000000000..18691ee543 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/makefile_defines.txt @@ -0,0 +1,18 @@ +#--- Inputs ----# +CPPUTEST_HOME = /usr +CPPUTEST_USE_EXTENSIONS = Y +CPPUTEST_USE_VPATH = Y +CPPUTEST_USE_GCOV = Y +CPP_PLATFORM = gcc +INCLUDE_DIRS =\ + .\ + ../common\ + ../stubs\ + ../../../..\ + ../../../../source\ + ../../../../mbed-client-randlib\ + /usr/include\ + $(CPPUTEST_HOME)/include\ + +CPPUTESTFLAGS = -D__thumb2__ -w +CPPUTEST_CFLAGS += -std=gnu99 diff --git a/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/main.cpp b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/main.cpp new file mode 100644 index 0000000000..d76b2f9173 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/main.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ + +#include "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP(randLIB); + diff --git a/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/randlibtest.cpp b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/randlibtest.cpp new file mode 100644 index 0000000000..79d2159684 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/randlibtest.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016 ARM. All rights reserved. + */ +#include "CppUTest/TestHarness.h" +#include "test_randlib.h" + +TEST_GROUP(randLIB) +{ + void setup() + { + } + + void teardown() + { + } +}; + +TEST(randLIB, test_randLIB_seed_random) +{ + CHECK(test_randLIB_seed_random()); +} + +TEST(randLIB, test_randLIB_get_8bit) +{ + CHECK(test_randLIB_get_8bit()); +} + +TEST(randLIB, test_randLIB_get_16bit) +{ + CHECK(test_randLIB_get_16bit()); +} + +TEST(randLIB, test_randLIB_get_32bit) +{ + CHECK(test_randLIB_get_32bit()); +} + +TEST(randLIB, test_randLIB_get_n_bytes_random) +{ + CHECK(test_randLIB_get_n_bytes_random()); +} + +TEST(randLIB, test_randLIB_get_random_in_range) +{ + CHECK(test_randLIB_get_random_in_range()); +} + +TEST(randLIB, test_randLIB_randomise_base) +{ + CHECK(test_randLIB_randomise_base()); +} diff --git a/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/test_randlib.c b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/test_randlib.c new file mode 100644 index 0000000000..a8187d8262 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/test_randlib.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2016 ARM. All rights reserved. + */ +#include "test_randlib.h" +#include +#include +#include "randLIB.h" + +bool test_randLIB_seed_random() +{ + randLIB_seed_random(); + return true; +} + +bool test_randLIB_get_8bit() +{ + randLIB_seed_random(); + uint8_t test = randLIB_get_8bit(); + if( test == 0 ) { + test = randLIB_get_8bit(); + if( test == 0 ) { + return false; + } + } + return true; +} + +bool test_randLIB_get_16bit() +{ + randLIB_seed_random(); + uint16_t test = randLIB_get_16bit(); + if( test == 0 ) { + test = randLIB_get_16bit(); + if( test == 0 ) { + return false; + } + } + return true; +} + +bool test_randLIB_get_32bit() +{ + randLIB_seed_random(); + uint32_t test = randLIB_get_32bit(); + if( test == 0 ) { + test = randLIB_get_32bit(); + if( test == 0 ) { + return false; + } + } + return true; +} + +bool test_randLIB_get_n_bytes_random() +{ + int8_t ret = randLIB_get_n_bytes_random(NULL, 0); + if( ret != -1){ + return false; + } + + uint8_t dat[5]; + ret = randLIB_get_n_bytes_random(&dat, 5); + if( ret != 0){ + return false; + } + return true; +} + +bool test_randLIB_get_random_in_range() +{ + uint16_t ret = randLIB_get_random_in_range(2, 2); + if( ret != 2 ){ + return false; + } + + ret = randLIB_get_random_in_range(2, 3); + if( ret != 2 && ret != 3){ + return false; + } + + ret = randLIB_get_random_in_range(0, 0xFFFF); + + return true; +} + +bool test_randLIB_randomise_base() +{ + uint32_t ret = randLIB_randomise_base(0,0,0); + if( ret ){ + return false; + } + ret = randLIB_randomise_base(0xffff0000,0x8888,0x8888); + if( ret != 0xffffffff ){ + return false; + } + return true; +} diff --git a/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/test_randlib.h b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/test_randlib.h new file mode 100644 index 0000000000..f83d7d60fe --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/test_randlib.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016 ARM. All rights reserved. + */ +#ifndef TEST_RANDLIB_H +#define TEST_RANDLIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +bool test_randLIB_seed_random(); + +bool test_randLIB_get_8bit(); + +bool test_randLIB_get_16bit(); + +bool test_randLIB_get_32bit(); + +bool test_randLIB_get_n_bytes_random(); + +bool test_randLIB_get_random_in_range(); + +bool test_randLIB_randomise_base(); + + +#ifdef __cplusplus +} +#endif + +#endif // TEST_RANDLIB_H + diff --git a/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib_linux/main.cpp b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib_linux/main.cpp new file mode 100644 index 0000000000..25a4c3b6d0 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib_linux/main.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ + +#include "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP(randLIB_linux); diff --git a/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib_linux/randlibtest.cpp b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib_linux/randlibtest.cpp new file mode 100644 index 0000000000..b0a1399257 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib_linux/randlibtest.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016 ARM. All rights reserved. + */ +#include "CppUTest/TestHarness.h" +#include "../randlib/test_randlib.h" +#include "randLIB.h" + +TEST_GROUP(randLIB_linux) +{ + void setup() + { + } + + void teardown() + { + } +}; + +extern bool allow_open; + +TEST(randLIB_linux, test_randLIB_seed_random) +{ + allow_open = true; + CHECK(test_randLIB_seed_random()); +} + +TEST(randLIB_linux, test_randLIB_get_8bit) +{ + allow_open = true; + CHECK(test_randLIB_get_8bit()); +} + +TEST(randLIB_linux, test_randLIB_get_16bit) +{ + allow_open = true; + CHECK(test_randLIB_get_16bit()); +} + +TEST(randLIB_linux, test_randLIB_get_32bit) +{ + allow_open = true; + CHECK(test_randLIB_get_32bit()); +} + +TEST(randLIB_linux, test_randLIB_get_n_bytes_random) +{ + allow_open = true; + CHECK(test_randLIB_get_n_bytes_random()); +} + +TEST(randLIB_linux, test_randLIB_get_random_in_range) +{ + allow_open = true; + CHECK(test_randLIB_get_random_in_range()); +} + +TEST(randLIB_linux, test_randLIB_randomise_base) +{ + allow_open = true; + CHECK(test_randLIB_randomise_base()); +} + +TEST(randLIB_linux, test_fail_to_open) +{ + uint8_t buf[4]; + allow_open = false; + CHECK(-1 == randLIB_get_n_bytes_random(buf, 4)); + allow_open = true; +} diff --git a/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/run_tests b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/run_tests new file mode 100755 index 0000000000..87f2f504e6 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/run_tests @@ -0,0 +1,43 @@ +#!/bin/bash +echo +echo Build mbed client randlib unit tests +echo + +# Remember to add new test folder to Makefile +make clean +make all + +echo +echo Create results +echo +mkdir results + +find ./ -name '*.xml' | xargs cp -t ./results/ + +echo +echo Create coverage document +echo +mkdir coverages +cd coverages + +#copy the .gcda & .gcno for all test projects (no need to modify +#cp ../../../source/*.gc* . +#find ../ -name '*.gcda' | xargs cp -t . +#find ../ -name '*.gcno' | xargs cp -t . +#find . -name "test*" -type f -delete +#find . -name "*test*" -type f -delete +#find . -name "*stub*" -type f -delete +#rm -rf main.* + +lcov -q -d ../. -c -o app.info +lcov -q -r app.info "/test*" -o app.info +lcov -q -r app.info "/usr*" -o app.info +genhtml --no-branch-coverage app.info +cd .. +echo +echo +echo +echo Have a nice bug hunt! +echo +echo +echo diff --git a/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/stubs/open_stub.c b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/stubs/open_stub.c new file mode 100644 index 0000000000..588c12096e --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/stubs/open_stub.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include + +bool allow_open = true; +int __real_open(const char *path, int flags, ...); +int __wrap_open(const char *path, int flags, ...) +{ + if (allow_open) { + if (flags & O_CREAT) { + va_list vl; + va_start(vl,flags); + mode_t mode = va_arg(vl, mode_t); + va_end(vl); + return __real_open(path, flags, mode); + } else { + return __real_open(path, flags); + } + } else { + return -1; + } +} diff --git a/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/stubs/random_stub.c b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/stubs/random_stub.c new file mode 100644 index 0000000000..773bb07d69 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client-randlib/test/mbed-client-randlib/unittest/stubs/random_stub.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2016, ARM Limited, All Rights Reserved + */ +#include "inttypes.h" + + +void arm_random_module_init(void) +{ + +} + +uint32_t arm_random_seed_get(void) +{ + return 4; +} diff --git a/features/FEATURE_CLIENT/mbed-client/.gitignore b/features/FEATURE_CLIENT/mbed-client/.gitignore new file mode 100644 index 0000000000..28ffc72a67 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/.gitignore @@ -0,0 +1,36 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +yotta_modules +yotta_targets +build +lcov/* +output/* +.yotta.json diff --git a/features/FEATURE_CLIENT/mbed-client/.mbedignore b/features/FEATURE_CLIENT/mbed-client/.mbedignore new file mode 100644 index 0000000000..402ef168e6 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/.mbedignore @@ -0,0 +1,4 @@ +config/* +docs/* +doxygen/* +test/* diff --git a/features/FEATURE_CLIENT/mbed-client/.yotta_ignore b/features/FEATURE_CLIENT/mbed-client/.yotta_ignore new file mode 100644 index 0000000000..d31dc1e1ab --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/.yotta_ignore @@ -0,0 +1,7 @@ +# files for linux builds + +# ignore linux test application +test/lwm2mtestapplication/* +test/lwm2m/* +coverage/* +results/* diff --git a/features/FEATURE_CLIENT/mbed-client/DOXYGEN_FRONTPAGE.md b/features/FEATURE_CLIENT/mbed-client/DOXYGEN_FRONTPAGE.md new file mode 100644 index 0000000000..05715d80e5 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/DOXYGEN_FRONTPAGE.md @@ -0,0 +1,11 @@ +ARM mbed Client +================ + +## Introduction +This is the Doxygen generated documentation of mbed Client. +It should be used in conjunction with the [mbed Client Guide](https://docs.mbed.com/docs/mbed-client-guide/en/latest/) +hosted in http://docs.mbed.com. + +# API documentation + +See [Files](files.html) section to find a documentation about specific API. diff --git a/features/FEATURE_CLIENT/mbed-client/LICENSE b/features/FEATURE_CLIENT/mbed-client/LICENSE new file mode 100644 index 0000000000..e06d208186 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/LICENSE @@ -0,0 +1,202 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/features/FEATURE_CLIENT/mbed-client/README.md b/features/FEATURE_CLIENT/mbed-client/README.md new file mode 100644 index 0000000000..56a2bfbf89 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/README.md @@ -0,0 +1,7 @@ +ARM mbed Client +======================= + +This repository contains ARM mbed Client: a library that connects devices to mbed Device Connector Service, mbed Device Server (mDS) and to mbed-enabled cloud services from our partners. + +The documentation is collected under the docs directory and the **mbed Client Guide** is also hosted [here](https://docs.mbed.com/docs/mbed-client-guide/en/latest/). + diff --git a/features/FEATURE_CLIENT/mbed-client/config/linux.mk b/features/FEATURE_CLIENT/mbed-client/config/linux.mk new file mode 100644 index 0000000000..100037bd88 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/config/linux.mk @@ -0,0 +1,2 @@ +FLAGS += \ + TARGET_LIKE_LINUX diff --git a/features/FEATURE_CLIENT/mbed-client/docs/Howto.md b/features/FEATURE_CLIENT/mbed-client/docs/Howto.md new file mode 100644 index 0000000000..9b61c33e3f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/docs/Howto.md @@ -0,0 +1,417 @@ +# How to use the mbed Client API + +This section explains how to use our C++ API to create and configure different types of Objects, Object Instances and Resources for mbed Client to comply with the OMA LWM2M specifications. These resources can then be communicated to mbed Device Server. + +**Note:** The API complies with the OMA LWM2M specifications. + +As per the OMA LWM2M specification: + +- The client must have defined Objects, under which it can create Object Instances. +- The client must have created Object Instances under Objects, which will eventually contain Resources. +- The client must have Resources under Object Instances which belong to Objects. +- The client must have created Resources under Object Instance. You can create M2MResource from the M2MObjectInstance class. +- The client must have created Resource Instances under Resources. You can create M2MResourceInstance from the M2MObjectInstance class. + + +## How to create and configure Objects + +With this API, you can create and configure the following Objects: + +- [Device Objects](#device-object) +- [Security Objects](#security-object) +- [Custom Objects](#custom-object) + +The M2MObject class is derived from the M2MBase class, so all the public methods can be used from the M2MObject and its derived classes. + +### Creating OMA-defined Objects + +#### Device Object + +To create a Device Object: + +`static M2MDevice *create_device();` + +Because there can be only one instance of M2MDevice, it is a static class and you can delete it as follows: + +`M2MDevice::delete_instance();` + +Check the [M2MDevice class documentation](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/classM2MDevice.html) to see how to configure the Device Object. + +#### Security Object + +To create a Security Object: + +`static M2MSecurity *create_security(M2MSecurity::ServerType server_type);` + +You can create a Bootstrap or normal mbed Device Server by passing the appropriate `enum` value. + +Check the [M2MSecurity class documentation](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/classM2MSecurity.html) to see how to configure the Security Object, as well as how to create appropriate Resources and assign values to them. + +#### Custom Object + +For a Custom Object, you need to pass the name of the Object that you would like to create (for example `Test`); this will create an Object with that name in mbed Device Server. + +To create an M2MObject: + +`static M2MObject *create_object(const String &name);` + +#### Configuring the Object + +Once you have created an Object (whether OMA-specific or custom), you can configure various parameters in it to control or modify communication with mbed Device Server. + +``` +M2MObject * _object = M2MInterfaceFactory::create_object("Test"); + if(_object) { + _object->set_register_uri(true); // The registration message explicitly sends this object path as registered resource such as /Test. + } +``` + +Here, we discuss a few of the most important parameters, which you must configure properly to work with the Objects. + +##### Setting Operation Mode + +To set the operation mode of the Objects so that they can handle `GET`, `PUT`, `POST`, `DELETE` or a combination of these requests coming from mbed Device Server: + +``` +virtual void set_operation(M2MBase::Operation operation); +_object->set_operation(M2MBase::GET_PUT_POST_ALLOWED); // This defines the REST operations that can be performed on this object. +``` + +##### Setting Observable Mode + +To set the Object to be an observing resource: + +`virtual void set_observable(bool observable);` + +By default, all the created objects are non-observable. You can set them to be observable or not observable using this API. + +``` +_object->set_observable(true); // The object can be observed from server. +_object->set_observable(false); // The object cannot be observed from server. +``` + +##### Setting CoAP content type + +Currently, the only available content type is the OMA TLV type. The OMA TLV type works only for Objects with a numeric value. For example, if you are creating a custom Object it must be of a numeric type such as `100`. + +`M2MObject * _object = M2MInterfaceFactory::create_object("100");` + +By default, all the numeric objects are assigned the CoAP content type of `99` by mbed Client but if you want your Object to assign any other CoAP content type, for example 120, you can do that by setting the object's CoAP content type as shown below: + +``` +virtual void set_coap_content_type(const uint8_t content_type); +_object->set_coap_content_type(120); +``` + +**Tip:** In future releases, we will introduce support for the JSON content types. + +## How to create and configure Object Instances + +With this API, you can create and configure the following Object Instances: + +- [Device Object Instance](#device-object-instance) +- [Security Object Instance](#security-object-instance) +- [Custom Object Instance](#custom-object-instance) + +The `M2MObjectInstance` class is derived from the `M2MBase` class, so all the public methods from `M2MObjectInstance` and its derived classes can be used. + +### Creating an OMA-defined Object Instance + +#### Device Object Instance + +Because there can only be one instance for the Device Object, the Object Instance is automatically created when creating an M2MDevice Object. + +#### Security Object Instance + +Because there can only be one instance for the Security Object, the Object Instance is automatically created when creating an M2MDevice Object based on a selected server type. + +#### Custom Object Instances + +Object Instances need IDs. Normally, the IDs start from '0' and increment, +so the Object Instance structure on the mbed Device Server side would look like this: + +`Object/Object Instance ID` + +When you create an Object Instance, you therefore need to pass the ID that you would like to create. For example, if you pass `0`, you get an object `/Test/0` on mbed Device Server. + +To create an M2M Object Instance: + +`M2MObject::create_object_instance(uint16_t instance_id);` + +You can pass an Object Instance ID to create appropriate Object Instances. Normally, Object Instances will start from `0` and increment. So the Object Instance structure on the mbed Device Server side would look like this: + +`Object/Object Instance ID` + +``` +M2MObjectInstance * object_instance = _object->create_object_instance(0); + if(object_instance) { + object_instance->set_register_uri(true); // The registration message explicitly sends this object instance path as registered resource such as /Test/0. + } +``` + +### Configuring the Object Instance + +When you have created an Object Instance (whether OMA-specific or custom), you can configure various parameters in it to control or modify communication with mbed Device Server. + +Here, we present a few of the most important parameters that you must configure properly to work with the object instances. + +##### Setting Operation Mode + +To set the operation mode of the Objects so that they can handle `GET`, `PUT`, `POST`, `DELETE` or a combination of these requests coming from mbed Device Server: + +``` +virtual void set_operation(M2MBase::Operation operation); +object_instance->set_operation(M2MBase::GET_PUT_POST_ALLOWED); // This defines the REST operations that can be performed on this object instance. +``` + +##### Setting Observable Mode + +To set the Object Instance to be an observing resource: + +`virtual void set_observable(bool observable);` + +By default, all the created Object Instances are non-observable. You can set them to be observable or not observable using this API. + +``` +_object_instance->set_observable(true); // This defines that the Object Instance can be observed from server. +_object_instance->set_observable(false); // This defines that the Object Instance cannot be observed from server. +``` + +##### Setting CoAP content type + +Currently, the only available content type is the OMA TLV type. The OMA TLV type works only for Objects and Object Instances with a numeric value. For example, if you are creating a custom Object and Object Instances it must be of a numeric type such as `100`. + +``` +M2MObject * _object = M2MInterfaceFactory::create_object("100"); +M2MObjectInstance * object_instance = _object->create_object_instance(0); +``` + +By default, all numeric objects are assigned the CoAP content type of `99` by mbed Client but if you want your Object Instance to assign any other CoAP content type, for example 120, you can do that by setting the object's CoAP content type as follows: + +``` +virtual void set_coap_content_type(const uint8_t content_type); +object_instance->set_coap_content_type(120); +``` + +**Tip:** In future version, we will introduce support for the JSON content types. + +There are additional APIs that provide getter and remove functions for Object Instances in the `M2MObjectInstance` class; [check the API documentation](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/classM2MObjectInstance.html) for their usage. + +## How to create and configure Resources and Resource Instances + +With this API, you can create and configure the following Resources and Resource Instances: + +- [Device Object Resources](#device-object-resources) +- [Security Object Resources](#security-object-resources) +- [Custom Resources](#custom-resources) + + +The `M2MResource` class is derived from the `M2MResourceInstance`, which in turn is derived from the `M2MBase` class, so all the public methods can be used from `M2MResource` or `M2MResourceInstance` and their derived classes. + +### Creating OMA-defined Resources + +#### Device Object Resources + +There are direct APIs to create and set values for the Device Resources. You can create the required Resource and set values based on their data types. + +- For Resources that take string values: + +`M2MResource* create_resource(DeviceResource resource, const String &value);` + +- For Resources that take integer values: + +`M2MResource* create_resource(DeviceResource resource, uint32_t value);` + +- There are a few Resources that can have multiple instances. To create these Resources: + +`M2MResourceInstance* create_resource_instance(DeviceResource resource, uint32_t value,uint16_t instance_id);` + +Where `instance_id` is the Resource Instance ID, for example `/3/0/11/0`. + +Check the [M2MDevice API documentation](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/classM2MDevice.html) to find which enums are supported for `integer` or `string` value types. + +There are other APIs in the `M2MDevice` class that you can use to set, remove and modify new values for the resources. + +#### Security Object Resources + +_Mandatory Resources_ + +Most of the mandatory Resources are created automatically when you create an M2MSecurity Object. You can set their values based on their data types. + +Resources that are automatically created and their accepted data types: + +- `SecurityMode` +- `ShortServerID` +- `M2MServerUri` +- `BootstrapServer` +- `PublicKey` +- `ServerPublicKey` +- `Secretkey` + +For Resources (`SecurityMode`, `ShortServerID`) that take integer values, you can set the values as follows: + +`bool set_resource_value(SecurityResource resource,uint32_t value);` + +``` +security_object->set_resource_value(M2MSecurity::SecurityMode, 1); +security_object->set_resource_value(M2MSecurity::ShortServerID, 1); +``` + +For Resources (`M2MServerUri`) that take string values, you can set the values as follows: + +`bool set_resource_value(SecurityResource resource,const String &value);` + +``` +security_object->set_resource_value(M2MSecurity::M2MServerUri, "coap://api.connector.mbed.com:5684"); +``` + +For Resources (`PublicKey`, `ServerPublicKey`, `Secretkey`) that take binary values, you can set the values as follows: + +`bool set_resource_value(SecurityResource resource,onst uint8_t *value,const uint16_t length);` + +``` +uint8_t key[] = {"key"}; +security_object->set_resource_value(M2MSecurity::PublicKey, key, sizeof(key)); +``` + +_Optional Resources_ + +Optional Resources as defined in the Security Object: + +- `SMSSecurityMode` +- `M2MServerSMSNumber` +- `ClientHoldOffTime` + +To create and set values for the optional Resources that take an integer value: + +`M2MResource* create_resource(SecurityResource resource, uint32_t value);` + +`security_object->create_resource(M2MSecurity::M2MServerSMSNumber, 123542323);` + + +Check the [M2MSecurity API documentation](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/classM2MSecurity.html) to find which enums are supported for `integer`, `string` or `uint8_t*` value types. + +There are more APIs in the `M2MSecurity` class that you can use to set, remove and modify Resource values. + +#### Custom Resources + +For Custom Objects, you can create Resources of two types: + +- **M2MResource**: a resource with a single instance, for example `/Test/0/Resource`. + +- **M2MResourceInstance**: a resource with multiple instances, for example `/Test/0/Resource/0`, `/Test/0/Resource/1`. + +For each of these types, the Resource and Resource Instances can be either static or dynamic: + +- **Static**: Resource and Resource Instances whose value does not change over time, these are not observable. +- **Dynamic**: Resource and Resource Instances whose value can change. These can be made observable. + +**Creating dynamic and static single-instance Resources** + +- To create a single-instance Resource with a static value (`/Test/0/Resource`): [see parameters here](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/classM2MObjectInstance.html#aaa596f731688730d7a883b7f1251a662) + +``` +M2MObject * object = M2MInterfaceFactory::create_object("Test"); +M2MObjectInstance * object_instance = object->create_object_instance(0); + +uint8_t value[] ={"value"}; +M2MResource* resource = object_instance->create_static_resource("Resource", "sensor",M2MResourceInstance::INTEGER,value,sizeof(value),false); +``` + +- To create an observable single-instance Resource (`/Test/0/Resource`) with a dynamic value that can be set later on: [see parameters here](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/classM2MObjectInstance.html#a9b3f88dc2d28512ea6c3db6f74168c3f) + +``` +M2MObject * object = M2MInterfaceFactory::create_object("Test"); +M2MObjectInstance * object_instance = object->create_object_instance(0); + +uint8_t value[] ={"value"}; +M2MResource* resource = object_instance->create_dynamic_resource("Resource", "sensor",M2MResourceInstance::INTEGER,value,sizeof(value), true, false); +``` + +**Creating dynamic and static Resource Instances** + +- To create a Resource Instance (`/Test/0/Resource/0`) with a static value: [see parameters here](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/classM2MObjectInstance.html#a6acac6e65bfbc8b731ab4afcc805c41b) + +``` +M2MObject * object = M2MInterfaceFactory::create_object("Test"); +M2MObjectInstance * object_instance = object->create_object_instance(0); + +uint8_t value[] ={"value"}; +M2MResourceInstance* resource_instance = object_instance->create_static_resource_instance("Resource", "sensor",M2MResourceInstance::INTEGER,value,sizeof(value),0); +``` + + +- To create an observable Resource Instance (`/Test/0/Resource/0`) with a dynamic value that can be set later on: [see parameters here](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/classM2MObjectInstance.html#adcaba046a484282983380edf8a370cfa) + +``` +M2MObject * object = M2MInterfaceFactory::create_object("Test"); +M2MObjectInstance * object_instance = object->create_object_instance(0); + +uint8_t value[] ={"value"}; +M2MResource* resource = object_instance->create_dynamic_resource_instance("Resource", "sensor",M2MResourceInstance::INTEGER,value,sizeof(value), true, 0); +``` + +#### Configuring the Resource and Resource Instance + +When you have created a Resource or Resource Instance (whether OMA-specific or custom), you can configure various parameters to control or modify communication with mbed Device Server. + +Here, we present a few of the most important parameters that you must configure properly to work with the Resource and Resource Instance. + +##### Setting Operation Mode + +You can set the Resource or Resource Instance operation mode so that they can handle `GET`, `PUT`, `POST`, `DELETE` or a combination of these requests coming from mbed Device Server. + +To set the operation mode: + +``` +virtual void set_operation(M2MBase::Operation operation); +resource->set_operation(M2MBase::GET_PUT_POST_ALLOWED); // This defines the REST operations that can be performed on this Resource. +resource_instance->set_operation(M2MBase::GET_PUT_POST_ALLOWED); // This defines the REST operations that can be performed on this Resource Instance. +``` +##### Setting Observable Mode + +To set the Resource or Resource Instance to be an observable resource: + +`virtual void set_observable(bool observable);` + +By default, all created static Resources or Resource Instances are non-observable. While creating a dynamic Resource or Resource Instance you can specify through API whether they are observable or not. You can change that later as well as follows: + +``` +resource->set_observable(true); // This defines that the Resource or Resource Instance can be observed from server. +resource->set_observable(false); // This defines that the Resource or Resource Instance cannot be observed from server. +``` + +##### Setting the value of a dynamic Resource or Resource Instance + +You can set the value of a dynamic Resource or Resource Instance so that they can be sent to mbed Device Server using `GET` requests. + +To set the values: + +``` +virtual bool set_value(const uint8_t *value, const uint32_t value_length); +uint8_t value[] = {"value"}; +resource->set_value(value,sizeof(value)); +``` + +##### Setting an executable function + +For dynamic Resources, you can pass a function pointer to the Resource or Resource Instance. It will be executed when mbed Device Server calls a `POST` method on that resource. The Resource or Resource Instance must support the `POST` operation mode for this feature to work. + +To pass the function pointer: + +``` +virtual void set_execute_function(execute_callback callback); +void execute_function_example(void *) { +// Code +}; +resource->set_execute_function(execute_callback(this,&execute_function_example)); +``` +In case execute callback function is defined as a global function and it's outside of your class scope you can use overloaded set_execute_function: +``` +virtual void set_execute_function(execute_callback_2 callback); +static void c_style_function(void *) { +// Code +} +resource->set_execute_function(&c_style_function); +``` +There are additional APIs that provide getter and remove functions for Resource and Resource Instances in the `M2MResource` and `M2MResourceInstance` classes. Check [the API documentation](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/annotated.html) for their usage. diff --git a/features/FEATURE_CLIENT/mbed-client/docs/Introduction.md b/features/FEATURE_CLIENT/mbed-client/docs/Introduction.md new file mode 100644 index 0000000000..d9a2c89acf --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/docs/Introduction.md @@ -0,0 +1,144 @@ +# ARM mbed Client overview + +ARM mbed Client is a library that provides the means to connect constrained embedded devices to mbed Device Connector Service, mbed Device Server and to mbed-enabled cloud services from our partners. + +The mbed Client high-level APIs allow mbed OS developers to create applications with LWM2M features as described in the [Lightweight Machine to Machine Technical Specification](http://technical.openmobilealliance.org/Technical/technical-information/release-program/current-releases/oma-lightweightm2m-v1-0): + +- Manage devices on mbed Device Server. +- Securely communicate with internet services over the industry standard TLS/DTLS. +- Fully control the endpoint and application logic. + +The API is written in C++ to allow quick application development. + +## Managing devices on mbed Device Server + +mbed Client supports the following three features introduced in the subsequent chapters: + +- [Client Registration and Deregistration](client_reg_dereg.md) +- [Device Management and Service Enablement](dev_man_serv_enable.md) +- [Information Reporting](info_reporting.md) + +The API also provides an interface to define the application endpoint information. This information will be delivered to mbed Device Server during the registration operation. + +First, you need to create an interface for mbed Client: + +``` +#include "mbed-client/m2minterfacefactory.h" +#include "mbed-client/m2minterface.h" + +M2MInterface* interface = M2MInterfaceFactory::create_interface(*this, + "mbed-endpoint", + "test", + 3600, + 5684, + "", + M2MInterface::UDP, + M2MInterface::LwIP_IPv4, + ""); +``` + +### Setting up own random number generator function + +To provide a stronger security mechanism, mbed Client requires a random number generator to feed a random number into the underlying SSL library. There is a default PRNG seeded with RTC for security but some platforms do not have RTC, and for some, time value seeded PRNG is not secure enough. + +Now, an application can pass its own RNG implementation to mbed Client as function pointer callback through an API, `set_random_number_callback(random_number_cb callback)`. + +Here is an example on how you can use it from an application: + +``` +#include "mbed-client/m2minterfacefactory.h" +#include "mbed-client/m2minterface.h" + +uint32_t get_random_number(void) +{ + uint32_t i = 0; + printf("\Your application's RNG logic\n"); + return i; +} + +_interface->set_random_number_callback(&get_random_number); + +``` + +### Setting up own entropy function for additional secure connectivity + +mbed Client provides an API to add your own entropy source into the underlying SSL library. There is a default entropy source provided by mbed Client. It uses PRNG seeded with RTC for the security but some platforms do not have RTC, and for some, this level of security may not be strong enough. + +Now, an application can pass its own entropy source to mbed Client as function pointer callback through an API, `set_entropy_callback(entropy_cb callback)`. + +Here is an example on how you can use it from an application: + +``` +#include "mbed-client/m2minterfacefactory.h" +#include "mbed-client/m2minterface.h" + +entropy_cb ent_cb; + +int ent_poll( void *, unsigned char *output, size_t len, + size_t *olen ) +{ + for(uint16_t i=0; i < len; i++){ + srand(time(NULL)); + output[i] = rand() % 256; + } + *olen = len; + + return( 0 ); +} + + ent_cb.entropy_source_ptr = ent_poll; + ent_cb.p_source = NULL; + ent_cb.threshold = 128; + ent_cb.strong = 0; + +_interface->set_entropy_callback(ent_cb); + +``` + +### Maximum UDP message size + +The maximum single UDP message size that mbed Client can receive is 1152 bytes. The actual payload size is 1137 bytes, the header information using the remaining 15 bytes. + +For transferring larger amounts of data, the Blockwise feature must be deployed. When using this feature, mbed Client can handle messages up to 64KB. This feature is disabled by default. + +To enable the Blockwise feature, you need to create a `config.json` file in the application level. + +*Example:* +``` +{ +"coap_max_blockwise_payload_size": 1024 +} +``` + +Acceptable values for the `coap_max_blockwise_payload_size` flag are: +0, 16, 32, 64, 128, 256, 512 and 1024. Value 0 means that the feature is not used. + +### CoAP message deduplication + +Message duplication is disabled by default. More information about deduplication in the [CoAP specification](https://tools.ietf.org/html/rfc7252#page-24). + +To enable message deduplication, you need to create a `config.json` file in the application level. + +*Example:* +``` +{ +"coap_duplication_max_msgs_count": 1 +} +``` +Recommended values for the `coap_duplication_max_msgs_count` flag are 0 to 6. Value 0 means that the feature is not used. It is not recommended to use higher value than 6, because it increases the memory consumption. + +## How to use the API +More information on how to use the API effectively to create and configure Objects, Object Instances and Resources, can be found [here](Howto.md). + +## API documentation + +The documentation for this API is [available here](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/annotated.html). + +## Example application + +We have an example application for + +1. [mbed OS](https://github.com/ARMmbed/mbed-client-examples). + +2. [Ubuntu](https://github.com/ARMmbed/mbed-client-linux-example). + diff --git a/features/FEATURE_CLIENT/mbed-client/docs/client_reg_dereg.md b/features/FEATURE_CLIENT/mbed-client/docs/client_reg_dereg.md new file mode 100644 index 0000000000..6a7a4b65b9 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/docs/client_reg_dereg.md @@ -0,0 +1,171 @@ +# The Client Registration feature + +The client uses the Client Registration to register with mbed Device Server, update registration and deregister. + +Currently, only one-to-one client-server registration is supported. One-to-many client-server registrations will be supported in an upcoming release. + +The Client Registration includes multiple sub-features. Currently supported: + +- [Register](#the-register-feature) +- [Update](#the-update-feature) +- [Deregister](#the-deregister-feature) + +## The Register feature + +This API enables the client registration functionality. + +When registering, the client: + +* Performs the **Register** operation and provides parameters that mbed Device Server requires to register the client (for example Endpoint Name). + +* Maintains the registration and session (for example, it sets the Lifetime and Queue Mode towards mbed Device Server). + +* Provides information on the Objects the client supports and existing Object Instances in the client. + +### Registering your client + +To provide information to mbed Device Server and issue the register command: + +**Step 1.** Create an mbed DS Object. This object contains information about mbed Device Server, such as its address and security mode. + +``` +#include "mbed-client/m2msecurity.h" + M2MSecurity *security = M2MInterfaceFactory::create_security(M2MSecurity::M2MServer); + if(security) { + security->set_resource_value(M2MSecurity::M2MServerUri, LWM2M_SERVER_ADDRESS); + security->set_resource_value(M2MSecurity::BootstrapServer, 0); + security->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::NoSecurity); + } +``` + +**Step 2.** mbed Client supports both non-secure and secure mode operations. For secure mode, you need to provide a certificate, private key and server public key through the API. + +To create a secure mode operation: + +``` +#include "mbed-client/m2msecurity.h" + M2MSecurity *security = M2MInterfaceFactory::create_security(M2MSecurity::M2MServer); + if(security) { + security->set_resource_value(M2MSecurity::M2MServerUri, LWM2M_SERVER_ADDRESS); + security->set_resource_value(M2MSecurity::BootstrapServer, 0); + security->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::Certificate); + security->set_resource_value(M2MSecurity::ServerPublicKey,,sizeof()); + security->set_resource_value(M2MSecurity::PublicKey,,sizeof()); + security->set_resource_value(M2MSecurity::Secretkey,,sizeof()); + } +``` + +**Step 3.** Register all the resources that you would like to monitor or follow using mbed Device Server. To do this, create the resource objects and pass them to the Register API for registration purposes. + +For example, if you want to register your OMA LWM2M based Device object, you need to create the object and set the values for mandatory resources as follows: + +``` +#include "mbed-client/m2mdevice.h" +M2MDevice *device = M2MInterfaceFactory::create_device(); +if(device) { + device->create_resource(M2MDevice::Manufacturer,MANUFACTURER); + device->create_resource(M2MDevice::DeviceType,TYPE); + device->create_resource(M2MDevice::ModelNumber,MODEL_NUMBER); + device->create_resource(M2MDevice::SerialNumber,SERIAL_NUMBER); + } +``` + +**Note:** You can register other resources, including custom resources. Please check the [API documentation](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/annotated.html) for a detailed description of the M2MObject, M2MObjectInstance and M2MResource classes. + +**Step 4.** You have the registration server object and resources that you want to register. Now, you need to call the register API and pass the following objects as parameters: + +``` +M2MInterface::register_object(M2MSecurity* register_object, M2MObjectList object_list); +``` + +**Success or failure callback** + +Because this is an asynchronous operation, you will receive the result of this operation through a callback defined in `m2minterfaceobserver.h` in your application. + +_Success_ + +If the register operation is successful and the client can register all your resources to mbed DS, your application will receive the following callback: + +``` +void object_registered(M2MSecurity *server_object, const M2MServer& server) +``` + +The `M2MSecurity *server_object` specifies to which mbed Device Server instance the client has just registered and `M2MServer &server` contains the data related to mbed Device Server, including the Short ServerID and the client registration period. + +_Failure_ + +If the registration operation fails for some reason, you will receive the following callback: + +``` +void error(M2MInterface::Error error) +``` + +You will get more information about the error from the `error` parameter passed with the callback; use it to fix the source of the error. + +## The Update feature + +Periodically, or in response to events within the client or as initiated by mbed Device Server, the client updates its registration information with mbed Device Server by sending it an **Update** operation. + +Normally, the enabler will update the registration automatically, but if you want to renew the registration before that, you can use this API. + +To update your registration: + +``` +M2MInterface::update_registration(M2MSecurity* security_object, const uint32_t lifetime) +``` + +**Success or failure callback** + +_Success_ + +If the update operation is successful, your application will receive the following callback: + +``` +void registration_updated(M2MSecurity *const M2MServer& server) +``` + +The `M2MSecurity *server_object` specifies with which mbed Device Server instance the client has just updated the registration and `M2MServer &server` contains the data related to mbed Device Server, including the Short ServerID and the client registration period. + +_Failure_ + +If the update operation fails for some reason, you will receive the following callback: + +``` +void error(M2MInterface::Error error) +``` + +## The Deregister feature + +The client can deregister from mbed Device Server when it no longer requires access to the server. When mbed Device Server receives the **Deregister** message it removes the device's registration information from its database. When the client needs mbed Device Server again, it has to register again. + +To deregister your endpoint client: + +If the endpoint has multiple server registrations, you need to provide the `server_object` of the server from which would like to deregister. If there is only one registration, you can pass `NULL` and the client will deregister from the default registration. + +``` +M2MInterface::unregister_object(M2MSecurity *object); +``` + +**Success or failure callback** + +Because this is an asynchronous operation, you will receive the result of this operation through a callback defined in `m2minterfaceobserver.h` in your application. + +_Success_ + +If the client is successfully deregistered from mbed Device Server, your application will receive the following callback: + +``` +void object_unregistered(M2MSecurity *server_object) +``` + +The `M2MSecurity *server_object` specifies from which mbed Device Server instance the client has just deregistered. + +_Failure_ + +If the deregistration operation fails for some reason, you will receive the following callback: + +``` +void error(M2MInterface::Error error) +``` + +You will get more information about the error from the `error` parameter passed with the callback; use it to fix the source of the problem. diff --git a/features/FEATURE_CLIENT/mbed-client/docs/data_types.md b/features/FEATURE_CLIENT/mbed-client/docs/data_types.md new file mode 100644 index 0000000000..fc0390ccb1 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/docs/data_types.md @@ -0,0 +1,162 @@ +mbed Client data types +====================== + +This chapter describes how the different data types are processed in the mbed Client and the REST API. + +The following two aspects are considered: + +- How the different data types should be passed to API on mbed Client. +- How the data is received on REST API side, and how it is converted into right data type. + +## Using mbed Client data types + +When data is transferred from mbed Client to mbed Device Server, the following need to be kept in mind: + +- mbed Client is based on CoAP client. The Resource values are represented as text/plain format. +- Different data type values have to be converted into corresponding text/plain format. +- For example, an integer value 100 is passed in a text buffer format of 100 and it appears on the web service side as 100 in text format. +- The service must interpret this data to an appropriate format. + +### Transferring integers from mbed Client to mbed Device Server + +**Integer (from the application)**: + +``` +int value = 1; +M2MResource* instance = objinst->create_dynamic_resource(“D", “IntegerType“,M2MResourceInstance::INTEGER, true); +char buffer[20]; +int size = sprintf(buffer,"%d",value); +instance->set_value((const uint8_t*)buffer, size); +``` + +If you want the value of the resource to be stored in the server cache for a certain period of time, you can set the `max_age` parameter. Subsequent requests to the same resource will get the response directly from the cache: + +``` +instance->set_max_age(15) ; // This is the resource lifetime in the server cache (in seconds). +``` + +**Response on the REST API**: + +``` +{"async-response-id":...{ "id" : "1131895768#f4b93d6e-4652-4874-82e4-41a3ced0cd56@b02ac40a-a501-44d9-be29-e6e0e5303f85/Test/0/D", "status" : 200, "payload" : "MQ==", "ct" : "text/plain", "max-age" : 0 } +``` + +- Base64 encoded value of the payload -> `MQ==` +- Base64 decoded value of the payload -> `1` + +**Note**: If the resource value is stored in the server cache and is still valid, the response comes straight from the cache in **plain text**, neither inside any json object nor encoded in B64. + +### Transferring a float value from mbed Client to mbed Device Server + +**Float (from the application)**: + +``` +float value = 1.0232f; +M2MResource* instance = objinst->create_dynamic_resource(“D", “IntegerType“,M2MResourceInstance::FLOAT, true); +char buffer[20]; +int size = sprintf(buffer,"%f",_value); +instance->set_value((const uint8_t*)buffer, size); +``` + +If you want the value of the resource to be stored in the server cache for a certain period of time, you can set the `max_age` parameter. Subsequent requests to the same resource will get the response directly from the cache: + +``` +instance->set_max_age(15) ; // This is the resource lifetime in the server cache (in seconds). +``` + +**Response on the REST API**: + +``` +{"async-response-id":...{ "id" : "1132945328#f4b93d6e-4652-4874-82e4-41a3ced0cd56@b02ac40a-a501-44d9-be29-e6e0e5303f85/Test/0/D", "status" : 200, "payload" : "MS4wMjMyMDA=", +"ct" : "text/plain", "max-age" : 0 } +``` + +- Base64 encoded value of the payload -> `MS4wMjMyMDA=` +- Base64 decoded value of the payload -> `1.023200` + +**Note**: If the resource value is stored in the server cache and is still valid, the response comes straight from the cache in **plain text**, neither inside any json object nor encoded in B64. + +### Transferring a boolean value from mbed Client to mbed Device Server + +**Boolean (from the application)**: + +``` +bool value = true; +M2MResource* instance = objinst->create_dynamic_resource(“D", “IntegerType“,M2MResourceInstance::BOOLEAN, true); +char buffer[20]; +int size = sprintf(buffer,"%d",_value); +instance->set_value((const uint8_t*)buffer, size); +``` + +If you want the value of the resource to be stored in the server cache for a certain period of time, you can set the `max_age` parameter. Subsequent requests to the same resource will get the response directly from the cache: + +``` +instance->set_max_age(15) ; // This is the resource lifetime in the server cache (in seconds). +``` + +**Response on the REST API**: + +``` +{"async-response-id":….{ "id" : "1131895768#f4b93d6e-4652-4874-82e4-41a3ced0cd56@b02ac40a-a501-44d9-be29-e6e0e5303f85/Test/0/D", "status" : 200, "payload" : "MQ==", "ct" : "text/plain", "max-age" : 0 } +``` + +- Base64 encoded value of the payload -> `MQ==` +- Base64 decoded value of the payload -> `1` + +**Note**: If the resource value is stored in the server cache and is still valid, the response comes straight from the cache in **plain text**, neither inside any json object nor encoded in B64. + +### Transferring a string value from mbed Client to mbed Device Server + +**String (from the application)**: + +``` +M2MResource* instance = objinst->create_dynamic_resource(“D", “IntegerType“,M2MResourceInstance::STRING, true); +char buffer[10] = “Test Data”; +instance->set_value((const uint8_t*)buffer, 10); +``` + +If you want the value of the resource to be stored in the server cache for a certain period of time, you can set the `max_age` parameter. Subsequent requests to the same resource will get the response directly from the cache: + +``` +instance->set_max_age(15) ; // This is the resource lifetime in the server cache (in seconds). +``` + +**Response on the REST API**: + +``` +{"async-response-id":... { "id" : "1133335779#f4b93d6e-4652-4874-82e4-41a3ced0cd56@b02ac40a-a501-44d9-be29-e6e0e5303f85/Test/0/D", "status" : 200, "payload" : "VGVzdCBEYXRh", +"ct" : "text/plain", "max-age" : 0 } +``` + +- Base64 encoded value of the payload -> `VGVzdCBEYXRh` +- Base64 decoded value of the payload -> `Test Data` + +**Note**: If the resource value is stored in the server cache and is still valid, the response comes straight from the cache in **plain text**, neither inside any json object nor encoded in B64. + +### Transferring an opaque value from mbed Client to mbed Device Server + +**Opaque(from the application)**: + +``` +M2MResource* instance = objinst->create_dynamic_resource(“D", “IntegerType“,M2MResourceInstance::OPAQUE, true); +uint8_t buffer[12] = “Opaque Data”; +instance->set_value(buffer, 12); +``` + +If you want the value of the resource to be stored in the server cache for a certain period of time, you can set the `max_age` parameter. Subsequent requests to the same resource will get the response directly from the cache: + +``` +instance->set_max_age(15) ; // This is the resource lifetime in the server cache (in seconds). +``` + +**Response on the REST API**: + +``` +{"async-response-id":... { "id" : "1134045351#f4b93d6e-4652-4874-82e4-41a3ced0cd56@b02ac40a-a501-44d9-be29-e6e0e5303f85/Test/0/D", "status" : 200, "payload" : "T3BhcXVlIERhdGEA", +"ct" : "application/octet-stream", "max-age" : 0 } +``` + +- Base64 encoded value of the payload -> `T3BhcXVlIERhdGEA` +- Base64 decoded value of the payload -> `Opaque Data` + +**Note**: If the resource value is stored in the server cache and is still valid, the response comes straight from the cache in **plain text**, neither inside any json object nor encoded in B64. diff --git a/features/FEATURE_CLIENT/mbed-client/docs/dev_man_serv_enable.md b/features/FEATURE_CLIENT/mbed-client/docs/dev_man_serv_enable.md new file mode 100644 index 0000000000..5955f861ce --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/docs/dev_man_serv_enable.md @@ -0,0 +1,191 @@ +# The Device Management and Service Enabler feature + +mbed Device Server uses the Device Management and Service Enabler to access Object Instances and Resources available on the client. The interface provides this access through the following operations: + +- [Create](#the-create-operation) +- Delete +- [Read](#the-read-operation) +- [Write](#the-write-operation) +- [Write Attributes](#the-write-attributes-operation) +- [Execute](#the-execute-operation) + +Currently, support for the Create and Delete actions is limited to Object Instances. + +The Device Management and Service Enabler Interface supports the following data types: + +- Text: for Resources. +- TLV: for Object and Object Instances. + +## The Create operation + +There are two types of resources you can create: + +- Static: you set the value of the resource once and it does not change during the course of operations. +- Dynamic: the value is expected to change during the course of operations. Therefore, the value is fetched from setter APIs every time the server requests a read operation. + +Here is an example of creating a custom static Resource: + +``` +#include "mbed-client/m2mobject.h" +#include "mbed-client/m2mobjectinstance.h" +#include "mbed-client/m2mresource.h" +_object = M2MInterfaceFactory::create_object("Test"); +if(_object) { + M2MObjectInstance* inst = _object->create_object_instance(); + if(inst) { + inst->create_static_resource("S", + "ResourceTest", + STATIC_VALUE, + sizeof(STATIC_VALUE)-1); +``` + +And here is an example of creating a custom dynamic Resource: + +``` +#include "mbed-client/m2mobject.h" +#include "mbed-client/m2mobjectinstance.h" +#include "mbed-client/m2mresource.h" +_object = M2MInterfaceFactory::create_object("Test"); +if(_object) { + M2MObjectInstance* inst = _object->create_object_instance(); + if(inst) { + M2MResource* res = inst->create_dynamic_resource("D","ResourceTest",true); + char buffer[20]; + int size = sprintf(buffer,"%d",_value); + res->set_operation(M2MBase::GET_PUT_ALLOWED); + res->set_value((const uint8_t*)buffer, + (const uint32_t)size); +``` + +For more information on different resource functionalities, please check the [API documentation](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/annotated.html) for the M2MObject, M2MObjectInstance and M2MResource classes. + +## The Read operation + +The Client API allows setting values to Resources, an array of Resource Instances, an Object Instance or all the Object Instances of an Object (TLV format supported). mbed Device Server can then read these values using the **Read** operation. + +## The Write operation + +The **Write** operation is used to overwrite the value of a Resource, an array of Resource Instances or multiple Resources from an Object Instance. + +Whenever there is a valid `PUT` operation for any of the resources, the application will receive a callback: + +``` +void value_updated(M2MBase *base, M2MBase::BaseType type) +``` +Where `M2MBase` is the Object whose value has been updated and `M2MBase::BaseType` is the object type. + +Check the code snippet below for usage. +``` +void value_updated(M2MBase *base, M2MBase::BaseType type) { + M2MResource* resource = NULL; + M2MResourceInstance* res_instance = NULL; + M2MObjectInstance* obj_instance = NULL; + M2MObject* obj = NULL; + String object_name = ""; + String resource_name = ""; + uint16_t object_instance_id = 0; + uint16_t resource_instance_id = 0; + if(base) { + switch(base->base_type()) { + case M2MBase::Object: + obj = (M2MObject *)base; + object_name = obj->name(); + break; + case M2MBase::ObjectInstance: + obj_instance = (M2MObjectInstance *)base; + object_name = obj_instance->name(); + object_instance_id = obj_instance->instance_id(); + break; + case M2MBase::Resource: { + resource = (M2MResource*)base; + object_name = resource->object_name(); + object_instance_id = resource->object_instance_id(); + resource_name = resource->name(); + printf("Value updated, object name %s, object instance id %d, resource name %s\r\n", + resource->object_name().c_str(), resource->object_instance_id(), resource->name().c_str()); + } + break; + case M2MBase::ResourceInstance: { + res_instance = (M2MResourceInstance*)base; + object_name = res_instance->object_name(); + object_instance_id = res_instance->object_instance_id(); + resource_name = res_instance->name(); + resource_instance_id = res_instance->instance_id(); + } + break; + default: + break; + } + } + } +``` + +## The Write Attributes operation + +Any readable Resource can have attributes that are considered during the [**Observe** operation](info_reporting.md#the-observe-feature). The following attributes are used: + +- Minimum Period (pmin) +- Maximum Period (pmax) +- Greater Than (gt) +- Less Than (lt) +- Step (st) + +mbed Device Server sets the endpoint attribute values that are used to determine when the endpoint sends the Resource value to the server. + +Check the [LWM2M Specification](http://technical.openmobilealliance.org/Technical/technical-information/release-program/current-releases/oma-lightweightm2m-v1-0) for details of all the possible **Write Attributes** defined for different types of Objects and Resources. + +## The Execute operation + +mbed Device Server uses the **Execute** operation to perform an action. This operation can only be performed on individual Resources. + +**Note:** mbed Client returns an error when the **Execute** operation is received for Object Instances or Resource Instances. + +If you want to execute a piece of code in your application, you can pass a `POST` request from mbed Device Server. +When your Resource receives the `POST` request, mbed Client parses the payload from the request and wraps it in the `M2MResource::M2MExecuteParameter` class. The class object is passed through the execute callback function. +You can then typecast the `void*` argument into the corresponding `M2MResource::M2MExecuteParameter` and access the passed payload and its length through the given API. M2MResource::M2MExecuteParameter contains also information which object and object instance resource belongs to. Make sure that the payload sent through POST request is in `plain/text` format and that the content-type is set as “plain/text” on the POST request call. + +Check the code snippet below for usage. + +``` +#include "mbed-client/m2mobject.h" +#include "mbed-client/m2mobjectinstance.h" +#include "mbed-client/m2mresource.h" + static void execute_function_2(void *argument) { + if(argument) { + M2MResource::M2MExecuteParameter* param = (M2MResource::M2MExecuteParameter*)argument; + int payload_length = param->get_argument_value_length(); + uint8_t* payload = param->get_argument_value(); + String object_name = param->get_argument_object_name(); + uint16_t object_instance_id = param->get_argument_object_instance_id(); + String resource_name = param->get_argument_resource_name(); + } + + void M2MLWClient::execute_function(void *argument) { + if(argument) { + M2MResource::M2MExecuteParameter* param = (M2MResource::M2MExecuteParameter*)argument; + int payload_length = param->get_argument_value_length(); + uint8_t* payload = param->get_argument_value(); + String object_name = param->get_argument_object_name(); + uint16_t object_instance_id = param->get_argument_object_instance_id(); + String resource_name = param->get_argument_resource_name(); + } + +_object = M2MInterfaceFactory::create_object("Test"); +if(_object) { + M2MObjectInstance* inst = _object->create_object_instance(); + if(inst) { + M2MResource* res = inst->create_dynamic_resource("D","ResourceTest",true); + char buffer[20]; + int size = sprintf(buffer,"%d",_value); + res->set_operation(M2MBase::GET_PUT_POST_ALLOWED); + res->set_value((const uint8_t*)buffer, + (const uint32_t)size); + res->set_execute_function(execute_callback(this,&M2MLWClient::execute_function)); + /* Overloaded function can be used If callback function is not in class scope. + res->set_execute_function(&execute_function_2); + */ +``` + +The POST method allows the client to respond immediately with the updated payload value as a piggyback response. If you want to send the payload response to the server later (because the Execute operation may take longer time on device to complete), you can handle this through the API. + +You can set the resource API `void set_delayed_response(bool)` to `true`. In this case, the POST request response to the server is an empty acknowledgment. When your resource is ready with the response, you can simply call `send_delayed_post_response()` on that resource and the client sends the latest resource value to the server as part of a separate response to the POST request. By default, `void set_delayed_response(bool)` is `false`, which means that the POST response returns the resource value as a piggyback payload immediately. diff --git a/features/FEATURE_CLIENT/mbed-client/docs/further-reading.md b/features/FEATURE_CLIENT/mbed-client/docs/further-reading.md new file mode 100644 index 0000000000..c168770a9d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/docs/further-reading.md @@ -0,0 +1,14 @@ +# Useful reading + +[Getting started with mbed Device Connector](https://docs.mbed.com/docs/getting-started-with-mbed-device-connector/en/latest/) provides you: + +- a generic introduction to mbed Device Connector. +- a quick start guide for using mbed Device Connector. + +[mbed Device Connector Web Interfaces](https://docs.mbed.com/docs/mbed-device-connector-web-interfaces/en/latest/) provides you: + +- an overview to the Web Interfaces, explaining how the web applications interact with mbed Device Connector using the REST API. + +[mbed Device Connector developer site](https://www.mbed.com/en/development/cloud/mbed-device-connector-service/) + +- a web site for developers diff --git a/features/FEATURE_CLIENT/mbed-client/docs/index.md b/features/FEATURE_CLIENT/mbed-client/docs/index.md new file mode 100644 index 0000000000..286248d83a --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/docs/index.md @@ -0,0 +1,15 @@ +About this document +===================== + +This document introduces the mbed Client and the use of its API. The document is divided into the following chapters: + +- [**Introduction**](Introduction.md) is a brief introduction to the mbed Client and its features. +- [**The Client Registration feature**](client_reg_dereg.md) introduces the Client Registration feature in detail. +- [**The Device Management and Service Enabler feature**](dev_man_serv_enable.md) introduces the Device Management and Service Enabler feature in detail. +- [**The Information Reporting feature**](info_reporting.md) introduces the Information Reporting feature in detail. +- [**mbed Client data types**](data_types.md) describes how the different data types are processed in the mbed Client and the REST API. +- [**How to use the mbed Client API**](Howto.md) contains detailed instructions on using the mbed Client API. +- [**Porting mbed Client**](porting-guide.md) is meant for advanced users and tells how to build mbed Client and port it for different platforms. +- [**Useful reading**](further-reading.md) links you to mbed Device Connector documentation and the developer site. + + diff --git a/features/FEATURE_CLIENT/mbed-client/docs/info_reporting.md b/features/FEATURE_CLIENT/mbed-client/docs/info_reporting.md new file mode 100644 index 0000000000..8ef941a166 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/docs/info_reporting.md @@ -0,0 +1,20 @@ +# The Information Reporting feature + +mbed Device Server uses the Information Reporting to observe any changes in a registered Resource on the client. The server registers to observe the Resource. When the Resource changes, it sends a notification with its new value to all servers who asked to observe it. + +The interface supports the following sub-features: + +## The Observe feature + +mbed Device Server initiates an observation request to observe the changing value of either an Object, Object Instance or Resource. + +**Tip:** Related parameters for the **Observe** operation are described in the [Write Attributes](dev_man_serv_enable.md#write-attributes) section. + +## The Notify feature + +The client sends the **Notify** operation to mbed Device Server during a valid observation on a Resource, when the notification conditions are met. + +## Cancel + +mbed Device Server sends the **Cancel Observation** operation to the client to end an observation relationship for an Object Instance or a Resource. + diff --git a/features/FEATURE_CLIENT/mbed-client/docs/known-issues-mbed-client1511.md b/features/FEATURE_CLIENT/mbed-client/docs/known-issues-mbed-client1511.md new file mode 100644 index 0000000000..4b7176ced3 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/docs/known-issues-mbed-client1511.md @@ -0,0 +1,59 @@ +# Known Issues + +## About this document + +This is the list of known issues for the 15.11 release of [mbed Client](https://github.com/ARMmbed/mbed-client). We publish mbed-client as module in GitHub, and track open issues as tickets in the repository. That makes for an easy development flow, but doesn’t make it very easy for you to get a single view of all the issues that affect the whole release. + +The purpose of this document is to provide that single view of all the key issues we are aware of. It isn’t a complete list; it’s a filtered and reviewed list, focusing on the issues we thought you’d want to be aware of. Each item explains the problem, as well as workarounds if those are possible. For items filed through GitHub, we’ve included a link to the issue so that you can follow the discussion and code - or even suggest a solution. + +For more information about an issue, contact us on the [mbed forums](http://forums.mbed.com). + +### Other information not in this document + +We’re still very actively building mbed Client and the 15.11 release is a technology preview. As such there are some other limitations of the release that you can find described in the [release note](https://www.mbed.com/en/development/software/mbed-client/releases/mbed-client1511). + +#### Important Note for Windows Users + +If you are using this release on Microsoft Windows, please be advised that because of the way Windows handles filename and paths, you may have problems if you attempt to use this in a deep directory hierarchy with a long path name (e.g. `c:\some\very\long\path`). If you experience problems unpacking or building this release, please try it in a location with a shorter path before filing a bug. Thanks. + +*** +### mbed Client API may not be fully interoperable with other LWM2M servers. + +*Description*: mbed Client API is OMA LWM2M compatible. However, some features may not be fully interoperable against other open source LWM2M servers. This is the first release version and more features will be made interoperable over coming releases. + +*Workaround*: mbed Client is compatible with mbed Device Connector Service, which can be tested at [https://connector.mbed.com](https://connector.mbed.com). + +*Reported Issue*: ARM internal reference IOTCLT-366 + +*Priority*: Major + +### mbed Client for Linux doesn't support IPv6 connectivity + +*Description*: mbed Client for Linux platform currently works only for IPv4-enabled LWM2M server addresses. IPv6 address support is currently broken. + +*Workaround*: mbed Client is compatible with mbed Device Connector Service which can be tested from [https://connector.mbed.com](https://connector.mbed.com) over IPv4 Address. + +*Reported Issue*: https://github.com/ARMmbed/mbed-client-linux/issues/19 + +*Priority*: Major + +### mbed Client will occasionally disconnect from LWM2M Server because of network errors + +*Description*: If mbed Client is kept running for long durations (over 24 hours) with long lifetime values, it occasionally goes offline due to unstable network conditions - and doesn't send periodic updates to LWM2M server. + +*Workaround*: Set the periodic lifetime value to less than 15 minutes if you want to run stability tests. Also, implement a network error handling mechanism on the application side, to handle `error()` callbacks received from the mbed-client library. + +*Reported Issue*: ARM internal reference IOTCLT-206 + +*Priority*: Major + +### mbed Client might experience a memory leak when running for long durations + +*Description*: mbed Client might have memory leak issues when left running for longer than 12 hours. + +*Workaround*: None + +*Reported Issue*: ARM internal reference IOTCLT-290 + +*Priority*: Major + diff --git a/features/FEATURE_CLIENT/mbed-client/docs/mbed_Client_Known_Issues_16_03.md b/features/FEATURE_CLIENT/mbed-client/docs/mbed_Client_Known_Issues_16_03.md new file mode 100644 index 0000000000..7c805ef530 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/docs/mbed_Client_Known_Issues_16_03.md @@ -0,0 +1,42 @@ +# mbed Client Known Issues + +## About this document + +This is the list of known issues for the [16.03 release of mbed Client](Release_Note.md). + +We publish mbed Client as a collection of modules on GitHub. Issues are raised in the specific repositories and then tracked internally. + +The purpose of this document is to provide a single view of the outstanding key issues that have not been addressed for this release. As such it is a filtered and reviewed list based on priority and potential impact. Each item summarises the problem and includes any known workarounds, along with a link to the GitHub issue (if applicable). We welcome any comments or proposed solutions. + +For more information about an issue, contact us on the [forums](http://forums.mbed.com). + +## Additional information + +For further information regarding this release please refer to the release notes referenced above. + +# Known issues + +## mbed Client API does not support float data type +* **Description**: mbed Client API doesn't work correctly with float data type, as it is disabled in the FRDM target configuration. +* **Workaround**: No workaround at the moment. There will be a fix for target-mbed-gcc soon, which will enable float data type usage. +* **Reported Issue**: ARM internal reference IOTCLT-649 +* **Priority**: Critical + +## mbed-trace module has a missing test dependency on Linux and Windows build targets. +* **Description**: The mbed-trace library has a test-dependency on cpputest, which is not yet available in the yotta registry. Since you can't download this dependency, "yt test" for mbed-trace will fail. +* **Workaround**: No workaround available. +* **Reported Issue**: ARM internal reference IOTCLT-650 +* **Priority**: Critical + +## mbed Client API may not be fully interoperable with other LWM2M servers. +* **Description**: mbed Client API is OMA LWM2M compatible. However, some features may not be fully interoperable against other open source LWM2M servers. +* **Workaround**: mbed Client is compatible with mbed Device Connector Service, which can be tested at [https://connector.mbed.com](https://connector.mbed.com). +* **Reported Issue**: ARM internal reference IOTCLT-366 +* **Priority**: Major + +## mbed Client example application may drop off from Connector if kept running for a long duration. +* **Description**: mbed Client example application sometimes drops off from Connector after a few hours. This may happen when mbed Client is kept running for long durations (over 24 hours) - it occasionally goes offline due to unstable network conditions, and doesn't send periodic updates to Connector. +* **Workaround**: Set the periodic lifetime value to less than 15 minutes if you want to run stability tests. Also, implement a network error handling mechanism on the application side, to handle error() callbacks received from the mbed-client library. +* **Reported Issue**: [https://github.com/ARMmbed/mbed-client-examples/issues/52](https://github.com/ARMmbed/mbed-client-examples/issues/52) +* **Priority**: Major + diff --git a/features/FEATURE_CLIENT/mbed-client/docs/mbed_Client_Release_Note_16_03.md b/features/FEATURE_CLIENT/mbed-client/docs/mbed_Client_Release_Note_16_03.md new file mode 100644 index 0000000000..9c0ca75cb5 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/docs/mbed_Client_Release_Note_16_03.md @@ -0,0 +1,79 @@ + +# Release note for mbed Client 16.03 + +mbed Client is an OS-agnostic embedded software library that provides the means to connect and manage constrained embedded devices to web applications through mbed Device Server. + +## Release summary + +This is an iterative release of mbed Client, which is available for mbed OS as well as for Ubuntu-like Linux distributions. We’re continuously maturing mbed Client and adding new features to mbed Client.. This release builds on the Technology Preview 15.11 release through the introduction of new APIs, enhanced functionalities and bug fixes. +## Collaboration +We’re building mbed Client as a collaborative project, bringing together industry and open source community contributions. If you’d like to work on mbed Client with us, we’d encourage you [to pitch in](https://github.com/ARMmbed/mbed-os/blob/master/CONTRIBUTING.md). With this technology preview we’re ready to start receiving contributions back from the community. +## Documentation +To get started with mbed Client, please visit our [getting started guide](https://docs.mbed.com/docs/mbed-client-guide/en/latest/). +# Changes since last release + +## New APIs and functions + +* New APIs: + * Setting the max-age of a resource value. See [https://tools.ietf.org/html/draft-ietf-core-coap-09#section-5.10.6](https://tools.ietf.org/html/draft-ietf-core-coap-09#section-5.10.6). + * Omitting registered resources' URI path from the registration message's body (which is sent from the client to the server). + * Allowing the client to send a delayed response to POST requests. See [https://tools.ietf.org/html/draft-ietf-core-coap-09#section-5.2.2](https://tools.ietf.org/html/draft-ietf-core-coap-09#section-5.2.2). + * Getting Object and Object Instance information from Resource Object. +* Added a new class for handling arguments received from POST method for Resource. +* Enabled CoAP Blockwise payload handling by client. See [https://tools.ietf.org/html/draft-ietf-core-block-08#section-2](https://tools.ietf.org/html/draft-ietf-core-block-08#section-2). +* Added support for handling observation cancellation through a RESET message from Device Connector Server. +* Disabled Bootstrap API functionality from source code. + +## Bug fixes + +1. Multiple fixes related to Object, Object Instance and Resource Observation. +2. Multiple fixes related to Write Attributes parameter handling for Object, Object Instance and Resource. +3. Multiple fixes for creating and deleting object instances. +4. Fixes related to sending notifications from multiple resource levels. +5. Fixing memory leaks. +6. Fixing mbed Client IPv6 connectivity for Linux. +7. Memory handling in the ``m2mstring`` class. +8. Fix for preventing the client from sending multiple confirmable messages on mbed OS. + +# Modules versions + +mbed Client is available as part of mbed OS or as a standalone component for Ubuntu-like Linux distributions. + +The yotta modules & versions released for these different product configurations are listed below. + +mbed Client as part of mbed OS: + +1. mbed-client-quickstart (example) +1. mbed-client - 1.6.x +1. mbed-client-c - 2.2.x +1. nanostack-libservice - 3.1.x +1. mbed-client-mbedtls - 1.0.x +1. mbedtls - 2.2.0 +1. mbed-client-mbed-os - 1.1.x +1. mbed-client-examples +1. target-frdm-k64f-gcc - 2.0.0 + + +mbed Client as a standalone distribution for Ubuntu-like Linux distributions: + +1. mbed-client-linux-example +1. mbed-client - 1.6.x +1. mbed-client-c - 2.2.x +1. nanostack-libservice - 3.1.x +1. mbed-client-mbedtls - 1.0.x +1. mbedtls - 2.2.0 +1. mbed-client-linux - 1.1.x +1. target-x86-linux-native - 1.0.0 +1. target-linux-native - 1.0.0 + + +### Known issues + +The known issues list for this release is available as [a separate document](Known_Issues.md) + +### Other ways of accessing this release + + +We prefer that you access and collaborate with mbed Client online. However, the release may also be downloaded as a [tar archive file](https://mbed-media.mbed.com/filer_public/7b/75/7b75d9fe-bf15-4818-b959-c54e11e767af/mbed-client-1603.zip). + + diff --git a/features/FEATURE_CLIENT/mbed-client/docs/porting-guide.md b/features/FEATURE_CLIENT/mbed-client/docs/porting-guide.md new file mode 100644 index 0000000000..04993c6927 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/docs/porting-guide.md @@ -0,0 +1,558 @@ +**Note:** To port mbed Client, you need to [install yotta and its dependencies](https://github.com/ARMmbed/yotta/blob/master/docs/index.md). + +# mbed Client structure and build process + +**Tip:** Before embarking on your own port, you should build the core mbed Client for an existing compilation target to get an understanding of how the mbed Client builds. + +mbed Client is structured as a set of modules. Each module declares which other modules it depends on. When you build a module, our build system `yotta` looks at these dependencies and installs the necessary modules before completing the build. + +This is also the process to build applications for the mbed Client (including the example application in the release). The application declares dependencies on the mbed Client and when it is built, `yotta` ensures that the modules (and anything that they depend on, recursively) are present before building. + +In general, `yotta` downloads and installs the necessary modules over the internet from the public yotta Registry (which saves published versions of modules) or from a specified source control URL. + +# Components of mbed Client + +## Component software modules + +mbed Client consists of one main component. More major components will be added in future development phases: + + * `mbed-client` is the core mbed Client, providing C++ APIs for the mbed Client. + +This module depends on further internal modules: + +``` +mbed-client x.x.x +| +|_mbed-client-c x.x.x +| |_mbed-client-libservice x.x.x +| +|_mbed-client-linux x.x.x +``` + +To list the dependency trees, use the [`yotta list --all` command](http://docs.yottabuild.org/reference/commands.html). + +**Note**: In this case, we have listed the dependencies for the `x86-linux-native` compilation target. Different modules are needed for different compilation targets. + +We are using the [mbed Client Linux example](https://github.com/ARMmbed/mbed-client-linux-example) in this document. You can see that it depends directly only on the `mbed-client` and `mbed-client-linux` modules. These modules depend internally on various other modules. + +``` +mbed-client-linux-example x.x.x +| +|_mbed-client x.x.x + | + |_mbed-client-c x.x.x + | |_mbed-client-libservice x.x.x + | + |_mbed-client-linux x.x.x +``` + +## Compilation targets + +To compile for a target board, you need a [target description](http://docs.yottabuild.org/tutorial/targets.html) that describes how to compile for the target. + +The `mbed-client` module uses the platform name that each target defines to choose which `mbed-client-` module to depend on to provide the platform-specific implementation. + +# Porting mbed Client to a different platform + +To port mbed Client to a new platform: + + 1. [Request for a development repository](#requesting-for-a-development-repository). + 2. [Create a yotta compilation target for your board](#creating-a-yotta-compilation-target). + 3. [Implement the `mbed-client-xxx` module for your target platform](#implementing-mbed-client-xxx). + 4. [Modify the `module.json` of the `mbed-client` module](#modifying-the-json-file-in-the-mbed-client-module). + 5. [Verify that your implementation is correct](#testing-and-verification). + +The `yotta` build system is designed for easy reuse of generic modules. If you intend to support multiple platforms that share common features, we recommend moving the common functionality into a separate module and use it for each platform. + +## Requesting for a development repository + +We provide private git repositories to our partners porting mbed Client. Only the members of the mbed Client team and relevant partner contacts and engineers have access to these repositories. + +When you contact `support@mbed.org`, a repository will be created for your module. You also need to provide the target description of your board as follows: + +- **`mbed-client-`** is the module that provides the `mbed-client-xxx` implementation for your platform. You may choose to split it into further modules in the future, to enable sharing of code, but we recommend that you implement the port for your first board in this module itself. + +- **`target-`** contains the yotta target description of the target you are porting to. This is usually your platform name. + +## Creating a yotta compilation target + +An example on compiling for linux target can be found in the `yotta_targets` directory of [the example application] (https://github.com/ARMmbed/mbed-client-linux-example). + +Please, refer to the [yotta documentation](http://yottadocs.mbed.com/tutorial/targets.html) for setting up your compilation target. + +1.To make your target available locally (without publishing it), you use the `yotta link-target` command to link it into the global install targets directory: + +``` +# in the directory of your target: +yotta link-target +``` + +2.Use `yotta link-target ` command to make the globally linked target available when compiling another module. + +3.Use the `yotta target ` command to select your target for the compilation. + +## Implementing mbed-client-xxx + +Clone your `mbed-client-` module and `mbed-client` modules from GitHub. + +The `mbed-client-` module needs to provide a socket and timer implementation for your target platform. The `mbed-client-xxx` module should include files `m2mconnectionhandler.h`and `m2mtimer.h` from `mbed-client` and implement a corresponding `.cpp` file that points to the platform-specific private implementations of the timer and the socket. + +**Note**: Private implementation classes **must** be named as `M2MConnectionHandlerPimpl` and `M2MTimerPimpl`, because of forward declarations. + +An example of mbed-client-platform: + +``` +|_module.json +| +|_mbed-client-platform +| |_m2mconnectionhandlerpimpl.h +| |_m2mtimerpimpl.h +| +|_source + |_m2mconnectionhandler.cpp + |_m2mconnectionhandlerpimpl.cpp + |_m2mtimer.cpp + |_m2mtimerpimpl.cpp +``` + +To make your module available to other modules that you want to build, you need to use the [`yotta link`](http://docs.yottabuild.org/reference/commands.html#yotta-link) command to link it to the module where you want to test it out. + +For example, to use your local your in-development mbed-client implementation, use the command `yotta link mbed-client-xxx` in the main `mbed-client` module. + +``` +# in mbed-client, link your module: +yotta link mbed-client-xxx +``` + +You can also just commit and push your untested code to GitHub, but it is always a good idea to test before committing. + +Your `mbed-client-xxx` module must provide a platform-specific implementation for the mbed-client. The APIs that need porting are defined in the `mbed-client-linux` module. The header files contain documentation alongside the declaration of each function, where the function is described along with its parameters and return value. + +There are two header files that require porting for your platform: + +- `m2mconnectionhandler.h` +- `m2mtimer.h` + +To see how this is done in Linux, check the `mbed-client-linux` module from the mbed [Client Linux Example](https://github.com/ARMmbed/mbed-client-linux-example). + +### Implementing the M2MConnectionHandler class for your platform + +``` +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ +#ifndef M2M_CONNECTION_HANDLER_H__ +#define M2M_CONNECTION_HANDLER_H__ + +#include "mbed-client/m2mconfig.h" +#include "mbed-client/m2minterface.h" +#include "mbed-client/m2mconnectionobserver.h" +#include "nsdl-c/sn_nsdl.h" + +/** + * \brief M2MConnectionHandler. + * This class handles the socket connection for the LWM2M Client. + */ + +class M2MConnectionHandler { +public: + + /** + * @enum ConnectionError + * This enum defines an error that can come from + * socket read and write operation. + */ + typedef enum { + CONNECTION_ERROR_WANTS_READ = -1000, + CONNECTION_ERROR_WANTS_WRITE = -1001, + ERROR_NONE = 0, + SSL_CONNECTION_ERROR, + SOCKET_READ_ERROR, + SOCKET_SEND_ERROR, + SOCKET_ABORT, + DNS_RESOLVING_ERROR, + SSL_HANDSHAKE_ERROR + }ConnectionError; + + +public: + + /** + * \brief Constructor + */ + M2MConnectionHandler(M2MConnectionObserver &observer, + M2MConnectionSecurity* sec, + M2MInterface::BindingMode mode, + M2MInterface::NetworkStack stack); + + /** + * \brief Destructor + */ + ~M2MConnectionHandler(); + + /** + * \brief This binds the socket connection. + * \param listen_port Port to be listened to for an incoming connection. + * \return True if successful, else false. + */ + bool bind_connection(const uint16_t listen_port); + + /** + * \brief This resolves the server address. Output is + * returned through a callback. + * \param String The server address. + * \param uint16_t The server port. + * \param ServerType The server type to be resolved. + * \param security The M2MSecurity object that determines which + * type of secure connection will be used by the socket. + * \return True if address is valid, else false. + */ + bool resolve_server_address(const String& server_address, + const uint16_t server_port, + M2MConnectionObserver::ServerType server_type, + const M2MSecurity* security); + + /** + * \brief Sends data to the connected server. + * \param data_ptr The data to be sent. + * \param data_len The length of data to be sent. + * \param address_ptr The address structure to which the data needs to be sent. + * \return True if data is sent successfully, else false. + */ + bool send_data(uint8_t *data_ptr, + uint16_t data_len, + sn_nsdl_addr_s *address_ptr); + + /** + * \brief Listens to the incoming data from a remote server. + * \return True if successful, else false. + */ + bool start_listening_for_data(); + + /** + * \brief Stops listening to the incoming data. + */ + void stop_listening(); + + /** + * \brief Sends directly to the socket. This is used by + * security classes to send the data after it has been encrypted. + * \param buf Buffer to send. + * \param len The length of the buffer. + * \return Number of bytes sent or -1 if failed. + */ + int send_to_socket(const unsigned char *buf, size_t len); + + /** + * \brief Receives directly from the socket. This + * is used by the security classes to receive raw data to be decrypted. + * \param buf Buffer to send. + * \param len The length of the buffer. + * \return Number of bytes read or -1 if failed. + */ + int receive_from_socket(unsigned char *buf, size_t len); + + /** + * \brief Closes the open connection. + */ + void close_connection(); + + /** + * \brief Error handling for DTLS connectivity. + * \param error Error code from the TLS library. + */ + void handle_connection_error(int error); + + /** + * \brief Sets the network interface handler that is used by client to connect + * to a network over IP.. + * \param handler A network interface handler that is used by client to connect. + * This API is optional but provides a mechanism for different platforms to + * manage usage of underlying network interface by client. + */ + void set_platform_network_handler(void *handler = NULL); + + /** + * \brief Claims mutex to prevent thread clashes + * in multithreaded environment. + */ + void claim_mutex(); + + /** + * \brief Releases mutex to prevent thread clashes + * in multithreaded environment. + */ + void release_mutex(); + +private: + + M2MConnectionObserver &_observer; + M2MConnectionHandlerPimpl *_private_impl; + +friend class Test_M2MConnectionHandler; +friend class Test_M2MConnectionHandler_mbed; +friend class Test_M2MConnectionHandler_linux; +friend class M2MConnection_TestObserver; +}; + +#endif //M2M_CONNECTION_HANDLER_H__ + +``` + +Please note that some of these functions are asynchronous in nature and some are expecting a callback from the network. For example, receiving data from a socket needs to be communicated back to `mbed-client` so that the library can act on the data received. The callback comes through the Observer class defined in `M2MConnectionObserver`. + +The file `m2mconnectionobserver.h` is present in `mbed-client`. To see how the callback needs to be called, check the implementation in `m2mconnectionhandlerpimpl.cpp` in `mbed-client-linux`. + +``` +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ +#ifndef M2M_CONNECTION_OBSERVER_H__ +#define M2M_CONNECTION_OBSERVER_H__ + +#include "mbed-client/m2minterface.h" + +/** + * @brief Observer class for informing socket activity to the state machine + */ + +class M2MConnectionObserver +{ + +public : + + /** + * \enum ServerType, Defines the type of the + * server that the client wants to use. + */ + typedef enum { + Bootstrap, + LWM2MServer + }ServerType; + + /** + * \brief The M2MSocketAddress struct. + * Unified container for holding socket address data + * across different platforms. + */ + struct SocketAddress{ + M2MInterface::NetworkStack _stack; + void *_address; + uint8_t _length; + uint16_t _port; + }; + + /** + * \brief Indicates that data is available from socket. + * \param data The data read from the socket. + * \param data_size The length of the data read from the socket. + * \param address The address of the server where the data is coming from. + */ + virtual void data_available(uint8_t* data, + uint16_t data_size, + const M2MConnectionObserver::SocketAddress &address) = 0; + + /** + * \brief Indicates an error occured in socket. + * \param error_code The error code from socket, it cannot be used any further. + * \param retry Indicates whether to re-establish connection. + */ + virtual void socket_error(uint8_t error_code, bool retry = true) = 0; + + /** + * \brief Indicates that the server address resolving is ready. + * \param address The resolved socket address. + * \param server_type The type of the server. + * \param server_port The port of the resolved server address. + */ + virtual void address_ready(const M2MConnectionObserver::SocketAddress &address, + M2MConnectionObserver::ServerType server_type, + const uint16_t server_port) = 0; + + /** + * \brief Indicates that data has been sent successfully. + */ + virtual void data_sent() = 0; +}; + +#endif // M2M_CONNECTION_OBSERVER_H__ + +``` + +### Implementing M2MTimer class for your platform + +This class provides the periodic timer functionality for your platform. + +``` +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ +#ifndef M2M_TIMER_H +#define M2M_TIMER_H + +#include + +class M2MTimerObserver; +/** + * @brief M2MTimerImpl + * Private implementation class for timer, this can be + * modified based on the board on which mbed Client needs + * to be used. + */ +class M2MTimerImpl +{ +private: + + // Prevents the use of assignment operator + M2MTimer& operator=(const M2MTimer& other); + + // Prevents the use of copy constructor + M2MTimer(const M2MTimer& other); + +public: + + /** + * Constructor. + */ + M2MTimer(M2MTimerObserver& _observer); + + /** + * Destructor. + */ + virtual ~M2MTimer(); + + /** + * Starts timer + * @param interval Timer's interval in milliseconds + * @param single_shot defines if timer is ticked + * once or is it restarted everytime timer expires. + */ + void start_timer(uint64_t interval, bool single_shot = true); + + /** + * @brief Starts timer in DTLS manner. + * @param intermediate_interval Intermediate interval to use, must be smaller than tiotal (usually 1/4 of total). + * @param total_interval Total interval to use, this is the timeout value of a DTLS packet. + * @param type Type of the timer + */ + void start_dtls_timer(uint64_t intermediate_interval, uint64_t total_interval, + M2MTimerObserver::Type type = M2MTimerObserver::Dtls); + + /** + * Stops timer. + * This cancels the ongoing timer. + */ + void stop_timer(); + + /** + * @brief Checks if the intermediate interval has passed. + * @return true if interval has passed, false otherwise. + */ + bool is_intermediate_interval_passed(); + + /** + * @brief Checks if the total interval has passed. + * @return true if interval has passed, false otherwise. + */ + bool is_total_interval_passed(); + +}; + +#endif // M2M_TIMER_H +``` + +The timer API functions are asynchronous in nature and whenever a timer event is available, `mbed-client` is notified, so that the library can act on the _timer expired_ signal. The callback is received through an Observer class defined in `M2MTimerObserver` . + +The file `m2mtimerobserver.h` is present in `mbed-client`. To see how the callback needs to be called, check the implementation in `m2mtimerimpl.cpp` in `mbed-client-linux`. + +``` +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ +#ifndef M2M_TIMER_OBSERVER_H +#define M2M_TIMER_OBSERVER_H + +/** + * Observer class for informing the parent class of the timer expiry. + */ +class M2MTimerObserver +{ +public: + /** + * \enum Defines the types of timer + * that can be created for mbed Client. + */ + typedef enum { + Notdefined, + Registration, + NsdlExecution, + PMinTimer, + PMaxTimer, + Dtls, + QueueSleep, + RetryTimer + }Type; + + /** + * \brief Indicates that the timer has expired. + * \param type The type of the timer that has expired. + */ + virtual void timer_expired(M2MTimerObserver::Type type = + M2MTimerObserver::Notdefined) = 0; +}; + +#endif // M2M_TIMER_OBSERVER_H +``` + +## Modifying the `json` file in the `mbed-client` module + +You need to add your target name to `module.json` so that when you set `yt target `, yotta can resolve the dependency correctly and link the main library with your module. + +Two platforms, mbed OS and Linux, are already supported. You just need to add your module support after that. + +``` +{ + "name": "mbed-client", + "version": "1.12.0", + "description": "Mbed Client API", + "private": true, + "keywords": [], + "author": "XXX XXX ", + "homepage": "https://github.com/ARMmbed/mbed-client", + "licenses": [ + { + "url": "https://spdx.org/licenses/Apache-2.0", + "type": "Apache-2.0" + } + ], + "dependencies": { + "mbed-client-c": "^2.0.0" + }, + "targetDependencies": { + "arm": { + "mbed-client-mbed": "^3.0.0" + }, + "linux": { + "mbed-client-linux": "^3.0.0" + }, + "" : { + "mbed-client-platform": "" + }, + } +} +``` + +## Testing and verification + +You can build your mbed-client port immediately: + +``` +# use the target we previously made locally available (not necessary if your target has been published): +yotta link-target +# build! +yotta build +``` + +A `helloworld-mbedclient` program will be produced inside the `build//test/` directory. This test application may require some changes to compile and run for your platform. Check for compilation errors. If you find any, fix the test application for your testing. + +Follow the `readme` [instructions](https://github.com/ARMmbed/mbed-client-linux-example) of the `mbed-client-linux` example to see what the test application can do. diff --git a/features/FEATURE_CLIENT/mbed-client/docs/release-note-mbed-client-1511.md b/features/FEATURE_CLIENT/mbed-client/docs/release-note-mbed-client-1511.md new file mode 100644 index 0000000000..53de0ca46c --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/docs/release-note-mbed-client-1511.md @@ -0,0 +1,56 @@ +# mbed Client 15.11 Technology Preview Release Note + +This is the first Technology Preview of mbed Client, which is available for mbed OS as well as Linux. We’re actively working on mbed Client and we expect to make exciting changes in the next six months. We’re making this technology preview available so you can see the trajectory we’re on. Our focus in this release is on laying the foundation for mbed Client development and collaboration, particularly core tools, technology and testing. + +We expect mbed Client developers to be able to access, build and run example projects and to explore the underlying code. + +## About this release + +Note that this is a technology preview release, which means that this release is not yet suitable for volume production use. The software is still maturing, and a number of things may change, including module names, repository URLs, APIs, header file names and configuration parameters. We'll try to mitigate the impact that these changes have on your code where possible. + +Note that in this release we're changing our version numbering scheme for mbed Client releases, to a calendar-based (year and month YY.MM) scheme. This release (15.11) has previously been called 3.0 in some communications. + +## Collaboration + +We’re building mbed Client as a collaborative project, bringing together industry and open source community contributions. If you’d like to work on mbed Client with us, we’d encourage you [to pitch in](https://github.com/ARMmbed/mbed-os/blob/master/CONTRIBUTING.md). With this technology preview we’re ready to start receiving contributions back from the community. + +## Documentation + +To get started with mbed Client, please visit our [getting started guide](https://docs.mbed.com/docs/mbed-client-guide/en/latest/). + +## Changes since the last release + +This section documents the changes between this release and the earlier mbed Client Beta (15.09) release. + +This release contains the following new features: +Securely connect to mbed Device Server (mbed DS) over TCP connection through TLS. The supported secure connection includes Certificate mode. We still support non-secure connection mode for fast development and debugging. + +New LWM2M Firmware Object class preview for application development. + +## Known issues + +The known issues for this release are described [on GitHub](https://github.com/ARMmbed/mbed-client/blob/master/docs/known-issues-mbed-client1511.md). + +## Other ways of accessing this release + +We prefer that you access and collaborate with mbed Client online. However, the release may also be downloaded as an archive [on mbed.com](https://www.mbed.com/en/development/software/mbed-client/releases/mbed-client1511/). + +# Module versions in this release + +This release comprises the following yotta modules and their versions: + + +| Module | Version | +|----------------------------------|------------| +| `mbed-client` | 1.2.1 | +| `mbed-client-c` | 1.1.1 | +| `mbed-client-libservice` | 3.0.8 | +| `mbed-client-linux` | 1.1.0 | +| `mbed-client-linux-example` | 1.0.0 | +| `mbedtls` | 2.2.0 | +| `mbed-client-mbed-tls` | 1.0.9 | +| `target-x86-linux-native` | 1.0.0 | +| `target-linux-native` | 1.0.0 | + + + diff --git a/features/FEATURE_CLIENT/mbed-client/doxygen/mbedclient_doxy b/features/FEATURE_CLIENT/mbed-client/doxygen/mbedclient_doxy new file mode 100644 index 0000000000..6d6e8ad126 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/doxygen/mbedclient_doxy @@ -0,0 +1,1850 @@ +# 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 = mbed-client + +# 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 = + +# 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 = "mbed Client C++ library" + +# 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 = 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, 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 = NO + +# 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 = NO + +# 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 = YES + +# 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 = YES + +# 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 = YES + +# 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 = YES + +# 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 = YES + +# 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 = 18 + +# 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 = + +# 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 = ../mbed-client + +# 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 + +# 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 = YES + +# 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 = */config/* +EXCLUDE_PATTERNS += */docs/* +EXCLUDE_PATTERNS += */doxygen/* +EXCLUDE_PATTERNS += */source/* +EXCLUDE_PATTERNS += */test/* + +# 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 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 = + +# 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 = NO + +# 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 = YES + +# 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 = YES + +# 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 = 44 + +# 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/features/FEATURE_CLIENT/mbed-client/get_sizes.sh b/features/FEATURE_CLIENT/mbed-client/get_sizes.sh new file mode 100755 index 0000000000..496d331bf6 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/get_sizes.sh @@ -0,0 +1,88 @@ +#!/bin/bash +# Copyright (c) 2016 ARM Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# * http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +echo +echo "Build mbed Client API for executable size collection" +echo + +BUILD_TARGET="frdm-k64f-armcc" + +yt target $BUILD_TARGET +yt build + +SIZE_CMD="size --totals" + +OUTPUT_PATH="results/" +OUTPUT_FILE_POSTFIX="_${BUILD_TARGET}_size.txt" + +MAIN_MODULE_NAME="mbed-client" + +# yotta dependencies +YOTTA_DEPS=( + 'cmsis-core' + 'cmsis-core-k64f' + 'core-util' + 'dlmalloc' + 'greentea-client' + 'mbed-client-c' + 'mbed-client-mbed-os' + 'mbed-client-mbedtls' + 'mbed-drivers' + 'mbed-hal' + 'mbed-hal-frdm-k64f' + 'mbed-hal-k64f' + 'mbed-hal-ksdk-mcu' + 'mbedtls' + 'mbed-trace' + 'minar' + 'minar-platform-mbed' + 'nanostack-libservice' + 'sal' + 'sal-driver-lwip-k64f-eth' + 'sal-iface-eth' + 'sal-stack-lwip' + 'sockets' + 'ualloc' + 'uvisor-lib' +) + + +# yotta dummy dependencies, which have different naming +YOTTA_DUMMY_DEPS=( + 'cmsis-core-freescale' + 'compiler-polyfill' + 'mbed-hal-freescale' + 'minar-platform' +) + + +echo "Writing object file size informations to ${OUTPUT_PATH}" + +# the "main" module is in build//source/.ar +${SIZE_CMD} ./build/${BUILD_TARGET}/source/${MAIN_MODULE_NAME}.ar >${OUTPUT_PATH}${MAIN_MODULE_NAME}${OUTPUT_FILE_POSTFIX} + +# these are the direct deps, found as build//ym//source/.ar +for MODULE in "${YOTTA_DEPS[@]}" +do + ${SIZE_CMD} ./build/${BUILD_TARGET}/ym/${MODULE}/source/${MODULE}.ar >${OUTPUT_PATH}${MODULE}${OUTPUT_FILE_POSTFIX} +done + +# dummy libs, which are named with different logic +for MODULE in "${YOTTA_DUMMY_DEPS[@]}" +do + # on paths the "-" char needs to be converted to "_" + MODULE_PATH=${MODULE//-/_} + ${SIZE_CMD} ./build/${BUILD_TARGET}/ym/${MODULE}/yotta_dummy_lib_${MODULE_PATH}/${MODULE}.ar >${OUTPUT_PATH}${MODULE}${OUTPUT_FILE_POSTFIX} +done diff --git a/features/FEATURE_CLIENT/mbed-client/include_dirs.mk b/features/FEATURE_CLIENT/mbed-client/include_dirs.mk new file mode 100644 index 0000000000..b45b09db66 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/include_dirs.mk @@ -0,0 +1,14 @@ +INCLUDE_DIRS := \ + ../ \ + . \ + ../../nsdl-c \ + ../../libService/libService \ + ../../libService/exported-libs/mbed-client-libservice \ + ../../libService \ + ../../mbedtls/include \ + ../lwm2m-client-linux \ + ../lwm2m-client-linux/source \ + ../lwm2m-client-mbedtls \ + source \ + + diff --git a/features/FEATURE_CLIENT/mbed-client/junit_xsl.xslt b/features/FEATURE_CLIENT/mbed-client/junit_xsl.xslt new file mode 100644 index 0000000000..7376b27f26 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/junit_xsl.xslt @@ -0,0 +1,101 @@ + + + + + + + + + +

+ Unittest report +

+ +

+ + Total tests run + , failures: + + + + + +

+
+ + +

+ +

+ + + + + + + + + + + +
Tests runTests failedOther errors
+
+ + + + + + + + +
Tests namePASS/FAILFailing caseReason
+
+ + + + + + + + + + + PASS + + + + + + + FAIL + + + + + + + + + + + + + + + + FAIL + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/functionpointer.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/functionpointer.h new file mode 100644 index 0000000000..e970e7dbf8 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/functionpointer.h @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 FUNCTIONPOINTER_H +#define FUNCTIONPOINTER_H + +#include +#include + + +/** A class for storing and calling a pointer to a static or member void function + */ +template +class FP0{ +public: + /** Create a Function Pointer, attaching a static function + * + * \param function The void static function to attach (default is none) + */ + FP0(R (*function)(void) = 0) { + attach(function); + } + + /** Create a FP, attaching a member function + * + * \param object The object pointer to invoke the member function on (i.e. the this pointer) + * \param function The address of the void member function to attach + */ + template + FP0(T *object, R (T::*member)(void)) { + attach(object, member); + } + + /** Attach a static function + * + * \param function The void static function to attach (default is none) + */ + void attach(R (*function)(void)) { + _p.function = function; + _membercaller = 0; + } + + /** Attach a member function + * + * \param object The object pointer to invoke the member function on (i.e. the this pointer) + * \param function The address of the void member function to attach + */ + template + void attach(T *object, R (T::*member)(void)) { + _p.object = static_cast(object); + *reinterpret_cast(_member) = member; + _membercaller = &FP0::membercaller; + } + + /** Call the attached static or member function + */ + R call(){ + if (_membercaller == 0 && _p.function) { + return _p.function(); + } else if (_membercaller && _p.object) { + return _membercaller(_p.object, _member); + } + return (R)0; + } + + typedef R (*static_fp)(); + static_fp get_function() const { + return (R(*)())_p.function; + } + + R operator ()(void) { + return call(); + } + operator bool(void) { + void *q = &_p.function; + return (_membercaller != NULL) && _p.object != NULL && (*static_cast(q) != NULL); + } + +private: + template + static void membercaller(void *object, uintptr_t *member) { + T* o = static_cast(object); + R (T::**m)(void) = reinterpret_cast(member); + (o->**m)(); + } + + union { + R (*function)(void); // static function pointer - 0 if none attached + void *object; // object this pointer - 0 if none attached + } _p; + uintptr_t _member[2]; // aligned raw member function pointer storage - converted back by registered _membercaller + R (*_membercaller)(void*, uintptr_t*); // registered membercaller function to convert back and call _m.member on _object +}; + +/* If we had variadic templates, this wouldn't be a problem, but until C++11 is enabled, we are stuck with multiple classes... */ + +/** A class for storing and calling a pointer to a static or member void function + */ +template +class FP1{ +public: + /** Create a FP, attaching a static function + * + * \param function The void static function to attach (default is none) + */ + FP1(R (*function)(A1) = 0) { + attach(function); + } + + /** Create a FP, attaching a member function + * + * \param object The object pointer to invoke the member function on (i.e. the this pointer) + * \param function The address of the void member function to attach + */ + template + FP1(T *object, R (T::*member)(A1)) { + attach(object, member); + } + + /** Attach a static function + * + * \param function The void static function to attach (default is none) + */ + void attach(R (*function)(A1)) { + _p.function = function; + _membercaller = 0; + } + + /** Attach a member function + * + * \param object The object pointer to invoke the member function on (i.e. the this pointer) + * \param function The address of the void member function to attach + */ + template + void attach(T *object, R (T::*member)(A1)) { + _p.object = static_cast(object); + *reinterpret_cast(_member) = member; + _membercaller = &FP1::membercaller; + } + + /** Call the attached static or member function + */ + R call(A1 a){ + if (_membercaller == 0 && _p.function) { + return _p.function(a); + } else if (_membercaller && _p.object) { + return _membercaller(_p.object, _member, a); + } + return (R)0; + } + + typedef R (*static_fp)(); + static_fp get_function() const { + return (R(*)())_p.function; + } + + R operator ()(A1 a) { + return call(a); + } + operator bool(void) + { + void *q = &_p.function; + return (_membercaller != NULL) && _p.object != NULL && (*static_cast(q) != NULL); + } +private: + template + static void membercaller(void *object, uintptr_t *member, A1 a) { + T* o = static_cast(object); + R (T::**m)(A1) = reinterpret_cast(member); + (o->**m)(a); + } + + union { + R (*function)(A1); // static function pointer - 0 if none attached + void *object; // object this pointer - 0 if none attached + } _p; + uintptr_t _member[2]; // aligned raw member function pointer storage - converted back by registered _membercaller + R (*_membercaller)(void*, uintptr_t*, A1); // registered membercaller function to convert back and call _m.member on _object +}; + + + +typedef FP0 FP; + +#endif diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mbase.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mbase.h new file mode 100644 index 0000000000..62d6ef6154 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mbase.h @@ -0,0 +1,498 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_BASE_H +#define M2M_BASE_H + +// Support for std args +#include +#include "mbed-client/m2mconfig.h" +#include "mbed-client/m2mreportobserver.h" +#include "mbed-client/functionpointer.h" + +//FORWARD DECLARATION +struct sn_coap_hdr_; +typedef sn_coap_hdr_ sn_coap_hdr_s; +struct nsdl_s; + +typedef FP1 value_updated_callback; +typedef void(*value_updated_callback2) (const char* object_name); +class M2MObservationHandler; +class M2MReportHandler; + +/** + * \brief M2MBase. + * This class is the base class based on which all LWM2M object models + * can be created. This serves base class for Object, ObjectInstances and Resources. + */ + + + +class M2MBase : public M2MReportObserver { + +public: + + /** + * Enum to define the type of object. + */ + typedef enum { + Object = 0x0, + Resource = 0x1, + ObjectInstance = 0x2, + ResourceInstance = 0x3 + } BaseType; + + /** + * Enum to define observation level. + */ + typedef enum { + None = 0x0, + R_Attribute = 0x01, + OI_Attribute = 0x02, + OIR_Attribute = 0x03, + O_Attribute = 0x04, + OR_Attribute = 0x05, + OOI_Attribute = 0x06, + OOIR_Attribute = 0x07 + } Observation; + + + /** + * \brief Enum defining an operation that can be + * supported by a given resource. + */ + typedef enum { + Static, + Dynamic, + Directory + }Mode; + + /** + * Enum defining an operation that can be + * supported by a given resource. + */ + typedef enum { + NOT_ALLOWED = 0x00, + GET_ALLOWED = 0x01, + PUT_ALLOWED = 0x02, + GET_PUT_ALLOWED = 0x03, + POST_ALLOWED = 0x04, + GET_POST_ALLOWED = 0x05, + PUT_POST_ALLOWED = 0x06, + GET_PUT_POST_ALLOWED = 0x07, + DELETE_ALLOWED = 0x08, + GET_DELETE_ALLOWED = 0x09, + PUT_DELETE_ALLOWED = 0x0A, + GET_PUT_DELETE_ALLOWED = 0x0B, + POST_DELETE_ALLOWED = 0x0C, + GET_POST_DELETE_ALLOWED = 0x0D, + PUT_POST_DELETE_ALLOWED = 0x0E, + GET_PUT_POST_DELETE_ALLOWED = 0x0F, + + }Operation; + +protected: + + // Prevents the use of default constructor. + M2MBase(); + + // Prevents the use of assignment operator. + M2MBase& operator=( const M2MBase& /*other*/ ); + + // Prevents the use of copy constructor + M2MBase( const M2MBase& /*other*/ ); + + /** + * \brief Constructor + * \param baseType Type of the object created + * \param name Name of the object + * \param id ID of the object + */ + M2MBase(const String &name, + M2MBase::Mode mode); +public: + + /** + * Destructor + */ + virtual ~M2MBase(); + + /** + * \brief Sets the operation type for an object. + * \param operation Operation to be set. + */ + virtual void set_operation(M2MBase::Operation operation); + + /** + * \brief Sets the interface description of the object. + * \param description Description to be set. + */ + virtual void set_interface_description(const String &description); + + /** + * \brief Sets the resource type of the object. + * \param resource_type Resource type to be set. + */ + virtual void set_resource_type(const String &resource_type); + + /** + * \brief Sets the CoAP content type of the object. + * \param content_type Content Type to be set based on + * CoAP specifications. + */ + virtual void set_coap_content_type(const uint8_t content_type); + + /** + * \brief Sets the observable mode for the object. + * \param observable Value for the observation. + */ + virtual void set_observable(bool observable); + + /** + * \brief Adds the observation level for the object. + * \param observation_level Level of the observation. + */ + virtual void add_observation_level(M2MBase::Observation observation_level); + + /** + * \brief Removes the observation level for the object. + * \param observation_level Level of the observation. + */ + virtual void remove_observation_level(M2MBase::Observation observation_level); + + /** + * \brief Sets the object under observation. + * \param observed Value for the observation. When true, starts observing. When false, ongoing observation is cancelled. + * \param handler Handler object for sending + * observation callbacks. + */ + virtual void set_under_observation(bool observed, + M2MObservationHandler *handler); + + /** + * \brief Sets the observation token value. + * \param token Pointer to the token of the resource. + * \param length Length of the token pointer. + */ + virtual void set_observation_token(const uint8_t *token, + const uint8_t length); + + /** + * \brief Sets the instance ID of the object. + * \param instance_id Instance ID of the object. + */ + virtual void set_instance_id(const uint16_t instance_id); + + /** + * Function is deprecated. Increment of observation number is done internally. + * \brief Sets the observation number of the object. + * \param observation_number Observation number of the object. + */ + virtual void set_observation_number(const uint16_t observation_number) + m2m_deprecated; + + /** + * \brief Sets the max age for the resource value to be cached. + * \param max_age Max age in seconds. + */ + virtual void set_max_age(const uint32_t max_age); + + /** + * \brief Returns object type. + * \return BaseType of the object. + */ + virtual M2MBase::BaseType base_type() const; + + /** + * \brief Returns the operation type of the object. + * \return Operation Supported operation on the object. + */ + virtual M2MBase::Operation operation() const; + + /** + * \brief Returns the object name. + * \return Name of the object. + */ + virtual const String &name() const; + + /** + * \brief Returns the object name in integer. + * \return Name of the object in integer. + */ + virtual int32_t name_id() const; + + /** + * \brief Returns the object's Instance ID. + * \returns Instance ID of the object. + */ + virtual uint16_t instance_id() const; + + /** + * \brief Returns the interface description of the object. + * \return Description of the object. + */ + virtual const String& interface_description() const; + + /** + * \brief Returns the resource type of the object. + * \return Resource type of the object. + */ + virtual const String& resource_type() const; + + /** + * \brief Returns the CoAP content type of the object. + * \return Content type of the object. + */ + virtual uint8_t coap_content_type() const; + + /** + * \brief Returns the observation status of the object. + * \return True if observable, else false. + */ + virtual bool is_observable() const; + + /** + * \brief Returns the observation level of the object. + * \return Observation level of the object. + */ + virtual M2MBase::Observation observation_level() const; + + /** + * \brief Provides the observation token of the object. + * \param value[OUT] A pointer to the value of the token. + * \param value_length[OUT] Length of the token pointer. + */ + virtual void get_observation_token(uint8_t *&token, uint32_t &token_length); + + /** + * \brief Returns the mode of the resource. + * \return Mode of the resource. + */ + virtual Mode mode() const; + + /** + * \brief Returns the observation number. + * \return Observation number of the object. + */ + virtual uint16_t observation_number() const; + + /** + * \brief Returns max age for the resource value to be cached. + * \return Max age in seconds. + */ + virtual uint32_t max_age() const; + + + /** + * \brief Parses the received query for the notification + * attribute. + * \param query The query that needs to be parsed. + * \return True if required attributes are present, else false. + */ + virtual bool handle_observation_attribute(char *&query); + + /** + * \brief Handles GET request for the registered objects. + * \param nsdl NSDL handler for the CoAP library. + * \param received_coap_header Received CoAP message from the server. + * \param observation_handler Handler object for sending + * observation callbacks. + * \return sn_coap_hdr_s The message that needs to be sent to server. + */ + virtual sn_coap_hdr_s* handle_get_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler = NULL); + /** + * \brief Handles PUT request for the registered objects. + * \param nsdl NSDL handler for the CoAP library. + * \param received_coap_header The received CoAP message from the server. + * \param observation_handler The handler object for sending + * observation callbacks. + * \param execute_value_updated True will execute "value_updated" callback. + * \return sn_coap_hdr_s The message that needs to be sent to server. + */ + virtual sn_coap_hdr_s* handle_put_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler, + bool &execute_value_updated); + + /** + * \brief Handles GET request for the registered objects. + * \param nsdl NSDL handler for the CoAP library. + * \param received_coap_header The received CoAP message from the server. + * \param observation_handler The handler object for sending + * observation callbacks. + * \param execute_value_updated True will execute "value_updated" callback. + * \return sn_coap_hdr_s The message that needs to be sent to server. + */ + virtual sn_coap_hdr_s* handle_post_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler, + bool &execute_value_updated); + + /** + * \brief Sets whether this resource will be published to server or not. + * \param register_uri True sets the resource as part of registration message. + */ + virtual void set_register_uri( bool register_uri); + + /** + * \brief Returns whether this resource will be published to server or not. + * \return True if the resource is part of the registration message, else false. + */ + virtual bool register_uri(); + + /** + * \brief Sets object URI path. + * \param path Object path + */ + virtual void set_uri_path(const String &path); + + /** + * \brief Returns the URI path of the object. + * \return URI path of the object. + */ + virtual const String &uri_path() const; + + /** + * @brief Returns whether this resource is under observation or not. + * @return True if the resource is under observation, else false, + */ + virtual bool is_under_observation() const; + + /** + * @brief Sets the function that is executed when this + * object receives a PUT or POST command. + * @param callback The function pointer that is called. + */ + virtual void set_value_updated_function(value_updated_callback callback); + + /** + * @brief Sets the function that is executed when this + * object receives a PUT or POST command. + * @param callback The function pointer that is called. + */ + virtual void set_value_updated_function(value_updated_callback2 callback); + + /** + * @brief Returns whether callback function is set or not. + * @return True if the callback function is set, else false. + */ + virtual bool is_value_updated_function_set(); + + /** + * @brief Calls the function that is set in "set_value_updated_function". + * @param name Name of the object. + */ + virtual void execute_value_updated(const String& name); + +protected : // from M2MReportObserver + + virtual void observation_to_be_sent(m2m::Vector changed_instance_ids, + bool send_object = false); + +protected: + + /** + * \brief Sets the Base type for object. + * \param type The type of the base object. + */ + virtual void set_base_type(M2MBase::BaseType type); + + /** + * \brief Removes the resource from the CoAP structure. + * \param resource_name The name of the resource. + */ + virtual void remove_resource_from_coap(const String &resource_name); + + /** + * \brief Removes an object from the NSDL list. + */ + virtual void remove_object_from_coap(); + + /** + * \brief Memory allocation required for libCoap. + * \param size The size of memory to be reserved. + */ + virtual void* memory_alloc(uint32_t size); + + /** + * \brief Memory free functions required for libCoap. + * \param ptr The Object whose memory needs to be freed. + */ + virtual void memory_free(void *ptr); + + /** + * \brief Allocate (size + 1) amount of memory, copy size bytes into + * it and add zero termination. + * \param source Source string to copy, may not be NULL. + * \param size The size of memory to be reserved. + */ + virtual uint8_t* alloc_string_copy(const uint8_t* source, uint32_t size); + + /** + * \brief Allocate (size) amount of memory, copy size bytes into it. + * \param source Source buffer to copy, may not be NULL. + * \param size The size of memory to be reserved. + */ + virtual uint8_t* alloc_copy(const uint8_t* source, uint32_t size); + + /** + * \brief Returns the Report Handler object. + * \return M2MReportHandler object. + */ + M2MReportHandler* report_handler(); + + /** + * \brief Returns the Observation Handler object. + * \return M2MObservationHandler object. + */ + M2MObservationHandler* observation_handler(); + +private: + + static bool is_integer(const String &value); + +private: + + M2MReportHandler *_report_handler; + M2MObservationHandler *_observation_handler; + String _name; + String _resource_type; + String _interface_description; + String _uri_path; + int32_t _name_id; + uint32_t _max_age; + uint16_t _instance_id; + uint16_t _observation_number; + uint8_t *_token; + uint8_t _token_length; + uint8_t _coap_content_type; + M2MBase::Operation _operation; + M2MBase::Mode _mode; + M2MBase::BaseType _base_type; + M2MBase::Observation _observation_level; + bool _observable; + bool _register_uri; + bool _is_under_observation; + value_updated_callback _value_updated_callback; + FP1 *_function_pointer; + +friend class Test_M2MBase; + +}; + +#endif // M2M_BASE_H + diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mconfig.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mconfig.h new file mode 100644 index 0000000000..cd27cbf775 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mconfig.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2MCONFIG_H +#define M2MCONFIG_H + +#include +#include +#include +#include "mbed-client/m2mstring.h" +using namespace m2m; + +#ifdef YOTTA_CFG_RECONNECTION_COUNT +#define MBED_CLIENT_RECONNECTION_COUNT YOTTA_CFG_RECONNECTION_COUNT +#elif defined MBED_CONF_MBED_CLIENT_RECONNECTION_COUNT +#define MBED_CLIENT_RECONNECTION_COUNT MBED_CONF_MBED_CLIENT_RECONNECTION_COUNT +#else +#define MBED_CLIENT_RECONNECTION_COUNT 3 +#endif + +#ifdef YOTTA_CFG_RECONNECTION_INTERVAL +#define MBED_CLIENT_RECONNECTION_INTERVAL YOTTA_CFG_RECONNECTION_INTERVAL +#elif defined MBED_CONF_MBED_CLIENT_RECONNECTION_INTERVAL +#define MBED_CLIENT_RECONNECTION_INTERVAL MBED_CONF_MBED_CLIENT_RECONNECTION_INTERVAL +#else +#define MBED_CLIENT_RECONNECTION_INTERVAL 5 +#endif + +#ifdef YOTTA_CFG_TCP_KEEPALIVE_TIME +#define MBED_CLIENT_TCP_KEEPALIVE_TIME YOTTA_CFG_TCP_KEEPALIVE_TIME +#elif defined MBED_CONF_MBED_CLIENT_TCP_KEEPALIVE_TIME +#define MBED_CLIENT_TCP_KEEPALIVE_TIME MBED_CONF_MBED_CLIENT_TCP_KEEPALIVE_TIME +#else +#define MBED_CLIENT_TCP_KEEPALIVE_TIME 300 +#endif + +#ifdef YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE +#define MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE +#elif defined MBED_CONF_MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +#define MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE MBED_CONF_MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +#endif + +#if defined (__ICCARM__) +#define m2m_deprecated +#else +#define m2m_deprecated __attribute__ ((deprecated)) +#endif + +// This is valid for mbed-client-mbedtls +// For other SSL implementation there +// can be other + +/* +*\brief A callback function for Random number +* required by the mbed-client-mbedtls module. +*/ +typedef uint32_t (*random_number_cb)(void) ; + +/* +*\brief An entropy structure for mbedtls entropy source. +* \param entropy_source_ptr Entropy function. +* \param p_source Function data. +* \param threshold Minimum required from source before entropy is released +* (with mbedtls_entropy_func()) (in bytes). +* \param strong MBEDTLS_ENTROPY_SOURCE_STRONG = 1 or +* MBEDTSL_ENTROPY_SOURCE_WEAK = 0. +* At least one strong source needs to be added. +* Weaker sources (such as the cycle counter) can be used as +* a complement. +*/ +typedef struct mbedtls_entropy { + int (*entropy_source_ptr)(void *, unsigned char *,size_t , size_t *); + void *p_source; + size_t threshold; + int strong; +}entropy_cb; + + +#endif // M2MCONFIG_H diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mconnectionhandler.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mconnectionhandler.h new file mode 100644 index 0000000000..683d24c17f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mconnectionhandler.h @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_CONNECTION_HANDLER_H__ +#define M2M_CONNECTION_HANDLER_H__ + +#include "mbed-client/m2mconnectionobserver.h" +#include "mbed-client/m2mconfig.h" +#include "mbed-client/m2minterface.h" +#include "nsdl-c/sn_nsdl.h" + +class M2MConnectionSecurity; +class M2MConnectionHandlerPimpl; + +/** + * \brief M2MConnectionHandler. + * This class handles the socket connection for the LWM2M Client. + */ + +class M2MConnectionHandler { +public: + + /** + * @enum ConnectionError + * This enum defines an error that can come from + * socket read and write operation. + */ + typedef enum { + CONNECTION_ERROR_WANTS_READ = -1000, + CONNECTION_ERROR_WANTS_WRITE = -1001, + ERROR_NONE = 0, + SSL_CONNECTION_ERROR, + SOCKET_READ_ERROR, + SOCKET_SEND_ERROR, + SOCKET_ABORT, + DNS_RESOLVING_ERROR, + SSL_HANDSHAKE_ERROR + }ConnectionError; + + +public: + + /** + * \brief Constructor + */ + M2MConnectionHandler(M2MConnectionObserver &observer, + M2MConnectionSecurity* sec, + M2MInterface::BindingMode mode, + M2MInterface::NetworkStack stack); + + /** + * \brief Destructor + */ + ~M2MConnectionHandler(); + + /** + * \brief This binds the socket connection. + * \param listen_port Port to be listened to for an incoming connection. + * \return True if successful, else false. + */ + bool bind_connection(const uint16_t listen_port); + + /** + * \brief This resolves the server address. Output is + * returned through a callback. + * \param String The server address. + * \param uint16_t The server port. + * \param ServerType The server type to be resolved. + * \param security The M2MSecurity object that determines which + * type of secure connection will be used by the socket. + * \return True if address is valid, else false. + */ + bool resolve_server_address(const String& server_address, + const uint16_t server_port, + M2MConnectionObserver::ServerType server_type, + const M2MSecurity* security); + + /** + * \brief Sends data to the connected server. + * \param data_ptr The data to be sent. + * \param data_len The length of data to be sent. + * \param address_ptr The address structure to which the data needs to be sent. + * \return True if data is sent successfully, else false. + */ + bool send_data(uint8_t *data_ptr, + uint16_t data_len, + sn_nsdl_addr_s *address_ptr); + + /** + * \brief Listens to the incoming data from a remote server. + * \return True if successful, else false. + */ + bool start_listening_for_data(); + + /** + * \brief Stops listening to the incoming data. + */ + void stop_listening(); + + /** + * \brief Sends directly to the socket. This is used by + * security classes to send the data after it has been encrypted. + * \param buf Buffer to send. + * \param len The length of the buffer. + * \return Number of bytes sent or -1 if failed. + */ + int send_to_socket(const unsigned char *buf, size_t len); + + /** + * \brief Receives directly from the socket. This + * is used by the security classes to receive raw data to be decrypted. + * \param buf Buffer to send. + * \param len The length of the buffer. + * \return Number of bytes read or -1 if failed. + */ + int receive_from_socket(unsigned char *buf, size_t len); + + /** + * \brief Closes the open connection. + */ + void close_connection(); + + /** + * \brief Error handling for DTLS connectivity. + * \param error Error code from the TLS library. + */ + void handle_connection_error(int error); + + /** + * \brief Sets the network interface handler that is used by client to connect + * to a network over IP.. + * \param handler A network interface handler that is used by client to connect. + * This API is optional but provides a mechanism for different platforms to + * manage usage of underlying network interface by client. + */ + void set_platform_network_handler(void *handler = NULL); + + /** + * \brief Claims mutex to prevent thread clashes + * in multithreaded environment. + */ + void claim_mutex(); + + /** + * \brief Releases mutex to prevent thread clashes + * in multithreaded environment. + */ + void release_mutex(); + +private: + + M2MConnectionObserver &_observer; + M2MConnectionHandlerPimpl *_private_impl; + +friend class Test_M2MConnectionHandler; +friend class Test_M2MConnectionHandler_mbed; +friend class Test_M2MConnectionHandler_linux; +friend class M2MConnection_TestObserver; +}; + +#endif //M2M_CONNECTION_HANDLER_H__ + diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mconnectionobserver.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mconnectionobserver.h new file mode 100644 index 0000000000..8068b2e77d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mconnectionobserver.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_CONNECTION_OBSERVER_H__ +#define M2M_CONNECTION_OBSERVER_H__ + +#include "mbed-client/m2minterface.h" + +/** + * \brief M2MConnectionObserver + * Observer class for informing socket activity to the state machine. + */ + +class M2MConnectionObserver +{ + +public : + + /** + * \enum ServerType, Defines the type of the + * server that the client wants to use. + */ + typedef enum { + Bootstrap, + LWM2MServer + }ServerType; + + /** + * \brief The M2MSocketAddress struct. + * Unified container for holding socket address data + * across different platforms. + */ + struct SocketAddress{ + M2MInterface::NetworkStack _stack; + void *_address; + uint8_t _length; + uint16_t _port; + }; + + /** + * \brief Indicates that data is available from socket. + * \param data The data read from the socket. + * \param data_size The length of the data read from the socket. + * \param address The address of the server where the data is coming from. + */ + virtual void data_available(uint8_t* data, + uint16_t data_size, + const M2MConnectionObserver::SocketAddress &address) = 0; + + /** + * \brief Indicates an error occured in socket. + * \param error_code The error code from socket, it cannot be used any further. + * \param retry Indicates whether to re-establish connection. + */ + virtual void socket_error(uint8_t error_code, bool retry = true) = 0; + + /** + * \brief Indicates that the server address resolving is ready. + * \param address The resolved socket address. + * \param server_type The type of the server. + * \param server_port The port of the resolved server address. + */ + virtual void address_ready(const M2MConnectionObserver::SocketAddress &address, + M2MConnectionObserver::ServerType server_type, + const uint16_t server_port) = 0; + + /** + * \brief Indicates that data has been sent successfully. + */ + virtual void data_sent() = 0; +}; + +#endif // M2M_CONNECTION_OBSERVER_H__ diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mconnectionsecurity.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mconnectionsecurity.h new file mode 100644 index 0000000000..53d4ac2991 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mconnectionsecurity.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 __M2M_CONNECTION_SECURITY_H__ +#define __M2M_CONNECTION_SECURITY_H__ + +#include "mbed-client/m2mconfig.h" +class M2MConnectionHandler; +class M2MSecurity; +class M2MConnectionSecurityPimpl; + +/** + * \brief M2MConnectionSecurity. + * This class provides a method to create a secure socket connection + * to handle connectivity for the mbed Client. It will handle sending, receiving + * and establishing a secure connection for mbed Client on top of the + * normal socket connection. + */ + +class M2MConnectionSecurity { +public: + typedef enum { + NO_SECURITY = 0, + TLS, + DTLS + } SecurityMode; + +private: + // Prevents the use of assignment operator by accident. + M2MConnectionSecurity& operator=( const M2MConnectionSecurity& /*other*/ ); + // Prevents the use of copy constructor by accident. + M2MConnectionSecurity( const M2MConnectionSecurity& /*other*/ ); + +public: + /** + * \brief Default Constructor. + */ + M2MConnectionSecurity(SecurityMode mode); + + /** + * \brief Default Destructor. + */ + ~M2MConnectionSecurity(); + + /** + * \brief Resets the socket connection states. + */ + void reset(); + + /** + * \brief Initiatlizes the socket connection states. + */ + int init(const M2MSecurity *security); + + /** + * \brief Starts the connection in non-blocking mode. + * \param connHandler The ConnectionHandler object that maintains the socket. + * \return Returns the state of the connection. Successful or not. + */ + int start_connecting_non_blocking(M2MConnectionHandler* connHandler); + + /** + * \brief Continues connectivity logic for secure connection. + * \return Returns an error code if any while continuing the connection sequence. + */ + int continue_connecting(); + + /** + * \brief Connects the client to the server. + * \param connHandler The ConnectionHandler object that maintains the socket. + * \return Returns the state of the connection. Successful or not. + */ + int connect(M2MConnectionHandler* connHandler); + + /** + * \brief Sends data to the server. + * \param message The data to be sent. + * \param len The length of the data. + * \return Indicates whether the data is sent successfully or not. + */ + int send_message(unsigned char *message, int len); + + /** + * \brief Reads the data received from the server. + * \param message The data to be read. + * \param len The length of the data. + * \return Indicates whether the data is read successfully or not. + */ + int read(unsigned char* buffer, uint16_t len); + + /** + * \brief Sets the function callback that is called by mbed-client to + * fetch a random number from an application to ensure strong entropy. + * \param random_callback A function pointer that is called by mbed-client + * while performing a secure handshake. + * The function signature should be uint32_t (*random_number_callback)(void); + */ + void set_random_number_callback(random_number_cb callback); + + /** + * \brief Sets the function callback that is called by mbed-client to + * provide an entropy source from an application to ensure strong entropy. + * \param entropy_callback A function pointer that is called by mbed-client + * while performing a secure handshake. + * Function signature, if using mbed-client-mbedtls, should be + * int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, + * size_t len, size_t *olen); + */ + void set_entropy_callback(entropy_cb callback); + +private: + + M2MConnectionSecurityPimpl* _private_impl; + + friend class Test_M2MConnectionSecurity; + //friend class Test_M2MConnectionSecurityImpl; +}; + +#endif //__M2M_CONNECTION_SECURITY_H__ diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mconstants.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mconstants.h new file mode 100644 index 0000000000..6a98b75aee --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mconstants.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2MCONSTANTS_H +#define M2MCONSTANTS_H + +#include +#include "m2mconfig.h" + +const int MAX_VALUE_LENGTH = 256; +const int BUFFER_LENGTH = 1152; + +const int32_t MINIMUM_REGISTRATION_TIME = 60; //in seconds +const uint64_t ONE_SECOND_TIMER = 1; +const uint16_t MAX_ALLOWED_STRING_LENGTH = 64; +const uint16_t OPTIMUM_LIFETIME = 3600; +const uint16_t REDUCE_LIFETIME = 900; +const float REDUCTION_FACTOR = 0.75f; + +// values per: draft-ietf-core-observe-16 +// OMA LWM2M CR ref. +#define START_OBSERVATION 0 +#define STOP_OBSERVATION 1 + +#define COAP "coap://" +#define COAPS "coaps://" +#define BOOTSTRAP_URI "bs" +// PUT attributes to be checked from server +#define EQUAL "=" +#define AMP "&" +#define PMIN "pmin" +#define PMAX "pmax" +#define GT "gt" +#define LT "lt" +#define ST_SIZE "st" +#define STP "stp" +#define CANCEL "cancel" + +// just a helper for "String default_value = "";" pattern +extern const String EMPTY; + +//LWM2MOBJECT NAME/ID +#define M2M_SECURITY_ID "0" +#define M2M_SERVER_ID "1" +#define M2M_ACCESS_CONTROL_ID "2" +#define M2M_DEVICE_ID "3" +#define M2M_CONNECTIVITY_MONITOR_ID "4" +#define M2M_FIRMWARE_ID "5" +#define M2M_LOCATION_ID "6" +#define M2M_CONNECTIVITY_STATISTICS_ID "7" +#define RESERVED_ID "8" + +//OMA RESOURCE TYPE +#define OMA_RESOURCE_TYPE "" //oma.lwm2m + +//DEVICE RESOURCES +#define DEVICE_MANUFACTURER "0" +#define DEVICE_DEVICE_TYPE "17" +#define DEVICE_MODEL_NUMBER "1" +#define DEVICE_SERIAL_NUMBER "2" +#define DEVICE_HARDWARE_VERSION "18" +#define DEVICE_FIRMWARE_VERSION "3" +#define DEVICE_SOFTWARE_VERSION "19" +#define DEVICE_REBOOT "4" +#define DEVICE_FACTORY_RESET "5" +#define DEVICE_AVAILABLE_POWER_SOURCES "6" +#define DEVICE_POWER_SOURCE_VOLTAGE "7" +#define DEVICE_POWER_SOURCE_CURRENT "8" +#define DEVICE_BATTERY_LEVEL "9" +#define DEVICE_BATTERY_STATUS "20" +#define DEVICE_MEMORY_FREE "10" +#define DEVICE_MEMORY_TOTAL "21" +#define DEVICE_ERROR_CODE "11" +#define DEVICE_RESET_ERROR_CODE "12" +#define DEVICE_CURRENT_TIME "13" +#define DEVICE_UTC_OFFSET "14" +#define DEVICE_TIMEZONE "15" +#define DEVICE_SUPPORTED_BINDING_MODE "16" +#define BINDING_MODE_UDP "U" +#define BINDING_MODE_UDP_QUEUE "UQ" +#define BINDING_MODE_SMS "S" +#define BINDING_MODE_SMS_QUEUE "SQ" +#define ERROR_CODE_VALUE "0" + +//SECURITY RESOURCES +#define SECURITY_M2M_SERVER_URI "0" +#define SECURITY_BOOTSTRAP_SERVER "1" +#define SECURITY_SECURITY_MODE "2" +#define SECURITY_PUBLIC_KEY "3" +#define SECURITY_SERVER_PUBLIC_KEY "4" +#define SECURITY_SECRET_KEY "5" +#define SECURITY_SMS_SECURITY_MODE "6" +#define SECURITY_SMS_BINDING_KEY "7" +#define SECURITY_SMS_BINDING_SECRET_KEY "8" +#define SECURITY_M2M_SERVER_SMS_NUMBER "9" +#define SECURITY_SHORT_SERVER_ID "10" +#define SECURITY_CLIENT_HOLD_OFF_TIME "11" + +//SERVER RESOURCES +#define SERVER_SHORT_SERVER_ID "0" +#define SERVER_LIFETIME "1" +#define SERVER_DEFAULT_MIN_PERIOD "2" +#define SERVER_DEFAULT_MAX_PERIOD "3" +#define SERVER_DISABLE "4" +#define SERVER_DISABLE_TIMEOUT "5" +#define SERVER_NOTIFICATION_STORAGE "6" +#define SERVER_BINDING "7" +#define SERVER_REGISTRATION_UPDATE "8" + +//FIRMWARE RESOURCES +#define FIRMWARE_PACKAGE "0" +#define FIRMWARE_PACKAGE_URI "1" +#define FIRMWARE_UPDATE "2" +#define FIRMWARE_STATE "3" +#define FIRMWARE_UPDATE_SUPPORTED_OBJECTS "4" +#define FIRMWARE_UPDATE_RESULT "5" +#define FIRMWARE_PACKAGE_NAME "6" +#define FIRMWARE_PACKAGE_VERSION "7" + +// TLV serializer / deserializer +const uint8_t TYPE_RESOURCE = 0xC0; +const uint8_t TYPE_MULTIPLE_RESOURCE = 0x80; +const uint8_t TYPE_RESOURCE_INSTANCE = 0x40; +const uint8_t TYPE_OBJECT_INSTANCE = 0x0; + +const uint8_t ID8 = 0x0; +const uint8_t ID16 = 0x20; + +const uint8_t LENGTH8 = 0x08; +const uint8_t LENGTH16 = 0x10; +const uint8_t LENGTH24 = 0x18; + +const uint8_t COAP_CONTENT_OMA_TLV_TYPE = 99; +const uint8_t COAP_CONTENT_OMA_JSON_TYPE = 100; +const uint8_t COAP_CONTENT_OMA_OPAQUE_TYPE = 42; + +const uint16_t MAX_UNINT_16_COUNT = 65535; + +#endif // M2MCONSTANTS_H diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mdevice.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mdevice.h new file mode 100644 index 0000000000..1b3098ee1d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mdevice.h @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_DEVICE_H +#define M2M_DEVICE_H + +#include "mbed-client/m2mobject.h" + +// FORWARD DECLARATION +class M2MResource; +class M2MResourceInstance; + +/** + * \brief M2MDevice. + * This class represents the Device Object model of the LWM2M framework. + * It provides an interface for handling the device object + * and all its corresponding resources. There can be only one instance + * of a Device Object. + */ +class M2MDevice : public M2MObject { + +friend class M2MInterfaceFactory; + +public: + + /** + * \brief Enum defining all the resources associated with the + * Device Object in the LWM2M framework. + */ + typedef enum { + Manufacturer, + DeviceType, + ModelNumber, + SerialNumber, + HardwareVersion, + FirmwareVersion, + SoftwareVersion, + Reboot, + FactoryReset, + AvailablePowerSources, + PowerSourceVoltage, + PowerSourceCurrent, + BatteryLevel, + BatteryStatus, + MemoryFree, + MemoryTotal, + ErrorCode, + ResetErrorCode, + CurrentTime, + UTCOffset, + Timezone, + SupportedBindingMode + }DeviceResource; + +private: + + /** + * Constructor + */ + M2MDevice(); + + // Prevents the use of assignment operator. + M2MDevice& operator=( const M2MDevice& /*other*/ ); + + // Prevents the use of copy constructor + M2MDevice( const M2MDevice& /*other*/ ); + + /** + * Destructor + */ + virtual ~M2MDevice(); + + static M2MDevice* get_instance(); + +public: + + /** + * \brief Deletes the M2MDevice instance. + */ + static void delete_instance(); + + /** + * \brief Creates a new resource for the given resource enum. + * \param resource With this function, the following resources can be created: + * 'Manufacturer', 'DeviceType','ModelNumber','SerialNumber', + * 'HardwareVersion', 'FirmwareVersion', 'SoftwareVersion', + * 'UTCOffset', 'Timezone', 'SupportedBindingMode'. + * \param value The value to be set on the resource, in String format. + * \return M2MResource if created successfully, else NULL. + */ + M2MResource* create_resource(DeviceResource resource, const String &value); + + /** + * \brief Creates a new resource for given resource enum. + * \param resource With this function, the following resources can be created: + * 'AvailablePowerSources','PowerSourceVoltage','PowerSourceCurrent', + * 'BatteryLevel', 'BatteryStatus', 'MemoryFree', 'MemoryTotal', + * 'ErrorCode', 'CurrentTime'. For 'CurrentTime', pass the time value in EPOCH format, for example + * 1438944683. + * \param value The value to be set on the resource, in Integer format. + * \return M2MResource if created successfully, else NULL. + */ + M2MResource* create_resource(DeviceResource resource, int64_t value); + + /** + * \brief Creates a new resource instance for given resource enum. + * \param resource With this function, the following resources can be created: + * 'AvailablePowerSources','PowerSourceVoltage','PowerSourceCurrent', + * 'ErrorCode'. + * \param value The value to be set on the resource, in Integer format. + * \return M2MResourceInstance if created successfully, else NULL. + */ + M2MResourceInstance* create_resource_instance(DeviceResource resource, int64_t value, + uint16_t instance_id); + + /** + * \brief Creates a new resource for given resource name. + * \param resource With this function, the following resources can be created: + * 'ResetErrorCode','FactoryReset'. + * \return M2MResource if created successfully, else NULL. + */ + M2MResource* create_resource(DeviceResource resource); + + /** + * \brief Deletes the resource with the given resource enum. + * Mandatory resources cannot be deleted. + * \param resource The name of the resource to be deleted. + * \return True if deleted, else false. + */ + bool delete_resource(DeviceResource resource); + + /** + * \brief Deletes the resource with the given resource enum. + * Mandatory resources cannot be deleted. + * \param resource The name of the resource to be deleted. + * \param instance_id The instance ID of the resource. + * \return True if deleted, else false. + */ + bool delete_resource_instance(DeviceResource resource, + uint16_t instance_id); + + /** + * \brief Sets the value of the given resource enum. + * \param resource With this function, a value can be set for the following resources: + * 'Manufacturer', 'DeviceType','ModelNumber','SerialNumber', + * 'HardwareVersion', 'FirmwareVersion', 'SoftwareVersion', + * 'UTCOffset', 'Timezone', 'SupportedBindingMode'. + * \param value The value to be set on the resource, in String format. + * \param instance_id The instance ID of the resource, default is 0. + * \return True if successfully set, else false. + */ + bool set_resource_value(DeviceResource resource, + const String &value, + uint16_t instance_id = 0); + + /** + * \brief Sets the value of the given resource enum. + * \param resource With this function, a value can be set for the following resources: + * 'AvailablePowerSources','PowerSourceVoltage','PowerSourceCurrent', + * 'BatteryLevel', 'BatteryStatus', 'MemoryFree', 'MemoryTotal', + * 'ErrorCode', 'CurrentTime'. + * \param value The value to be set on the resource, in Integer format. + * \param instance_id The instance ID of the resource, default is 0. + * \return True if successfully set, else false. + */ + bool set_resource_value(DeviceResource resource, + int64_t value, + uint16_t instance_id = 0); + + /** + * \brief Returns the value of the given resource enum, in String. + * \param resource With this function, the following resources can return a value: + * 'Manufacturer', 'DeviceType','ModelNumber','SerialNumber', + * 'HardwareVersion', 'FirmwareVersion', 'SoftwareVersion', + * 'UTCOffset', 'Timezone', 'SupportedBindingMode'. + * \param instance_id The instance ID of the resource, default is 0. + * \return The value associated with that resource. If the resource is not valid NULL is returned. + */ + String resource_value_string(DeviceResource resource, + uint16_t instance_id = 0) const; + + /** + * \brief Returns the value of the given resource key name, in Integer. + * \param resource With this function, the following resources can return a value: + * 'AvailablePowerSources','PowerSourceVoltage','PowerSourceCurrent', + * 'BatteryLevel', 'BatteryStatus', 'MemoryFree', 'MemoryTotal', + * 'ErrorCode', 'CurrentTime'. + * \param instance_id The instance ID of the resource, default is 0 + * \return The value associated with that resource. If the resource is not valid -1 is returned. + */ + int64_t resource_value_int(DeviceResource resource, + uint16_t instance_id = 0) const; + + /** + * \brief Indicates whether the resource instance with given resource enum exists or not. + * \param resource Resource enum. + * \return True if at least one instance exists, else false. + */ + bool is_resource_present(DeviceResource resource)const; + + /** + * \brief Returns the number of resources for the whole device object. + * \return Total number of resources belonging to the device object. + */ + uint16_t total_resource_count()const; + + /** + * \brief Returns the number of resources for a given resource enum. + * \param resource Resource enum. + * \return The number of resources for a given resource enum. Returns 1 for the + * mandatory resources. Can be 0 as well if no instances exist for an + * optional resource. + */ + uint16_t per_resource_count(DeviceResource resource)const; + +private: + + M2MResourceInstance* get_resource_instance(DeviceResource dev_res, + uint16_t instance_id) const; + + static const String resource_name(DeviceResource resource); + + bool check_value_range(DeviceResource resource, const int64_t value) const; + +private : + + M2MObjectInstance* _device_instance; //Not owned + +protected: + + static M2MDevice* _instance; + + friend class Test_M2MDevice; + friend class Test_M2MInterfaceFactory; +}; + +#endif // M2M_DEVICE_H + diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mfirmware.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mfirmware.h new file mode 100644 index 0000000000..dbfb896617 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mfirmware.h @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2MFIRMWARE_H +#define M2MFIRMWARE_H + +#include "mbed-client/m2mobject.h" + +// FORWARD DECLARATION +class M2MResource; +class M2MResourceInstance; + +/** + * \brief M2MFirmware. + * This class represents the Firmware Object model of the LWM2M framework. + * It provides an interface for handling the Firmware Object + * and all its corresponding resources. There can be only one instance + * of a Firmware Object. + */ +class M2MFirmware : public M2MObject { + +friend class M2MInterfaceFactory; + +public: + + /** + * \brief Enum defining all the resources associated with a + * Firmware Object in the LWM2M framework. + */ + typedef enum { + Package, + PackageUri, + Update, + State, + UpdateSupportedObjects, + UpdateResult, + PackageName, + PackageVersion + } FirmwareResource; + + /** + * \brief Enum defining the state of the firmware update. + */ + typedef enum { + Idle = 0, + Downloading, + Downloaded, + Updating + } UpdateState; + + /** + * \brief Enum defining the result of the firmware update. + */ + typedef enum { + Default = 0, + SuccessfullyUpdated, + NotEnoughSpace, + OutOfMemory, + ConnectionLost, + CRCCheckFailure, + UnsupportedPackageType, + InvalidURI + } ResultOfUpdate; + +private: + + /** + * Constructor + */ + M2MFirmware(); + + // Prevents the use of assignment operator. + M2MFirmware& operator=( const M2MFirmware& /*other*/ ); + + // Prevents the use of copy constructor. + M2MFirmware( const M2MFirmware& /*other*/ ); + + /** + * Destructor + */ + virtual ~M2MFirmware(); + + static M2MFirmware* get_instance(); + +public: + + /** + * \brief Deletes the M2MFirmware instance. + */ + static void delete_instance(); + + /** + * \brief Creates a new resource for given resource enum. + * \param resource With this function, the following resources can be created: + * 'PackageUri', 'PackageName','PackageVersion'. + * \param value The value to be set on the resource, in String format. + * \return M2MResource if created successfully, else NULL. + */ + M2MResource* create_resource(FirmwareResource resource, const String &value); + + /** + * \brief Creates a new resource for given resource enum. + * \param resource With this function, the following resources can be created: + * 'State','UpdateSupportedObjects','UpdateResult'. + * \param value The value to be set on the resource, in Integer format. + * \return M2MResource if created successfully, else NULL. + */ + M2MResource* create_resource(FirmwareResource resource, int64_t value); + + /** + * \brief Deletes the resource with the given resource enum. + * Mandatory resources cannot be deleted. + * \param resource The name of the resource to be deleted. + * \return True if deleted, else false. + */ + bool delete_resource(FirmwareResource resource); + + /** + * \brief Sets the value of the given resource enum. + * \param resource With this function, a value can be set on the following resources: + * 'Package', 'PackageUri', 'PackageName','PackageVersion'. + * \param value The value to be set on the resource, in String format. + * \return True if successfully set, else false. + */ + bool set_resource_value(FirmwareResource resource, + const String &value); + + /** + * \brief Sets the value of the given resource enum. + * \param resource With this function, a value can be set for the following resources: + * 'State','UpdateSupportedObjects','UpdateResult'. + * \param value The value to be set on the resource, in Integer format. + * \return True if successfully set, else false. + */ + bool set_resource_value(FirmwareResource resource, + int64_t value); + + /** + * \brief Sets the value of the given resource enum. + * \param resource With this function, a value can be set for the following resources: + * 'Package'. + * \param value The value to be set on the resource, in uint8_t format. + * \param size The size of the buffer value to be set on the resource. + * \return True if successfully set, else false. + */ + bool set_resource_value(FirmwareResource resource, + const uint8_t *value, + const uint32_t length); + + /** + * \brief Returns the value of the given resource enum, in String. + * \param resource With this function, the following resources can return value: + * 'PackageUri', 'PackageName','PackageVersion'. + * \return The value associated with that resource, if key is not valid it returns NULL. + */ + String resource_value_string(FirmwareResource resource) const; + + /** + * \brief Returns the value of the given resource key name, in Integer. + * \param resource With this function, the following resources can return a value: + * 'State','UpdateSupportedObjects','UpdateResult'. + * \return The value associated with that resource. If the resource is not valid -1 is returned. + */ + int64_t resource_value_int(FirmwareResource resource) const; + + /** + * \brief Populates the data buffer and returns the size of the buffer. + * \param resource With this function, the following resources can return a value: + * 'Package'. + * \param [OUT]data The data buffer containing the value. + * \return The size of the buffer populated. + */ + uint32_t resource_value_buffer(FirmwareResource resource, + uint8_t *&data) const; + + /** + * \brief Returns whether the resource instance with given resource enum exists or not. + * \param resource Resource enum. + * \return True if at least one instance exists, else false. + */ + bool is_resource_present(FirmwareResource resource) const; + + /** + * \brief Returns the number of resources for the whole firmware object. + * \return Total number of resources belonging to the firmware object. + */ + uint16_t total_resource_count() const; + + /** + * \brief Returns the number of resources for a given resource enum. + * \param resource Resource enum. + * \return The number of resources for a given resource enum. Returns 1 for the + * mandatory resources. Can be 0 as well if no instance exists for an + * optional resource. + */ + uint16_t per_resource_count(FirmwareResource resource) const; + + +private: + + M2MResource* get_resource(FirmwareResource resource) const; + + static const String resource_name(FirmwareResource resource); + + void create_mandatory_resources(); + + bool check_value_range(FirmwareResource resource, const int64_t value) const; + + void set_zero_value(M2MResource *resource); + +private : + + M2MObjectInstance* _firmware_instance; //Not owned + +protected: + + static M2MFirmware* _instance; + + friend class Test_M2MFirmware; + friend class Test_M2MInterfaceFactory; +}; + + +#endif // M2MFIRMWARE_H diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2minterface.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2minterface.h new file mode 100644 index 0000000000..3d20fe07de --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2minterface.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_INTERFACE_H +#define M2M_INTERFACE_H + +#include +#include "mbed-client/m2mvector.h" +#include "mbed-client/m2mconfig.h" +#include "mbed-client/functionpointer.h" + +//FORWARD DECLARATION +class M2MSecurity; +class M2MObject; +class M2MInterfaceObserver; + +typedef Vector M2MObjectList; +typedef FP callback_handler; + +/** + * \brief M2MInterface. + * This class provides an interface for handling all the mbed Client Interface operations + * defined in the OMA LWM2M specifications. + * This includes Bootstrapping, Client Registration, Device Management & + * Service Enablement and Information Reporting. + */ + +class M2MInterface { + +public: + + /** + * \brief Enum defining different kinds of errors + * that can occur during various client operations. + */ + typedef enum { + ErrorNone = 0, + AlreadyExists, + BootstrapFailed, + InvalidParameters, + NotRegistered, + Timeout, + NetworkError, + ResponseParseFailed, + UnknownError, + MemoryFail, + NotAllowed, + SecureConnectionFailed, + DnsResolvingFailed + }Error; + + /** + * \brief Enum defining different kinds of binding + * modes handled for client operations. + */ + typedef enum { + NOT_SET = 0, + UDP = 0x01, + UDP_QUEUE = 0x03, + SMS = 0x04, + SMS_QUEUE =0x06, + UDP_SMS_QUEUE = 0x07, + TCP = 0x08, //not real value, spec does not have one! + TCP_QUEUE = 0x09 //not real value, spec does not have one! + }BindingMode; + + /** + * \brief Enum defining different kinds of network + * stacks that can be used by mbed Client. + */ + typedef enum { + Uninitialized = 0, + LwIP_IPv4, + LwIP_IPv6, + Reserved, + Nanostack_IPv6, + ATWINC_IPv4, + Unknown + }NetworkStack; + +public: + + virtual ~M2MInterface(){} + + /** + * \brief Initiates bootstrapping of the client with the provided Bootstrap + * Server information. + * NOTE: This API is not supported for developers!! + * \param security_object The security object that contains information + * required for successful bootstrapping of the client. + */ + virtual void bootstrap(M2MSecurity *security_object) = 0; + + /** + * \brief Cancels the ongoing bootstrapping operation of the client. If the client has + * already successfully bootstrapped, this function deletes the existing + * bootstrap information from the client. + * NOTE: This API is not supported for developers!! + */ + virtual void cancel_bootstrap() = 0; + + /** + * \brief Initiates the registration of the provided Security object to the + * corresponding LWM2M server. + * \param security_object The security object that contains information + * required for registering to the LWM2M server. + * If the client wants to register to multiple LWM2M servers, it must call + * this function once for each of the LWM2M server objects separately. + * \param object_list Objects that contain information about the + * client attempting to register to the LWM2M server. + */ + virtual void register_object(M2MSecurity *security_object, const M2MObjectList &object_list) = 0; + + /** + * \brief Updates or refreshes the client's registration on the LWM2M + * server. + * \param security_object The security object from which the device object + * needs to update the registration. If there is only one LWM2M server registered, + * this parameter can be NULL. + * \param lifetime The lifetime of the endpoint client in seconds. If the same value + * has to be passed, set the default value to 0. + */ + virtual void update_registration(M2MSecurity *security_object, const uint32_t lifetime = 0) = 0; + + /** + * \brief Unregisters the registered object from the LWM2M server. + * \param security_object The security object from which the device object + * needs to be unregistered. If there is only one LWM2M server registered, + * this parameter can be NULL. + */ + virtual void unregister_object(M2MSecurity* security_object = NULL) = 0; + + /** + * \brief Sets the function that is called for indicating that the client + * is going to sleep when the Binding mode is selected with Queue mode. + * \param callback A function pointer that is called when the client + * goes to sleep. + */ + virtual void set_queue_sleep_handler(callback_handler handler) = 0; + + /** + * \brief Sets the function callback that is called by mbed-client to + * fetch a random number from an application to ensure strong entropy. + * \param random_callback A function pointer that is called by mbed-client + * while performing a secure handshake. + * The function signature should be uint32_t (*random_number_callback)(void); + */ + virtual void set_random_number_callback(random_number_cb callback) = 0; + + /** + * \brief Sets the function callback that is called by mbed-client to + * provide an entropy source from an application to ensure strong entropy. + * \param entropy_callback A function pointer that is called by mbed-client + * while performing a secure handshake. + * Function signature, if using mbed-client-mbedtls, should be + * int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, + * size_t len, size_t *olen); + */ + virtual void set_entropy_callback(entropy_cb callback) = 0; + + /** + * \brief Sets the network interface handler that is used by client to connect + * to a network over IP.. + * \param handler A network interface handler that is used by client to connect. + * This API is optional but provides a mechanism for different platforms to + * manage usage of underlying network interface by client. + */ + virtual void set_platform_network_handler(void *handler = NULL) = 0; +}; + +#endif // M2M_INTERFACE_H diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2minterfacefactory.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2minterfacefactory.h new file mode 100644 index 0000000000..d76ff5a88b --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2minterfacefactory.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_INTERFACE_FACTORY_H +#define M2M_INTERFACE_FACTORY_H + +#include +#include "mbed-client/m2msecurity.h" +#include "mbed-client/m2mresource.h" +#include "mbed-client/m2minterfaceobserver.h" + +//FORWARD DECLARATION +class M2MDevice; +class M2MServer; +class M2MInterfaceImpl; +class M2MFirmware; + +/** + * \brief M2MInterfaceFactory. + * This is a factory class that provides an interface for creating an mbed Client Interface + * object for an application to utilize the LWM2M features provided by the client. + */ + +class M2MInterfaceFactory { +private: + // Prevents the use of assignment operator by accident. + M2MInterfaceFactory& operator=( const M2MInterfaceFactory& /*other*/ ); + + // Prevents the use of copy constructor by accident + M2MInterfaceFactory( const M2MInterfaceFactory& /*other*/ ); + +public: + + /** + * \brief Creates an interface object for the mbed Client Inteface. With this, the + * client can handle client operations like Bootstrapping, Client + * Registration, Device Management and Information Reporting. + * \param endpoint_name The endpoint name of the mbed client. + * \param endpoint_type The endpoint type of the mbed client, default is empty. + * \param life_time The lifetime of the endpoint in seconds, + * if -1 it is optional. + * \param listen_port The listening port for the endpoint, default is 5683. + * \param domain The domain of the endpoint, default is empty. + * \param mode The binding mode of the endpoint, default is NOT_SET. + * \param stack The underlying network stack to be used for the connection, + * default is LwIP_IPv4. + * \param context_address The context address for M2M-HTTP, not used currently. + * \return M2MInterfaceImpl An object for managing other client operations. + */ + static M2MInterface *create_interface(M2MInterfaceObserver &observer, + const String &endpoint_name, + const String &endpoint_type = "", + const int32_t life_time = -1, + const uint16_t listen_port = 5683, + const String &domain = "", + M2MInterface::BindingMode mode = M2MInterface::NOT_SET, + M2MInterface::NetworkStack stack = M2MInterface::LwIP_IPv4, + const String &context_address = ""); + + /** + * \brief Creates a security object for the mbed Client Inteface. With this, the + * client can manage Bootstrapping and Client Registration. + * \param ServerType The type of the Security Object, bootstrap or LWM2M server. + * \return M2MSecurity An object for managing other client operations. + */ + static M2MSecurity *create_security(M2MSecurity::ServerType server_type); + + /** + * \brief Creates a server object for the mbed Client Inteface. With this, the + * client can manage the server resources used for client operations + * such as Client Registration, server lifetime etc. + * \return M2MServer An object for managing server client operations. + */ + static M2MServer *create_server(); + + /** + * \brief Creates a device object for the mbed Client Inteface. With this, the + * client can manage the device resources used for client operations + * such as Client Registration, Device Management and Information Reporting. + * \param name The name of the device object. + * \return M2MDevice An object for managing other client operations. + */ + static M2MDevice *create_device(); + + /** + * \brief Creates a firmware object for the mbed Client Inteface. With this, the + * client can manage the firmware resources used for the client operations + * such as Client Registration, Device Management and Information Reporting. + * \return M2MFirmware An object for managing other client operations. + */ + static M2MFirmware *create_firmware(); + + /** + * \brief Creates a generic object for the mbed Client Inteface. With this, the + * client can manage its own customized resources used for registering + * Device Management and Information Reporting for those resources. + * \param name The name of the object. + * \param id A unique ID for the object. It should be other than the reserved + * LWM2M object IDs. + * \return M2MObject An object for managing other mbed Client operations. + */ + static M2MObject *create_object(const String &name); + + + friend class Test_M2MInterfaceFactory; +}; + +#endif // M2M_INTERFACE_FACTORY_H diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2minterfaceobserver.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2minterfaceobserver.h new file mode 100644 index 0000000000..6fcb715e40 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2minterfaceobserver.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_INTERFACE_OBSERVER_H +#define M2M_INTERFACE_OBSERVER_H + +#include "mbed-client/m2mbase.h" +#include "mbed-client/m2minterface.h" + +//FORWARD DECLARATION +class M2MServer; + +/** + * \brief M2MInterfaceObserver + * This is an observer class that updates the calling application about + * various events associated with various Interface operations. + * Also, it informs about various errors that can occur during any of the above + * operations. + */ +class M2MInterfaceObserver { + +public: + + /** + * \brief A callback indicating that the bootstap has been performed successfully. + * \param server_object The server object that contains information fetched + * about the LWM2M server from the bootstrap server. This object can be used + * to register to the LWM2M server. The object ownership is passed. + */ + virtual void bootstrap_done(M2MSecurity *server_object) = 0; + + /** + * \brief A callback indicating that the device object has been registered + * successfully to the LWM2M server. + * \param security_object The server object on which the device object is + * registered. The object ownership is passed. + * \param server_object An object containing information about the LWM2M server. + * The client maintains the object. + */ + virtual void object_registered(M2MSecurity *security_object, const M2MServer &server_object) = 0; + + /** + * \brief A callback indicating that the device object has been successfully unregistered + * from the LWM2M server. + * \param server_object The server object from which the device object is + * unregistered. The object ownership is passed. + */ + virtual void object_unregistered(M2MSecurity *server_object) = 0; + + /** + * \brief A callback indicating that the device object registration has been successfully + * updated on the LWM2M server. + * \param security_object The server object on which the device object registration + * updated. The object ownership is passed. + * \param server_object An object containing information about the LWM2M server. + * The client maintains the object. + */ + virtual void registration_updated(M2MSecurity *security_object, const M2MServer & server_object) = 0; + + /** + * \brief A callback indicating that there was an error during the operation. + * \param error An error code for the occurred error. + */ + virtual void error(M2MInterface::Error error) = 0; + + /** + * \brief A callback indicating that the value of the resource object is updated by the server. + * \param base The object whose value is updated. + * \param type The type of the object. + */ + virtual void value_updated(M2MBase *base, M2MBase::BaseType type) = 0; +}; + +#endif // M2M_INTERFACE_OBSERVER_H diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mobject.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mobject.h new file mode 100644 index 0000000000..4aafa07939 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mobject.h @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_OBJECT_H +#define M2M_OBJECT_H + +#include "mbed-client/m2mvector.h" +#include "mbed-client/m2mbase.h" +#include "mbed-client/m2mobjectinstance.h" + +//FORWARD DECLARATION +typedef Vector M2MObjectInstanceList; + +/** + * \brief M2MObject. + * This class is the base class for the mbed Client Objects. All defined + * LWM2M object models can be created based on it. This class also holds all object + * instances associated with the given object. + */ + +class M2MObject : public M2MBase, + public M2MObjectCallback +{ + +friend class M2MInterfaceFactory; + +protected : + + /** + * \brief Constructor + * \param name The name of the object. + */ + M2MObject(const String &object_name); + + // Prevents the use of default constructor. + M2MObject(); + + // Prevents the use of assignment operator. + M2MObject& operator=( const M2MObject& /*other*/ ); + + // Prevents the use of copy constructor. + M2MObject( const M2MObject& /*other*/ ); + +public: + + /** + * \brief Destructor + */ + virtual ~M2MObject(); + + /** + * \brief Creates a new object instance for a given mbed Client Interface object. With this, + * the client can respond to server's GET methods with the provided value. + * \return M2MObjectInstance. An object instance for managing other client operations. + */ + M2MObjectInstance* create_object_instance(uint16_t instance_id = 0); + + /** + * \brief Removes the object instance resource with the given instance id. + * \param instance_id The instance ID of the object instance to be removed, default is 0. + * \return True if removed, else false. + */ + virtual bool remove_object_instance(uint16_t instance_id = 0); + + /** + * \brief Returns the object instance with the the given instance ID. + * \param instance_id The instance ID of the requested object instance ID, default is 0. + * \return Object instance reference if found, else NULL. + */ + virtual M2MObjectInstance* object_instance(uint16_t instance_id = 0) const; + + /** + * \brief Returns a list of object instances. + * \return A list of object instances. + */ + virtual const M2MObjectInstanceList& instances() const; + + /** + * \brief Returns the total number of object instances- + * \return The total number of the object instances. + */ + virtual uint16_t instance_count() const; + + /** + * \brief Returns the object type. + * \return BaseType. + */ + virtual M2MBase::BaseType base_type() const; + + /** + * \brief Adds the observation level for the object. + * \param observation_level The level of observation. + */ + virtual void add_observation_level(M2MBase::Observation observation_level); + + /** + * \brief Removes the observation level from the object. + * \param observation_level The level of observation. + */ + virtual void remove_observation_level(M2MBase::Observation observation_level); + + /** + * \brief Handles GET request for the registered objects. + * \param nsdl The NSDL handler for the CoAP library. + * \param received_coap_header The CoAP message received from the server. + * \param observation_handler The handler object for sending + * observation callbacks. + * \return sn_coap_hdr_s The message that needs to be sent to server. + */ + virtual sn_coap_hdr_s* handle_get_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler = NULL); + + /** + * \brief Handles PUT request for the registered objects. + * \param nsdl The NSDL handler for the CoAP library. + * \param received_coap_header The received CoAP message from the server. + * \param observation_handler The handler object for sending + * observation callbacks. + * \param execute_value_updated True will execute the "value_updated" callback. + * \return sn_coap_hdr_s The message that needs to be sent to server. + */ + virtual sn_coap_hdr_s* handle_put_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler, + bool &execute_value_updated); + + /** + * \brief Handles GET request for the registered objects. + * \param nsdl The NSDL handler for the CoAP library. + * \param received_coap_header The received CoAP message from the server. + * \param observation_handler The handler object for sending + * observation callbacks. + * \param execute_value_updated True will execute the "value_updated" callback. + * \return sn_coap_hdr_s The message that needs to be sent to server. + */ + virtual sn_coap_hdr_s* handle_post_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler, + bool &execute_value_updated); + +protected : + + virtual void notification_update(uint16_t obj_instance_id); + +private: + + M2MObjectInstanceList _instance_list; // owned + uint16_t _max_instance_count; + +friend class Test_M2MObject; +friend class Test_M2MInterfaceImpl; +friend class Test_M2MNsdlInterface; +friend class Test_M2MTLVSerializer; +friend class Test_M2MTLVDeserializer; + +}; + +#endif // M2M_OBJECT_H diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mobjectinstance.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mobjectinstance.h new file mode 100644 index 0000000000..bb2a1f3498 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mobjectinstance.h @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_OBJECT_INSTANCE_H +#define M2M_OBJECT_INSTANCE_H + +#include "mbed-client/m2mvector.h" +#include "mbed-client/m2mresource.h" + +//FORWARD DECLARATION +typedef Vector M2MResourceList; +typedef Vector M2MResourceInstanceList; + +class M2MObjectCallback { +public: + virtual void notification_update(uint16_t obj_instance_id) = 0; +}; + +/** + * \brief M2MObjectInstance. + * This class is the instance class for mbed Client Objects. All defined + * LWM2M object models can be created based on it. This class also holds all resource + * instances associated with the given object. + */ + +class M2MObjectInstance : public M2MBase, + public M2MObjectInstanceCallback +{ + +friend class M2MObject; + +private: // Constructor and destructor are private which means + // that these objects can be created or + // deleted only through function provided by M2MObject. + + /** + * \brief Constructor + * \param name Name of the object + */ + M2MObjectInstance(const String &object_name, + M2MObjectCallback &object_callback); + + + // Prevents the use of default constructor. + M2MObjectInstance(); + + // Prevents the use of assignment operator. + M2MObjectInstance& operator=( const M2MObjectInstance& /*other*/ ); + + // Prevents the use of copy constructor. + M2MObjectInstance( const M2MObjectInstance& /*other*/ ); + + /** + * Destructor + */ + virtual ~M2MObjectInstance(); + +public: + + /** + * \brief Creates a static resource for a given mbed Client Inteface object. With this, the + * client can respond to server's GET methods with the provided value. + * \param resource_name The name of the resource. + * \param resource_type The type of the resource. + * \param value A pointer to the value of the resource. + * \param value_length The length of the value in the pointer. + * \param multiple_instance A resource can have + * multiple instances, default is false. + * \return M2MResource The resource for managing other client operations. + */ + M2MResource* create_static_resource(const String &resource_name, + const String &resource_type, + M2MResourceInstance::ResourceType type, + const uint8_t *value, + const uint8_t value_length, + bool multiple_instance = false); + + /** + * \brief Creates a dynamic resource for a given mbed Client Inteface object. With this, + * the client can respond to different queries from the server (GET,PUT etc). + * This type of resource is also observable and carries callbacks. + * \param resource_name The name of the resource. + * \param resource_type The type of the resource. + * \param observable Indicates whether the resource is observable or not. + * \param multiple_instance The resource can have + * multiple instances, default is false. + * \return M2MResource The resource for managing other client operations. + */ + M2MResource* create_dynamic_resource(const String &resource_name, + const String &resource_type, + M2MResourceInstance::ResourceType type, + bool observable, + bool multiple_instance = false); + + + /** + * \brief Creates a static resource instance for a given mbed Client Inteface object. With this, + * the client can respond to server's GET methods with the provided value. + * \param resource_name The name of the resource. + * \param resource_type The type of the resource. + * \param value A pointer to the value of the resource. + * \param value_length The length of the value in pointer. + * \param instance_id The instance ID of the resource. + * \return M2MResourceInstance The resource instance for managing other client operations. + */ + M2MResourceInstance* create_static_resource_instance(const String &resource_name, + const String &resource_type, + M2MResourceInstance::ResourceType type, + const uint8_t *value, + const uint8_t value_length, + uint16_t instance_id); + + /** + * \brief Creates a dynamic resource instance for a given mbed Client Inteface object. With this, + * the client can respond to different queries from the server (GET,PUT etc). + * This type of resource is also observable and carries callbacks. + * \param resource_name The name of the resource. + * \param resource_type The type of the resource. + * \param observable Indicates whether the resource is observable or not. + * \param instance_id The instance ID of the resource. + * \return M2MResourceInstance The resource instance for managing other client operations. + */ + M2MResourceInstance* create_dynamic_resource_instance(const String &resource_name, + const String &resource_type, + M2MResourceInstance::ResourceType type, + bool observable, + uint16_t instance_id); + + /** + * \brief Removes the resource with the given name. + * \param name The name of the resource to be removed. + * \return True if removed, else false. + */ + virtual bool remove_resource(const String &name); + + /** + * \brief Removes the resource instance with the given name. + * \param resource_name The name of the resource instance to be removed. + * \param instance_id The instance ID of the instance. + * \return True if removed, else false. + */ + virtual bool remove_resource_instance(const String &resource_name, + uint16_t instance_id); + + /** + * \brief Returns the resource with the given name. + * \param name The name of the requested resource. + * \return Resource reference if found, else NULL. + */ + virtual M2MResource* resource(const String &name) const; + + /** + * \brief Returns a list of M2MResourceBase objects. + * \return A list of M2MResourceBase objects. + */ + virtual const M2MResourceList& resources() const; + + /** + * \brief Returns the total number of resources with the object. + * \return Total number of the resources. + */ + virtual uint16_t resource_count() const; + + /** + * \brief Returns the total number of single resource instances. + * \param resource The name of the resource. + * \return Total number of the resources. + */ + virtual uint16_t resource_count(const String& resource) const; + + /** + * \brief Returns the object type. + * \return BaseType. + */ + virtual M2MBase::BaseType base_type() const; + + /** + * \brief Adds the observation level for the object. + * \param observation_level The level of observation. + */ + virtual void add_observation_level(M2MBase::Observation observation_level); + + /** + * \brief Removes the observation level from the object. + * \param observation_level The level of observation. + */ + virtual void remove_observation_level(M2MBase::Observation observation_level); + + /** + * \brief Handles GET request for the registered objects. + * \param nsdl The NSDL handler for the CoAP library. + * \param received_coap_header The CoAP message received from the server. + * \param observation_handler The handler object for sending + * observation callbacks. + * return sn_coap_hdr_s The message that needs to be sent to the server. + */ + virtual sn_coap_hdr_s* handle_get_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler = NULL); + /** + * \brief Handles PUT request for the registered objects. + * \param nsdl The NSDL handler for the CoAP library. + * \param received_coap_header The CoAP message received from the server. + * \param observation_handler The handler object for sending + * observation callbacks. + * \param execute_value_updated True will execute the "value_updated" callback. + * \return sn_coap_hdr_s The message that needs to be sent to server. + */ + virtual sn_coap_hdr_s* handle_put_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler, + bool &execute_value_updated); + + /** + * \brief Handles POST request for the registered objects. + * \param nsdl The NSDL handler for the CoAP library. + * \param received_coap_header The CoAP message received from the server. + * \param observation_handler The handler object for sending + * observation callbacks. + * \param execute_value_updated True will execute the "value_updated" callback. + * \return sn_coap_hdr_s The message that needs to be sent to server. + */ + virtual sn_coap_hdr_s* handle_post_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler, + bool &execute_value_updated); + + +protected : + + virtual void notification_update(M2MBase::Observation observation_level); + +private: + + M2MObjectCallback &_object_callback; + M2MResourceList _resource_list; // owned + + friend class Test_M2MObjectInstance; + friend class Test_M2MObject; + friend class Test_M2MDevice; + friend class Test_M2MSecurity; + friend class Test_M2MServer; + friend class Test_M2MNsdlInterface; + friend class Test_M2MFirmware; + friend class Test_M2MTLVSerializer; + friend class Test_M2MTLVDeserializer; +}; + +#endif // M2M_OBJECT_INSTANCE_H diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mobservationhandler.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mobservationhandler.h new file mode 100644 index 0000000000..0826a5b6e3 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mobservationhandler.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_OBSERVATION_HANDLER_H +#define M2M_OBSERVATION_HANDLER_H + +//FORWARD DECLARATION +class M2MBase; +class M2MResourceInstance; + +/** + * \brief M2MObservationHandler + * An interface for handling observation + * callbacks from different objects. + * + */ +class M2MObservationHandler +{ + public: + + /** + * \brief The observation callback to be sent to the + * server due to a change in a parameter under observation. + * \param object The observed object whose information needs to be sent. + * \param obs_number The observation number. + * \param changed_instance_ids A list of changed object instance IDs. + * \param send_object Indicates whether the whole object will be sent or not. + */ + virtual void observation_to_be_sent(M2MBase *object, + uint16_t obs_number, + m2m::Vector changed_instance_ids, + bool send_object = false) = 0; + + /** + * \brief A callback for deleting an NSDL resource. + * \param resource_name The name of the observed object whose information + * needs to be deleted. + */ + virtual void resource_to_be_deleted(const String &resource_name) = 0; + + /** + * \brief A callback indicating that the value of the resource object is updated by server. + * \param base The object whose value is updated. + * \param object_name The name of the updated resource, default is empty. + */ + virtual void value_updated(M2MBase *base, const String &object_name = "") = 0; + + /** + * \brief A callback for removing an object from the list. + * \param object The M2MObject to be removed. + */ + virtual void remove_object(M2MBase *object) = 0; + + /** + * \brief A delayed response callback to be sent to the + * server due to a changed response. + * \param base The resource sending the response. + */ + virtual void send_delayed_response(M2MBase *base) = 0; + +}; + + +#endif // M2M_OBSERVATION_HANDLER_H diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mreportobserver.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mreportobserver.h new file mode 100644 index 0000000000..b9ef96d529 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mreportobserver.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2MREPORTOBSERVER_H +#define M2MREPORTOBSERVER_H + +#include +#include + +/** + * \brief M2MReportObserver + * An interface for inviting the base class + * to send a report to the server. + * + */ +class M2MReportObserver +{ + public: + + /** + * \brief An observation callback to be sent to the + * server due to a change in the observed parameter. + * \param changed_instance_ids A list of changed object instance IDs. + * \param send_object Indicates whether the whole object will be sent or not. + */ + virtual void observation_to_be_sent(m2m::Vector changed_instance_ids, + bool send_object = false) = 0; + +}; + +#endif // M2MREPORTOBSERVER_H diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mresource.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mresource.h new file mode 100644 index 0000000000..598fa20386 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mresource.h @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_RESOURCE_H +#define M2M_RESOURCE_H + +#include "mbed-client/m2mvector.h" +#include "mbed-client/m2mresourceinstance.h" + +//FORWARD DECLARATION +class M2MObjectInstance; +typedef Vector M2MResourceInstanceList; + +class M2MResourceCallback { +public: + virtual void notification_update() = 0; +}; + +/** + * \brief M2MResource. + * This class is the base class for mbed Client Resources. All defined + * LWM2M object models can be created using it. This class will also hold all resources + * instances associated with the given object. + */ + +class M2MResource : public M2MResourceInstance, M2MResourceCallback { + + friend class M2MObjectInstance; + +public: + class M2MExecuteParameter; + +private: // Constructor and destructor are private + // which means that these objects can be created or + // deleted only through a function provided by the M2MObjectInstance. + + /** + * \brief Constructor + * \param resource_name The resource name of the object. + * \param resource_type The resource type of the object. + * \param type The resource data type of the object. + * \param value The value pointer of the object. + * \param value_length The length of the value pointer. + * \param object_instance_id Object instance id where resource exists. + * \param object_name Object name where resource exists. + * \param multiple_instance True if the resource supports instances. + */ + M2MResource(M2MObjectInstanceCallback &object_instance_callback, + const String &resource_name, + const String &resource_type, + M2MResourceInstance::ResourceType type, + const uint8_t *value, + const uint8_t value_length, + const uint16_t object_instance_id = 0, + const String &object_name = "", + bool multiple_instance = false); + + /** + * \brief Constructor + * \param resource_name The resource name of the object. + * \param resource_type The resource type of the object. + * \param type The resource data type of the object. + * \param observable Indicates whether the resource is observable or not. + * \param object_instance_id Object instance id where resource exists. + * \param object_name Object name where resource exists. + * \param multiple_instance True if the resource supports instances. + */ + M2MResource(M2MObjectInstanceCallback &object_instance_callback, + const String &resource_name, + const String &resource_type, + M2MResourceInstance::ResourceType type, + bool observable, + const uint16_t object_instance_id = 0, + const String &object_name = "", + bool multiple_instance = false); + + // Prevents the use of default constructor. + M2MResource(); + + // Prevents the use of assignment operator. + M2MResource& operator=( const M2MResource& /*other*/ ); + + // Prevents the use of copy constructor + M2MResource( const M2MResource& /*other*/ ); + + /** + * Destructor + */ + virtual ~M2MResource(); + +public: + + /** + * \brief Adds resource instances to the M2MResource. + * \param resource_instance The resource instance to be added. + */ + void add_resource_instance(M2MResourceInstance *resource_instance); + + /** + * \brief Returns whether the resource has multiple + * resource instances or not. + * \return True if the resource base has multiple instances, + * else false. + */ + bool supports_multiple_instances() const; + + /** + * \brief Sets whether the resource should send a delayed response for POST request. + * \param delayed_response A boolean value to set the delayed response. + */ + void set_delayed_response(bool delayed_response); + + /** + * \brief A trigger to send the delayed response for the POST request. + * The delayed_response flag must be set before receiving the POST request + * and the value of the resource must be updated before calling this function. + * \return True if response is sent, else false. + */ + bool send_delayed_post_response(); + + /** + * \brief Provides the value of the given token. + * \param value[OUT] A pointer to the token value. + * \param value_length[OUT] The length of the token pointer. + */ + void get_delayed_token(uint8_t *&token, uint8_t &token_length); + + /** + * \brief Removes the resource with the given name. + * \param name The name of the resource to be removed. + * \param instance_id The instance ID of the resource to be removed, default is 0. + * \return True if removed, else false. + */ + virtual bool remove_resource_instance(uint16_t instance_id = 0); + + /** + * \brief Returns the resource instance with the given name. + * \param instance_id The instance ID of the requested resource, default is 0 + * \return M2MResourceInstance object if found, else NULL. + */ + virtual M2MResourceInstance* resource_instance(uint16_t instance_id = 0) const; + + /** + * \brief Returns a list of resources. + * \return A list of resources. + */ + virtual const M2MResourceInstanceList& resource_instances() const; + + /** + * \brief Returns the total number of resources. + * \return The total number of resources. + */ + virtual uint16_t resource_instance_count() const; + + /** + * \brief Returns the value set for delayed response. + * \return The value for delayed response. + */ + bool delayed_response() const; + + /** + * \brief Parses the received query for a notification + * attribute. + * \return True if required attributes are present, else false. + */ + virtual bool handle_observation_attribute(char *&query); + + /** + * \brief Adds the observation level for the object. + * \param observation_level The öevel of observation. + */ + virtual void add_observation_level(M2MBase::Observation observation_level); + + /** + * \brief Removes the observation level from the object. + * \param observation_level The level of observation. + */ + virtual void remove_observation_level(M2MBase::Observation observation_level); + + /** + * \brief Handles the GET request for the registered objects. + * \param nsdl The NSDL handler for the CoAP library. + * \param received_coap_header The CoAP message received from the server. + * \param observation_handler The handler object for sending + * observation callbacks. + * \return sn_coap_hdr_s The message that needs to be sent to the server. + */ + virtual sn_coap_hdr_s* handle_get_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler = NULL); + /** + * \brief Handles the PUT request for the registered objects. + * \param nsdl The NSDL handler for the CoAP library. + * \param received_coap_header The CoAP message received from the server. + * \param observation_handler The handler object for sending + * observation callbacks. + * \param execute_value_updated True will execute the "value_updated" callback. + * \return sn_coap_hdr_s The message that needs to be sent to the server. + */ + virtual sn_coap_hdr_s* handle_put_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler, + bool &execute_value_updated); + /** + * \brief Handles the POST request for the registered objects. + * \param nsdl The NSDL handler for the CoAP library. + * \param received_coap_header The CoAP message received from the server. + * \param observation_handler The handler object for sending + * observation callbacks. + * \param execute_value_updated True will execute the "value_updated" callback. + * \return sn_coap_hdr_s The message that needs to be sent to the server. + */ + virtual sn_coap_hdr_s* handle_post_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler, + bool &execute_value_updated); + +protected: + virtual void notification_update(); + +private: + + M2MResourceInstanceList _resource_instance_list; // owned + uint8_t *_delayed_token; + uint8_t _delayed_token_len; + bool _has_multiple_instances; + bool _delayed_response; + +friend class Test_M2MResource; +friend class Test_M2MObjectInstance; +friend class Test_M2MObject; +friend class Test_M2MDevice; +friend class Test_M2MSecurity; +friend class Test_M2MServer; +friend class Test_M2MNsdlInterface; +friend class Test_M2MFirmware; +friend class Test_M2MTLVSerializer; +friend class Test_M2MTLVDeserializer; + +}; + +/** + * \brief M2MResource::M2MExecuteParameter. + * This class handles the "Execute" operation arguments. + */ +class M2MResource::M2MExecuteParameter { + +private: + + /** + * \brief Constructor + */ + M2MExecuteParameter(); + + /** + * Destructor + */ + ~M2MExecuteParameter(); + +public: + + /** + * \brief Returns the value of the argument. + * \return uint8_t * The argument value. + */ + uint8_t *get_argument_value() const; + + /** + * \brief Returns the length of the value argument. + * \return uint8_t The argument value length. + */ + uint16_t get_argument_value_length() const; + + /** + * \brief Returns the object name where resource exists. + * \return Object name. + */ + const String& get_argument_object_name() const; + + /** + * \brief Returns the resource name. + * \return Resource name. + */ + const String& get_argument_resource_name() const; + + /** + * \brief Returns the object instance id where resource exists. + * \return Object instance id. + */ + uint16_t get_argument_object_instance_id() const; + +private: + + String _object_name; + String _resource_name; + uint8_t * _value; + uint16_t _value_length; + uint16_t _object_instance_id; + + +friend class Test_M2MResource; +friend class M2MResource; +}; + +#endif // M2M_RESOURCE_H diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mresourceinstance.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mresourceinstance.h new file mode 100644 index 0000000000..85df331a98 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mresourceinstance.h @@ -0,0 +1,281 @@ + /* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_RESOURCE_INSTANCE_H +#define M2M_RESOURCE_INSTANCE_H + +#include "mbed-client/m2mbase.h" +#include "mbed-client/functionpointer.h" + +class M2MObjectInstanceCallback { +public: + virtual void notification_update(M2MBase::Observation observation_level) = 0; +}; + +/** + * \brief M2MResourceInstance. + * This class is the base class for mbed Client Resources. All defined + * LWM2M resource models can be created based on it. + */ +typedef FP1 execute_callback; +typedef void(*execute_callback_2) (void *arguments); + +class M2MResourceCallback; + +class M2MResourceInstance : public M2MBase { + +friend class M2MObjectInstance; +friend class M2MResource; + +public: + + /** + * Enum defining a resource type that can be + * supported by a given resource. + */ + typedef enum { + STRING, + INTEGER, + FLOAT, + BOOLEAN, + OPAQUE, + TIME, + OBJLINK + }ResourceType; + + +private: // Constructor and destructor are private + // which means that these objects can be created or + // deleted only through a function provided by the M2MObjectInstance. + /** + * \brief A constructor for creating a resource. + * \param resource_name The name of the resource. + * \param resource_type The type of the resource. + * \param type, The resource data type of the object. + * \param object_instance_id Object instance id where resource exists. + * \param object_name Object name where resource exists. + */ + M2MResourceInstance(const String &resource_name, + const String &resource_type, + M2MResourceInstance::ResourceType type, + M2MObjectInstanceCallback &object_instance_callback, + const uint16_t object_instance_id = 0, + const String &object_name = ""); + + /** + * \brief A Constructor for creating a resource. + * \param resource_name The name of the resource. + * \param resource_type The type of the resource. + * \param type The resource data type of the object. + * \param value The value pointer of the object. + * \param value_length The length of the value pointer. + * \param value_length The length of the value pointer. + * \param object_instance_id Object instance id where resource exists. + * \param object_name Object name where resource exists. + */ + M2MResourceInstance(const String &resource_name, + const String &resource_type, + M2MResourceInstance::ResourceType type, + const uint8_t *value, + const uint8_t value_length, + M2MObjectInstanceCallback &object_instance_callback, + const uint16_t object_instance_id = 0, + const String &object_name = ""); + + // Prevents the use of default constructor. + M2MResourceInstance(); + + // Prevents the use of assignment operator. + M2MResourceInstance& operator=( const M2MResourceInstance& /*other*/ ); + + // Prevents the use of copy constructor + M2MResourceInstance( const M2MResourceInstance& /*other*/ ); + + /** + * Destructor + */ + virtual ~M2MResourceInstance(); + +public: + + /** + * \brief Returns the object type. + * \return BaseType. + */ + virtual M2MBase::BaseType base_type() const; + + /** + * \brief Returns the resource data type. + * \return ResourceType. + */ + virtual M2MResourceInstance::ResourceType resource_instance_type() const; + + /** + * \brief Parses the received query for a notification + * attribute. + * \return True if required attributes are present, else false. + */ + virtual bool handle_observation_attribute(char *&query); + + /** + * \brief Sets the function that should be executed when this + * resource receives a POST command. + * \param callback The function pointer that needs to be executed. + */ + virtual void set_execute_function(execute_callback callback); + + /** + * \brief Sets the function that should be executed when this + * resource receives a POST command. + * \param callback The function pointer that needs to be executed. + */ + virtual void set_execute_function(execute_callback_2 callback); + + /** + * \brief Sets the value of the given resource. + * \param value, A pointer to the value to be set on the resource. + * \param value_length The length of the value pointer. + * \return True if successfully set, else false. + */ + virtual bool set_value(const uint8_t *value, const uint32_t value_length); + + /** + * \brief Sets the value of the given resource. + * \param value, new value which is to be formatted into a string + * and set on the resource. + * \return True if successfully set, else false. + */ + virtual bool set_value(int64_t value); + + /** + * \brief Clears the value of the given resource. + */ + virtual void clear_value(); + + /** + * \brief Executes the function that is set in "set_execute_function". + * \param arguments The arguments that will be passed to be executed. + */ + void execute(void *arguments); + + /** + * \brief Provides the value of the given resource. + * \param value[OUT] A pointer to the resource value. + * \param value_length[OUT] The length of the value pointer. + */ + virtual void get_value(uint8_t *&value, uint32_t &value_length); + + /** + * \brief Converts value to int and return it. Note: conversion + * errors are not detected. + */ + int get_value_int(); + + /** + * Get the value as a String object. No encoding/charset conversions + * done for the value, just a raw copy. + */ + String get_value_string() const; + + /** + * \brief Returns the value pointer of the object. + * \return The value pointer of the object. + */ + uint8_t* value() const; + + /** + * \brief Returns the length of the value pointer. + * \return The length of the value pointer. + */ + uint32_t value_length() const; + + /** + * \brief Handles the GET request for the registered objects. + * \param nsdl The NSDL handler for the CoAP library. + * \param received_coap_header The CoAP message received from the server. + * \param observation_handler The handler object for sending + * observation callbacks. + * \return sn_coap_hdr_s The message that needs to be sent to the server. + */ + virtual sn_coap_hdr_s* handle_get_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler = NULL); + /** + * \brief Handles the PUT request for the registered objects. + * \param nsdl The NSDL handler for the CoAP library. + * \param received_coap_header The CoAP message received from the server. + * \param observation_handler The handler object for sending + * observation callbacks. + * \param execute_value_updated True will execute the "value_updated" callback. + * \return sn_coap_hdr_s The message that needs to be sent to the server. + */ + virtual sn_coap_hdr_s* handle_put_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler, + bool &execute_value_updated); + + /** + * \brief Returns the object instance id where resource exists. + * \return Object instance id. + */ + uint16_t object_instance_id() const; + + /** + * \brief Returns the object name where resource exists. + * \return Object name. + */ + const String& object_name() const; + +protected: + + /** + * \brief Set observer for sending the notification update. + * \param resource The callback handle. + */ + void set_resource_observer(M2MResourceCallback *resource); + +private: + + void report(); + + bool is_value_changed(const uint8_t* value, const uint32_t value_len); + +private: + + M2MObjectInstanceCallback &_object_instance_callback; + execute_callback _execute_callback; + uint8_t *_value; + uint32_t _value_length; + M2MResourceCallback *_resource_callback; // Not owned + String _object_name; + FP1 *_function_pointer; + + uint16_t _object_instance_id; + ResourceType _resource_type; + + friend class Test_M2MResourceInstance; + friend class Test_M2MResource; + friend class Test_M2MObjectInstance; + friend class Test_M2MObject; + friend class Test_M2MDevice; + friend class Test_M2MSecurity; + friend class Test_M2MServer; + friend class Test_M2MNsdlInterface; + friend class Test_M2MFirmware; + friend class Test_M2MTLVSerializer; + friend class Test_M2MTLVDeserializer; +}; + +#endif // M2M_RESOURCE_INSTANCE_H diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2msecurity.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2msecurity.h new file mode 100644 index 0000000000..adfdceac75 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2msecurity.h @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_SECURITY_H +#define M2M_SECURITY_H + +#include "mbed-client/m2mobject.h" + +// FORWARD DECLARATION +class M2MResource; + +/** + * \brief M2MSecurity. + * This class represents an interface for the Security Object model of the LWM2M framework. + * It handles the security object instances and all corresponding + * resources. + */ + +class M2MSecurity : public M2MObject { + +friend class M2MInterfaceFactory; +friend class M2MNsdlInterface; + +public: + + /** + * \brief Enum defining all resources associated with a + * Security Object in the LWM2M framework. + */ + typedef enum { + M2MServerUri, + BootstrapServer, + SecurityMode, + PublicKey, + ServerPublicKey, + Secretkey, + SMSSecurityMode, + SMSBindingKey, + SMSBindingSecretKey, + M2MServerSMSNumber, + ShortServerID, + ClientHoldOffTime + }SecurityResource; + + /** + * \brief Enum defining the type of a security attribute + * used by the Security Object. + */ + typedef enum { + SecurityNotSet = -1, + Psk = 0, + Certificate = 2, + NoSecurity = 3 + } SecurityModeType; + + /** + * \brief Enum defining an interface operation that can be + * handled by the Security Object. + */ + typedef enum { + Bootstrap = 0x0, + M2MServer = 0x1 + } ServerType; + +private: + + /** + * \brief Constructor + * \param server_type The type of the security object created. Either bootstrap or LWM2M server. + */ + M2MSecurity(ServerType server_type); + + // Prevents the use of default constructor. + M2MSecurity(); + + // Prevents the use of assignment operator. + M2MSecurity& operator=( const M2MSecurity& /*other*/ ); + + // Prevents the use of copy constructor + M2MSecurity( const M2MSecurity& /*other*/ ); + +public: + + /** + * \brief Destructor + */ + virtual ~M2MSecurity(); + + /** + * \brief Creates a new resource for the given resource enum. + * \param rescource With this function, the following resources can be created: + * ' BootstrapServer', 'SecurityMode', 'SMSSecurityMode', + * 'M2MServerSMSNumber', 'ShortServerID', 'ClientHoldOffTime'. + * \param value The value to be set on the resource, in Integer format. + * \return M2MResource if created successfully, else NULL. + */ + M2MResource* create_resource(SecurityResource rescource, uint32_t value); + + /** + * \brief Deletes the resource with the given resource enum. + * Mandatory resources cannot be deleted. + * \param resource The resource to be deleted. + * \return True if deleted, else false. + */ + bool delete_resource(SecurityResource rescource); + + /** + * \brief Sets the value of the given resource enum. + * \param resource With this function, a value can be set for the following resources: + * 'M2MServerUri', 'SMSBindingKey', 'SMSBindingSecretKey'. + * \param value The value to be set on the resource, in String format. + * \return True if successfully set, else false. + */ + bool set_resource_value(SecurityResource resource, + const String &value); + + /** + * \brief Sets the value of the given resource enum. + * \param resource With this function, a value can be set for the following resourecs: + * 'BootstrapServer', 'SecurityMode', 'SMSSecurityMode', + * 'M2MServerSMSNumber', 'ShortServerID', 'ClientHoldOffTime'. + * \param value The value to be set on the resource, in Integer format. + * \return True if successfully set, else false. + */ + bool set_resource_value(SecurityResource resource, + uint32_t value); + + /** + * \brief Sets the value of the given resource enum. + * \param resource With this function, a value can be set for the follwing resources: + * 'PublicKey', 'ServerPublicKey', 'Secretkey'. + * \param value The value to be set on the resource, in uint8_t format. + * \param size The size of the buffer value to be set on the resource. + * \return True if successfully set, else false. + */ + bool set_resource_value(SecurityResource resource, + const uint8_t *value, + const uint16_t length); + + /** + * \brief Returns the value of the given resource enum, in String. + * \param resource With this function, the following resources can return a value: + * 'M2MServerUri','SMSBindingKey', 'SMSBindingSecretKey'. + * \return The value associated with the resource. If the resource is not valid an empty string is returned. + */ + String resource_value_string(SecurityResource resource) const; + + /** + * \brief Populates the data buffer and returns the size of the buffer. + * \param resource With this function, the following resources can return a value: + * 'PublicKey', 'ServerPublicKey', 'Secretkey'. + * \param [OUT]data Copy of the data buffer that contains the value. Caller + * is responsible of freeing this buffer. + * \return The size of the populated buffer. + */ + uint32_t resource_value_buffer(SecurityResource resource, + uint8_t *&data) const; + + /** + * \brief Returns the pointer to the value and size of the buffer. + * \param resource With this function, the following resources can return a value: + * 'PublicKey', 'ServerPublicKey', 'Secretkey'. + * \param [OUT]data Pointer to the data buffer that contains the value. + * \return The size of the populated buffer. + */ + uint32_t resource_value_buffer(SecurityResource resource, + const uint8_t *&data) const; + + /** + * \brief Returns the value of the given resource name, in Integer. + * \param resource With this function, the following resources can return a value: + * 'BootstrapServer', 'SecurityMode', 'SMSSecurityMode', + * 'M2MServerSMSNumber', 'ShortServerID', 'ClientHoldOffTime'. + * \return The value associated with the resource. If the resource is not valid 0 is returned. + */ + uint32_t resource_value_int(SecurityResource resource) const; + + + /** + * \brief Returns whether the resource instance with the given resource enum exists or not + * \param resource Resource enum. + * \return True if at least one instance exists, else false. + */ + bool is_resource_present(SecurityResource resource)const; + + /** + * \brief Returns the total number of resources for a security object. + * \return The total number of resources. + */ + uint16_t total_resource_count()const; + + /** + * \brief Returns the type of the Security Object. It can be either + * Bootstrap or M2MServer. + * \return ServerType The type of the Security Object. + */ + ServerType server_type() const; + +private: + + M2MResource* get_resource(SecurityResource resource) const; + void clear_resources(); + +private: + + M2MObjectInstance* _server_instance; + ServerType _server_type; + + friend class Test_M2MSecurity; + friend class Test_M2MInterfaceImpl; + friend class Test_M2MConnectionSecurityImpl; + friend class Test_M2MConnectionHandlerPimpl_linux; + friend class Test_M2MConnectionHandlerPimpl_mbed; + friend class Test_M2MConnectionSecurityPimpl; + friend class Test_M2MNsdlInterface; +}; + +#endif // M2M_SECURITY_H + + diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mserver.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mserver.h new file mode 100644 index 0000000000..e2b2b1cf3e --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mserver.h @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_SERVER_H +#define M2M_SERVER_H + +#include "mbed-client/m2mobject.h" + +// FORWARD DECLARATION +class M2MResource; + +/** + * \brief M2MServer. + * This class represents an interface for the Server Object model of the LWM2M framework. + * It handles the server object and all its corresponding + * resources. + */ + +class M2MServer : public M2MObject +{ + +friend class M2MInterfaceFactory; +friend class M2MNsdlInterface; + +public: + + /** + * \brief Enum defining all resources associated with + * a Server Object in the LWM2M framework. + */ + typedef enum { + ShortServerID, + Lifetime, + DefaultMinPeriod, + DefaultMaxPeriod, + Disable, + DisableTimeout, + NotificationStorage, + Binding, + RegistrationUpdate + }ServerResource; + +private: + + /** + * \brief Constructor + */ + M2MServer(); + + + // Prevents the use of assignment operator. + M2MServer& operator=( const M2MServer& /*other*/ ); + + // Prevents the use of copy constructor + M2MServer( const M2MServer& /*other*/ ); + +public: + + /** + * \brief Destructor + */ + virtual ~M2MServer(); + + /** + * \brief Creates a new resource for a given resource enum. + * \param resource With this function, a value can be set to the following resources: + * 'ShortServerID','Lifetime','DefaultMinPeriod','DefaultMaxPeriod','DisableTimeout', + * 'NotificationStorage'. + * \param value The value to be set on the resource, in Integer format. + * \return M2MResource if created successfully, else NULL. + */ + M2MResource* create_resource(ServerResource resource, uint32_t value); + + /** + * \brief Creates a new resource for a given resource enum. + * \param resource With this function, the following resources can be created: + * 'Disable', 'RegistrationUpdate' + * \return M2MResource if created successfully, else NULL. + */ + M2MResource* create_resource(ServerResource resource); + + /** + * \brief Deletes the resource with the given resource enum. + * Mandatory resources cannot be deleted. + * \param resource The name of the resource to be deleted. + * \return True if deleted, else false. + */ + bool delete_resource(ServerResource rescource); + + /** + * \brief Sets the value of the given resource enum. + * \param resource With this function, a value can be set on the following resources: + * 'Binding'. + * \param value The value to be set on the resource, in String format. + * \return True if successfully set, else false. + */ + bool set_resource_value(ServerResource resource, + const String &value); + + /** + * \brief Sets the value of the given resource enum. + * \param resource With this function, a value can be set to the following resources: + * 'ShortServerID','Lifetime','DefaultMinPeriod','DefaultMaxPeriod','DisableTimeout', + * 'NotificationStorage'. + * \param value The value to be set on the resource, in Integer format. + * \return True if successfully set else false. + */ + bool set_resource_value(ServerResource resource, + uint32_t value); + /** + * \brief Returns the value of the given resource enum, in String. + * \param resource With this function, the following resources can return a value: + * 'Binding'. + * \return The value associated with the resource. If the resource is not valid an empty string is returned. + */ + String resource_value_string(ServerResource resource) const; + + /** + * \brief Returns the value of the given resource name, in Integer. + * \param resource With this function, the following resources can return a value: + * 'ShortServerID','Lifetime','DefaultMinPeriod','DefaultMaxPeriod','DisableTimeout', + * 'NotificationStorage' + * \return The value associated with the resource. If the resource is not valid -1 is returned. + */ + uint32_t resource_value_int(ServerResource resource) const; + + /** + * \brief Returns whether the resource instance with the given resource enum exists or not. + * \param resource Resource enum. + * \return True if at least one instance exists, else false. + */ + bool is_resource_present(ServerResource resource)const; + + /** + * \brief Returns the total number of resources for the server object. + * \return The total number of resources. + */ + uint16_t total_resource_count()const; + +private: + + M2MResource* get_resource(ServerResource res) const; + + +private: + + M2MObjectInstance* _server_instance; + + friend class Test_M2MServer; + friend class Test_M2MNsdlInterface; +}; + +#endif // M2M_SERVER_H diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mstring.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mstring.h new file mode 100644 index 0000000000..19c2f5469e --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mstring.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_STRING_H +#define M2M_STRING_H + +#include // size_t +#include +#include + +class Test_M2MString; + +namespace m2m +{ + + /** \brief Simple C++ string class, used as replacement for + std::string. + */ + class String + { + char* p; ///< The data + size_t allocated_; ///< The allocated memory size (including trailing NULL) + size_t size_; ///< The currently used memory size (excluding trailing NULL) + + public: + typedef size_t size_type; + static const size_type npos; + + String(); + ~String(); + String(const String&); + String(const char*); + + String& operator=(const char*); + String& operator=(const String&); + + String& operator+=(const String&); + String& operator+=(const char*); + String& operator+=(char); + void push_back(char); + + bool operator==(const char*) const; + bool operator==(const String&) const; + + void clear(); // set string to empty string (memory remains reserved) + + size_type size() const { return size_; } ///< size without terminating NULL + size_type length() const { return size_; } ///< as size() + + size_type capacity() const { return allocated_-1; } + + bool empty() const { return size_ == 0; } + + const char* c_str() const { return p; } ///< raw data + + /** Reserve internal string memory so that n characters can be put into the + string (plus 1 for the NULL char). If there is already enough memory, + nothing happens, if not, the memory will be realloated to exactly this + amount. + */ + void reserve( size_type n); + + /** Resize string. If n is less than the current size, the string will be truncated. + If n is larger, the memory will be reallocated to exactly this amount, and + the additional characters will be NULL characters. + */ + void resize( size_type n); + + /** Resize string. If n is less than the current size, the string will be truncated. + If n is larger, the memory will be reallocated to exactly this amount, and + the additional characters will be c characters. + */ + void resize( size_type n, char c); + + /// swap contents + void swap( String& ); + + String substr(const size_type pos, size_type length) const; + + // unchecked access: + char& operator[](const size_type i) { return p[i]; } + char operator[](const size_type i) const { return p[i]; } + // checked access: + char at(const size_type i) const; + + /// erase len characters at position pos + String& erase(size_type pos, size_type len); + /// Append n characters of a string + String& append(const char* str, size_type n); + + // Append n characters of a non-zero-terminated string + // (in contrast with other append(), which performs strlen() for the given string). + String& append_raw(const char*, size_type); + + // convert int to ascii and append it to end of string + void append_int(int); + + int compare( size_type pos, size_type len, const String& str ) const; + int compare( size_type pos, size_type len, const char* str ) const; + + int find_last_of(char c) const; + + static uint8_t* convert_integer_to_array(int64_t value, uint8_t &size, uint8_t *array = NULL, uint32_t array_size = 0); + static int64_t convert_array_to_integer(uint8_t *value, uint32_t size); + + private: + // reallocate the internal memory + void new_realloc( size_type n); + char* strdup(const char* other); + + friend class ::Test_M2MString; + + }; + // class + + bool operator<(const String&, const String&); + + void reverse(char s[], uint32_t length); + + uint32_t itoa_c (int64_t n, char s[]); +} // namespace + + +#endif // M2M_STRING_H diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mtimer.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mtimer.h new file mode 100644 index 0000000000..c186447559 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mtimer.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_TIMER_H +#define M2M_TIMER_H + +#include +#include "mbed-client/m2mtimerobserver.h" + +class M2MTimerPimpl; + +/** +* \brief M2MTimer. +* Timer class for mbed client. +*/ +class M2MTimer +{ +private: + // Prevents the use of assignment operator + M2MTimer& operator=(const M2MTimer& other); + + // Prevents the use of copy constructor + M2MTimer(const M2MTimer& other); + +public: + + /** + * Constructor. + */ + M2MTimer(M2MTimerObserver& observer); + + /** + * Destructor. + */ + virtual ~M2MTimer(); + + /** + * \brief Starts the timer. + * \param interval The timer interval in milliseconds. + * \param single_shot Defines whether the timer is ticked once or restarted every time at expiry. + */ + void start_timer(uint64_t interval, M2MTimerObserver::Type type, bool single_shot = true); + + /** + * \brief Starts the timer in DTLS manner. + * \param intermediate_interval The intermediate interval to use, must be smaller than total (usually 1/4 of total). + * \param total_interval The total interval to use; This is the timeout value of a DTLS packet. + * \param type The type of the timer. + */ + void start_dtls_timer(uint64_t intermediate_interval, uint64_t total_interval, M2MTimerObserver::Type type = M2MTimerObserver::Dtls); + + /** + * \brief Stops the timer. + * This cancels the ongoing timer. + */ + void stop_timer(); + + /** + * \brief Checks if the intermediate interval has passed. + * \return True if the interval has passed, else false. + */ + bool is_intermediate_interval_passed(); + + /** + * \brief Checks if the total interval has passed. + * \return True if the interval has passed, else false. + */ + bool is_total_interval_passed(); + +private: + + M2MTimerObserver& _observer; + M2MTimerPimpl *_private_impl; + friend class Test_M2MTimerImpl_linux; +}; + +#endif // M2M_TIMER_H diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mtimerobserver.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mtimerobserver.h new file mode 100644 index 0000000000..bb2b0fee29 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mtimerobserver.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_TIMER_OBSERVER_H +#define M2M_TIMER_OBSERVER_H + +/** + * \brief M2MTimerObserver + * Observer class for indicating the timer expiry to the parent class. + */ +class M2MTimerObserver +{ +public: + /** + * \enum Defines the types of timer + * that can be created for mbed Client. + */ + typedef enum { + Notdefined, + Registration, + NsdlExecution, + PMinTimer, + PMaxTimer, + Dtls, + QueueSleep, + RetryTimer, + BootstrapTimer + }Type; + + /** + * \brief Indicates that the timer has expired. + * \param type The type of the timer that has expired. + */ + virtual void timer_expired(M2MTimerObserver::Type type = + M2MTimerObserver::Notdefined) = 0; +}; + +#endif // M2M_TIMER_OBSERVER_H diff --git a/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mvector.h b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mvector.h new file mode 100644 index 0000000000..4907fb8bf8 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed-client/m2mvector.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2015-2016 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_VECTOR_H +#define M2M_VECTOR_H + +#include + +namespace m2m +{ + +template + +class Vector +{ + public: + explicit Vector( int init_size = MIN_CAPACITY) + : _size(0), + _capacity((init_size >= MIN_CAPACITY) ? init_size : MIN_CAPACITY) { + _object_template = new ObjectTemplate[ _capacity ]; + } + + Vector(const Vector & rhs ): _object_template(0) { + operator=(rhs); + } + + ~Vector() { + delete [] _object_template; + } + + const Vector & operator=(const Vector & rhs) { + if(this != &rhs) { + delete[] _object_template; + _size = rhs.size(); + _capacity = rhs._capacity; + + _object_template = new ObjectTemplate[capacity()]; + for(int k = 0; k < size(); k++) { + _object_template[k] = rhs._object_template[k]; + } + } + return *this; + } + + void resize(int new_size) { + if(new_size > _capacity) { + reserve(new_size * 2 + 1); + } + _size = new_size; + } + + void reserve(int new_capacity) { + if(new_capacity < _size) { + return; + } + ObjectTemplate *old_array = _object_template; + + _object_template = new ObjectTemplate[new_capacity]; + for(int k = 0; k < _size; k++) { + _object_template[k] = old_array[k]; + } + _capacity = new_capacity; + delete [] old_array; + } + + ObjectTemplate & operator[](int idx) { + return _object_template[idx]; + } + + const ObjectTemplate& operator[](int idx) const { + return _object_template[idx]; + } + + bool empty() const{ + return size() == 0; + } + + int size() const { + return _size; + } + + int capacity() const { + return _capacity; + } + + void push_back(const ObjectTemplate& x) { + if(_size == _capacity) { + reserve(2 * _capacity + 1); + } + _object_template[_size] = x; + _size++; + } + + void pop_back() { + _size--; + } + + void clear() { + _size = 0; + } + + const ObjectTemplate& back() const { + return _object_template[_size - 1]; + } + + typedef ObjectTemplate* iterator; + typedef const ObjectTemplate* const_iterator; + + iterator begin() { + return &_object_template[0]; + } + + const_iterator begin() const { + return &_object_template[0]; + } + + iterator end() { + return &_object_template[_size]; + } + + const_iterator end() const { + return &_object_template[_size]; + } + + void erase(int position) { + if(position < _size) { + _object_template[position] = 0; + for(int k = position; k + 1 < _size; k++) { + _object_template[k] = _object_template[k + 1]; + } + _size--; + } + } + + enum { + MIN_CAPACITY = 1 + }; + + private: + int _size; + int _capacity; + ObjectTemplate* _object_template; +}; + +} // namespace + +#endif // M2M_VECTOR_H diff --git a/features/FEATURE_CLIENT/mbed-client/mbed_lib.json b/features/FEATURE_CLIENT/mbed-client/mbed_lib.json new file mode 100644 index 0000000000..ba1d5a30d3 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mbed_lib.json @@ -0,0 +1,13 @@ +{ + "name": "mbed-client", + "config": { + "event-loop-size": 1024, + "reconnection-count": 3, + "reconnection-interval": 5, + "tcp-keepalive-time": 300, + "disable-bootstrap-feature": null, + "coap-disable-obs-feature":null, + "sn-coap-max-blockwise-payload-size" : 0, + "sn-coap-duplication-max-msgs-count": 0 + } + } diff --git a/features/FEATURE_CLIENT/mbed-client/mkdocs.yml b/features/FEATURE_CLIENT/mbed-client/mkdocs.yml new file mode 100644 index 0000000000..15b93997e3 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/mkdocs.yml @@ -0,0 +1,17 @@ +site_name: ARM mbed Client Guide +theme: readthedocs +use directory_urls: false +pages: +- ['index.md','ARM mbed Client Guide'] +- ['Introduction.md','Introduction to mbed Client'] +- ['client_reg_dereg.md','Features','Client Registration'] +- ['dev_man_serv_enable.md','Features','Device Management and Service Enablement'] +- ['info_reporting.md','Features','Information Reporting'] +- ['data_types.md','Data types'] +- ['Howto.md','Quick start guide for using mbed Client API'] +- ['porting-guide.md','Porting mbed Client'] +- ['further-reading.md','mbed Device Connector service'] + + + + diff --git a/features/FEATURE_CLIENT/mbed-client/module.json b/features/FEATURE_CLIENT/mbed-client/module.json new file mode 100644 index 0000000000..be25ff6a9a --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/module.json @@ -0,0 +1,23 @@ +{ + "name": "mbed-client", + "version": "1.13.1", + "description": "mbed Client C++ API", + "keywords": [], + "author": "Yogesh Pande ", + "homepage": "https://github.com/ARMmbed/mbed-client", + "license": "Apache-2.0", + "dependencies": { + "mbed-client-c": "^2.0.0", + "mbed-trace": ">=0.2.0,<2.0.0" + }, + "targetDependencies": { + "arm": { + "mbed-client-mbed-os": "^3.0.0", + "mbed-client-mbedtls": "^3.0.0" + }, + "linux": { + "mbed-client-linux": "^3.0.0", + "mbed-client-mbedtls": "^3.0.0" + } + } +} diff --git a/features/FEATURE_CLIENT/mbed-client/run_unit_tests.sh b/features/FEATURE_CLIENT/mbed-client/run_unit_tests.sh new file mode 100755 index 0000000000..04939785a6 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/run_unit_tests.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# Copyright (c) 2015 ARM Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# * http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +echo +echo "Build mbed Client API unit tests" +echo +yt target x86-linux-native-coverage +yt clean +yt build +yt test --no-build -- -ojunit +echo +echo Create results +echo +rm -rf results +rm -rf coverage +mkdir results +mkdir coverage + +find ./build -name '*.xml' | xargs cp -t ./results/ +find ./build/x86-linux-native-coverage/test -name '*.gcno' | xargs cp -t ./coverage/ +find ./build/x86-linux-native-coverage/test -name '*.gcda' | xargs cp -t ./coverage/ +touch coverage/*.gcda +exclude_files="${PWD}/test/" +gcovr -r ./ --gcov-filter='.*source*.' --exclude-unreachable-branches --exclude $exclude_files --object-directory ./coverage -x -o ./results/gcovr.xml +echo +echo "Create coverage document" +echo +lcov -b ./ -d ./coverage -c -o ./coverage/app.info +lcov -q -r ./coverage/app.info "/test/mbedclient/*" -o ./coverage/app.info +lcov -q -r ./coverage/app.info "/usr*" -o ./coverage/app.info +genhtml -q --no-branch-coverage --function-coverage --demangle-cpp --title "mbed Client coverage" ./coverage/app.info -o ./coverage +rm -f ./coverage/*.gcno +rm -f ./coverage/*.gcda +echo +echo "Creating report" +echo +echo ' + +' >> index.xml + +for f in results/*.xml +do +name=${f##*/} +echo ''>> index.xml +done + +echo '' >> index.xml + +echo +echo "Report created to index.xml (outputs html)" +echo +xsltproc -o results/testresults.html junit_xsl.xslt index.xml +rm -f index.xml + diff --git a/features/FEATURE_CLIENT/mbed-client/run_unit_tests_with_valgrind.sh b/features/FEATURE_CLIENT/mbed-client/run_unit_tests_with_valgrind.sh new file mode 100755 index 0000000000..12af385396 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/run_unit_tests_with_valgrind.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# Execute script with root path where to find binaries. +# For example ./run_unit_tests_with_valgrind.sh ./build/x86-linux-native-coverage/test/mbedclient/ + +input="binaries.txt" +valgrind_logs="valgrind_logs" +rm -rf $valgrind_logs +mkdir $valgrind_logs +find $1 -type f -executable -exec sh -c "file -i '{}' | grep -q 'x-executable; charset=binary'" \; -print > $input +while file= read -r binary +do + valgrind --track-origins=yes --xml=yes --xml-file="${valgrind_logs}/valgrind_$(basename $binary).xml" "$binary" +done < "$input" diff --git a/features/FEATURE_CLIENT/mbed-client/source/include/eventdata.h b/features/FEATURE_CLIENT/mbed-client/source/include/eventdata.h new file mode 100644 index 0000000000..1aeba31297 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/include/eventdata.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 EVENT_DATA_H +#define EVENT_DATA_H + +#include "mbed-client/m2mvector.h" + +//FORWARD DECLARATION +class M2MObject; + + +typedef Vector M2MObjectList; + +class M2MSecurity; + +class EventData +{ +public: + virtual ~EventData() {} +}; + +class M2MSecurityData : public EventData +{ +public: + M2MSecurityData() + :_object(NULL){} + virtual ~M2MSecurityData() {} + M2MSecurity *_object; +}; + +class ResolvedAddressData : public EventData +{ +public: + ResolvedAddressData() + :_address(NULL), + _port(0){} + virtual ~ResolvedAddressData() {} + const M2MConnectionObserver::SocketAddress *_address; + uint16_t _port; +}; + +class ReceivedData : public EventData +{ +public: + ReceivedData() + :_data(NULL), + _size(0), + _port(0), + _address(NULL){} + virtual ~ReceivedData() {} + uint8_t *_data; + uint16_t _size; + uint16_t _port; + const M2MConnectionObserver::SocketAddress *_address; +}; + +class M2MRegisterData : public EventData +{ +public: + M2MRegisterData() + :_object(NULL){} + virtual ~M2MRegisterData() {} + M2MSecurity *_object; + M2MObjectList _object_list; +}; + +class M2MUpdateRegisterData : public EventData +{ +public: + M2MUpdateRegisterData() + :_object(NULL), + _lifetime(0){} + virtual ~M2MUpdateRegisterData() {} + M2MSecurity *_object; + uint32_t _lifetime; +}; + + +#endif //EVENT_DATA_H + diff --git a/features/FEATURE_CLIENT/mbed-client/source/include/m2minterfaceimpl.h b/features/FEATURE_CLIENT/mbed-client/source/include/m2minterfaceimpl.h new file mode 100644 index 0000000000..65b8de0fd7 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/include/m2minterfaceimpl.h @@ -0,0 +1,422 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_INTERFACE_IMPL_H +#define M2M_INTERFACE_IMPL_H + +#include "mbed-client/m2minterface.h" +#include "mbed-client/m2mserver.h" +#include "mbed-client/m2mconnectionobserver.h" +#include "mbed-client/m2mconnectionsecurity.h" +#include "include/m2mnsdlobserver.h" +#include "mbed-client/m2mtimerobserver.h" + +//FORWARD DECLARATION +class M2MNsdlInterface; +class M2MConnectionHandler; +class M2MConnectionSecurity; +class EventData; +class M2MTimer; + +/** + * @brief M2MInterfaceImpl. + * This class implements handling of all mbed Client Interface operations + * defined in OMA LWM2M specifications. + * This includes Bootstrapping, Client Registration, Device Management & + * Service Enablement and Information Reporting. + */ + +class M2MInterfaceImpl : public M2MInterface, + public M2MNsdlObserver, + public M2MConnectionObserver, + public M2MTimerObserver +{ +private: + // Prevents the use of assignment operator by accident. + M2MInterfaceImpl& operator=( const M2MInterfaceImpl& /*other*/ ); + + // Prevents the use of copy constructor by accident + M2MInterfaceImpl( const M2MInterfaceImpl& /*other*/ ); + +friend class M2MInterfaceFactory; + +private: + + /** + * @brief Constructor + * @param observer, Observer to pass the event callbacks for various + * interface operations. + * @param endpoint_name, Endpoint name of the client. + * @param endpoint_type, Endpoint type of the client. + * @param life_time, Life time of the client in seconds + * @param listen_port, Listening port for the endpoint, default is 8000. + * @param domain, Domain of the client. + * @param mode, Binding mode of the client, default is UDP + * @param stack, Network Stack to be used for connection, default is LwIP_IPv4 + * @param context_address, Context address default is empty. + */ + M2MInterfaceImpl(M2MInterfaceObserver& observer, + const String &endpoint_name, + const String &endpoint_type, + const int32_t life_time, + const uint16_t listen_port, + const String &domain = "", + BindingMode mode = M2MInterface::NOT_SET, + M2MInterface::NetworkStack stack = M2MInterface::LwIP_IPv4, + const String &context_address = ""); + +public: + + /** + * @brief Destructor + */ + virtual ~M2MInterfaceImpl(); + + /** + * @brief Initiates bootstrapping of the client with the provided Bootstrap + * server information. + * @param security_object, Security object which contains information + * required for successful bootstrapping of the client. + */ + virtual void bootstrap(M2MSecurity *security); + + /** + * @brief Cancels on going bootstrapping operation of the client. If the client has + * already successfully bootstrapped then this function deletes existing + * bootstrap information from the client. + */ + virtual void cancel_bootstrap(); + + /** + * @brief Initiates registration of the provided Security object to the + * corresponding LWM2M server. + * @param security_object, Security object which contains information + * required for registering to the LWM2M server. + * If client wants to register to multiple LWM2M servers then it has call + * this function once for each of LWM2M server object separately. + * @param object_list, Objects which contains information + * which the client want to register to the LWM2M server. + */ + virtual void register_object(M2MSecurity *security_object, const M2MObjectList &object_list); + + /** + * @brief Updates or refreshes the client's registration on the LWM2M + * server. + * @param security_object, Security object from which the device object + * needs to update registration, if there is only one LWM2M server registered + * then this parameter can be NULL. + * @param lifetime, Lifetime for the endpoint client in seconds. + */ + virtual void update_registration(M2MSecurity *security_object, const uint32_t lifetime = 0); + + /** + * @brief Unregisters the registered object from the LWM2M server + * @param security_object, Security object from which the device object + * needs to be unregistered, if there is only one LWM2M server registered + * then this parameter can be NULL. + */ + virtual void unregister_object(M2MSecurity* security = NULL); + + /** + * @brief Sets the function which will be called indicating client + * is going to sleep when the Binding mode is selected with Queue mode. + * @param callback, Function pointer which will be called when client + * goes to seleep. + */ + virtual void set_queue_sleep_handler(callback_handler handler); + + /** + * @brief Sets the network interface handler that is used by client to connect + * to a network over IP.. + * @param handler A network interface handler that is used by client to connect. + * This API is optional but provides a mechanism for different platforms to + * manage usage of underlying network interface by client. + */ + virtual void set_platform_network_handler(void *handler = NULL); + +/** + * \brief Sets the function callback that will be called by mbed-client for + * fetching random number from application for ensuring strong entropy. + * \param random_callback A function pointer that will be called by mbed-client + * while performing secure handshake. + * Function signature should be uint32_t (*random_number_callback)(void); + */ + virtual void set_random_number_callback(random_number_cb callback); + + /** + * \brief Sets the function callback that will be called by mbed-client for + * providing entropy source from application for ensuring strong entropy. + * \param entropy_callback A function pointer that will be called by mbed-client + * while performing secure handshake. + * Function signature , if using mbed-client-mbedtls should be + * int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, + * size_t len, size_t *olen); + */ + virtual void set_entropy_callback(entropy_cb callback); + + +protected: // From M2MNsdlObserver + + virtual void coap_message_ready(uint8_t *data_ptr, + uint16_t data_len, + sn_nsdl_addr_s *address_ptr); + + virtual void client_registered(M2MServer *server_object); + + virtual void registration_updated(const M2MServer &server_object); + + virtual void registration_error(uint8_t error_code, bool retry = false); + + virtual void client_unregistered(); + + virtual void bootstrap_done(M2MSecurity *security_object); + + virtual void bootstrap_error(); + + virtual void coap_data_processed(); + + virtual void value_updated(M2MBase *base); + +protected: // From M2MConnectionObserver + + virtual void data_available(uint8_t* data, + uint16_t data_size, + const M2MConnectionObserver::SocketAddress &address); + + virtual void socket_error(uint8_t error_code, bool retry = true); + + virtual void address_ready(const M2MConnectionObserver::SocketAddress &address, + M2MConnectionObserver::ServerType server_type, + const uint16_t server_port); + + virtual void data_sent(); + +protected: // from M2MTimerObserver + + virtual void timer_expired(M2MTimerObserver::Type type); + + +private: // state machine state functions + + /** + * When the state is Idle. + */ + void state_idle(EventData* data); + + /** + * When the client starts bootstrap. + */ + void state_bootstrap( EventData *data); + + /** + * When the bootstrap server address is resolved. + */ + void state_bootstrap_address_resolved( EventData *data); + + /** + * When the bootstrap resource is created. + */ + void state_bootstrap_resource_created( EventData *data); + + /** + * When the server has sent response and bootstrapping is done. + */ + void state_bootstrapped( EventData *data); + + /** + * When the client starts register. + */ + void state_register( EventData *data); + + /** + * When the server address for register is resolved. + */ + void state_register_address_resolved( EventData *data); + + /** + * When the register resource is created. + */ + void state_register_resource_created( EventData *data); + + /** + * When the client is registered. + */ + void state_registered( EventData *data); + + /** + * When the client is updating registration. + */ + void state_update_registration( EventData *data); + + /** + * When the client starts unregister. + */ + void state_unregister( EventData *data); + + /** + * When the client has been unregistered. + */ + void state_unregistered( EventData *data); + + /** + * When the coap data is been sent through socket. + */ + void state_sending_coap_data( EventData *data); + + /** + * When the coap data is sent successfully. + */ + void state_coap_data_sent( EventData *data); + + /** + * When the socket is receiving coap data. + */ + void state_receiving_coap_data( EventData *data); + + /** + * When the socket has received coap data. + */ + void state_coap_data_received( EventData *data); + + /** + * When the coap message is being processed. + */ + void state_processing_coap_data( EventData *data); + + /** + * When the coap message has been processed. + */ + void state_coap_data_processed( EventData *data); + + /** + * When the client is waiting to receive or send data. + */ + void state_waiting( EventData *data); + + /** + * State enumeration order must match the order of state + * method entries in the state map + */ + enum E_States { + STATE_IDLE = 0, + STATE_BOOTSTRAP, + STATE_BOOTSTRAP_ADDRESS_RESOLVED, + STATE_BOOTSTRAP_RESOURCE_CREATED, + STATE_BOOTSTRAPPED, + STATE_REGISTER, //5 + STATE_REGISTER_ADDRESS_RESOLVED, + STATE_REGISTER_RESOURCE_CREATED, + STATE_REGISTERED, + STATE_UPDATE_REGISTRATION, + STATE_UNREGISTER, //10 + STATE_UNREGISTERED, + STATE_SENDING_COAP_DATA, + STATE_COAP_DATA_SENT, + STATE_COAP_DATA_RECEIVED, + STATE_PROCESSING_COAP_DATA, //15 + STATE_COAP_DATA_PROCESSED, + STATE_WAITING, + STATE_MAX_STATES + }; + + /** + * @brief Redirects the state machine to right function. + * @param current_state Current state to be set. + * @param data, Data to be passed to the state function. + */ + void state_function( uint8_t current_state, EventData* data ); + + /** + * @brief State Engine maintaining state machine logic. + */ + void state_engine(void); + + /** + * External event which can trigger the state machine. + * @param New State which the state machine should go to. + * @param data to be passed to the state machine. + */ + void external_event(uint8_t, EventData* = NULL); + + /** + * Internal event generated by state machine. + * @param New State which the state machine should go to. + * @param data to be passed to the state machine. + */ + void internal_event(uint8_t, EventData* = NULL); + + enum + { + EVENT_IGNORED = 0xFE, + CANNOT_HAPPEN + }; + + /** + * Helper method for extracting the IP address part and port from the + * given server address. + * @param server_address source url (without "coap" or "coaps" prefix) + * @param ip_address extracted IP + * @param port extracted port + */ + static void process_address(const String& server_address, String& ip_address, uint16_t& port); + +private: + + M2MInterfaceObserver &_observer; + M2MConnectionHandler *_connection_handler; + M2MConnectionSecurity *_security_connection; // Doesn't own + M2MNsdlInterface *_nsdl_interface; + uint8_t _current_state; + const int _max_states; + bool _event_generated; + EventData *_event_data; + String _endpoint_type; + String _domain; + int32_t _life_time; + BindingMode _binding_mode; + String _context_address; + uint16_t _listen_port; + uint16_t _server_port; + String _server_ip_address; + M2MSecurity *_register_server; //TODO: to be the list not owned + bool _event_ignored; + bool _register_ongoing; + bool _update_register_ongoing; + M2MTimer *_queue_sleep_timer; + M2MTimer *_retry_timer; + M2MTimer *_bootstrap_timer; + callback_handler _callback_handler; + M2MSecurity *_security; + uint8_t _retry_count; + bool _reconnecting; + bool _retry_timer_expired; + + friend class Test_M2MInterfaceImpl; + +}; + +#define BEGIN_TRANSITION_MAP \ + static const uint8_t TRANSITIONS[] = {\ + +#define TRANSITION_MAP_ENTRY(entry)\ + entry, + +#define END_TRANSITION_MAP(data) \ + 0 };\ + external_event(TRANSITIONS[_current_state], data); + +#endif //M2M_INTERFACE_IMPL_H + + diff --git a/features/FEATURE_CLIENT/mbed-client/source/include/m2mnsdlinterface.h b/features/FEATURE_CLIENT/mbed-client/source/include/m2mnsdlinterface.h new file mode 100644 index 0000000000..14d78e4246 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/include/m2mnsdlinterface.h @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2MNSDLINTERFACE_H +#define M2MNSDLINTERFACE_H + +#include "mbed-client/m2mvector.h" +#include "mbed-client/m2mconfig.h" +#include "mbed-client/m2minterface.h" +#include "mbed-client/m2mtimerobserver.h" +#include "mbed-client/m2mobservationhandler.h" +#include "mbed-client/m2mbase.h" +#include "include/nsdllinker.h" + +//FORWARD DECLARARTION +class M2MSecurity; +class M2MObject; +class M2MObjectInstance; +class M2MResource; +class M2MResourceInstance; +class M2MNsdlObserver; +class M2MServer; +class M2MTimer; + +typedef Vector M2MObjectList; + +/** + * @brief M2MNsdlInterface + * Class which interacts between mbed Client C++ Library and mbed-client-c library. + */ +class M2MNsdlInterface : public M2MTimerObserver, + public M2MObservationHandler +{ +private: + // Prevents the use of assignment operator by accident. + M2MNsdlInterface& operator=( const M2MNsdlInterface& /*other*/ ); + + // Prevents the use of copy constructor by accident + M2MNsdlInterface( const M2MNsdlInterface& /*other*/ ); + +public: + /** + * @brief Constructor + * @param observer, Observer to pass the event callbacks from nsdl library. + */ + M2MNsdlInterface(M2MNsdlObserver &observer); + + /** + * @brief Destructor + */ + virtual ~M2MNsdlInterface(); + + /** + * @brief Creates endpoint object for the nsdl stack. + * @param endpoint_name, Endpoint name of the client. + * @param endpoint_type, Endpoint type of the client. + * @param life_time, Life time of the client in seconds + * @param domain, Domain of the client. + * @param mode, Binding mode of the client, default is UDP + * @param context_address, Context address default is empty. + */ + void create_endpoint(const String &endpoint_name, + const String &endpoint_type, + const int32_t life_time, + const String &domain, + const uint8_t mode, + const String &context_address); + + /** + * @brief Deletes the endpoint. + */ + void delete_endpoint(); + + /** + * @brief Creates the NSDL structure for the registered objectlist. + * @param object_list, List of objects to be registered. + * @return true if structure created successfully else false. + */ + bool create_nsdl_list_structure(const M2MObjectList &object_list); + + /** + * @brief Removed the NSDL resource for the given resource. + * @param resource_name, Resource name to be removed. + * @return true if removed successfully else false. + */ + bool delete_nsdl_resource(const String &resource_name); + + /** + * @brief Creates the bootstrap object. + * @param address Bootstrap address. + * @return true if created and sent successfully else false. + */ + bool create_bootstrap_resource(sn_nsdl_addr_s *address, const String &bootstrap_endpoint_name); + + /** + * @brief Sends the register message to the server. + * @param address M2MServer address. + * @param port M2MServer port. + * @param address_type IP Address type. + * @return true if register sent successfully else false. + */ + bool send_register_message(uint8_t* address, + const uint16_t port, + sn_nsdl_addr_type_e address_type); + + /** + * @brief Sends the update registration message to the server. + * @param lifetime, Updated lifetime value in seconds. + * @return true if sent successfully else false. + * + */ + bool send_update_registration(const uint32_t lifetime = 0); + + /** + * @brief Sends unregister message to the server. + * @return true if unregister sent successfully else false. + */ + bool send_unregister_message(); + + /** + * @brief Memory Allocation required for libCoap. + * @param size, Size of memory to be reserved. + */ + void* memory_alloc(uint16_t size); + + /** + * @brief Memory free functions required for libCoap + * @param ptr, Object whose memory needs to be freed. + */ + void memory_free(void *ptr); + + /** + * @brief Callback from nsdl library to inform the data is ready + * to be sent to server. + * @param nsdl_handle, Handler for the nsdl structure for this endpoint + * @param protocol, Protocol format of the data + * @param data, Data to be sent. + * @param data_len, Size of the data to be sent + * @param address, server address where data has to be sent. + * @return 1 if successful else 0. + */ + uint8_t send_to_server_callback(struct nsdl_s * nsdl_handle, + sn_nsdl_capab_e protocol, + uint8_t *data, + uint16_t data_len, + sn_nsdl_addr_s *address); + + /** + * @brief Callback from nsdl library to inform the data which is + * received from server for the client has been converted to coap message. + * @param nsdl_handle, Handler for the nsdl structure for this endpoint + * @param coap_header, Coap message formed from data. + * @param address, Server address from where the data is received. + * @return 1 if successful else 0. + */ + uint8_t received_from_server_callback(struct nsdl_s * nsdl_handle, + sn_coap_hdr_s *coap_header, + sn_nsdl_addr_s *address); + + /** + * @brief Callback from nsdl library to inform the data which is + * received from server for the resources has been converted to coap message. + * @param nsdl_handle, Handler for the nsdl resource structure for this endpoint.. + * @param coap_header, Coap message formed from data. + * @param address, Server address from where the data is received. + * @param nsdl_capab, Protocol for the message, currently only coap is supported. + * @return 1 if successful else 0. + */ + uint8_t resource_callback(struct nsdl_s *nsdl_handle, sn_coap_hdr_s *coap, + sn_nsdl_addr_s *address, + sn_nsdl_capab_e nsdl_capab); + + /** + * @brief Callback when there is data received from server and needs to be processed. + * @param data, data received from server. + * @param data_size, data size received from server. + * @param addres, address structure of the server. + * @return true if successfully processed else false. + */ + bool process_received_data(uint8_t *data, + uint16_t data_size, + sn_nsdl_addr_s *address); + + /** + * @brief Stops all the timers in case there is any errors. + */ + void stop_timers(); + + /** + * @brief Returns nsdl handle. + * @return ndsl handle + */ + nsdl_s* get_nsdl_handle(); + + /** + * @brief Get endpoint name + * @return endpoint name + */ + const String& endpoint_name() const; + +protected: // from M2MTimerObserver + + virtual void timer_expired(M2MTimerObserver::Type type); + +protected: // from M2MObservationHandler + + virtual void observation_to_be_sent(M2MBase *object, + uint16_t obs_number, + m2m::Vector changed_instance_ids, + bool send_object = false); + + virtual void resource_to_be_deleted(const String &resource_name); + + virtual void value_updated(M2MBase *base, const String &object_name); + + virtual void remove_object(M2MBase *object); + + virtual void send_delayed_response(M2MBase *base); + +private: + + /** + * @brief Initializes all the nsdl library component to be usable. + * @return true if initialization is successful else false. + */ + bool initialize(); + + bool add_object_to_list(M2MObject *object); + + bool create_nsdl_object_structure(M2MObject *object); + + bool create_nsdl_object_instance_structure(M2MObjectInstance *object_instance); + + bool create_nsdl_resource_structure(M2MResource *resource, + const String &object_name = "", + bool multiple_instances = false); + + bool create_nsdl_resource(M2MBase *base, const String &name = "", bool publish_uri = true); + + String coap_to_string(uint8_t *coap_data_ptr, + int coap_data_ptr_length); + + void execute_nsdl_process_loop(); + + uint64_t registration_time(); + + M2MBase* find_resource(const String &object); + + M2MBase* find_resource(const M2MObject *object, + const String &object_instance); + + M2MBase* find_resource(const M2MObjectInstance *object_instance, + const String &resource_instance); + + M2MBase* find_resource(const M2MResource *resource, + const String &object_name, + const String &resource_instance); + + bool object_present(M2MObject * object) const; + + void clear_resource(sn_nsdl_resource_info_s *&resource); + + M2MInterface::Error interface_error(sn_coap_hdr_s *coap_header); + + void send_object_observation(M2MObject *object, + uint16_t obs_number, + m2m::Vector changed_instance_ids, + bool send_object); + + void send_object_instance_observation(M2MObjectInstance *object_instance, + uint16_t obs_number); + + void send_resource_observation(M2MResource *resource, uint16_t obs_number); + + void build_observation_number(uint8_t *obs_number, + uint8_t *obs_len, + uint16_t number); + + void send_notification(uint8_t *token, + uint8_t token_length, + uint8_t *value, + uint32_t value_length, + uint16_t observation, + uint32_t max_age, + uint8_t coap_content_type, + const String &uri_path); + + /** + * @brief Allocate (size + 1) amount of memory, copy size bytes into + * it and add zero termination. + * @param source Source string to copy, may not be NULL. + * @param size The size of memory to be reserved. + */ + uint8_t* alloc_string_copy(const uint8_t* source, uint16_t size); + + /** + * @brief Utility method to convert given lifetime int to ascii + * and allocate a buffer for it and set it to _endpoint->lifetime_ptr. + * @param lifetime A new value for lifetime. + */ + void set_endpoint_lifetime_buffer(int lifetime); + + /** + * @brief Handle incoming bootstrap PUT message. + * @param coap_header, Received CoAP message + * @param address, Server address + */ + void handle_bootstrap_put_message(sn_coap_hdr_s *coap_header, sn_nsdl_addr_s *address); + + /** + * @brief Handle bootstrap finished message. + * @param coap_header, Received CoAP message + * @param address, Server address + */ + void handle_bootstrap_finished(sn_coap_hdr_s *coap_header,sn_nsdl_addr_s *address); + + /** + * @brief Handle bootstrap delete message. + * @param coap_header, Received CoAP message + * @param address, Server address + */ + void handle_bootstrap_delete(sn_coap_hdr_s *coap_header,sn_nsdl_addr_s *address); + + /** + * @brief Parse bootstrap TLV message. + * @param coap_header, Received CoAP message + * @return True if parsing was succesful else false + */ + bool parse_bootstrap_message(sn_coap_hdr_s *coap_header, bool is_security_object); + + /** + * @brief Parse bootstrap TLV message. + * @param coap_header, Received CoAP message + * @return True if parsing was succesful else false + */ + bool validate_security_object(); + + /** + * @brief Handle bootstrap errors. + */ + void handle_bootstrap_error(); + +private: + + M2MNsdlObserver &_observer; + M2MObjectList _object_list; + M2MServer *_server; // Not owned + M2MSecurity *_security; // Not owned + M2MTimer *_nsdl_exceution_timer; + M2MTimer *_registration_timer; + sn_nsdl_ep_parameters_s *_endpoint; + sn_nsdl_resource_info_s *_resource; + sn_nsdl_addr_s _sn_nsdl_address; + nsdl_s *_nsdl_handle; + uint32_t _counter_for_nsdl; + uint16_t _bootstrap_id; + bool _register_ongoing; + bool _unregister_ongoing; + bool _update_register_ongoing; + String _endpoint_name; + +friend class Test_M2MNsdlInterface; + +}; + +#endif // M2MNSDLINTERFACE_H + diff --git a/features/FEATURE_CLIENT/mbed-client/source/include/m2mnsdlobserver.h b/features/FEATURE_CLIENT/mbed-client/source/include/m2mnsdlobserver.h new file mode 100644 index 0000000000..2d76903b43 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/include/m2mnsdlobserver.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_NSDL_OBSERVER_H +#define M2M_NSDL_OBSERVER_H + +#include "include/nsdllinker.h" + +//FORWARD DECLARATION +class M2MSecurity; +class M2MServer; + +/** + * @brief Observer class for informing NSDL callback to the state machine + */ + +class M2MNsdlObserver +{ + +public : + + /** + * @brief Informs that coap message is ready. + * @param data_ptr, Data object of coap message. + * @param data_len, Length of the data object. + * @param address_ptr, Address structure of the server. + */ + virtual void coap_message_ready(uint8_t *data_ptr, + uint16_t data_len, + sn_nsdl_addr_s *address_ptr) = 0; + + /** + * @brief Informs that client is registered successfully. + * @param server_object, Server object associated with + * registered server. + */ + virtual void client_registered(M2MServer *server_object) = 0; + + /** + * @brief Informs that client registration is updated successfully. + * @param server_object, Server object associated with + * registered server. + */ + virtual void registration_updated(const M2MServer &server_object) = 0; + + /** + * @brief Informs that some error occured during + * registration. + * @param error_code, Error code for registration error + * @param retry, Indicates state machine to re-establish connection + */ + virtual void registration_error(uint8_t error_code, bool retry = false) = 0; + + /** + * @brief Informs that client is unregistered successfully. + */ + virtual void client_unregistered() = 0; + + /** + * @brief Informs that client bootstrapping is done. + * @param security_object, M2MSecurity Object which contains information about + * LWM2M server fetched from bootstrap server. + */ + virtual void bootstrap_done(M2MSecurity *security_object) = 0; + + /** + * @brief Informs that some error occured during + * bootstrapping. + */ + virtual void bootstrap_error() = 0; + + /** + * @brief Informs that received data has been processed. + */ + virtual void coap_data_processed() = 0; + + /** + * @brief Callback informing that the value of the resource object is updated by server. + * @param base Object whose value is updated. + */ + virtual void value_updated(M2MBase *base) = 0; +}; +#endif // M2M_NSDL_OBSERVER_H diff --git a/features/FEATURE_CLIENT/mbed-client/source/include/m2mreporthandler.h b/features/FEATURE_CLIENT/mbed-client/source/include/m2mreporthandler.h new file mode 100644 index 0000000000..809908d41d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/include/m2mreporthandler.h @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2MREPORTHANDLER_H +#define M2MREPORTHANDLER_H + +// Support for std args +#include +#include "mbed-client/m2mconfig.h" +#include "mbed-client/m2mbase.h" +#include "mbed-client/m2mtimerobserver.h" +#include "mbed-client/m2mresourceinstance.h" +#include "mbed-client/m2mvector.h" + +//FORWARD DECLARATION +class M2MReportObserver; +class M2MTimer; +class M2MResourceInstance; + +/** + * @brief M2MReportHandler. + * This class is handles all the observation related operations. + */ +class M2MReportHandler: public M2MTimerObserver +{ +private: + // Prevents the use of assignment operator by accident. + M2MReportHandler& operator=( const M2MReportHandler& /*other*/ ); + +public: + + M2MReportHandler(M2MReportObserver &observer); + +public: + + /** + * Enum defining which write attributes are set. + */ + enum { + Cancel = 1, + Pmin = 2, + Pmax = 4, + Lt = 8, + Gt = 16, + St = 32 + }; + + /** + * Destructor + */ + virtual ~M2MReportHandler(); + + /** + * @brief Sets that object is under observation. + * @param Value for the observation. + * @param handler, Handler object for sending + * observation callbacks. + */ + virtual void set_under_observation(bool observed); + + /** + * @brief Sets the value of the given resource. + * @param value, Value of the observed resource. + */ + virtual void set_value(float value); + + /** + * @brief Sets notification trigger. + * @param obj_instance_id, Object instance id that has changed + */ + void set_notification_trigger(uint16_t obj_instance_id = 0); + + /** + * @brief Parses the received query for notification + * attribute. + * @param query Query to be parsed for attributes. + * @param type Type of the Base Object. + * @param resource_type Type of the Resource. + * @return true if required attributes are present else false. + */ + virtual bool parse_notification_attribute(char *&query, + M2MBase::BaseType type, + M2MResourceInstance::ResourceType resource_type = M2MResourceInstance::OPAQUE); + + /** + * @brief Set back to default values. + */ + void set_default_values(); + + /** + * @brief Return write attribute flags. + */ + uint8_t attribute_flags(); + +protected : // from M2MTimerObserver + + virtual void timer_expired(M2MTimerObserver::Type type = + M2MTimerObserver::Notdefined); + +private: + + + + bool set_notification_attribute(char* option, + M2MBase::BaseType type, + M2MResourceInstance::ResourceType resource_type); + + /** + * @brief Schedule a report, if the pmin is exceeded + * then report immediately else store the state to be + * reported once the time fires. + */ + void schedule_report(); + + /** + * @brief Reports a sample that satisfies the reporting criteria. + */ + void report(); + + /** + * @brief Manage timers for pmin and pmax. + */ + void handle_timers(); + + /** + * @brief Check whether notification params can be accepted. + */ + bool check_attribute_validity(); + + /** + * @brief Stop pmin & pmax timers. + */ + void stop_timers(); + + /** + * @brief Check if current value match threshold values. + * @return True if notify can be send otherwise false. + */ + bool check_threshold_values(); + + /** + * @brief Check whether current value matches with GT & LT. + * @return True if current value match with GT or LT values. + */ + bool check_gt_lt_params(); + +private: + M2MReportObserver &_observer; + int _pmax; + int _pmin; + float _gt; + float _lt; + float _st; + bool _pmin_exceeded; + bool _pmax_exceeded; + M2MTimer *_pmin_timer; + M2MTimer *_pmax_timer; + float _high_step; + float _low_step; + float _current_value; + float _last_value; + uint8_t _attribute_state; + bool _notify; + m2m::Vector _changed_instance_ids; + +friend class Test_M2MReportHandler; + +}; + +#endif // M2MREPORTHANDLER_H diff --git a/features/FEATURE_CLIENT/mbed-client/source/include/m2mtlvdeserializer.h b/features/FEATURE_CLIENT/mbed-client/source/include/m2mtlvdeserializer.h new file mode 100644 index 0000000000..600d637714 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/include/m2mtlvdeserializer.h @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client/m2mvector.h" +#include "mbed-client/m2mobject.h" +#include "mbed-client/m2mobjectinstance.h" +#include "mbed-client/m2mresource.h" + +/** + * @brief M2MTLVDeserializer + * TLV Deserialiser get the object instances and resources as binary data and + * builds the lwm2m representation from it. See OMA-LWM2M + * specification, chapter 6.1 for the resource model and chapter 6.3.3 for + * the OMA-TLV specification. + */ +class M2MTLVDeserializer { + +public : + + typedef enum { + None, + NotFound, + NotAllowed, + NotValid + } Error; + + typedef enum { + Put, + Post + } Operation; + + + /** + * Constructor. + */ + M2MTLVDeserializer(); + + /** + * Destructor. + */ + virtual ~M2MTLVDeserializer(); + + /** + * This method checks whether the given binary encodes an object instance + * or something else. It returns true if bits 7-6 of the first + * byte is "00". + * @param tlv Binary to be checked as LWM2M object instance + * @return true or false. + */ + bool is_object_instance(uint8_t *tlv); + + + /** + * This method checks whether the given binary encodes a resource or + * something else. It returns true if bits 7-6 of the first + * byte is "11". + * @param tlv Binary to be checked as LWM2M resource. + * @return true or false. + */ + bool is_resource(uint8_t *tlv); + + /** + * This method checks whether the given binary encodes a multiple resource + * or something else. It returns true if bits 7-6 of the first + * byte is "10". + * @param tlv Binary to be checked as LWM2M multiple resource. + * @return true or false. + */ + bool is_multiple_resource(uint8_t *tlv); + + /** + * This method checks whether the given binary encodes a resource instance + * or something else. It returns true if bits 7-6 of the first + * byte is "01". + * @param tlv Binary to be checked as LWM2M resource instance. + * @return true or false. + */ + bool is_resource_instance(uint8_t *tlv); + + /** + * Deserialises the given binary that must encode object instances. Binary + * array can be checked before invoking this method with + */ + M2MTLVDeserializer::Error deserialise_object_instances(uint8_t* tlv, + uint32_t tlv_size, + M2MObject &object, + M2MTLVDeserializer::Operation operation); + + /** + * Deserialises the given binary that must encode resources. Binary array + * can be checked before invoking this method. + */ + M2MTLVDeserializer::Error deserialize_resources(uint8_t *tlv, + uint32_t tlv_size, + M2MObjectInstance &object_instance, + M2MTLVDeserializer::Operation operation); + + /** + * Deserialises the given binary that must encode resource instances. Binary array + * can be checked before invoking this method. + */ + M2MTLVDeserializer::Error deserialize_resource_instances(uint8_t *tlv, + uint32_t tlv_size, + M2MResource &resource, + M2MTLVDeserializer::Operation operation); + /** + * This method return object instance id or resource id. + * @param tlv Binary to be checked + * @return Object instance id or resource id. + */ + uint16_t instance_id(uint8_t *tlv); + +private: + + M2MTLVDeserializer::Error deserialize_object_instances(uint8_t *tlv, + uint32_t tlv_size, + uint32_t offset, + M2MObject &object, + M2MTLVDeserializer::Operation operation, + bool update_value); + + M2MTLVDeserializer::Error deserialize_resources(uint8_t *tlv, + uint32_t tlv_size, + uint32_t offset, + M2MObjectInstance &object_instance, + M2MTLVDeserializer::Operation operation, + bool update_value); + + M2MTLVDeserializer::Error deserialize_resource_instances(uint8_t *tlv, + uint32_t tlv_size, + uint32_t offset, + M2MResource &resource, + M2MObjectInstance &object_instance, + M2MTLVDeserializer::Operation operation, + bool update_value); + + M2MTLVDeserializer::Error deserialize_resource_instances(uint8_t *tlv, + uint32_t tlv_size, + uint32_t offset, + M2MResource &resource, + M2MTLVDeserializer::Operation operation, + bool update_value); + + bool is_object_instance(uint8_t *tlv, uint32_t offset); + + bool is_resource(uint8_t *tlv, uint32_t offset); + + bool is_multiple_resource(uint8_t *tlv, uint32_t offset); + + bool is_resource_instance(uint8_t *tlv, uint32_t offset); +}; + +class TypeIdLength { + +public: + + static TypeIdLength* createTypeIdLength(uint8_t *tlv, uint32_t offset); + + TypeIdLength* deserialize(); + + void deserialiseID (uint32_t idLength); + + void deserialiseLength (uint32_t lengthType); + + uint8_t *_tlv; + uint32_t _offset; + uint32_t _type; + uint16_t _id; + uint32_t _length; + + friend class Test_M2MTLVDeserializer; +}; diff --git a/features/FEATURE_CLIENT/mbed-client/source/include/m2mtlvserializer.h b/features/FEATURE_CLIENT/mbed-client/source/include/m2mtlvserializer.h new file mode 100644 index 0000000000..9e068095cd --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/include/m2mtlvserializer.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client/m2mvector.h" +#include "mbed-client/m2mobject.h" +#include "mbed-client/m2mobjectinstance.h" +#include "mbed-client/m2mresource.h" + +/** + * @brief M2MTLVSerializer + * TLV Serialiser constructs the binary representation of object instances, + * resources and resource instances (see OMA-LWM2M specification, chapter 6.1 + * for resource model) as OMA-TLV according described in chapter 6.3.3. + * + */ +class M2MTLVSerializer { + +public: + + /** + * Constructor. + */ + M2MTLVSerializer(); + + /** + * Destructor. + */ + virtual ~M2MTLVSerializer(); + + /** + * Serialises given objects instances that contain resources or multiple + * resources. Object instance IDs are also encoded. This method must be + * used when an operation targets an object with (potential) multiple + * instances like "GET /1". In that case the generated TLV will contain the + * following data: + *
    + *
  • ./0 + *
  • ./0/0 + *
  • ./0/1 + *
  • ... + *
  • ./1 + *
  • ./1/0 + *
  • ./1/1 + *
  • ... + *
+ * + * @param objects List of object instances. + * @return Object instances encoded binary as OMA-TLV + * @see #serializeObjectInstances(List) + */ + uint8_t* serialize(M2MObjectInstanceList object_instance_list, uint32_t &size); + + /** + * Serialises given resources with no information about the parent object + * instance. This method must be used when an operation targets an object + * instance like "GET /1/0" or a single-instance object like "GET /3//". + * Resources may have single or multiple instances. The generated TLV will + * contain the following data as response to "GET /3//": + *
    + *
  • ./0 + *
  • ./1 + *
  • ./2 + *
  • ./6/0 (1st instance of a multiple resource) + *
  • ./6/1 (2nd instance of a multiple resource) + *
  • ... + *
+ * @param resources Array of resources and resource instances. + * @return Resources encoded binary as OMA-TLV + * @see #serializeResources(List) + */ + uint8_t* serialize(M2MResourceList resource_list, uint32_t &size); + + uint8_t* serialize(M2MResource *resource, uint32_t &size); + +private : + + uint8_t* serialize_object_instances(M2MObjectInstanceList object_instance_list, uint32_t &size); + + uint8_t* serialize_resources(M2MResourceList resource_list, uint32_t &size, bool &valid); + + void serialize(uint16_t id, M2MObjectInstance *object_instance, uint8_t *&data, uint32_t &size); + + bool serialize (M2MResource *resource, uint8_t *&data, uint32_t &size); + + bool serialize_resource(M2MResource *resource, uint8_t *&data, uint32_t &size); + + bool serialize_multiple_resource(M2MResource *resource, uint8_t *&data, uint32_t &size); + + void serialize_resource_instance(uint16_t id, M2MResourceInstance *resource, uint8_t *&data, uint32_t &size); + + void serialize_TILV (uint8_t type, uint16_t id, uint8_t *value, uint32_t value_length, uint8_t *&data, uint32_t &size); + + uint8_t* serialize_id(uint16_t id, uint32_t &size); + + uint8_t* serialize_length(uint32_t length, uint32_t &size); +}; diff --git a/features/FEATURE_CLIENT/mbed-client/source/include/nsdlaccesshelper.h b/features/FEATURE_CLIENT/mbed-client/source/include/nsdlaccesshelper.h new file mode 100644 index 0000000000..f8ed1da5e3 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/include/nsdlaccesshelper.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 NSDL_ACCESS_HELPER_H +#define NSDL_ACCESS_HELPER_H +#include "mbed-client/m2mconnectionhandler.h" +#include "include/m2mnsdlinterface.h" + +typedef Vector M2MNsdlInterfaceList; +extern M2MNsdlInterfaceList __nsdl_interface_list; +extern M2MConnectionHandler *__connection_handler; + +#ifdef __cplusplus +extern "C" { +#endif + +uint8_t __nsdl_c_callback(struct nsdl_s * nsdl_handle, + sn_coap_hdr_s *received_coap_ptr, + sn_nsdl_addr_s *address, + sn_nsdl_capab_e nsdl_capab); +void *__nsdl_c_memory_alloc(uint16_t size); +void __nsdl_c_memory_free(void *ptr); +uint8_t __nsdl_c_send_to_server(struct nsdl_s * nsdl_handle, + sn_nsdl_capab_e protocol, + uint8_t *data_ptr, + uint16_t data_len, + sn_nsdl_addr_s *address_ptr); +uint8_t __nsdl_c_received_from_server(struct nsdl_s * nsdl_handle, + sn_coap_hdr_s *coap_header, + sn_nsdl_addr_s *address_ptr); + +void *__socket_malloc( void * context, size_t size); +void __socket_free(void * context, void * ptr); + +M2MNsdlInterface* get_interface(struct nsdl_s* nsdl_handle); + +void __mutex_claim(); +void __mutex_release(); + +#ifdef __cplusplus +} +#endif + +#endif // NSDL_ACCESS_HELPER_H diff --git a/features/FEATURE_CLIENT/mbed-client/source/include/nsdllinker.h b/features/FEATURE_CLIENT/mbed-client/source/include/nsdllinker.h new file mode 100644 index 0000000000..bc57367d25 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/include/nsdllinker.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 NSDL_LINKER_H +#define NSDL_LINKER_H + +#include +#include "nsdl-c/sn_nsdl.h" // libCoap includes +#include "nsdl-c/sn_coap_header.h" +#include "nsdl-c/sn_coap_protocol.h" +#include "nsdl-c/sn_nsdl_lib.h" +#include "ns_list.h" + +#endif // NSDL_LINKER_H diff --git a/features/FEATURE_CLIENT/mbed-client/source/include/smartpointer.h b/features/FEATURE_CLIENT/mbed-client/source/include/smartpointer.h new file mode 100644 index 0000000000..7bb0b1ed87 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/include/smartpointer.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 SMART_POINTER_H +#define SMART_POINTER_H + +class ReferenceCount +{ +private: + + int _count; // Reference count + +public: + +void add_ref() +{ + // Increment the reference count + _count++; +} + +int release() +{ + // Decrement the reference count and + // return the reference count. + return --_count; +} +}; + +template < typename T > class SmartPointer +{ +private: + + T *_data; // Generic pointer to be stored + ReferenceCount *_reference; // Reference count + + +public: + +SmartPointer() +: _data(0), _reference(0) +{ + // Create a new reference + _reference = new ReferenceCount(); + // Increment the reference count + _reference->add_ref(); +} + +SmartPointer(T* value) +: _data(value), _reference(0) +{ + // Create a new reference + _reference = new ReferenceCount(); + // Increment the reference count + _reference->add_ref(); +} + +SmartPointer(const SmartPointer& smart_pointer) +: _data(smart_pointer._data), reference(smart_pointer._reference) +{ + // Copy constructor + // Copy the data and reference pointer + // and increment the reference count + _reference->add_ref(); +} + +~SmartPointer() +{ + if(_reference->release() == 0) { + delete _data; + delete _reference; + } +} + +T& operator* () +{ + return *_data; +} + +T* operator-> () +{ + return _data; +} + +SmartPointer& operator = (const SmartPointer& smart_pointer) +{ + // Assignment operator + if (this != &SmartPointer) { // Avoid self assignment + // Decrement the old reference count + // if reference become zero delete the old data + if(_reference->release() == 0) { + delete _data; + delete _reference; + } + + // Copy the data and reference pointer + // and increment the reference count + _data = SmartPointer._data; + _reference = SmartPointer._reference; + _reference->add_ref(); + } + return *this; +} + +}; + +#endif // SMART_POINTER_H diff --git a/features/FEATURE_CLIENT/mbed-client/source/m2mbase.cpp b/features/FEATURE_CLIENT/mbed-client/source/m2mbase.cpp new file mode 100644 index 0000000000..a518a080e4 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/m2mbase.cpp @@ -0,0 +1,479 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client/m2mbase.h" +#include "mbed-client/m2mobservationhandler.h" +#include "mbed-client/m2mconstants.h" +#include "mbed-client/m2mtimer.h" +#include "include/m2mreporthandler.h" +#include "include/nsdllinker.h" +#include "mbed-trace/mbed_trace.h" +#include +#include +#include + +#define TRACE_GROUP "mClt" + +M2MBase& M2MBase::operator=(const M2MBase& other) +{ + if (this != &other) { // protect against invalid self-assignment + _operation = other._operation; + _mode = other._mode; + _name = other._name; + _resource_type = other._resource_type; + _interface_description = other._interface_description; + _coap_content_type = other._coap_content_type; + _instance_id = other._instance_id; + _observable = other._observable; + _observation_number = other._observation_number; + _observation_level = other._observation_level; + _observation_handler = other._observation_handler; + _register_uri = other._register_uri; + _uri_path = other._uri_path; + _max_age = other._max_age; + _is_under_observation = other._is_under_observation; + + free(_token); + _token = NULL; + + _token_length = other._token_length; + if(other._token) { + _token = alloc_string_copy(other._token, other._token_length); + } + + delete _report_handler; + _report_handler = NULL; + + if(other._report_handler) { + _report_handler = new M2MReportHandler(*other._report_handler); + } + } + return *this; +} + +M2MBase::M2MBase(const M2MBase& other) : + _report_handler(NULL), + _observation_handler(other._observation_handler), + _name(other._name), + _resource_type(other._resource_type), + _interface_description(other._interface_description), + _uri_path(other._uri_path), + _max_age(other._max_age), + _instance_id(other._instance_id), + _observation_number(other._observation_number), + _token(NULL), + _token_length(other._token_length), + _coap_content_type(other._coap_content_type), + _operation(other._operation), + _mode(other._mode), + _observation_level(other._observation_level), + _observable(other._observable), + _register_uri(other._register_uri), + _is_under_observation(other._is_under_observation), + _function_pointer(NULL) +{ + + if(other._token) { + _token = alloc_string_copy((uint8_t *)other._token, other._token_length); + } + + if(other._report_handler) { + _report_handler = new M2MReportHandler(*other._report_handler); + } +} + +M2MBase::M2MBase(const String & resource_name, + M2MBase::Mode mde) +: _report_handler(NULL), + _observation_handler(NULL), + _name(resource_name), + _uri_path(""), + _max_age(0), + _instance_id(0), + _observation_number(0), + _token(NULL), + _token_length(0), + _coap_content_type(0), + _operation(M2MBase::NOT_ALLOWED), + _mode(mde), + _observation_level(M2MBase::None), + _observable(false), + _register_uri(true), + _is_under_observation(false), + _function_pointer(NULL) +{ + if(is_integer(_name) && _name.size() <= MAX_ALLOWED_STRING_LENGTH) { + _name_id = strtoul(_name.c_str(), NULL, 10); + if(_name_id > 65535){ + _name_id = -1; + } + } else { + _name_id = -1; + } +} + +M2MBase::~M2MBase() +{ + delete _report_handler; + free(_token); + delete _function_pointer; +} + +void M2MBase::set_operation(M2MBase::Operation opr) +{ + // If the mode is Static, there is only GET_ALLOWED + // supported. + if(M2MBase::Static == _mode) { + _operation = M2MBase::GET_ALLOWED; + } else { + _operation = opr; + } +} + +void M2MBase::set_interface_description(const String &desc) +{ + _interface_description = desc; +} + +void M2MBase::set_resource_type(const String &res_type) +{ + _resource_type = res_type; +} + +void M2MBase::set_coap_content_type(const uint8_t con_type) +{ + _coap_content_type = con_type; +} + +void M2MBase::set_observable(bool observable) +{ + _observable = observable; +} + +void M2MBase::add_observation_level(M2MBase::Observation obs_level) +{ + _observation_level = (M2MBase::Observation)(_observation_level | obs_level); +} + +void M2MBase::remove_observation_level(M2MBase::Observation obs_level) +{ + _observation_level = (M2MBase::Observation)(_observation_level & ~obs_level); +} + +void M2MBase::set_under_observation(bool observed, + M2MObservationHandler *handler) +{ + + tr_debug("M2MBase::set_under_observation - observed: %d", observed); + tr_debug("M2MBase::set_under_observation - base_type: %d", _base_type); + _is_under_observation = observed; + _observation_handler = handler; + if(handler) { + if (_base_type != M2MBase::ResourceInstance) { + if(!_report_handler){ + _report_handler = new M2MReportHandler(*this); + } + _report_handler->set_under_observation(observed); + } + } else { + delete _report_handler; + _report_handler = NULL; + } +} + +void M2MBase::set_observation_token(const uint8_t *token, const uint8_t length) +{ + free(_token); + _token = NULL; + _token_length = 0; + + if( token != NULL && length > 0 ) { + _token = alloc_string_copy((uint8_t *)token, length); + if(_token) { + _token_length = length; + } + } +} + +void M2MBase::set_instance_id(const uint16_t inst_id) +{ + _instance_id = inst_id; +} + + +void M2MBase::set_observation_number(const uint16_t /*observation_number*/) +{ +} + +void M2MBase::set_max_age(const uint32_t max_age) +{ + _max_age = max_age; +} + +M2MBase::BaseType M2MBase::base_type() const +{ + return _base_type; +} + +M2MBase::Operation M2MBase::operation() const +{ + return _operation; +} + +const String& M2MBase::name() const +{ + return _name; +} + +int32_t M2MBase::name_id() const +{ + return _name_id; +} + +uint16_t M2MBase::instance_id() const +{ + return _instance_id; +} + +const String& M2MBase::interface_description() const +{ + return _interface_description; +} + +const String& M2MBase::resource_type() const +{ + return _resource_type; +} + +uint8_t M2MBase::coap_content_type() const +{ + return _coap_content_type; +} + +bool M2MBase::is_observable() const +{ + return _observable; +} + +M2MBase::Observation M2MBase::observation_level() const +{ + return _observation_level; +} + +void M2MBase::get_observation_token(uint8_t *&token, uint32_t &token_length) +{ + token_length = 0; + free(token); + + token = alloc_string_copy((uint8_t *)_token, _token_length); + if(token) { + token_length = _token_length; + } +} + +M2MBase::Mode M2MBase::mode() const +{ + return _mode; +} + +uint16_t M2MBase::observation_number() const +{ + return _observation_number; +} + +uint32_t M2MBase::max_age() const +{ + return _max_age; +} + +bool M2MBase::handle_observation_attribute(char *&query) +{ + tr_debug("M2MBase::handle_observation_attribute - under observation(%d)", is_under_observation()); + bool success = false; + if(_report_handler) { + success = _report_handler->parse_notification_attribute(query,_base_type); + if (success) { + if (is_under_observation()) { + _report_handler->set_under_observation(true); + } + } else { + _report_handler->set_default_values(); + } + } + return success; +} + +void M2MBase::observation_to_be_sent(m2m::Vector changed_instance_ids, bool send_object) +{ + //TODO: Move this to M2MResourceInstance + if(_observation_handler) { + _observation_number++; + _observation_handler->observation_to_be_sent(this, + _observation_number, + changed_instance_ids, + send_object); + } +} + +void M2MBase::set_base_type(M2MBase::BaseType type) +{ + _base_type = type; +} + +void M2MBase::remove_resource_from_coap(const String &resource_name) +{ + if(_observation_handler) { + _observation_handler->resource_to_be_deleted(resource_name); + } +} + +void M2MBase::remove_object_from_coap() +{ + if(_observation_handler) { + _observation_handler->remove_object(this); + } +} + +sn_coap_hdr_s* M2MBase::handle_get_request(nsdl_s */*nsdl*/, + sn_coap_hdr_s */*received_coap_header*/, + M2MObservationHandler */*observation_handler*/) +{ + //Handled in M2MResource, M2MObjectInstance and M2MObject classes + return NULL; +} + +sn_coap_hdr_s* M2MBase::handle_put_request(nsdl_s */*nsdl*/, + sn_coap_hdr_s */*received_coap_header*/, + M2MObservationHandler */*observation_handler*/, + bool &) +{ + //Handled in M2MResource, M2MObjectInstance and M2MObject classes + return NULL; +} + +sn_coap_hdr_s* M2MBase::handle_post_request(nsdl_s */*nsdl*/, + sn_coap_hdr_s */*received_coap_header*/, + M2MObservationHandler */*observation_handler*/, + bool &) +{ + //Handled in M2MResource, M2MObjectInstance and M2MObject classes + return NULL; +} + +void *M2MBase::memory_alloc(uint32_t size) +{ + if(size) + return malloc(size); + else + return 0; +} + +void M2MBase::memory_free(void *ptr) +{ + free(ptr); +} + +uint8_t* M2MBase::alloc_string_copy(const uint8_t* source, uint32_t size) +{ + assert(source != NULL); + + uint8_t* result = (uint8_t*)memory_alloc(size + 1); + if (result) { + memcpy(result, source, size); + result[size] = '\0'; + } + return result; +} + +uint8_t* M2MBase::alloc_copy(const uint8_t* source, uint32_t size) +{ + assert(source != NULL); + + uint8_t* result = (uint8_t*)memory_alloc(size); + if (result) { + memcpy(result, source, size); + } + return result; +} + +M2MReportHandler* M2MBase::report_handler() +{ + return _report_handler; +} + +M2MObservationHandler* M2MBase::observation_handler() +{ + return _observation_handler; +} + +void M2MBase::set_register_uri( bool register_uri) +{ + _register_uri = register_uri; +} + +bool M2MBase::register_uri() +{ + return _register_uri; +} + +bool M2MBase::is_integer(const String &value) +{ + const char *s = value.c_str(); + if(value.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) { + return false; + } + char * p ; + strtol(value.c_str(), &p, 10); + return (*p == 0); +} + +void M2MBase::set_uri_path(const String &path) +{ + _uri_path = path; +} + +const String& M2MBase::uri_path() const +{ + return _uri_path; +} + +bool M2MBase::is_under_observation() const +{ + return _is_under_observation; +} + +void M2MBase::set_value_updated_function(value_updated_callback callback) +{ + _value_updated_callback = callback; +} + +void M2MBase::set_value_updated_function(value_updated_callback2 callback) +{ + delete _function_pointer; + _function_pointer = new FP1(callback); + set_value_updated_function(value_updated_callback(_function_pointer, + &FP1::call)); +} +bool M2MBase::is_value_updated_function_set() +{ + return (_value_updated_callback) ? true : false; +} + +void M2MBase::execute_value_updated(const String& name) +{ + if(_value_updated_callback) { + _value_updated_callback(name.c_str()); + } +} diff --git a/features/FEATURE_CLIENT/mbed-client/source/m2mdevice.cpp b/features/FEATURE_CLIENT/mbed-client/source/m2mdevice.cpp new file mode 100644 index 0000000000..46891bb807 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/m2mdevice.cpp @@ -0,0 +1,562 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client/m2mdevice.h" +#include "mbed-client/m2mconstants.h" +#include "mbed-client/m2mobject.h" +#include "mbed-client/m2mobjectinstance.h" +#include "mbed-client/m2mresource.h" +#include "mbed-trace/mbed_trace.h" + +#define BUFFER_SIZE 21 +#define TRACE_GROUP "mClt" + +M2MDevice* M2MDevice::_instance = NULL; + +M2MDevice* M2MDevice::get_instance() +{ + if(_instance == NULL) { + _instance = new M2MDevice(); + } + return _instance; +} + +void M2MDevice::delete_instance() +{ + delete _instance; + _instance = NULL; +} + +M2MDevice::M2MDevice() +: M2MObject(M2M_DEVICE_ID) +{ + M2MBase::set_register_uri(false); + M2MBase::set_operation(M2MBase::GET_ALLOWED); + + _device_instance = M2MObject::create_object_instance(); + _device_instance->set_operation(M2MBase::GET_ALLOWED); + _device_instance->set_register_uri(true); + if(_device_instance) { + _device_instance->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE); + M2MResource* res = _device_instance->create_dynamic_resource(DEVICE_REBOOT, + OMA_RESOURCE_TYPE, + M2MResourceInstance::OPAQUE, + false); + if(res) { + res->set_operation(M2MBase::POST_ALLOWED); + res->set_register_uri(false); + } + + M2MResourceInstance* instance = _device_instance->create_dynamic_resource_instance(DEVICE_ERROR_CODE, + OMA_RESOURCE_TYPE, + M2MResourceInstance::INTEGER, + true,0); + if(instance) { + M2MResource * dev_res = _device_instance->resource(DEVICE_ERROR_CODE); + if(dev_res) { + dev_res->set_register_uri(false); + } + instance->set_operation(M2MBase::GET_ALLOWED); + + instance->set_value(0); + + instance->set_register_uri(false); + } + res = _device_instance->create_dynamic_resource(DEVICE_SUPPORTED_BINDING_MODE, + OMA_RESOURCE_TYPE, + M2MResourceInstance::STRING, + true); + if(res) { + res->set_operation(M2MBase::GET_ALLOWED); + res->set_value((const uint8_t*)BINDING_MODE_UDP,sizeof(BINDING_MODE_UDP)-1); + res->set_register_uri(false); + } + } +} + +M2MDevice::~M2MDevice() +{ +} + +M2MResource* M2MDevice::create_resource(DeviceResource resource, const String &value) +{ + M2MResource* res = NULL; + const char* device_id_ptr = ""; + M2MBase::Operation operation = M2MBase::GET_ALLOWED; + if(!is_resource_present(resource) && value.size() <= MAX_ALLOWED_STRING_LENGTH) { + switch(resource) { + case Manufacturer: + device_id_ptr = DEVICE_MANUFACTURER; + break; + case DeviceType: + device_id_ptr = DEVICE_DEVICE_TYPE; + break; + case ModelNumber: + device_id_ptr = DEVICE_MODEL_NUMBER; + break; + case SerialNumber: + device_id_ptr = DEVICE_SERIAL_NUMBER; + break; + case HardwareVersion: + device_id_ptr = DEVICE_HARDWARE_VERSION; + break; + case FirmwareVersion: + device_id_ptr = DEVICE_FIRMWARE_VERSION; + break; + case SoftwareVersion: + device_id_ptr = DEVICE_SOFTWARE_VERSION; + break; + case UTCOffset: + device_id_ptr = DEVICE_UTC_OFFSET; + operation = M2MBase::GET_PUT_ALLOWED; + break; + case Timezone: + device_id_ptr = DEVICE_TIMEZONE; + operation = M2MBase::GET_PUT_ALLOWED; + break; + default: + break; + } + } + const String device_id(device_id_ptr); + + if(!device_id.empty()) { + if(_device_instance) { + res = _device_instance->create_dynamic_resource(device_id, + OMA_RESOURCE_TYPE, + M2MResourceInstance::STRING, + true); + + if(res ) { + res->set_operation(operation); + if (value.empty()) { + res->clear_value(); + } else { + res->set_value((const uint8_t*)value.c_str(), + (uint32_t)value.length()); + } + res->set_register_uri(false); + } + } + } + return res; +} + +M2MResource* M2MDevice::create_resource(DeviceResource resource, int64_t value) +{ + M2MResource* res = NULL; + const char* device_id_ptr = ""; + M2MBase::Operation operation = M2MBase::GET_ALLOWED; + if(!is_resource_present(resource)) { + switch(resource) { + case BatteryLevel: + if(check_value_range(resource, value)) { + device_id_ptr = DEVICE_BATTERY_LEVEL; + } + break; + case BatteryStatus: + if(check_value_range(resource, value)) { + device_id_ptr = DEVICE_BATTERY_STATUS; + } + break; + case MemoryFree: + device_id_ptr = DEVICE_MEMORY_FREE; + break; + case MemoryTotal: + device_id_ptr = DEVICE_MEMORY_TOTAL; + break; + case CurrentTime: + device_id_ptr = DEVICE_CURRENT_TIME; + operation = M2MBase::GET_PUT_ALLOWED; + break; + default: + break; + } + } + + const String device_id(device_id_ptr); + + if(!device_id.empty()) { + if(_device_instance) { + res = _device_instance->create_dynamic_resource(device_id, + OMA_RESOURCE_TYPE, + M2MResourceInstance::INTEGER, + true); + + if(res) { + + + res->set_operation(operation); + res->set_value(value); + + res->set_register_uri(false); + } + } + } + return res; +} + +M2MResourceInstance* M2MDevice::create_resource_instance(DeviceResource resource, int64_t value, + uint16_t instance_id) +{ + M2MResourceInstance* res = NULL; + const char* device_id_ptr = ""; + // For these resources multiple instance can exist + if(AvailablePowerSources == resource) { + if(check_value_range(resource, value)) { + device_id_ptr = DEVICE_AVAILABLE_POWER_SOURCES; + } + } else if(PowerSourceVoltage == resource) { + device_id_ptr = DEVICE_POWER_SOURCE_VOLTAGE; + } else if(PowerSourceCurrent == resource) { + device_id_ptr = DEVICE_POWER_SOURCE_CURRENT; + } else if(ErrorCode == resource) { + if(check_value_range(resource, value)) { + device_id_ptr = DEVICE_ERROR_CODE; + } + } + + const String device_id(device_id_ptr); + + if(!device_id.empty()) { + if(_device_instance) { + res = _device_instance->create_dynamic_resource_instance(device_id,OMA_RESOURCE_TYPE, + M2MResourceInstance::INTEGER, + true, instance_id); + + M2MResource *resource = _device_instance->resource(device_id); + if(resource) { + resource->set_register_uri(false); + } + if(res) { + res->set_value(value); + // Only read operation is allowed for above resources + res->set_operation(M2MBase::GET_ALLOWED); + + res->set_register_uri(false); + } + } + } + return res; +} +M2MResource* M2MDevice::create_resource(DeviceResource resource) +{ + M2MResource* res = NULL; + if(!is_resource_present(resource)) { + const char* device_Id_ptr = ""; + if(FactoryReset == resource) { + device_Id_ptr = DEVICE_FACTORY_RESET; + } else if(ResetErrorCode == resource) { + device_Id_ptr = DEVICE_RESET_ERROR_CODE; + } + const String device_Id(device_Id_ptr); + + if(_device_instance && !device_Id.empty()) { + res = _device_instance->create_dynamic_resource(device_Id, + OMA_RESOURCE_TYPE, + M2MResourceInstance::OPAQUE, + true); + M2MResource *resource = _device_instance->resource(device_Id); + if(resource) { + resource->set_register_uri(false); + } + if(res) { + res->set_operation(M2MBase::POST_ALLOWED); + res->set_register_uri(false); + } + } + } + return res; +} + +bool M2MDevice::delete_resource(DeviceResource resource) +{ + bool success = false; + if(M2MDevice::Reboot != resource && + M2MDevice::ErrorCode != resource && + M2MDevice::SupportedBindingMode != resource) { + if(_device_instance) { + success = _device_instance->remove_resource(resource_name(resource)); + } + } + return success; +} + +bool M2MDevice::delete_resource_instance(DeviceResource resource, + uint16_t instance_id) +{ + bool success = false; + if(M2MDevice::Reboot != resource && + M2MDevice::ErrorCode != resource && + M2MDevice::SupportedBindingMode != resource) { + if(_device_instance) { + success = _device_instance->remove_resource_instance(resource_name(resource),instance_id); + } + } + return success; +} + +bool M2MDevice::set_resource_value(DeviceResource resource, + const String &value, + uint16_t instance_id) +{ + bool success = false; + M2MResourceInstance* res = get_resource_instance(resource,instance_id); + if(res && value.size() <= MAX_ALLOWED_STRING_LENGTH) { + if(M2MDevice::Manufacturer == resource || + M2MDevice::ModelNumber == resource || + M2MDevice::DeviceType == resource || + M2MDevice::SerialNumber == resource || + M2MDevice::HardwareVersion == resource || + M2MDevice::FirmwareVersion == resource || + M2MDevice::SoftwareVersion == resource || + M2MDevice::UTCOffset == resource || + M2MDevice::Timezone == resource) { + if (value.empty()) { + res->clear_value(); + success = true; + } else { + success = res->set_value((const uint8_t*)value.c_str(),(uint32_t)value.length()); + } + } + } + return success; +} + +bool M2MDevice::set_resource_value(DeviceResource resource, + int64_t value, + uint16_t instance_id) +{ + bool success = false; + M2MResourceInstance* res = get_resource_instance(resource,instance_id); + if(res) { + if(M2MDevice::BatteryLevel == resource || + M2MDevice::BatteryStatus == resource || + M2MDevice::MemoryFree == resource || + M2MDevice::MemoryTotal == resource || + M2MDevice::ErrorCode == resource || + M2MDevice::CurrentTime == resource || + M2MDevice::AvailablePowerSources == resource || + M2MDevice::PowerSourceVoltage == resource || + M2MDevice::PowerSourceCurrent == resource) { + // If it is any of the above resource + // set the value of the resource. + if (check_value_range(resource, value)) { + + success = res->set_value(value); + } + } + } + return success; +} + +String M2MDevice::resource_value_string(DeviceResource resource, + uint16_t instance_id) const +{ + String value = ""; + M2MResourceInstance* res = get_resource_instance(resource,instance_id); + if(res) { + if(M2MDevice::Manufacturer == resource || + M2MDevice::ModelNumber == resource || + M2MDevice::DeviceType == resource || + M2MDevice::SerialNumber == resource || + M2MDevice::HardwareVersion == resource || + M2MDevice::FirmwareVersion == resource || + M2MDevice::SoftwareVersion == resource || + M2MDevice::UTCOffset == resource || + M2MDevice::Timezone == resource) { + + + value = res->get_value_string(); + } + } + return value; +} + +int64_t M2MDevice::resource_value_int(DeviceResource resource, + uint16_t instance_id) const +{ + int64_t value = -1; + M2MResourceInstance* res = get_resource_instance(resource,instance_id); + if(res) { + if(M2MDevice::BatteryLevel == resource || + M2MDevice::BatteryStatus == resource || + M2MDevice::MemoryFree == resource || + M2MDevice::MemoryTotal == resource || + M2MDevice::ErrorCode == resource || + M2MDevice::CurrentTime == resource || + M2MDevice::AvailablePowerSources == resource || + M2MDevice::PowerSourceVoltage == resource || + M2MDevice::PowerSourceCurrent == resource) { + + // note: the value may be 32bit int on 32b archs. + value = res->get_value_int(); + } + } + return value; +} + +bool M2MDevice::is_resource_present(DeviceResource resource) const +{ + bool success = false; + M2MResourceInstance* res = get_resource_instance(resource,0); + if(res) { + success = true; + } + return success; +} + +uint16_t M2MDevice::per_resource_count(DeviceResource res) const +{ + uint16_t count = 0; + if(_device_instance) { + count = _device_instance->resource_count(resource_name(res)); + } + return count; +} + +uint16_t M2MDevice::total_resource_count() const +{ + uint16_t count = 0; + if(_device_instance) { + count = _device_instance->resources().size(); + } + return count; +} + +M2MResourceInstance* M2MDevice::get_resource_instance(DeviceResource dev_res, + uint16_t instance_id) const +{ + M2MResource* res = NULL; + M2MResourceInstance* inst = NULL; + if(_device_instance) { + res = _device_instance->resource(resource_name(dev_res)); + if(res) { + if(res->supports_multiple_instances()) { + inst = res->resource_instance(instance_id); + } else { + inst = res; + } + } + } + return inst; +} + +const String M2MDevice::resource_name(DeviceResource resource) +{ + const char* res_name = ""; + switch(resource) { + case Manufacturer: + res_name = DEVICE_MANUFACTURER; + break; + case DeviceType: + res_name = DEVICE_DEVICE_TYPE; + break; + case ModelNumber: + res_name = DEVICE_MODEL_NUMBER; + break; + case SerialNumber: + res_name = DEVICE_SERIAL_NUMBER; + break; + case HardwareVersion: + res_name = DEVICE_HARDWARE_VERSION; + break; + case FirmwareVersion: + res_name = DEVICE_FIRMWARE_VERSION; + break; + case SoftwareVersion: + res_name = DEVICE_SOFTWARE_VERSION; + break; + case Reboot: + res_name = DEVICE_REBOOT; + break; + case FactoryReset: + res_name = DEVICE_FACTORY_RESET; + break; + case AvailablePowerSources: + res_name = DEVICE_AVAILABLE_POWER_SOURCES; + break; + case PowerSourceVoltage: + res_name = DEVICE_POWER_SOURCE_VOLTAGE; + break; + case PowerSourceCurrent: + res_name = DEVICE_POWER_SOURCE_CURRENT; + break; + case BatteryLevel: + res_name = DEVICE_BATTERY_LEVEL; + break; + case BatteryStatus: + res_name = DEVICE_BATTERY_STATUS; + break; + case MemoryFree: + res_name = DEVICE_MEMORY_FREE; + break; + case MemoryTotal: + res_name = DEVICE_MEMORY_TOTAL; + break; + case ErrorCode: + res_name = DEVICE_ERROR_CODE; + break; + case ResetErrorCode: + res_name = DEVICE_RESET_ERROR_CODE; + break; + case CurrentTime: + res_name = DEVICE_CURRENT_TIME; + break; + case UTCOffset: + res_name = DEVICE_UTC_OFFSET; + break; + case Timezone: + res_name = DEVICE_TIMEZONE; + break; + case SupportedBindingMode: + res_name = DEVICE_SUPPORTED_BINDING_MODE; + break; + } + return String(res_name); +} + +bool M2MDevice::check_value_range(DeviceResource resource, int64_t value) const +{ + bool success = false; + switch (resource) { + case AvailablePowerSources: + if(value >= 0 && value <= 7) { + success = true; + } + break; + case BatteryLevel: + if (value >= 0 && value <= 100) { + success = true; + } + break; + case BatteryStatus: + if (value >= 0 && value <= 6) { + success = true; + } + break; + case ErrorCode: + if (value >= 0 && value <= 8) { + success = true; + } + break; + default: + success = true; + break; + } + return success; +} + diff --git a/features/FEATURE_CLIENT/mbed-client/source/m2mfirmware.cpp b/features/FEATURE_CLIENT/mbed-client/source/m2mfirmware.cpp new file mode 100644 index 0000000000..5cf2461d81 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/m2mfirmware.cpp @@ -0,0 +1,434 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client/m2mfirmware.h" +#include "mbed-client/m2mconstants.h" +#include "mbed-client/m2mobject.h" +#include "mbed-client/m2mobjectinstance.h" +#include "mbed-client/m2mresource.h" + +#define BUFFER_SIZE 21 +#define TRACE_GROUP "mClt" + +M2MFirmware* M2MFirmware::_instance = NULL; + +M2MFirmware* M2MFirmware::get_instance() +{ + if(_instance == NULL) { + _instance = new M2MFirmware(); + } + return _instance; +} + +void M2MFirmware::delete_instance() +{ + delete _instance; + _instance = NULL; +} + +M2MFirmware::M2MFirmware() +: M2MObject(M2M_FIRMWARE_ID) +{ + M2MBase::set_register_uri(false); + M2MBase::set_operation(M2MBase::GET_PUT_ALLOWED); + _firmware_instance = M2MObject::create_object_instance(); + if(_firmware_instance) { + _firmware_instance->set_operation(M2MBase::GET_PUT_ALLOWED); + create_mandatory_resources(); + } +} + +M2MFirmware::~M2MFirmware() +{ +} + +void M2MFirmware::create_mandatory_resources() +{ + _firmware_instance->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE); + M2MResource* res = _firmware_instance->create_dynamic_resource(FIRMWARE_PACKAGE, + OMA_RESOURCE_TYPE, + M2MResourceInstance::OPAQUE, + false); + if(res) { + res->set_operation(M2MBase::PUT_ALLOWED); + res->set_register_uri(false); + } + + res = _firmware_instance->create_dynamic_resource(FIRMWARE_PACKAGE_URI, + OMA_RESOURCE_TYPE, + M2MResourceInstance::STRING, + false); + if(res) { + res->set_operation(M2MBase::PUT_ALLOWED); + res->set_register_uri(false); + } + + res = _firmware_instance->create_dynamic_resource(FIRMWARE_UPDATE, + OMA_RESOURCE_TYPE, + M2MResourceInstance::OPAQUE, + false); + if(res) { + res->set_operation(M2MBase::NOT_ALLOWED); + res->set_register_uri(false); + } + + res = _firmware_instance->create_dynamic_resource(FIRMWARE_STATE, + OMA_RESOURCE_TYPE, + M2MResourceInstance::INTEGER, + true); + set_zero_value(res); + if(res) { + res->set_operation(M2MBase::GET_ALLOWED); + res->set_register_uri(false); + } + res = _firmware_instance->create_dynamic_resource(FIRMWARE_UPDATE_RESULT, + OMA_RESOURCE_TYPE, + M2MResourceInstance::INTEGER, + true); + set_zero_value(res); + if(res) { + res->set_operation(M2MBase::GET_ALLOWED); + res->set_register_uri(false); + } +} + +M2MResource* M2MFirmware::create_resource(FirmwareResource resource, const String &value) +{ + M2MResource* res = NULL; + const char* firmware_id_ptr = ""; + M2MBase::Operation operation = M2MBase::GET_ALLOWED; + if(!is_resource_present(resource)) { + switch(resource) { + case PackageName: + firmware_id_ptr = FIRMWARE_PACKAGE_NAME; + break; + case PackageVersion: + firmware_id_ptr = FIRMWARE_PACKAGE_VERSION; + break; + default: + break; + } + } + String firmware_id(firmware_id_ptr); + + if(!firmware_id.empty() && value.size() < 256) { + if(_firmware_instance) { + res = _firmware_instance->create_dynamic_resource(firmware_id, + OMA_RESOURCE_TYPE, + M2MResourceInstance::STRING, + false); + + if(res) { + res->set_register_uri(false); + res->set_operation(operation); + if(value.empty()) { + res->clear_value(); + } else { + res->set_value((const uint8_t*)value.c_str(), + (uint32_t)value.length()); + } + } + } + } + return res; +} + +M2MResource* M2MFirmware::create_resource(FirmwareResource resource, int64_t value) +{ + M2MResource* res = NULL; + const char* firmware_id_ptr = ""; + M2MBase::Operation operation = M2MBase::GET_ALLOWED; + if(!is_resource_present(resource)) { + switch(resource) { + case UpdateSupportedObjects: + if(check_value_range(resource, value)) { + firmware_id_ptr = FIRMWARE_UPDATE_SUPPORTED_OBJECTS; + operation = M2MBase::GET_PUT_ALLOWED; + } + break; + default: + break; + } + } + + const String firmware_id(firmware_id_ptr); + + if(!firmware_id.empty()) { + if(_firmware_instance) { + res = _firmware_instance->create_dynamic_resource(firmware_id, + OMA_RESOURCE_TYPE, + M2MResourceInstance::INTEGER, + false); + + if(res) { + res->set_register_uri(false); + + res->set_operation(operation); + res->set_value(value); + } + } + } + return res; +} + +bool M2MFirmware::set_resource_value(FirmwareResource resource, + const String &value) +{ + bool success = false; + M2MResource* res = get_resource(resource); + if(res) { + if(M2MFirmware::PackageUri == resource || + M2MFirmware::PackageName == resource || + M2MFirmware::PackageVersion == resource) { + if (value.size() < 256) { + if(value.empty()) { + res->clear_value(); + success = true; + } else { + success = res->set_value((const uint8_t*)value.c_str(),(uint32_t)value.length()); + } + } + } + } + return success; +} + +bool M2MFirmware::set_resource_value(FirmwareResource resource, + int64_t value) +{ + bool success = false; + M2MResource* res = get_resource(resource); + if(res) { + if(M2MFirmware::State == resource || + M2MFirmware::UpdateSupportedObjects == resource || + M2MFirmware::UpdateResult == resource) { + // If it is any of the above resource + // set the value of the resource. + if (check_value_range(resource, value)) { + + success = res->set_value(value); + } + } + } + return success; +} + +bool M2MFirmware::set_resource_value(FirmwareResource resource, + const uint8_t *value, + const uint32_t length) +{ + bool success = false; + M2MResource* res = get_resource(resource); + if(res) { + if(M2MFirmware::Package == resource) { + success = res->set_value(value,length); + } + } + return success; +} + +bool M2MFirmware::is_resource_present(FirmwareResource resource) const +{ + bool success = false; + M2MResource* res = get_resource(resource); + if(res) { + success = true; + } + return success; +} + +const String M2MFirmware::resource_name(FirmwareResource resource) +{ + const char* res_name = ""; + switch(resource) { + case Package: + res_name = FIRMWARE_PACKAGE; + break; + case PackageUri: + res_name = FIRMWARE_PACKAGE_URI; + break; + case Update: + res_name = FIRMWARE_UPDATE; + break; + case State: + res_name = FIRMWARE_STATE; + break; + case UpdateSupportedObjects: + res_name = FIRMWARE_UPDATE_SUPPORTED_OBJECTS; + break; + case UpdateResult: + res_name = FIRMWARE_UPDATE_RESULT; + break; + case PackageName: + res_name = FIRMWARE_PACKAGE_NAME; + break; + case PackageVersion: + res_name = FIRMWARE_PACKAGE_VERSION; + break; + } + return String(res_name); +} + +uint16_t M2MFirmware::per_resource_count(FirmwareResource res) const +{ + uint16_t count = 0; + if(_firmware_instance) { + count = _firmware_instance->resource_count(resource_name(res)); + } + return count; +} + +uint16_t M2MFirmware::total_resource_count() const +{ + uint16_t count = 0; + if(_firmware_instance) { + count = _firmware_instance->resources().size(); + } + return count; +} + +uint32_t M2MFirmware::resource_value_buffer(FirmwareResource resource, + uint8_t *&data) const +{ + uint32_t size = 0; + M2MResource* res = get_resource(resource); + if(res) { + if(M2MFirmware::Package == resource) { + res->get_value(data,size); + } + } + return size; +} + +M2MResource* M2MFirmware::get_resource(FirmwareResource res) const +{ + M2MResource* res_object = NULL; + if(_firmware_instance) { + const char* res_name_ptr = ""; + switch(res) { + case Package: + res_name_ptr = FIRMWARE_PACKAGE; + break; + case PackageUri: + res_name_ptr = FIRMWARE_PACKAGE_URI; + break; + case Update: + res_name_ptr = FIRMWARE_UPDATE; + break; + case State: + res_name_ptr = FIRMWARE_STATE; + break; + case UpdateSupportedObjects: + res_name_ptr = FIRMWARE_UPDATE_SUPPORTED_OBJECTS; + break; + case UpdateResult: + res_name_ptr = FIRMWARE_UPDATE_RESULT; + break; + case PackageName: + res_name_ptr = FIRMWARE_PACKAGE_NAME; + break; + case PackageVersion: + res_name_ptr = FIRMWARE_PACKAGE_VERSION; + break; + } + const String res_name(res_name_ptr); + + res_object = _firmware_instance->resource(res_name); + } + return res_object; +} + +bool M2MFirmware::delete_resource(FirmwareResource resource) +{ + bool success = false; + if(M2MFirmware::UpdateSupportedObjects == resource || + M2MFirmware::PackageName == resource || + M2MFirmware::PackageVersion == resource) { + if(_firmware_instance) { + success = _firmware_instance->remove_resource(resource_name(resource)); + } + } + return success; +} + +int64_t M2MFirmware::resource_value_int(FirmwareResource resource) const +{ + int64_t value = -1; + M2MResource* res = get_resource(resource); + if(res) { + if(M2MFirmware::State == resource || + M2MFirmware::UpdateSupportedObjects == resource || + M2MFirmware::UpdateResult == resource) { + + value = res->get_value_int(); + } + } + return value; +} + +String M2MFirmware::resource_value_string(FirmwareResource resource) const +{ + String value = ""; + M2MResource* res = get_resource(resource); + if(res) { + if(M2MFirmware::PackageUri == resource || + M2MFirmware::PackageName == resource || + M2MFirmware::PackageVersion == resource) { + + value = res->get_value_string(); + } + } + return value; +} + +bool M2MFirmware::check_value_range(FirmwareResource resource, int64_t value) const +{ + bool success = false; + switch (resource) { + case UpdateSupportedObjects: + if(value == 0 || value == 1) { + success = true; + } + break; + case State: + if (value >= 0 && value <= 3) { + success = true; + M2MResource* updateRes = get_resource(M2MFirmware::Update); + if (updateRes){ + if (value == M2MFirmware::Downloaded) { + updateRes->set_operation(M2MBase::POST_ALLOWED); + } + else { + updateRes->set_operation(M2MBase::NOT_ALLOWED); + } + } + } + break; + case UpdateResult: + if (value >= 0 && value <= 7) { + success = true; + } + break; + default: + break; + } + return success; +} + +void M2MFirmware::set_zero_value(M2MResource *resource) +{ + resource->set_value((const uint8_t*)"0", 1); +} diff --git a/features/FEATURE_CLIENT/mbed-client/source/m2minterfacefactory.cpp b/features/FEATURE_CLIENT/mbed-client/source/m2minterfacefactory.cpp new file mode 100644 index 0000000000..32345db8ae --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/m2minterfacefactory.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client/m2minterfacefactory.h" +#include "mbed-client/m2mserver.h" +#include "mbed-client/m2mdevice.h" +#include "mbed-client/m2mfirmware.h" +#include "mbed-client/m2mobject.h" +#include "mbed-client/m2mconstants.h" +#include "mbed-client/m2mconfig.h" +#include "include/m2minterfaceimpl.h" +#include "mbed-trace/mbed_trace.h" + +#define TRACE_GROUP "mClt" + +M2MInterface* M2MInterfaceFactory::create_interface(M2MInterfaceObserver &observer, + const String &endpoint_name, + const String &endpoint_type, + const int32_t life_time, + const uint16_t listen_port, + const String &domain, + M2MInterface::BindingMode mode, + M2MInterface::NetworkStack stack, + const String &context_address) +{ + tr_debug("M2MInterfaceFactory::create_interface - IN"); + tr_debug("M2MInterfaceFactory::create_interface - parameters endpoint name : %s",endpoint_name.c_str()); + tr_debug("M2MInterfaceFactory::create_interface - parameters endpoint type : %s",endpoint_type.c_str()); + tr_debug("M2MInterfaceFactory::create_interface - parameters life time(in secs): %d",life_time); + tr_debug("M2MInterfaceFactory::create_interface - parameters Listen Port : %d",listen_port); + tr_debug("M2MInterfaceFactory::create_interface - parameters Binding Mode : %d",(int)mode); + tr_debug("M2MInterfaceFactory::create_interface - parameters NetworkStack : %d",(int)stack); + M2MInterfaceImpl *interface = NULL; + + + bool endpoint_type_valid = true; + if(!endpoint_type.empty()) { + if(endpoint_type.size() > MAX_ALLOWED_STRING_LENGTH){ + endpoint_type_valid = false; + } + } + + bool domain_valid = true; + if(!domain.empty()) { + if(domain.size() > MAX_ALLOWED_STRING_LENGTH){ + domain_valid = false; + } + } + + if(((life_time == -1) || (life_time >= MINIMUM_REGISTRATION_TIME)) && + !endpoint_name.empty() && (endpoint_name.size() <= MAX_ALLOWED_STRING_LENGTH) && + endpoint_type_valid && domain_valid) { + tr_debug("M2MInterfaceFactory::create_interface - Creating M2MInterfaceImpl"); + interface = new M2MInterfaceImpl(observer, endpoint_name, + endpoint_type, life_time, + listen_port, domain, mode, + stack, context_address); + + } + tr_debug("M2MInterfaceFactory::create_interface - OUT"); + return interface; +} + +M2MSecurity* M2MInterfaceFactory::create_security(M2MSecurity::ServerType server_type) +{ + tr_debug("M2MInterfaceFactory::create_security"); + M2MSecurity *security = new M2MSecurity(server_type); + return security; +} + +M2MServer* M2MInterfaceFactory::create_server() +{ + tr_debug("M2MInterfaceFactory::create_server"); + M2MServer *server = new M2MServer(); + return server; +} + +M2MDevice* M2MInterfaceFactory::create_device() +{ + tr_debug("M2MInterfaceFactory::create_device"); + M2MDevice* device = M2MDevice::get_instance(); + return device; +} + +M2MFirmware* M2MInterfaceFactory::create_firmware() +{ + tr_debug("M2MInterfaceFactory::create_firmware"); + M2MFirmware* firmware = M2MFirmware::get_instance(); + return firmware; +} + +M2MObject* M2MInterfaceFactory::create_object(const String &name) +{ + tr_debug("M2MInterfaceFactory::create_object : Name : %s", name.c_str()); + if(name.size() > MAX_ALLOWED_STRING_LENGTH || name.empty()){ + return NULL; + } + + M2MObject *object = NULL; + object = new M2MObject(name); + return object; +} diff --git a/features/FEATURE_CLIENT/mbed-client/source/m2minterfaceimpl.cpp b/features/FEATURE_CLIENT/mbed-client/source/m2minterfaceimpl.cpp new file mode 100644 index 0000000000..3058c6f675 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/m2minterfaceimpl.cpp @@ -0,0 +1,973 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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/m2minterfaceimpl.h" +#include "include/eventdata.h" +#include "mbed-client/m2minterfaceobserver.h" +#include "mbed-client/m2mconnectionhandler.h" +#include "mbed-client/m2mconnectionsecurity.h" +#include "include/m2mnsdlinterface.h" +#include "include/nsdlaccesshelper.h" +#include "mbed-client/m2msecurity.h" +#include "mbed-client/m2mconstants.h" +#include "mbed-client/m2mtimer.h" +#include "mbed-trace/mbed_trace.h" + +#define TRACE_GROUP "mClt" + +M2MInterfaceImpl::M2MInterfaceImpl(M2MInterfaceObserver& observer, + const String &ep_name, + const String &ep_type, + const int32_t l_time, + const uint16_t listen_port, + const String &dmn, + M2MInterface::BindingMode mode, + M2MInterface::NetworkStack stack, + const String &con_addr) +: _observer(observer), + _nsdl_interface(new M2MNsdlInterface(*this)), + _current_state(0), + _max_states( STATE_MAX_STATES ), + _event_generated(false), + _event_data(NULL), + _endpoint_type(ep_type), + _domain( dmn), + _life_time(l_time), + _binding_mode(mode), + _context_address(con_addr), + _listen_port(listen_port), + _server_port(0), + _register_server(NULL), + _event_ignored(false), + _register_ongoing(false), + _update_register_ongoing(false), + _queue_sleep_timer(new M2MTimer(*this)), + _retry_timer(new M2MTimer(*this)), + _bootstrap_timer(NULL), + _callback_handler(NULL), + _security(NULL), + _retry_count(0), + _reconnecting(false), + _retry_timer_expired(false) +{ + M2MConnectionSecurity::SecurityMode sec_mode = M2MConnectionSecurity::DTLS; + //Hack for now + if( _binding_mode == M2MInterface::TCP ){ + _binding_mode = M2MInterface::UDP; + sec_mode = M2MConnectionSecurity::TLS; + }else if( _binding_mode == M2MInterface::TCP_QUEUE ){ + _binding_mode = M2MInterface::UDP_QUEUE; + sec_mode = M2MConnectionSecurity::TLS; + } + tr_debug("M2MInterfaceImpl::M2MInterfaceImpl() -IN"); + _nsdl_interface->create_endpoint(ep_name, + _endpoint_type, + _life_time, + _domain, + (uint8_t)_binding_mode, + _context_address); + + //Doesn't own, ownership is passed to ConnectionHandler class + _security_connection = new M2MConnectionSecurity(sec_mode); + //Here we must use TCP still + _connection_handler = new M2MConnectionHandler(*this, _security_connection, mode, stack); + __connection_handler = _connection_handler; + _connection_handler->bind_connection(_listen_port); +#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + _bootstrap_timer = new M2MTimer(*this); +#endif + tr_debug("M2MInterfaceImpl::M2MInterfaceImpl() -OUT"); +} + + +M2MInterfaceImpl::~M2MInterfaceImpl() +{ + tr_debug("M2MInterfaceImpl::~M2MInterfaceImpl() - IN"); + delete _queue_sleep_timer; + delete _nsdl_interface; + _connection_handler->stop_listening(); + __connection_handler = NULL; + delete _connection_handler; + delete _retry_timer; + delete _bootstrap_timer; + _security_connection = NULL; + tr_debug("M2MInterfaceImpl::~M2MInterfaceImpl() - OUT"); +} + +void M2MInterfaceImpl::bootstrap(M2MSecurity *security) +{ +#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + tr_debug("M2MInterfaceImpl::bootstrap(M2MSecurity *security) - IN"); + // Transition to a new state based upon + // the current state of the state machine + M2MSecurityData* data = new M2MSecurityData(); + data->_object = security; + BEGIN_TRANSITION_MAP // - Current State - + TRANSITION_MAP_ENTRY (STATE_BOOTSTRAP) // state_idle + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_bootstrap + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state__bootstrap_address_resolved + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_bootstrap_resource_created + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_bootstrapped + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_register + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_register_address_resolved + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_register_resource_created + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_registered + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_update_registration + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_unregister + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_unregistered + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_sending_coap_data + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_coap_data_sent + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_coap_data_received + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_processing_coap_data + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_coap_data_processed + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_waiting + END_TRANSITION_MAP(data) + if(_event_ignored) { + _event_ignored = false; + _observer.error(M2MInterface::NotAllowed); + } + tr_debug("M2MInterfaceImpl::bootstrap(M2MSecurity *security) - OUT"); +#else + _observer.error(M2MInterface::NotAllowed); +#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +} + +void M2MInterfaceImpl::cancel_bootstrap() +{ +#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +//TODO: Do we need this ? +#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +} + +void M2MInterfaceImpl::register_object(M2MSecurity *security, const M2MObjectList &object_list) +{ + tr_debug("M2MInterfaceImpl::register_object - IN"); + // Transition to a new state based upon + // the current state of the state machine + //TODO: manage register object in a list. + if(!_register_ongoing) { + _register_ongoing = true; + _register_server = security; + M2MRegisterData *data = new M2MRegisterData(); + data->_object = security; + data->_object_list = object_list; + BEGIN_TRANSITION_MAP // - Current State - + TRANSITION_MAP_ENTRY (STATE_REGISTER) // state_idle + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_bootstrap + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state__bootstrap_address_resolved + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_bootstrap_resource_created + TRANSITION_MAP_ENTRY (STATE_REGISTER) // state_bootstrapped + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_register + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_register_address_resolved + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_register_resource_created + TRANSITION_MAP_ENTRY (STATE_REGISTER) // state_registered + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_update_registration + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_unregister + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_unregistered + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_sending_coap_data + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_coap_data_sent + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_coap_data_received + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_processing_coap_data + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_coap_data_processed + TRANSITION_MAP_ENTRY (STATE_REGISTER) // state_waiting + END_TRANSITION_MAP(data) + if(_event_ignored) { + _event_ignored = false; + _observer.error(M2MInterface::NotAllowed); + } + } else { + tr_debug("M2MInterfaceImpl::register_object - NOT ALLOWED"); + _observer.error(M2MInterface::NotAllowed); + } + tr_debug("M2MInterfaceImpl::register_object - OUT"); +} + +void M2MInterfaceImpl::update_registration(M2MSecurity *security_object, const uint32_t lifetime) +{ + tr_debug("M2MInterfaceImpl::update_registration - IN"); + // Transition to a new state based upon + // the current state of the state machine + if(lifetime != 0 && (lifetime < MINIMUM_REGISTRATION_TIME)) { + _observer.error(M2MInterface::InvalidParameters); + } else if(!_update_register_ongoing){ + tr_debug("M2MInterfaceImpl::update_registration - already ongoing"); + _update_register_ongoing = true; + M2MUpdateRegisterData *data = new M2MUpdateRegisterData(); + data->_object = security_object; + data->_lifetime = lifetime; + BEGIN_TRANSITION_MAP // - Current State - + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_idle + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_bootstrap + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state__bootstrap_address_resolved + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_bootstrap_resource_created + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_bootstrapped + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_register + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_register_address_resolved + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_register_resource_created + TRANSITION_MAP_ENTRY (STATE_UPDATE_REGISTRATION) // state_registered + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_update_registration + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_unregister + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_unregistered + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_sending_coap_data + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_coap_data_sent + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_coap_data_received + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_processing_coap_data + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_coap_data_processed + TRANSITION_MAP_ENTRY (STATE_UPDATE_REGISTRATION) // state_waiting + END_TRANSITION_MAP(data) + if(_event_ignored) { + _event_ignored = false; + if (!_reconnecting) + _observer.error(M2MInterface::NotAllowed); + } + } else if(!_reconnecting) { + tr_debug("M2MInterfaceImpl::update_registration - NOT ALLOWED"); + _observer.error(M2MInterface::NotAllowed); + } else { + tr_debug("M2MInterfaceImpl::update_registration - reconnecting"); + } + tr_debug("M2MInterfaceImpl::update_registration - OUT"); +} + +void M2MInterfaceImpl::unregister_object(M2MSecurity* /*security*/) +{ + tr_debug("M2MInterfaceImpl::unregister_object - IN"); + // Transition to a new state based upon + // the current state of the state machine + BEGIN_TRANSITION_MAP // - Current State - + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_idle + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_bootstrap + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state__bootstrap_address_resolved + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_bootstrap_resource_created + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_bootstrapped + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_register + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_register_address_resolved + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_register_resource_created + TRANSITION_MAP_ENTRY (STATE_UNREGISTER) // state_registered + TRANSITION_MAP_ENTRY (STATE_UNREGISTER) // state_update_registration + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_unregister + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_unregistered + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_sending_coap_data + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_coap_data_sent + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_coap_data_received + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_processing_coap_data + TRANSITION_MAP_ENTRY (EVENT_IGNORED) // state_coap_data_processed + TRANSITION_MAP_ENTRY (STATE_UNREGISTER) // state_waiting + END_TRANSITION_MAP(NULL) + if(_event_ignored) { + _event_ignored = false; + _observer.error(M2MInterface::NotAllowed); + } + tr_debug("M2MInterfaceImpl::unregister_object - OUT"); +} + +void M2MInterfaceImpl::set_queue_sleep_handler(callback_handler handler) +{ + tr_debug("M2MInterfaceImpl::set_queue_sleep_handler()"); + _callback_handler = handler; +} + +void M2MInterfaceImpl::set_random_number_callback(random_number_cb callback) +{ + if(_security_connection) { + _security_connection->set_random_number_callback(callback); + } +} + +void M2MInterfaceImpl::set_entropy_callback(entropy_cb callback) +{ + if(_security_connection) { + _security_connection->set_entropy_callback(callback); + } +} + +void M2MInterfaceImpl::set_platform_network_handler(void *handler) +{ + tr_debug("M2MInterfaceImpl::set_platform_network_handler()"); + if(_connection_handler) { + _connection_handler->set_platform_network_handler(handler); + } +} + +void M2MInterfaceImpl::coap_message_ready(uint8_t *data_ptr, + uint16_t data_len, + sn_nsdl_addr_s *address_ptr) +{ + tr_debug("M2MInterfaceImpl::coap_message_ready"); + internal_event(STATE_SENDING_COAP_DATA); + if(!_connection_handler->send_data(data_ptr,data_len,address_ptr)) { + internal_event( STATE_IDLE); + tr_error("M2MInterfaceImpl::coap_message_ready() - M2MInterface::NetworkError"); + if (!_reconnecting) { + _observer.error(M2MInterface::NetworkError); + } + } +} + +void M2MInterfaceImpl::client_registered(M2MServer *server_object) +{ + tr_debug("M2MInterfaceImpl::client_registered"); + _retry_count = 0; + internal_event(STATE_REGISTERED); + //Inform client is registered. + //TODO: manage register object in a list. + _observer.object_registered(_register_server,*server_object); +} + +void M2MInterfaceImpl::registration_updated(const M2MServer &server_object) +{ + tr_debug("M2MInterfaceImpl::registration_updated"); + internal_event(STATE_REGISTERED); + _observer.registration_updated(_register_server,server_object); +} + +void M2MInterfaceImpl::registration_error(uint8_t error_code, bool retry) +{ + tr_debug("M2MInterfaceImpl::registration_error code [%d]", error_code); + // Try to register again + if (retry) { + socket_error(M2MConnectionHandler::SOCKET_SEND_ERROR); + } else { + internal_event(STATE_IDLE); + _observer.error((M2MInterface::Error)error_code); + } +} + +void M2MInterfaceImpl::client_unregistered() +{ + tr_debug("M2MInterfaceImpl::client_unregistered()"); + internal_event(STATE_UNREGISTERED); + //TODO: manage register object in a list. + _observer.object_unregistered(_register_server); +} + +void M2MInterfaceImpl::bootstrap_done(M2MSecurity *security_object) +{ +#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + tr_debug("M2MInterfaceImpl::bootstrap_done"); + _bootstrap_timer->stop_timer(); + internal_event(STATE_BOOTSTRAPPED); + _observer.bootstrap_done(security_object); +#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +} + +void M2MInterfaceImpl::bootstrap_error() +{ +#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + tr_debug("M2MInterfaceImpl::bootstrap_error()"); + _bootstrap_timer->stop_timer(); + internal_event(STATE_IDLE); + _observer.error(M2MInterface::BootstrapFailed); +#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +} + +void M2MInterfaceImpl::coap_data_processed() +{ + tr_debug("M2MInterfaceImpl::coap_data_processed()"); + internal_event(STATE_COAP_DATA_PROCESSED); +} + +void M2MInterfaceImpl::value_updated(M2MBase *base) +{ + tr_debug("M2MInterfaceImpl::value_updated(M2MBase *base)"); + if(base) { + M2MBase::BaseType type = base->base_type(); + _observer.value_updated(base, type); + } +} + +void M2MInterfaceImpl::data_available(uint8_t* data, + uint16_t data_size, + const M2MConnectionObserver::SocketAddress &address) +{ + tr_debug("M2MInterfaceImpl::data_available"); + ReceivedData *event = new ReceivedData(); + event->_data = data; + event->_size = data_size; + event->_address = &address; + internal_event(STATE_COAP_DATA_RECEIVED, event); +} + +void M2MInterfaceImpl::socket_error(uint8_t error_code, bool retry) +{ + tr_debug("M2MInterfaceImpl::socket_error: (%d), retry (%d), reconnecting (%d)", error_code, retry, _reconnecting); + if (!_retry_timer_expired && _reconnecting) { + tr_debug("M2MInterfaceImpl::socket_error - retry timer running - return"); + return; + } + M2MInterface::Error error = M2MInterface::ErrorNone; + switch (error_code) { + case M2MConnectionHandler::SSL_CONNECTION_ERROR: + error = M2MInterface::SecureConnectionFailed; + break; + case M2MConnectionHandler::DNS_RESOLVING_ERROR: + error = M2MInterface::DnsResolvingFailed; + break; + case M2MConnectionHandler::SOCKET_READ_ERROR: + error = M2MInterface::NetworkError; + break; + case M2MConnectionHandler::SOCKET_SEND_ERROR: + error = M2MInterface::NetworkError; + break; + case M2MConnectionHandler::SSL_HANDSHAKE_ERROR: + error = M2MInterface::SecureConnectionFailed; + break; + case M2MConnectionHandler::SOCKET_ABORT: + error = M2MInterface::NetworkError; + break; + default: + break; + } + + // Try to do reconnecting + if (retry) { + if (_retry_count < MBED_CLIENT_RECONNECTION_COUNT) { + internal_event(STATE_IDLE); + _reconnecting = true; + _retry_count++; + _connection_handler->stop_listening(); + int retry_time = MBED_CLIENT_RECONNECTION_INTERVAL * + MBED_CLIENT_RECONNECTION_COUNT * _retry_count * 1000; + _retry_timer_expired = false; + _retry_timer->start_timer(retry_time, + M2MTimerObserver::RetryTimer); + tr_debug("M2MInterfaceImpl::socket_error - reconnecting in %d(s), count %d/%d", retry_time / 1000, + _retry_count, MBED_CLIENT_RECONNECTION_COUNT); + } else { + tr_debug("M2MInterfaceImpl::socket_error - no more retries"); + _connection_handler->stop_listening(); + _retry_timer->stop_timer(); + retry = false; + } + } + // Inform application + if (!retry && M2MInterface::ErrorNone != error) { + tr_debug("M2MInterfaceImpl::socket_error - send error to application"); + _connection_handler->stop_listening(); + _retry_timer->stop_timer(); + _retry_count = 0; + _reconnecting = false; + _observer.error(error); + internal_event(STATE_IDLE); + } +} + +void M2MInterfaceImpl::address_ready(const M2MConnectionObserver::SocketAddress &address, + M2MConnectionObserver::ServerType server_type, + const uint16_t server_port) +{ + tr_debug("M2MInterfaceImpl::address_ready"); + ResolvedAddressData *data = new ResolvedAddressData(); + data->_address = &address; + data->_port = server_port; + if( M2MConnectionObserver::Bootstrap == server_type) { + tr_debug("M2MInterfaceImpl::address_ready() Server Type Bootstrap"); + internal_event(STATE_BOOTSTRAP_ADDRESS_RESOLVED, data); + } else { + tr_debug("M2MInterfaceImpl::address_ready() Server Type LWM2M"); + internal_event(STATE_REGISTER_ADDRESS_RESOLVED, data); + } +} + +void M2MInterfaceImpl::data_sent() +{ + tr_debug("M2MInterfaceImpl::data_sent()"); + if(_binding_mode == M2MInterface::UDP_QUEUE || + _binding_mode == M2MInterface::TCP_QUEUE || + _binding_mode == M2MInterface::SMS_QUEUE || + _binding_mode == M2MInterface::UDP_SMS_QUEUE) { + if(_callback_handler) { + _queue_sleep_timer->stop_timer(); + _queue_sleep_timer->start_timer(MBED_CLIENT_RECONNECTION_COUNT*MBED_CLIENT_RECONNECTION_INTERVAL*1000, + M2MTimerObserver::QueueSleep); + } + } + internal_event(STATE_COAP_DATA_SENT); +} + +void M2MInterfaceImpl::timer_expired(M2MTimerObserver::Type type) +{ + tr_debug("M2MInterfaceImpl::timer_expired()"); + if(M2MTimerObserver::QueueSleep == type) { + if(_callback_handler) { + _callback_handler(); + } + } + else if (M2MTimerObserver::RetryTimer == type) { + _retry_timer_expired = true; + _listen_port = rand() % 64511 + 1024; + tr_debug("M2MInterfaceImpl::timer_expired() - new port: %d", _listen_port); + _connection_handler->bind_connection(_listen_port); + internal_event(STATE_REGISTER); + } + else if (M2MTimerObserver::BootstrapTimer == type) { + bootstrap_error(); + } +} + +// state machine sits here. +void M2MInterfaceImpl::state_idle(EventData* /*data*/) +{ + tr_debug("M2MInterfaceImpl::state_idle"); + _nsdl_interface->stop_timers(); + _register_ongoing = false; + _update_register_ongoing = false; +} + +void M2MInterfaceImpl::state_bootstrap( EventData *data) +{ +#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + tr_debug("M2MInterfaceImpl::state_bootstrap"); + // Start with bootstrapping preparation + bool success = false; + if(data) { + M2MSecurityData *event = static_cast (data); + M2MSecurity *security = event->_object; + if(security) { + if(M2MSecurity::Bootstrap == security->server_type()) { + tr_debug("M2MInterfaceImpl::state_bootstrap - server_type : M2MSecurity::Bootstrap"); + String server_address = security->resource_value_string(M2MSecurity::M2MServerUri); + tr_debug("M2MInterfaceImpl::state_bootstrap - server_address %s", server_address.c_str()); + _bootstrap_timer->start_timer(MBED_CLIENT_RECONNECTION_COUNT * MBED_CLIENT_RECONNECTION_INTERVAL * 8 * 1000, + M2MTimerObserver::BootstrapTimer); + String ip_address; + String coap; + if(server_address.compare(0,sizeof(COAP)-1,COAP) == 0) { + coap = COAP; + } + else if(server_address.compare(0,sizeof(COAPS)-1,COAPS) == 0) { + security->resource_value_int(M2MSecurity::SecurityMode) != M2MSecurity::NoSecurity ? coap = COAPS: coap = ""; + } + if(!coap.empty()) { + server_address = server_address.substr(coap.size(), + server_address.size()-coap.size()); + + process_address(server_address, ip_address, _server_port); + + tr_debug("M2MInterfaceImpl::state_bootstrap - IP address %s , Port %d", ip_address.c_str(), _server_port); + // If bind and resolving server address succeed then proceed else + // return error to the application and go to Idle state. + if(ip_address.empty()) { + tr_error("M2MInterfaceImpl::state_bootstrap - set error as M2MInterface::InvalidParameters"); + success = false; + } else if(_connection_handler->resolve_server_address(ip_address, + _server_port, + M2MConnectionObserver::Bootstrap, + security)) { + tr_debug("M2MInterfaceImpl::state_bootstrap - resolve_server_address - success"); + success = true; + } + } + } + } + } + if(!success) { + tr_error("M2MInterfaceImpl::state_bootstrap - M2MInterface::InvalidParameters"); + _observer.error(M2MInterface::InvalidParameters); + internal_event(STATE_IDLE); + } +#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +} + +void M2MInterfaceImpl::state_bootstrap_address_resolved( EventData *data) +{ +#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + tr_debug("M2MInterfaceImpl::state_bootstrap_address_resolved"); + ResolvedAddressData *event = static_cast (data); + sn_nsdl_addr_s address; + + M2MInterface::NetworkStack stack = event->_address->_stack; + + if(M2MInterface::LwIP_IPv4 == stack) { + tr_debug("M2MInterfaceImpl::state_bootstrap_address_resolved : IPv4 address"); + address.type = SN_NSDL_ADDRESS_TYPE_IPV4; + address.addr_len = 4; + } else if((M2MInterface::LwIP_IPv6 == stack) || + (M2MInterface::Nanostack_IPv6 == stack)) { + tr_debug("M2MInterfaceImpl::state_bootstrap_address_resolved : IPv6 address"); + address.type = SN_NSDL_ADDRESS_TYPE_IPV6; + address.addr_len = 16; + } + address.port = event->_port; + address.addr_ptr = (uint8_t*)event->_address->_address; + _connection_handler->start_listening_for_data(); + + // Include domain id to be part of endpoint name + String new_ep_name; + new_ep_name += _nsdl_interface->endpoint_name(); + if (!_domain.empty()) { + new_ep_name += '@'; + new_ep_name += _domain; + } + if(_nsdl_interface->create_bootstrap_resource(&address, new_ep_name)) { + tr_debug("M2MInterfaceImpl::state_bootstrap_address_resolved : create_bootstrap_resource - success"); + internal_event(STATE_BOOTSTRAP_RESOURCE_CREATED); + } else{ + // If resource creation fails then inform error to application + tr_error("M2MInterfaceImpl::state_bootstrap_address_resolved : M2MInterface::InvalidParameters"); + internal_event(STATE_IDLE); + _observer.error(M2MInterface::InvalidParameters); + } +#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +} + +void M2MInterfaceImpl::state_bootstrap_resource_created( EventData */*data*/) +{ +#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + tr_debug("M2MInterfaceImpl::state_bootstrap_resource_created"); +#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +} + +void M2MInterfaceImpl::state_bootstrapped( EventData */*data*/) +{ +#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + tr_debug("M2MInterfaceImpl::state_bootstrapped"); +#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +} + +void M2MInterfaceImpl::state_register( EventData *data) +{ + tr_debug("M2MInterfaceImpl::state_register"); + if (!_security) { + M2MInterface::Error error = M2MInterface::InvalidParameters; + // Start with registration preparation + if(data) { + M2MRegisterData *event = static_cast (data); + _security = event->_object; + if(_security) { + if(M2MSecurity::M2MServer == _security->server_type()) { + tr_debug("M2MInterfaceImpl::state_register - server_type : M2MSecurity::M2MServer"); + if(_nsdl_interface->create_nsdl_list_structure(event->_object_list)) { + tr_debug("M2MInterfaceImpl::state_register - create_nsdl_list_structure - success"); + // If the nsdl resource structure is created successfully + String server_address = _security->resource_value_string(M2MSecurity::M2MServerUri); + tr_debug("M2MInterfaceImpl::state_register - server_address %s", server_address.c_str()); + String coap; + if(server_address.compare(0,sizeof(COAP)-1,COAP) == 0) { + coap = COAP; + } + else if(server_address.compare(0,sizeof(COAPS)-1,COAPS) == 0) { + _security->resource_value_int(M2MSecurity::SecurityMode) != M2MSecurity::NoSecurity ? coap = COAPS: coap = ""; + } + if(!coap.empty()) { + server_address = server_address.substr(coap.size(), + server_address.size() - coap.size()); + process_address(server_address, _server_ip_address, _server_port); + + tr_debug("M2MInterfaceImpl::state_register - IP address %s , Port %d", _server_ip_address.c_str(), _server_port); + if(!_server_ip_address.empty()) { + // Connection related errors are coming through callback + error = M2MInterface::ErrorNone; + _connection_handler->resolve_server_address(_server_ip_address,_server_port, + M2MConnectionObserver::LWM2MServer, + _security); + } + } + } + } + } + } + if (error != M2MInterface::ErrorNone) { + tr_error("M2MInterfaceImpl::state_register - set error as M2MInterface::InvalidParameters"); + internal_event(STATE_IDLE); + _observer.error(error); + } + } else { + _connection_handler->resolve_server_address(_server_ip_address,_server_port, + M2MConnectionObserver::LWM2MServer, + _security); + } +} + +void M2MInterfaceImpl::process_address(const String& server_address, String& ip_address, uint16_t& port) { + + int colonFound = server_address.find_last_of(':'); //10 + if(colonFound != -1) { + ip_address = server_address.substr(0,colonFound); + port = atoi(server_address.substr(colonFound+1, + server_address.size()-ip_address.size()).c_str()); + colonFound = ip_address.find_last_of(']'); + if(ip_address.compare(0,1,"[") == 0) { + if(colonFound == -1) { + ip_address.clear(); + } else { + ip_address = ip_address.substr(1,colonFound-1); + } + } else if(colonFound != -1) { + ip_address.clear(); + } + } +} + +void M2MInterfaceImpl::state_register_address_resolved( EventData *data) +{ + tr_debug("M2MInterfaceImpl::state_register_address_resolved"); + if(data) { + ResolvedAddressData *event = static_cast (data); + + sn_nsdl_addr_type_e address_type = SN_NSDL_ADDRESS_TYPE_IPV6; + + M2MInterface::NetworkStack stack = event->_address->_stack; + + if(M2MInterface::LwIP_IPv4 == stack) { + tr_debug("M2MInterfaceImpl::state_register_address_resolved : IPv4 address"); + address_type = SN_NSDL_ADDRESS_TYPE_IPV4; + } else if((M2MInterface::LwIP_IPv6 == stack) || + (M2MInterface::Nanostack_IPv6 == stack)) { + tr_debug("M2MInterfaceImpl::state_register_address_resolved : IPv6 address"); + address_type = SN_NSDL_ADDRESS_TYPE_IPV6; + } + _connection_handler->start_listening_for_data(); + if(_nsdl_interface->send_register_message((uint8_t*)event->_address->_address,event->_port, address_type)) { + internal_event(STATE_REGISTER_RESOURCE_CREATED); + } else { + // If resource creation fails then inform error to application + tr_error("M2MInterfaceImpl::state_register_address_resolved : M2MInterface::InvalidParameters"); + internal_event(STATE_IDLE); + _observer.error(M2MInterface::InvalidParameters); + } + } +} + +void M2MInterfaceImpl::state_register_resource_created( EventData */*data*/) +{ + tr_debug("M2MInterfaceImpl::state_register_resource_created"); +} + +void M2MInterfaceImpl::state_registered( EventData */*data*/) +{ + tr_debug("M2MInterfaceImpl::state_registered"); + _retry_count = 0; + _register_ongoing = false; + _update_register_ongoing = false; + _reconnecting = false; +} + +void M2MInterfaceImpl::state_update_registration( EventData *data) +{ + tr_debug("M2MInterfaceImpl::state_update_registration"); + // Start with registration preparation + if(data) { + M2MUpdateRegisterData *event = static_cast (data); + _nsdl_interface->send_update_registration(event->_lifetime); + } +} + +void M2MInterfaceImpl::state_unregister( EventData */*data*/) +{ + tr_debug("M2MInterfaceImpl::state_unregister"); + internal_event(STATE_SENDING_COAP_DATA); + if(!_nsdl_interface->send_unregister_message()) { + tr_error("M2MInterfaceImpl::state_unregister : M2MInterface::NotRegistered"); + internal_event(STATE_IDLE); + _observer.error(M2MInterface::NotRegistered); + } +} + +void M2MInterfaceImpl::state_unregistered( EventData */*data*/) +{ + tr_debug("M2MInterfaceImpl::state_unregistered"); + internal_event(STATE_IDLE); +} + +void M2MInterfaceImpl::state_sending_coap_data( EventData */*data*/) +{ + tr_debug("M2MInterfaceImpl::state_sending_coap_data"); + internal_event(STATE_WAITING); +} + +void M2MInterfaceImpl::state_coap_data_sent( EventData */*data*/) +{ + tr_debug("M2MInterfaceImpl::state_coap_data_sent"); + internal_event(STATE_WAITING); +} + +void M2MInterfaceImpl::state_coap_data_received( EventData *data) +{ + tr_debug("M2MInterfaceImpl::state_coap_data_received"); + if(data) { + ReceivedData *event = static_cast (data); + sn_nsdl_addr_s address; + + M2MInterface::NetworkStack stack = event->_address->_stack; + + if(M2MInterface::LwIP_IPv4 == stack) { + tr_debug("M2MInterfaceImpl::state_coap_data_received : IPv4 address"); + address.type = SN_NSDL_ADDRESS_TYPE_IPV4; + address.addr_len = 4; + } else if((M2MInterface::LwIP_IPv6 == stack) || + (M2MInterface::Nanostack_IPv6 == stack)) { + tr_debug("M2MInterfaceImpl::state_coap_data_received : IPv6 address"); + address.type = SN_NSDL_ADDRESS_TYPE_IPV6; + address.addr_len = 16; + } + address.port = event->_address->_port; + address.addr_ptr = (uint8_t*)event->_address->_address; + + // Process received data + internal_event(STATE_PROCESSING_COAP_DATA); + if(!_nsdl_interface->process_received_data(event->_data, + event->_size, + &address)) { + tr_error("M2MInterfaceImpl::state_coap_data_received : M2MInterface::ResponseParseFailed"); + _observer.error(M2MInterface::ResponseParseFailed); + } + } +} + +void M2MInterfaceImpl::state_processing_coap_data( EventData */*data*/) +{ + tr_debug("M2MInterfaceImpl::state_processing_coap_data"); + internal_event(STATE_WAITING); +} + +void M2MInterfaceImpl::state_coap_data_processed( EventData */*data*/) +{ + tr_debug("M2MInterfaceImpl::state_coap_data_processed"); + internal_event(STATE_WAITING); +} + +void M2MInterfaceImpl::state_waiting( EventData */*data*/) +{ + tr_debug("M2MInterfaceImpl::state_waiting"); +} + +// generates an external event. called once per external event +// to start the state machine executing +void M2MInterfaceImpl::external_event(uint8_t new_state, + EventData* p_data) +{ + tr_debug("M2MInterfaceImpl::external_event : new state %d", new_state); + // if we are supposed to ignore this event + if (new_state == EVENT_IGNORED) { + tr_debug("M2MInterfaceImpl::external_event : new state is EVENT_IGNORED"); + // just delete the event data, if any + if (p_data) { + delete p_data; + p_data = NULL; + } + _event_ignored = true; + } + else { + tr_debug("M2MInterfaceImpl::external_event : handle new state"); + // generate the event and execute the state engine + internal_event(new_state, p_data); + } +} + +// generates an internal event. called from within a state +// function to transition to a new state +void M2MInterfaceImpl::internal_event(uint8_t new_state, + EventData* p_data) +{ + tr_debug("M2MInterfaceImpl::internal_event : new state %d", new_state); + _event_data = p_data; + _event_generated = true; + _current_state = new_state; + state_engine(); +} + +// the state engine executes the state machine states +void M2MInterfaceImpl::state_engine (void) +{ + tr_debug("M2MInterfaceImpl::state_engine"); + EventData* p_data_temp = NULL; + + // while events are being generated keep executing states + while (_event_generated) { + p_data_temp = _event_data; // copy of event data pointer + _event_data = NULL; // event data used up, reset ptr + _event_generated = false; // event used up, reset flag + + assert(_current_state < _max_states); + + state_function( _current_state, p_data_temp ); + + // if event data was used, then delete it + if (p_data_temp) { + delete p_data_temp; + p_data_temp = NULL; + } + } +} + +void M2MInterfaceImpl::state_function( uint8_t current_state, EventData* data ) +{ + switch( current_state ) { + case STATE_IDLE: + M2MInterfaceImpl::state_idle(data); + break; + case STATE_BOOTSTRAP: + #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + M2MInterfaceImpl::state_bootstrap(data); + #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + break; + case STATE_BOOTSTRAP_ADDRESS_RESOLVED: + #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + M2MInterfaceImpl::state_bootstrap_address_resolved(data); + #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + break; + case STATE_BOOTSTRAP_RESOURCE_CREATED: + #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + M2MInterfaceImpl::state_bootstrap_resource_created(data); + #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + break; + case STATE_BOOTSTRAPPED: + #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + M2MInterfaceImpl::state_bootstrapped(data); + #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + break; + case STATE_REGISTER: + M2MInterfaceImpl::state_register(data); + break; + case STATE_REGISTER_ADDRESS_RESOLVED: + M2MInterfaceImpl::state_register_address_resolved(data); + break; + case STATE_REGISTER_RESOURCE_CREATED: + M2MInterfaceImpl::state_register_resource_created(data); + break; + case STATE_REGISTERED: + M2MInterfaceImpl::state_registered(data); + break; + case STATE_UPDATE_REGISTRATION: + M2MInterfaceImpl::state_update_registration(data); + break; + case STATE_UNREGISTER: + M2MInterfaceImpl::state_unregister(data); + break; + case STATE_UNREGISTERED: + M2MInterfaceImpl::state_unregistered(data); + break; + case STATE_SENDING_COAP_DATA: + M2MInterfaceImpl::state_sending_coap_data(data); + break; + case STATE_COAP_DATA_SENT: + M2MInterfaceImpl::state_coap_data_sent(data); + break; + case STATE_COAP_DATA_RECEIVED: + M2MInterfaceImpl::state_coap_data_received(data); + break; + case STATE_PROCESSING_COAP_DATA: + M2MInterfaceImpl::state_processing_coap_data(data); + break; + case STATE_COAP_DATA_PROCESSED: + M2MInterfaceImpl::state_coap_data_processed(data); + break; + case STATE_WAITING: + M2MInterfaceImpl::state_waiting(data); + break; + } +} diff --git a/features/FEATURE_CLIENT/mbed-client/source/m2mnsdlinterface.cpp b/features/FEATURE_CLIENT/mbed-client/source/m2mnsdlinterface.cpp new file mode 100644 index 0000000000..7d710dd7b4 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/m2mnsdlinterface.cpp @@ -0,0 +1,1786 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Note: this macro is needed on armcc to get the the PRI*32 macros +// from inttypes.h in a C++ code. +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif + +// Note: this macro is needed on armcc to get the the limit macros like UINT16_MAX +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS +#endif + + +#include "include/nsdlaccesshelper.h" +#include "include/m2mnsdlobserver.h" +#include "include/m2mtlvdeserializer.h" +#include "include/m2mtlvserializer.h" +#include "include/m2mnsdlinterface.h" +#include "mbed-client/m2mstring.h" +#include "mbed-client/m2msecurity.h" +#include "mbed-client/m2mserver.h" +#include "mbed-client/m2mobject.h" +#include "mbed-client/m2mobjectinstance.h" +#include "mbed-client/m2mresource.h" +#include "mbed-client/m2mconstants.h" +#include "mbed-trace/mbed_trace.h" +#include "mbed-client/m2mtimer.h" +#include "source/libNsdl/src/include/sn_grs.h" + +#include +#include + +#define BUFFER_SIZE 21 +#define TRACE_GROUP "mClt" + +M2MNsdlInterface::M2MNsdlInterface(M2MNsdlObserver &observer) +: _observer(observer), + _server(NULL), + _security(NULL), + _nsdl_exceution_timer(new M2MTimer(*this)), + _registration_timer(new M2MTimer(*this)), + _endpoint(NULL), + _resource(NULL), + _nsdl_handle(NULL), + _counter_for_nsdl(0), + _bootstrap_id(0), + _register_ongoing(false), + _unregister_ongoing(false), + _update_register_ongoing(false) +{ + tr_debug("M2MNsdlInterface::M2MNsdlInterface()"); + __nsdl_interface_list.push_back(this); + _sn_nsdl_address.addr_len = 0; + _sn_nsdl_address.addr_ptr = NULL; + _sn_nsdl_address.port = 0; + + // This initializes libCoap and libNsdl + // Parameters are function pointers to used memory allocation + // and free functions in structure and used functions for sending + // and receiving purposes. + _nsdl_handle = sn_nsdl_init(&(__nsdl_c_send_to_server), &(__nsdl_c_received_from_server), + &(__nsdl_c_memory_alloc), &(__nsdl_c_memory_free)); + + + _server = new M2MServer(); + initialize(); +} + +M2MNsdlInterface::~M2MNsdlInterface() +{ + tr_debug("M2MNsdlInterface::~M2MNsdlInterface() - IN"); + if(_resource) { + memory_free(_resource->resource_parameters_ptr); + memory_free(_resource); + } + if(_endpoint) { + memory_free(_endpoint->endpoint_name_ptr); + memory_free(_endpoint->lifetime_ptr); + memory_free(_endpoint->location_ptr); + memory_free(_endpoint); + } + delete _nsdl_exceution_timer; + delete _registration_timer; + _object_list.clear(); + delete _server; + _security = NULL; + + sn_nsdl_destroy(_nsdl_handle); + _nsdl_handle = NULL; + + M2MNsdlInterfaceList::const_iterator it; + it = __nsdl_interface_list.begin(); + int index = 0; + for (; it!=__nsdl_interface_list.end(); it++) { + if ((*it) == this) { + __nsdl_interface_list.erase(index); + break; + } + index++; + } + tr_debug("M2MNsdlInterface::~M2MNsdlInterface() - OUT"); +} + +bool M2MNsdlInterface::initialize() +{ + tr_debug("M2MNsdlInterface::initialize()"); + bool success = false; + + //Sets the packet retransmission attempts and time interval + sn_nsdl_set_retransmission_parameters(_nsdl_handle, + MBED_CLIENT_RECONNECTION_COUNT, + MBED_CLIENT_RECONNECTION_INTERVAL); + + // We want to parse and handle bootstrap messages + if (_nsdl_handle) { + _nsdl_handle->handle_bootstrap_msg = false; + } + + // Allocate the memory for resources + _resource = (sn_nsdl_resource_info_s*)memory_alloc(sizeof(sn_nsdl_resource_info_s)); + if(_resource) { + memset(_resource, 0, sizeof(sn_nsdl_resource_info_s)); + _resource->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)memory_alloc(sizeof(sn_nsdl_resource_parameters_s)); + if(_resource->resource_parameters_ptr) { + memset(_resource->resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s)); + } + } + + //Allocate the memory for endpoint + _endpoint = (sn_nsdl_ep_parameters_s*)memory_alloc(sizeof(sn_nsdl_ep_parameters_s)); + if(_endpoint) { + memset(_endpoint, 0, sizeof(sn_nsdl_ep_parameters_s)); + success = true; + } + return success; +} + +void M2MNsdlInterface::create_endpoint(const String &name, + const String &type, + const int32_t life_time, + const String &domain, + const uint8_t mode, + const String &/*context_address*/) +{ + tr_debug("M2MNsdlInterface::create_endpoint( name %s type %s lifetime %" PRId32 ", domain %s, mode %d)", + name.c_str(), type.c_str(), life_time, domain.c_str(), mode); + _endpoint_name = name; + if(_endpoint){ + memset(_endpoint, 0, sizeof(sn_nsdl_ep_parameters_s)); + if(!_endpoint_name.empty()) { + memory_free(_endpoint->endpoint_name_ptr); + _endpoint->endpoint_name_ptr = alloc_string_copy((uint8_t*)_endpoint_name.c_str(), _endpoint_name.length()); + _endpoint->endpoint_name_len = _endpoint_name.length(); + } + if(!type.empty()) { + _endpoint->type_ptr = (uint8_t*)type.c_str(); + _endpoint->type_len = type.length(); + } + if(!domain.empty()) { + _endpoint->domain_name_ptr = (uint8_t*)domain.c_str(); + _endpoint->domain_name_len = domain.length(); + } + _endpoint->binding_and_mode = (sn_nsdl_oma_binding_and_mode_t)mode; + + // If lifetime is less than zero then leave the field empty + if( life_time > 0) { + set_endpoint_lifetime_buffer(life_time); + } + } +} + +void M2MNsdlInterface::set_endpoint_lifetime_buffer(int lifetime) +{ + // max len of "-9223372036854775808" plus zero termination + char buffer[20+1]; + + uint32_t size = m2m::itoa_c(lifetime, buffer); + + if (size <= sizeof(buffer)) { + _endpoint->lifetime_ptr = alloc_string_copy((uint8_t*)buffer, size); + if(_endpoint->lifetime_ptr) { + _endpoint->lifetime_len = size; + } else { + _endpoint->lifetime_len = 0; + } + } +} + + +void M2MNsdlInterface::delete_endpoint() +{ + tr_debug("M2MNsdlInterface::delete_endpoint()"); + if(_endpoint) { + free(_endpoint->lifetime_ptr); + + memory_free(_endpoint); + _endpoint = NULL; + } +} + +bool M2MNsdlInterface::create_nsdl_list_structure(const M2MObjectList &object_list) +{ + tr_debug("M2MNsdlInterface::create_nsdl_list_structure()"); + bool success = false; + if(!object_list.empty()) { + tr_debug("M2MNsdlInterface::create_nsdl_list_structure - Object count is %d", object_list.size()); + M2MObjectList::const_iterator it; + it = object_list.begin(); + for ( ; it != object_list.end(); it++ ) { + // Create NSDL structure for all Objects inside + success = create_nsdl_object_structure(*it); + add_object_to_list(*it); + } + } + return success; +} + +bool M2MNsdlInterface::delete_nsdl_resource(const String &resource_name) +{ + tr_debug("M2MNsdlInterface::delete_nsdl_resource( %s)", resource_name.c_str()); + return (sn_nsdl_delete_resource(_nsdl_handle, + resource_name.length(), + (uint8_t *)resource_name.c_str()) == 0) ? true : false; +} + + +bool M2MNsdlInterface::create_bootstrap_resource(sn_nsdl_addr_s *address, const String &bootstrap_endpoint_name) +{ +#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + tr_debug("M2MNsdlInterface::create_bootstrap_resource()"); + bool success = false; + sn_nsdl_bs_ep_info_t bootstrap_endpoint; + tr_debug("M2MNsdlInterface::create_bootstrap_resource() - endpoint name: %s", bootstrap_endpoint_name.c_str()); + if (_endpoint->endpoint_name_ptr) { + memory_free(_endpoint->endpoint_name_ptr); + } + //_endpoint->endpoint_name_ptr = (uint8_t*)bootstrap_endpoint_name.c_str(); + _endpoint->endpoint_name_ptr = alloc_string_copy((uint8_t*)bootstrap_endpoint_name.c_str(), bootstrap_endpoint_name.length()); + _endpoint->endpoint_name_len = bootstrap_endpoint_name.length(); + if(_bootstrap_id == 0) { + _bootstrap_id = sn_nsdl_oma_bootstrap(_nsdl_handle, + address, + _endpoint, + &bootstrap_endpoint); + tr_debug("M2MNsdlInterface::create_bootstrap_resource - _bootstrap_id %d", _bootstrap_id); + success = _bootstrap_id != 0; + + } + return success; +#else + (void)address; + (void)bootstrap_endpoint_name; + return false; +#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE +} + +bool M2MNsdlInterface::send_register_message(uint8_t* address, + const uint16_t port, + sn_nsdl_addr_type_e address_type) +{ + tr_debug("M2MNsdlInterface::send_register_message()"); + _nsdl_exceution_timer->stop_timer(); + _nsdl_exceution_timer->start_timer(ONE_SECOND_TIMER * 1000, + M2MTimerObserver::NsdlExecution, + false); + bool success = false; + if(set_NSP_address(_nsdl_handle,address, port, address_type) == 0) { + if(!_register_ongoing) { + _register_ongoing = true; + success = sn_nsdl_register_endpoint(_nsdl_handle,_endpoint) != 0; + } + } + return success; +} + +bool M2MNsdlInterface::send_update_registration(const uint32_t lifetime) +{ + if (_update_register_ongoing) { + tr_debug("M2MNsdlInterface::send_update_registration - update already in progress"); + return true; + } + tr_debug("M2MNsdlInterface::send_update_registration( lifetime %" PRIu32 ")", lifetime); + bool success = false; + + create_nsdl_list_structure(_object_list); + //If Lifetime value is 0, then don't change the existing lifetime value + if(lifetime != 0) { + if(_endpoint->lifetime_ptr) { + memory_free(_endpoint->lifetime_ptr); + _endpoint->lifetime_ptr = NULL; + _endpoint->lifetime_len = 0; + } + set_endpoint_lifetime_buffer(lifetime); + + _registration_timer->stop_timer(); + _registration_timer->start_timer(registration_time() * 1000, + M2MTimerObserver::Registration, + false); + if(_nsdl_handle && + _endpoint && _endpoint->lifetime_ptr) { + tr_debug("M2MNsdlInterface::send_update_registration - new lifetime value"); + _update_register_ongoing = true; + success = sn_nsdl_update_registration(_nsdl_handle, + _endpoint->lifetime_ptr, + _endpoint->lifetime_len) != 0; + } + } else { + if(_nsdl_handle) { + tr_debug("M2MNsdlInterface::send_update_registration - regular update"); + _update_register_ongoing = true; + success = sn_nsdl_update_registration(_nsdl_handle, NULL, 0) != 0; + } + } + return success; +} + +bool M2MNsdlInterface::send_unregister_message() +{ + tr_debug("M2MNsdlInterface::send_unregister_message"); + if (_unregister_ongoing) { + tr_debug("M2MNsdlInterface::send_unregister_message - unregistration already in progress"); + return true; + } + + bool success = false; + _unregister_ongoing = true; + success = sn_nsdl_unregister_endpoint(_nsdl_handle) != 0; + return success; +} + +// XXX: move these to common place, no need to copy these wrappers to multiple places: +void *M2MNsdlInterface::memory_alloc(uint16_t size) +{ + if(size) + return malloc(size); + else + return 0; +} + +void M2MNsdlInterface::memory_free(void *ptr) +{ + if(ptr) + free(ptr); +} + +uint8_t* M2MNsdlInterface::alloc_string_copy(const uint8_t* source, uint16_t size) +{ + assert(source != NULL); + + uint8_t* result = (uint8_t*)memory_alloc(size + 1); + if (result) { + memcpy(result, source, size); + result[size] = '\0'; + } + return result; +} + +uint8_t M2MNsdlInterface::send_to_server_callback(struct nsdl_s * /*nsdl_handle*/, + sn_nsdl_capab_e /*protocol*/, + uint8_t *data_ptr, + uint16_t data_len, + sn_nsdl_addr_s *address) +{ + tr_debug("M2MNsdlInterface::send_to_server_callback()"); + _observer.coap_message_ready(data_ptr,data_len,address); + return 1; +} + +uint8_t M2MNsdlInterface::received_from_server_callback(struct nsdl_s * nsdl_handle, + sn_coap_hdr_s *coap_header, + sn_nsdl_addr_s *address) +{ + tr_debug("M2MNsdlInterface::received_from_server_callback - msg id:%" PRIu16, coap_header->msg_id); + tr_debug("M2MNsdlInterface::received_from_server_callback - registration id:%" PRIu16, nsdl_handle->register_msg_id); + tr_debug("M2MNsdlInterface::received_from_server_callback - unregistration id:%" PRIu16, nsdl_handle->unregister_msg_id); + tr_debug("M2MNsdlInterface::received_from_server_callback - update registration id:%" PRIu16, nsdl_handle->update_register_msg_id); + _observer.coap_data_processed(); + uint8_t value = 0; + if(nsdl_handle && coap_header) { + bool is_bootstrap_msg = address && (nsdl_handle->oma_bs_address_len == address->addr_len) && + (nsdl_handle->oma_bs_port == address->port) && + !memcmp(nsdl_handle->oma_bs_address_ptr, address->addr_ptr, nsdl_handle->oma_bs_address_len); + if(coap_header->msg_id == nsdl_handle->register_msg_id) { + _register_ongoing = false; + if(coap_header->msg_code == COAP_MSG_CODE_RESPONSE_CREATED) { + tr_debug("M2MNsdlInterface::received_from_server_callback - registration callback"); + _observer.client_registered(_server); + // If lifetime is less than zero then leave the field empty + if(coap_header->options_list_ptr) { + if(coap_header->options_list_ptr->max_age_ptr) { + memory_free(_endpoint->lifetime_ptr); + _endpoint->lifetime_ptr = NULL; + _endpoint->lifetime_len = 0; + + uint32_t max_time = 0; + for(int i=0;i < coap_header->options_list_ptr->max_age_len; i++) { + max_time += (*(coap_header->options_list_ptr->max_age_ptr + i) & 0xff) << + 8*(coap_header->options_list_ptr->max_age_len- 1 - i); + } + // If lifetime is less than zero then leave the field empty + if( max_time > 0) { + set_endpoint_lifetime_buffer(max_time); + } + } + if(coap_header->options_list_ptr->location_path_ptr) { + + memory_free(_endpoint->location_ptr); + + _endpoint->location_ptr = alloc_string_copy(coap_header->options_list_ptr->location_path_ptr, coap_header->options_list_ptr->location_path_len); + if (_endpoint->location_ptr != NULL) { + _endpoint->location_len = coap_header->options_list_ptr->location_path_len; + } + sn_nsdl_set_endpoint_location(_nsdl_handle,_endpoint->location_ptr,_endpoint->location_len); + } + } + if(_endpoint->lifetime_ptr) { + _registration_timer->stop_timer(); + _registration_timer->start_timer(registration_time() * 1000, + M2MTimerObserver::Registration, + false); + } + } else { + tr_error("M2MNsdlInterface::received_from_server_callback - registration error %d", coap_header->msg_code); + // Try to do clean register again + if(COAP_MSG_CODE_RESPONSE_BAD_REQUEST == coap_header->msg_code || + COAP_MSG_CODE_RESPONSE_FORBIDDEN == coap_header->msg_code) { + _observer.registration_error(M2MInterface::InvalidParameters, false); + } else { + _observer.registration_error(M2MInterface::NetworkError, true); + } + + } + } else if(coap_header->msg_id == nsdl_handle->unregister_msg_id) { + _unregister_ongoing = false; + tr_debug("M2MNsdlInterface::received_from_server_callback - unregistration callback"); + if(coap_header->msg_code == COAP_MSG_CODE_RESPONSE_DELETED) { + _registration_timer->stop_timer(); + _observer.client_unregistered(); + } else { + tr_error("M2MNsdlInterface::received_from_server_callback - unregistration error %d", coap_header->msg_code); + M2MInterface::Error error = interface_error(coap_header); + _observer.registration_error(error); + } + } else if(coap_header->msg_id == nsdl_handle->update_register_msg_id) { + _update_register_ongoing = false; + if(coap_header->msg_code == COAP_MSG_CODE_RESPONSE_CHANGED) { + tr_debug("M2MNsdlInterface::received_from_server_callback - registration_updated successfully"); + _observer.registration_updated(*_server); + } else { + tr_error("M2MNsdlInterface::received_from_server_callback - registration_updated failed %d", coap_header->msg_code); + _registration_timer->stop_timer(); + _register_ongoing = true; + sn_nsdl_register_endpoint(_nsdl_handle,_endpoint); + } + } +#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + else if(coap_header->msg_id == nsdl_handle->bootstrap_msg_id) { + tr_debug("M2MNsdlInterface::received_from_server_callback - bootstrap"); + _bootstrap_id = 0; + M2MInterface::Error error = interface_error(coap_header); + if(error != M2MInterface::ErrorNone) { + handle_bootstrap_error(); + } + } +#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE + else { + if(COAP_MSG_CODE_REQUEST_PUT == coap_header->msg_code) { + if (is_bootstrap_msg) { + handle_bootstrap_put_message(coap_header, address); + } + } + else if(COAP_MSG_CODE_REQUEST_DELETE == coap_header->msg_code) { + if (is_bootstrap_msg) { + handle_bootstrap_delete(coap_header, address); + } + } + else if(COAP_MSG_CODE_REQUEST_POST == coap_header->msg_code) { + if(is_bootstrap_msg) { + handle_bootstrap_finished(coap_header, address); + } + else if(coap_header->uri_path_ptr) { + sn_coap_hdr_s *coap_response = NULL; + bool execute_value_updated = false; + M2MObjectInstance *obj_instance = NULL; + String resource_name = coap_to_string(coap_header->uri_path_ptr, + coap_header->uri_path_len); + + String object_name; + int slash_found = resource_name.find_last_of('/'); + //The POST operation here is only allowed for non-existing object instances + if(slash_found != -1) { + object_name = resource_name.substr(0,slash_found); + if( object_name.find_last_of('/') != -1){ + coap_response = sn_nsdl_build_response(_nsdl_handle, + coap_header, + COAP_MSG_CODE_RESPONSE_NOT_FOUND); + } else { + int32_t instance_id = atoi(resource_name.substr(slash_found+1, + resource_name.size()-object_name.size()).c_str()); + M2MBase* base = find_resource(object_name); + if(base && (instance_id >= 0) && (instance_id < UINT16_MAX)) { + if(coap_header->payload_ptr) { + M2MObject* object = static_cast (base); + obj_instance = object->create_object_instance(instance_id); + if(obj_instance) { + obj_instance->set_operation(M2MBase::GET_PUT_POST_ALLOWED); + coap_response = obj_instance->handle_post_request(_nsdl_handle, + coap_header, + this, + execute_value_updated); + } + if(coap_response && coap_response->msg_code != COAP_MSG_CODE_RESPONSE_CREATED) { + //Invalid request so remove created ObjectInstance + object->remove_object_instance(instance_id); + } else { + tr_debug("M2MNsdlInterface::received_from_server_callback - Send Update registration for Create"); + send_update_registration(); + } + } else { + tr_debug("M2MNsdlInterface::received_from_server_callback - Missing Payload - Cannot create"); + coap_response = sn_nsdl_build_response(_nsdl_handle, + coap_header, + COAP_MSG_CODE_RESPONSE_BAD_REQUEST); + } + } else { //if(base) + tr_debug("M2MNsdlInterface::received_from_server_callback - Missing BASE - Cannot create"); + coap_response = sn_nsdl_build_response(_nsdl_handle, + coap_header, + COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED); + } + } + } else{ // if(slash_found != -1) + tr_debug("M2MNsdlInterface::received_from_server_callback - slash_found - Cannot create"); + coap_response = sn_nsdl_build_response(_nsdl_handle, + coap_header, + COAP_MSG_CODE_RESPONSE_NOT_FOUND); + } + if(coap_response) { + tr_debug("M2MNsdlInterface::received_from_server_callback - send CoAP response"); + (sn_nsdl_send_coap_message(_nsdl_handle, address, coap_response) == 0) ? value = 0 : value = 1; + sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, coap_response); + } + if (execute_value_updated) { + value_updated(obj_instance, obj_instance->name()); + } + } + } + } + } + return value; +} + +uint8_t M2MNsdlInterface::resource_callback(struct nsdl_s */*nsdl_handle*/, + sn_coap_hdr_s *received_coap_header, + sn_nsdl_addr_s *address, + sn_nsdl_capab_e /*nsdl_capab*/) +{ + tr_debug("M2MNsdlInterface::resource_callback()"); + _observer.coap_data_processed(); + uint8_t result = 1; + sn_coap_hdr_s *coap_response = NULL; + sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 4.00 + String resource_name = coap_to_string(received_coap_header->uri_path_ptr, + received_coap_header->uri_path_len); + tr_debug("M2MNsdlInterface::resource_callback() - resource_name %s", resource_name.c_str()); + bool execute_value_updated = false; + M2MBase* base = find_resource(resource_name); + if(base) { + base->set_uri_path(resource_name); + if(COAP_MSG_CODE_REQUEST_GET == received_coap_header->msg_code) { + coap_response = base->handle_get_request(_nsdl_handle, received_coap_header,this); + } else if(COAP_MSG_CODE_REQUEST_PUT == received_coap_header->msg_code) { + coap_response = base->handle_put_request(_nsdl_handle, received_coap_header, this, execute_value_updated); + } else if(COAP_MSG_CODE_REQUEST_POST == received_coap_header->msg_code) { + if(base->base_type() == M2MBase::ResourceInstance) { + msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; + } else { + coap_response = base->handle_post_request(_nsdl_handle, received_coap_header,this, execute_value_updated); + } + } else if(COAP_MSG_CODE_REQUEST_DELETE == received_coap_header->msg_code) { + // Delete the object instance + tr_debug("M2MNsdlInterface::resource_callback() - DELETE the object instance"); + M2MBase::BaseType type = base->base_type(); + if(M2MBase::ObjectInstance == type) { + M2MBase* base_object = find_resource(base->name()); + if(base_object) { + M2MObject *object = static_cast (base_object); + int slash_found = resource_name.find_last_of('/'); + // Object instance validty checks done in upper level, no need for error handling + if(slash_found != -1) { + String object_name; + object_name = resource_name.substr(slash_found + 1, resource_name.length()); + if (object->remove_object_instance(strtoul( + object_name.c_str(), + NULL, + 10))) { + msg_code = COAP_MSG_CODE_RESPONSE_DELETED; + } + } + } + } else { + msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // 4.00 + } + } else if(COAP_MSG_TYPE_RESET == received_coap_header->msg_type) { + // Cancel ongoing observation + tr_error("M2MNsdlInterface::resource_callback() - RESET message"); + M2MBase::BaseType type = base->base_type(); + switch (type) { + case M2MBase::Object: + base->remove_observation_level(M2MBase::O_Attribute); + break; + case M2MBase::Resource: + base->remove_observation_level(M2MBase::R_Attribute); + break; + case M2MBase::ObjectInstance: + base->remove_observation_level(M2MBase::OI_Attribute); + break; + default: + break; + } + base->set_under_observation(false, this); + } + } else { + tr_debug("M2MNsdlInterface::resource_callback() - Resource NOT FOUND"); + msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // 4.00 + } + if(!coap_response) { + coap_response = sn_nsdl_build_response(_nsdl_handle, + received_coap_header, + msg_code); + } + + if(coap_response) { + tr_debug("M2MNsdlInterface::resource_callback() - send CoAP response"); + (sn_nsdl_send_coap_message(_nsdl_handle, address, coap_response) == 0) ? result = 0 : result = 1; + if(coap_response->payload_ptr) { + free(coap_response->payload_ptr); + coap_response->payload_ptr = NULL; + } + sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, coap_response); + } + if (execute_value_updated) { + value_updated(base,base->uri_path()); + } + + return result; +} + +bool M2MNsdlInterface::process_received_data(uint8_t *data, + uint16_t data_size, + sn_nsdl_addr_s *address) +{ + tr_debug("M2MNsdlInterface::process_received_data( data size %d)", data_size); + __mutex_claim(); + return (0 == sn_nsdl_process_coap(_nsdl_handle, + data, + data_size, + address)) ? true : false; + __mutex_release(); +} + +void M2MNsdlInterface::stop_timers() +{ + tr_debug("M2MNsdlInterface::stop_timers()"); + if(_registration_timer) { + _registration_timer->stop_timer(); + } + if (_nsdl_exceution_timer) { + _nsdl_exceution_timer->stop_timer(); + } + _bootstrap_id = 0; + _register_ongoing = false; + _unregister_ongoing = false; + _update_register_ongoing = false; +} + +void M2MNsdlInterface::timer_expired(M2MTimerObserver::Type type) +{ + if(M2MTimerObserver::NsdlExecution == type) { + __mutex_claim(); + sn_nsdl_exec(_nsdl_handle, _counter_for_nsdl); + __mutex_release(); + _counter_for_nsdl++; + } else if(M2MTimerObserver::Registration == type) { + tr_debug("M2MNsdlInterface::timer_expired - M2MTimerObserver::Registration - Send update registration"); + send_update_registration(); + } +} + +void M2MNsdlInterface::observation_to_be_sent(M2MBase *object, + uint16_t obs_number, + m2m::Vector changed_instance_ids, + bool send_object) +{ + __mutex_claim(); + tr_debug("M2MNsdlInterface::observation_to_be_sent(), %s", object->uri_path().c_str()); + if(object) { + M2MBase::BaseType type = object->base_type(); + if(type == M2MBase::Object) { + send_object_observation(static_cast (object), + obs_number, + changed_instance_ids, + send_object); + } else if(type == M2MBase::ObjectInstance) { + send_object_instance_observation(static_cast (object), obs_number); + } else if(type == M2MBase::Resource) { + send_resource_observation(static_cast (object), obs_number); + } + } + __mutex_release(); +} + +void M2MNsdlInterface::send_delayed_response(M2MBase *base) +{ + __mutex_claim(); + tr_debug("M2MNsdlInterface::send_delayed_response()"); + M2MResource *resource = NULL; + if(base) { + if(M2MBase::Resource == base->base_type()) { + resource = static_cast (base); + } + if(resource) { + sn_coap_hdr_s * coap_response = static_cast(malloc(sizeof(sn_coap_hdr_s))); + if(coap_response) { + memset(coap_response,0,sizeof(sn_coap_hdr_s)); + + coap_response->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + coap_response->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT; + resource->get_delayed_token(coap_response->token_ptr,coap_response->token_len); + + uint32_t length = 0; + resource->get_value(coap_response->payload_ptr, length); + coap_response->payload_len = length; + + sn_nsdl_send_coap_message(_nsdl_handle, _nsdl_handle->nsp_address_ptr->omalw_address_ptr, coap_response); + + if(coap_response->payload_ptr) { + free(coap_response->payload_ptr); + coap_response->payload_ptr = NULL; + } + if(coap_response->token_ptr) { + free(coap_response->token_ptr); + coap_response->token_ptr = NULL; + } + free(coap_response); + } + } + } + __mutex_release(); +} + +void M2MNsdlInterface::resource_to_be_deleted(const String &resource_name) +{ + __mutex_claim(); + tr_debug("M2MNsdlInterface::resource_to_be_deleted(resource_name %s)", resource_name.c_str()); + delete_nsdl_resource(resource_name); + __mutex_release(); +} + +void M2MNsdlInterface::value_updated(M2MBase *base, + const String &object_name) +{ + tr_debug("M2MNsdlInterface::value_updated()"); + if(base) { + switch(base->base_type()) { + case M2MBase::Object: + create_nsdl_object_structure(static_cast (base)); + break; + case M2MBase::ObjectInstance: + create_nsdl_object_instance_structure(static_cast (base)); + break; + case M2MBase::Resource: { + M2MResource* resource = static_cast (base); + create_nsdl_resource_structure(resource,object_name, + resource->supports_multiple_instances()); + } + break; + case M2MBase::ResourceInstance: { + M2MResourceInstance* instance = static_cast (base); + create_nsdl_resource(instance,object_name); + } + break; + } + } + + if (base->is_value_updated_function_set()) { + base->execute_value_updated(base->name()); + } + else { + _observer.value_updated(base); + } +} + +void M2MNsdlInterface::remove_object(M2MBase *object) +{ + __mutex_claim(); + tr_debug("M2MNsdlInterface::remove_object()"); + M2MObject* rem_object = static_cast (object); + if(rem_object && !_object_list.empty()) { + M2MObjectList::const_iterator it; + it = _object_list.begin(); + int index = 0; + for ( ; it != _object_list.end(); it++, index++ ) { + if((*it) == rem_object) { + _object_list.erase(index); + break; + } + } + } + if(_object_list.empty()) { + _object_list.clear(); + } + __mutex_release(); +} + +bool M2MNsdlInterface::create_nsdl_object_structure(M2MObject *object) +{ + tr_debug("M2MNsdlInterface::create_nsdl_object_structure()"); + bool success = false; + if(object) { + M2MObjectInstanceList instance_list = object->instances(); + tr_debug("M2MNsdlInterface::create_nsdl_object_structure - Object Instance count %d", instance_list.size()); + if(!instance_list.empty()) { + M2MObjectInstanceList::const_iterator it; + it = instance_list.begin(); + for ( ; it != instance_list.end(); it++ ) { + // Create NSDL structure for all object instances inside + success = create_nsdl_object_instance_structure(*it); + } + } + } + if((object->operation() != M2MBase::NOT_ALLOWED)) { + success = create_nsdl_resource(object,object->name(),object->register_uri()); + } + return success; +} + +bool M2MNsdlInterface::create_nsdl_object_instance_structure(M2MObjectInstance *object_instance) +{ + tr_debug("M2MNsdlInterface::create_nsdl_object_instance_structure()"); + bool success = false; + if( object_instance) { + + // Append object instance id to the object name. + String object_name = object_instance->name(); + object_name.push_back('/'); + object_name.append_int(object_instance->instance_id()); + + M2MResourceList res_list = object_instance->resources(); + tr_debug("M2MNsdlInterface::create_nsdl_object_instance_structure - ResourceBase count %d", res_list.size()); + if(!res_list.empty()) { + M2MResourceList::const_iterator it; + it = res_list.begin(); + for ( ; it != res_list.end(); it++ ) { + // Create NSDL structure for all resources inside + success = create_nsdl_resource_structure(*it,object_name, + (*it)->supports_multiple_instances()); + } + } + if(object_instance->operation() != M2MBase::NOT_ALLOWED) { + success = create_nsdl_resource(object_instance,object_name,object_instance->register_uri()); + } + } + return success; +} + +bool M2MNsdlInterface::create_nsdl_resource_structure(M2MResource *res, + const String &object_name, + bool multiple_instances) +{ + tr_debug("M2MNsdlInterface::create_nsdl_resource_structure(object_name %s)", object_name.c_str()); + bool success = false; + if(res) { + // Append object name to the resource. + // Take out the instance Id and append to the + // resource name like "object/0/+ resource + / + 0" + String res_name = object_name; + if (strcmp(res_name.c_str(), res->uri_path().c_str()) != 0) { + res_name.push_back('/'); + res_name.append(res->name().c_str(),res->name().length()); + } + + // if there are multiple instances supported + // then add instance Id into creating resource path + // else normal /object_id/object_instance/resource_id format. + if(multiple_instances) { + M2MResourceInstanceList res_list = res->resource_instances(); + tr_debug("M2MNsdlInterface::create_nsdl_resource_structure - ResourceInstance count %d", res_list.size()); + if(!res_list.empty()) { + M2MResourceInstanceList::const_iterator it; + it = res_list.begin(); + for ( ; it != res_list.end(); it++ ) { + String inst_name = res_name; + // Create NSDL structure for all resources inside + inst_name.push_back('/'); + inst_name.append_int((*it)->instance_id()); + + success = create_nsdl_resource((*it),inst_name,(*it)->register_uri()); + } + // Register the main Resource as well along with ResourceInstances + success = create_nsdl_resource(res,res_name,res->register_uri()); + } + } else { + tr_debug("M2MNsdlInterface::create_nsdl_resource_structure - res_name %s", res_name.c_str()); + success = create_nsdl_resource(res,res_name,res->register_uri()); + } + } + return success; +} + +bool M2MNsdlInterface::create_nsdl_resource(M2MBase *base, const String &name, bool publish_uri) +{ + __mutex_claim(); + tr_debug("M2MNsdlInterface::create_nsdl_resource(name %s)", name.c_str()); + bool success = false; + uint8_t* buffer = 0; + uint32_t length = 0; + + // Create the NSDL Resource Pointer... + if(base) { + sn_nsdl_resource_info_s* resource = sn_nsdl_get_resource(_nsdl_handle, + name.length(), + (uint8_t*)name.c_str()); + + if(resource) { + bool changed = false; + success = true; + if(resource->mode == SN_GRS_STATIC) { + if((M2MBase::Resource == base->base_type() || + M2MBase::ResourceInstance == base->base_type()) && + M2MBase::Static == base->mode()) { + M2MResourceInstance *res = (M2MResourceInstance*) base; + res->get_value(buffer,length); + if(resource->resource) { + memory_free(resource->resource); + } + resource->resource = buffer; + resource->resourcelen = length; + resource->publish_uri = publish_uri; + } + } + // Check if the access level for the resource has changed. + if(resource->access != (sn_grs_resource_acl_e)base->operation()) { + changed = true; + resource->access = (sn_grs_resource_acl_e)base->operation(); + } + if(resource->resource_parameters_ptr) { + // Check if the observation parameter for the resource has changed. + if(resource->resource_parameters_ptr->observable != (uint8_t)base->is_observable()) { + changed = true; + resource->resource_parameters_ptr->observable = (uint8_t)base->is_observable(); + } + } + if(changed && resource->resource_parameters_ptr) { + resource->resource_parameters_ptr->registered = SN_NDSL_RESOURCE_NOT_REGISTERED; + } + } else if(_resource) { + base->set_under_observation(false,this); + //TODO: implement access control + // Currently complete access is given + _resource->access = (sn_grs_resource_acl_e)base->operation(); + + if((M2MBase::Resource == base->base_type() || + M2MBase::ResourceInstance == base->base_type()) && + M2MBase::Static == base->mode()) { + M2MResourceInstance *res = (M2MResourceInstance*)base; + // Static resource is updated + _resource->mode = SN_GRS_STATIC; + + res->get_value(buffer,length); + _resource->resource = buffer; + _resource->resourcelen = length; + } + + if(M2MBase::Dynamic == base->mode()){ + // Dynamic resource is updated + _resource->mode = SN_GRS_DYNAMIC; + _resource->sn_grs_dyn_res_callback = __nsdl_c_callback; + } + + if( _resource->path != NULL ){ + memory_free(_resource->path); + _resource->path = NULL; + } + if(name.length() > 0 ){ + _resource->path = alloc_string_copy((uint8_t*)name.c_str(), name.length()); + if(_resource->path) { + _resource->pathlen = name.length(); + } + } + if(!base->resource_type().empty() && _resource->resource_parameters_ptr) { + _resource->resource_parameters_ptr->resource_type_ptr = + alloc_string_copy((uint8_t*)base->resource_type().c_str(), + base->resource_type().length()); + if(_resource->resource_parameters_ptr->resource_type_ptr) { + _resource->resource_parameters_ptr->resource_type_len = + base->resource_type().length(); + } + } + if(!base->interface_description().empty() && _resource->resource_parameters_ptr) { + _resource->resource_parameters_ptr->interface_description_ptr = + alloc_string_copy((uint8_t*)base->interface_description().c_str(), + base->interface_description().length()); + if(_resource->resource_parameters_ptr->interface_description_ptr) { + _resource->resource_parameters_ptr->interface_description_len = + base->interface_description().length(); + } + } + if(_resource->resource_parameters_ptr) { + _resource->resource_parameters_ptr->coap_content_type = base->coap_content_type(); + _resource->resource_parameters_ptr->observable = (uint8_t)base->is_observable(); + } + _resource->publish_uri = publish_uri; + int8_t result = sn_nsdl_create_resource(_nsdl_handle,_resource); + tr_debug("M2MNsdlInterface::create_nsdl_resource - Creating in NSDL-C result %d", result); + + // Either the resource is created or it already + // exists , then result is success. + if (result == 0 || + result == -2){ + success = true; + } + + if(_resource->path) { + memory_free(_resource->path); + } + if(_resource->resource_parameters_ptr->resource_type_ptr){ + memory_free(_resource->resource_parameters_ptr->resource_type_ptr); + } + if(_resource->resource_parameters_ptr->interface_description_ptr){ + memory_free(_resource->resource_parameters_ptr->interface_description_ptr); + } + if (_resource->resource) { + memory_free(_resource->resource); + } + + //Clear up the filled resource to fill up new resource. + clear_resource(_resource); + + if(success) { + base->set_under_observation(false,this); + } + } + } + __mutex_release(); + return success; +} + +// convenience method to get the URI from its buffer field... +String M2MNsdlInterface::coap_to_string(uint8_t *coap_data,int coap_data_length) +{ + String value = ""; + if (coap_data != NULL && coap_data_length > 0) { + value.append_raw((char *)coap_data,coap_data_length); + } + return value; +} + +uint64_t M2MNsdlInterface::registration_time() +{ + uint64_t value = 0; + if(_endpoint->lifetime_ptr) { + value = atol((const char*)_endpoint->lifetime_ptr); + } + + if(value >= OPTIMUM_LIFETIME) { + value = value - REDUCE_LIFETIME; + } else { + value = REDUCTION_FACTOR * value; + } + tr_debug("M2MNsdlInterface::registration_time - value (in seconds) %ld", value); + return value; +} + +M2MBase* M2MNsdlInterface::find_resource(const String &object_name) +{ + M2MBase *object = NULL; + if(!_object_list.empty()) { + M2MObjectList::const_iterator it; + it = _object_list.begin(); + for ( ; it != _object_list.end(); it++ ) { + if((*it)->name() == object_name) { + object = (*it); + tr_debug("M2MNsdlInterface::find_resource(%s) found", object_name.c_str()); + break; + } + object = find_resource((*it),object_name); + if(object != NULL) { + tr_debug("M2MNsdlInterface::find_resource(%s) found", object_name.c_str()); + break; + } + } + } + return object; +} + +M2MBase* M2MNsdlInterface::find_resource(const M2MObject *object, + const String &object_instance) +{ + M2MBase *instance = NULL; + if(object) { + M2MObjectInstanceList list = object->instances(); + if(!list.empty()) { + M2MObjectInstanceList::const_iterator it; + it = list.begin(); + for ( ; it != list.end(); it++ ) { + // Append object instance id to the object name. + String name = (*it)->name(); + name.push_back('/'); + name.append_int((*it)->instance_id()); + + if(name == object_instance){ + instance = (*it); + break; + } + instance = find_resource((*it),object_instance); + if(instance != NULL){ + break; + } + } + } + } + return instance; +} + +M2MBase* M2MNsdlInterface::find_resource(const M2MObjectInstance *object_instance, + const String &resource_instance) +{ + M2MBase *instance = NULL; + if(object_instance) { + M2MResourceList list = object_instance->resources(); + if(!list.empty()) { + M2MResourceList::const_iterator it; + it = list.begin(); + for ( ; it != list.end(); it++ ) { + String name = object_instance->name(); + // Append object instance id to the object name. + name.push_back('/'); + name.append_int(object_instance->instance_id()); + + name.push_back('/'); + name+= (*it)->name(); + + if(name == resource_instance) { + instance = *it; + break; + } else if((*it)->supports_multiple_instances()) { + instance = find_resource((*it),name, resource_instance); + if(instance != NULL){ + break; + } + } + } + } + } + return instance; +} + +M2MBase* M2MNsdlInterface::find_resource(const M2MResource *resource, + const String &object_name, + const String &resource_instance) +{ + M2MBase *res = NULL; + if(resource) { + if(resource->supports_multiple_instances()) { + M2MResourceInstanceList list = resource->resource_instances(); + if(!list.empty()) { + M2MResourceInstanceList::const_iterator it; + it = list.begin(); + for ( ; it != list.end(); it++ ) { + String name = object_name; + // if there are multiple instances supported + // then add instance Id into creating resource path + // else normal /object_id/object_instance/resource_id format. + + name.push_back('/'); + name.append_int((*it)->instance_id()); + + if(name == resource_instance){ + res = (*it); + break; + } + } + } + } + } + return res; +} + +bool M2MNsdlInterface::object_present(M2MObject* object) const +{ + bool success = false; + if(object && !_object_list.empty()) { + M2MObjectList::const_iterator it; + it = _object_list.begin(); + for ( ; it != _object_list.end(); it++ ) { + if((*it) == object) { + success = true; + break; + } + } + } + return success; +} + +bool M2MNsdlInterface::add_object_to_list(M2MObject* object) +{ + bool success = false; + if(object && !object_present(object)) { + _object_list.push_back(object); + success = true; + } + return success; +} + +void M2MNsdlInterface::clear_resource(sn_nsdl_resource_info_s *&resource) +{ + //Clear up the filled resource to fill up new resource. + if(resource && resource->resource_parameters_ptr) { + sn_nsdl_resource_parameters_s *temp_resource_parameter = resource->resource_parameters_ptr; + memset(resource->resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s)); + memset(resource,0, sizeof(sn_nsdl_resource_info_s)); + resource->resource_parameters_ptr = temp_resource_parameter; + } +} + +M2MInterface::Error M2MNsdlInterface::interface_error(sn_coap_hdr_s *coap_header) +{ + M2MInterface::Error error = M2MInterface::ErrorNone; + if(coap_header) { + switch(coap_header->msg_code) { + case COAP_MSG_CODE_RESPONSE_BAD_REQUEST: + case COAP_MSG_CODE_RESPONSE_BAD_OPTION: + case COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE: + case COAP_MSG_CODE_RESPONSE_PRECONDITION_FAILED: + case COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE: + case COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT: + error = M2MInterface::InvalidParameters; + break; + case COAP_MSG_CODE_RESPONSE_UNAUTHORIZED: + case COAP_MSG_CODE_RESPONSE_FORBIDDEN: + case COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE: + case COAP_MSG_CODE_RESPONSE_NOT_FOUND: + case COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED: + error = M2MInterface::NotAllowed; + break; + case COAP_MSG_CODE_RESPONSE_CREATED: + case COAP_MSG_CODE_RESPONSE_DELETED: + case COAP_MSG_CODE_RESPONSE_VALID: + case COAP_MSG_CODE_RESPONSE_CHANGED: + case COAP_MSG_CODE_RESPONSE_CONTENT: + error = M2MInterface::ErrorNone; + break; + default: + error = M2MInterface::UnknownError; + break; + } + if(coap_header->coap_status == COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED) { + error = M2MInterface::NetworkError; + } + } + return error; +} + +void M2MNsdlInterface::send_object_observation(M2MObject *object, + uint16_t obs_number, + m2m::Vector changed_instance_ids, + bool send_object) +{ + tr_debug("M2MNsdlInterface::send_object_observation"); + if(object) { + uint8_t *value = 0; + uint32_t length = 0; + uint8_t *token = 0; + uint32_t token_length = 0; + + M2MTLVSerializer serializer; + // Send whole object structure + if (send_object) { + value = serializer.serialize(object->instances(), length); + } + // Send only changed object instances + else { + M2MObjectInstanceList list; + Vector::const_iterator it; + it = changed_instance_ids.begin(); + for (; it != changed_instance_ids.end(); it++){ + M2MObjectInstance* obj_instance = object->object_instance(*it); + if (obj_instance){ + list.push_back(obj_instance); + } + } + if (!list.empty()) { + value = serializer.serialize(list, length); + list.clear(); + } + } + + object->get_observation_token(token,token_length); + + send_notification(token, + token_length, + value, + length, + obs_number, + object->max_age(), + object->coap_content_type(), + object->uri_path()); + + memory_free(value); + memory_free(token); + } +} + +void M2MNsdlInterface::send_object_instance_observation(M2MObjectInstance *object_instance, + uint16_t obs_number) +{ + tr_debug("M2MNsdlInterface::send_object_instance_observation"); + if(object_instance) { + uint8_t *value = 0; + uint32_t length = 0; + uint8_t *token = 0; + uint32_t token_length = 0; + + M2MTLVSerializer serializer; + value = serializer.serialize(object_instance->resources(), length); + + object_instance->get_observation_token(token,token_length); + + send_notification(token, + token_length, + value, + length, + obs_number, + object_instance->max_age(), + object_instance->coap_content_type(), + object_instance->uri_path()); + + memory_free(value); + memory_free(token); + } +} + +void M2MNsdlInterface::send_resource_observation(M2MResource *resource, + uint16_t obs_number) +{ + tr_debug("M2MNsdlInterface::send_resource_observation"); + if(resource) { + uint8_t *value = 0; + uint32_t length = 0; + uint8_t *token = 0; + uint32_t token_length = 0; + + resource->get_observation_token(token,token_length); + uint8_t content_type = 0; + if(M2MResourceInstance::OPAQUE == resource->resource_instance_type()) { + content_type = COAP_CONTENT_OMA_OPAQUE_TYPE; + } + if (resource->resource_instance_count() > 0) { + content_type = COAP_CONTENT_OMA_TLV_TYPE; + M2MTLVSerializer serializer; + value = serializer.serialize(resource, length); + } else { + resource->get_value(value,length); + } + send_notification(token, + token_length, + value, + length, + obs_number, + resource->max_age(), + content_type, + resource->uri_path()); + + memory_free(value); + memory_free(token); + } +} + +void M2MNsdlInterface::build_observation_number(uint8_t *obs_number, + uint8_t *obs_len, + uint16_t number) +{ + if(number > 0xFF) { + *obs_len = 2; + *(obs_number) = (number >> 8) & 0x00FF; + obs_number[1] = number & 0x00FF; + } else { + *obs_len = 1; + *(obs_number) = number & 0x00FF; + } +} + +void M2MNsdlInterface::send_notification(uint8_t *token, + uint8_t token_length, + uint8_t *value, + uint32_t value_length, + uint16_t observation, + uint32_t max_age, + uint8_t coap_content_type, + const String &uri_path) + +{ + tr_debug("M2MNsdlInterface::send_notification"); + sn_coap_hdr_s *notification_message_ptr; + + /* Allocate and initialize memory for header struct */ + notification_message_ptr = static_cast(memory_alloc(sizeof(sn_coap_hdr_s))); + if (notification_message_ptr) { + memset(notification_message_ptr, 0, sizeof(sn_coap_hdr_s)); + + notification_message_ptr->options_list_ptr = (sn_coap_options_list_s *)memory_alloc(sizeof(sn_coap_options_list_s)); + if (notification_message_ptr->options_list_ptr) { + + memset(notification_message_ptr->options_list_ptr , 0, sizeof(sn_coap_options_list_s)); + + /* Fill header */ + notification_message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE; + notification_message_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT; + + /* Fill token */ + notification_message_ptr->token_len = token_length; + notification_message_ptr->token_ptr = token; + + /* Fill payload */ + notification_message_ptr->payload_len = value_length; + notification_message_ptr->payload_ptr = value; + + /* Fill uri path */ + notification_message_ptr->uri_path_len = uri_path.size(); + notification_message_ptr->uri_path_ptr = (uint8_t *)uri_path.c_str(); + + /* Fill observe */ + uint8_t observation_number[2]; + uint8_t observation_number_length = 0; + + build_observation_number(observation_number, + &observation_number_length, + observation); + notification_message_ptr->options_list_ptr->observe_len = observation_number_length; + notification_message_ptr->options_list_ptr->observe_ptr = observation_number; + + notification_message_ptr->options_list_ptr->max_age_ptr = + m2m::String::convert_integer_to_array(max_age, + notification_message_ptr->options_list_ptr->max_age_len); + + notification_message_ptr->content_type_ptr = + m2m::String::convert_integer_to_array(coap_content_type, + notification_message_ptr->content_type_len); + + /* Send message */ + sn_nsdl_send_coap_message(_nsdl_handle, + _nsdl_handle->nsp_address_ptr->omalw_address_ptr, + notification_message_ptr); + + /* Free memory */ + notification_message_ptr->uri_path_ptr = NULL; + notification_message_ptr->payload_ptr = NULL; + notification_message_ptr->options_list_ptr->observe_ptr = NULL; + notification_message_ptr->token_ptr = NULL; + if (notification_message_ptr->content_type_ptr) { + free(notification_message_ptr->content_type_ptr); + } + notification_message_ptr->content_type_ptr = NULL; + if (notification_message_ptr->options_list_ptr->max_age_ptr) { + free(notification_message_ptr->options_list_ptr->max_age_ptr); + } + notification_message_ptr->options_list_ptr->max_age_ptr = NULL; + } + sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, notification_message_ptr); + } +} + +nsdl_s * M2MNsdlInterface::get_nsdl_handle() +{ + return _nsdl_handle; +} + +void M2MNsdlInterface::handle_bootstrap_put_message(sn_coap_hdr_s *coap_header, + sn_nsdl_addr_s *address) { +#ifndef M2M_CLIENT_DISABLE_BOOTSTRAP_FEATURE + tr_debug("M2MNsdlInterface::handle_bootstrap_message"); + uint8_t response_code = COAP_MSG_CODE_RESPONSE_CHANGED; + sn_coap_hdr_s *coap_response = NULL; + bool success = false; + bool security_object = false; + uint16_t content_type = 0; + + if (!_security) { + _security = new M2MSecurity(M2MSecurity::M2MServer); + } + + String resource_name = coap_to_string(coap_header->uri_path_ptr, + coap_header->uri_path_len); + tr_debug("M2MNsdlInterface::handle_bootstrap_message - uri %s", resource_name.c_str()); + + // Check incoming object + if (resource_name.compare(0,1,"0") == 0) { + security_object = true; + if(_security) { + success = true; + // Not mandatory resource that's why it must be created first + _security->create_resource(M2MSecurity::ShortServerID, 1); + // Change operation mode + M2MResourceList list = _security->object_instance()->resources(); + if(!list.empty()) { + M2MResourceList::const_iterator it; + it = list.begin(); + for ( ; it != list.end(); it++ ) { + (*it)->set_operation(M2MBase::PUT_ALLOWED); + } + } + } + } + else if (resource_name.compare(0,1,"1") == 0) { + success = true; + } + + if (success) { + // Send delayed response if token is part of the message + if (coap_header->token_ptr) { + tr_debug("M2MNsdlInterface::handle_bootstrap_message - send delayed response"); + coap_response = sn_nsdl_build_response(_nsdl_handle, + coap_header, + COAP_MSG_CODE_EMPTY); + if (coap_response) { + coap_response->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + sn_nsdl_send_coap_message(_nsdl_handle, address, coap_response); + sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, coap_response); + } + } + + if(coap_header->content_type_ptr) { + content_type = String::convert_array_to_integer(coap_header->content_type_ptr, + coap_header->content_type_len); + } + + tr_debug("M2MNsdlInterface::handle_bootstrap_message - content_type %d", content_type); + if (content_type != COAP_CONTENT_OMA_TLV_TYPE) { + success = false; + } + if (success) { + success = parse_bootstrap_message(coap_header, security_object); + // Set operation back to default ones + if (_security) { + M2MResourceList list = _security->object_instance()->resources(); + if(!list.empty()) { + M2MResourceList::const_iterator it; + it = list.begin(); + for ( ; it != list.end(); it++ ) { + (*it)->set_operation(M2MBase::NOT_ALLOWED); + } + } + } + } + } + + if (!success) { + response_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; + handle_bootstrap_error(); + } + coap_response = sn_nsdl_build_response(_nsdl_handle, + coap_header, + response_code); + if (coap_response) { + sn_nsdl_send_coap_message(_nsdl_handle, address, coap_response); + sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, coap_response); + } +#else + (void) coap_header; + (void) address; +#endif +} + +bool M2MNsdlInterface::parse_bootstrap_message(sn_coap_hdr_s *coap_header, bool is_security_object) +{ +#ifndef M2M_CLIENT_DISABLE_BOOTSTRAP_FEATURE + tr_debug("M2MNsdlInterface::parse_bootstrap_put_message"); + M2MTLVDeserializer *deserializer = new M2MTLVDeserializer(); + bool ret = false; + bool is_obj_instance = false; + uint16_t instance_id = 0; + if (deserializer && _security) { + ret = is_obj_instance = deserializer->is_object_instance(coap_header->payload_ptr); + if (!is_obj_instance) { + ret = deserializer->is_resource(coap_header->payload_ptr); + } + + if (ret) { + M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; + if (is_obj_instance) { + if (is_security_object) { + error = deserializer->deserialise_object_instances(coap_header->payload_ptr, + coap_header->payload_len, + *_security, + M2MTLVDeserializer::Put); + } + else { + error = deserializer->deserialise_object_instances(coap_header->payload_ptr, + coap_header->payload_len, + *_server, + M2MTLVDeserializer::Put); + } + } + else { + if (is_security_object) { + instance_id = deserializer->instance_id(coap_header->payload_ptr); + error = deserializer->deserialize_resources(coap_header->payload_ptr, + coap_header->payload_len, + *_security->object_instance(instance_id), + M2MTLVDeserializer::Put); + } + else { + instance_id = deserializer->instance_id(coap_header->payload_ptr); + error = deserializer->deserialize_resources(coap_header->payload_ptr, + coap_header->payload_len, + *_server->object_instance(instance_id), + M2MTLVDeserializer::Post); + } + } + + if (error != M2MTLVDeserializer::None) { + tr_error("M2MNsdlInterface::parse_bootstrap_put_message - error %d", error); + ret = false; + } + } + } + delete deserializer; + return ret; +#else + (void) coap_header; + (void) is_security_object; + return false; +#endif +} + +void M2MNsdlInterface::handle_bootstrap_finished(sn_coap_hdr_s *coap_header,sn_nsdl_addr_s *address) +{ +#ifndef M2M_CLIENT_DISABLE_BOOTSTRAP_FEATURE + String object_name = coap_to_string(coap_header->uri_path_ptr, + coap_header->uri_path_len); + tr_debug("M2MNsdlInterface::handle_bootstrap_finished - path: %s", object_name.c_str()); + sn_coap_hdr_s *coap_response = NULL; + uint8_t msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; + + // Accept only '/bs' path and check that needed data is in security object + if (object_name.size() != 2 || + object_name.compare(0,2,BOOTSTRAP_URI) != 0 || + !validate_security_object()) { + msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; + } else { + // Add short server id to server object + _server->set_resource_value(M2MServer::ShortServerID, + _security->resource_value_int(M2MSecurity::ShortServerID)); + } + + coap_response = sn_nsdl_build_response(_nsdl_handle, + coap_header, + msg_code); + if(coap_response) { + sn_nsdl_send_coap_message(_nsdl_handle, address, coap_response); + sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, coap_response); + } + if (COAP_MSG_CODE_RESPONSE_CHANGED == msg_code) { + // Switch back to original ep name + if (_endpoint->endpoint_name_ptr) { + memory_free(_endpoint->endpoint_name_ptr); + } + _endpoint->endpoint_name_ptr = alloc_string_copy((uint8_t*)_endpoint_name.c_str(), _endpoint_name.length()); + _endpoint->endpoint_name_len = _endpoint_name.length(); + _observer.bootstrap_done(_security); + } else { + handle_bootstrap_error(); + } +#else + (void) coap_header; + (void) address; +#endif +} + +void M2MNsdlInterface::handle_bootstrap_delete(sn_coap_hdr_s *coap_header,sn_nsdl_addr_s *address) +{ +#ifndef M2M_CLIENT_DISABLE_BOOTSTRAP_FEATURE + sn_coap_hdr_s *coap_response = NULL; + uint8_t msg_code = COAP_MSG_CODE_RESPONSE_DELETED; + String object_name = coap_to_string(coap_header->uri_path_ptr, + coap_header->uri_path_len); + tr_debug("M2MNsdlInterface::handle_bootstrap_delete - obj %s", object_name.c_str()); + + // Only following paths are accepted, 0, 0/0 + if (object_name.size() == 2 || object_name.size() > 3) { + msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; + } + else if ((object_name.size() == 1 && object_name.compare(0,1,"0") != 0) || + (object_name.size() == 3 && object_name.compare(0,3,"0/0") != 0)) { + msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; + } + + coap_response = sn_nsdl_build_response(_nsdl_handle, + coap_header, + msg_code); + + if(coap_response) { + sn_nsdl_send_coap_message(_nsdl_handle, address, coap_response); + sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, coap_response); + if(_security) { + _security->clear_resources(); + } + } else { + handle_bootstrap_error(); + } +#else + (void) coap_header; + (void) address; +#endif +} + +bool M2MNsdlInterface::validate_security_object() +{ +#ifndef M2M_CLIENT_DISABLE_BOOTSTRAP_FEATURE + tr_debug("M2MNsdlInterface::validate_security_object"); + if (_security) { + String address = _security->resource_value_string(M2MSecurity::M2MServerUri); + uint32_t sec_mode = _security->resource_value_int(M2MSecurity::SecurityMode); + bool is_bs_server = _security->resource_value_int(M2MSecurity::BootstrapServer); + uint32_t public_key_size = _security->get_resource(M2MSecurity::PublicKey)->value_length(); + uint32_t server_key_size = _security->get_resource(M2MSecurity::ServerPublicKey)->value_length(); + uint32_t pkey_size = _security->get_resource(M2MSecurity::Secretkey)->value_length(); + tr_debug("M2MNsdlInterface::validate_security_object - Server URI /0/0: %s", address.c_str()); + tr_debug("M2MNsdlInterface::validate_security_object - is bs server /0/1: %d", is_bs_server); + tr_debug("M2MNsdlInterface::validate_security_object - Security Mode /0/2: %d", sec_mode); + tr_debug("M2MNsdlInterface::validate_security_object - Public key size /0/3: %d", public_key_size); + tr_debug("M2MNsdlInterface::validate_security_object - Server Public key size /0/4: %d", server_key_size); + tr_debug("M2MNsdlInterface::validate_security_object - Secret key size /0/5: %d", pkey_size); + // Only NoSec and Certificate modes are supported + if (!address.empty() && !is_bs_server) { + if (M2MSecurity::Certificate == sec_mode) { + if (!public_key_size || !server_key_size || !pkey_size) { + return false; + } else { + return true; + } + } else if (M2MSecurity::NoSecurity == sec_mode){ + return true; + } else { + return false; + } + } else { + return false; + } + } + return false; +#else + return false; +#endif +} + +void M2MNsdlInterface::handle_bootstrap_error() +{ + tr_debug("M2MNsdlInterface::handle_bootstrap_error()"); + if (_security) { + delete _security; + _security = NULL; + } + _observer.bootstrap_error(); +} + +const String& M2MNsdlInterface::endpoint_name() const +{ + return _endpoint_name; +} diff --git a/features/FEATURE_CLIENT/mbed-client/source/m2mobject.cpp b/features/FEATURE_CLIENT/mbed-client/source/m2mobject.cpp new file mode 100644 index 0000000000..93e61618c4 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/m2mobject.cpp @@ -0,0 +1,511 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client/m2mobject.h" +#include "mbed-client/m2mobservationhandler.h" +#include "mbed-client/m2mconstants.h" +#include "include/m2mtlvserializer.h" +#include "include/m2mtlvdeserializer.h" +#include "include/nsdllinker.h" +#include "include/m2mreporthandler.h" +#include "mbed-trace/mbed_trace.h" + +#define BUFFER_SIZE 10 +#define TRACE_GROUP "mClt" + +M2MObject::M2MObject(const String &object_name) +: M2MBase(object_name,M2MBase::Dynamic), + _max_instance_count(MAX_UNINT_16_COUNT) +{ + M2MBase::set_base_type(M2MBase::Object); + if(M2MBase::name_id() != -1) { + M2MBase::set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE); + } +} + +M2MObject::~M2MObject() +{ + if(!_instance_list.empty()) { + remove_resource_from_coap(name()); + M2MObjectInstanceList::const_iterator it; + it = _instance_list.begin(); + M2MObjectInstance* obj = NULL; + uint16_t index = 0; + for (; it!=_instance_list.end(); it++, index++ ) { + //Free allocated memory for object instances. + obj = *it; + delete obj; + } + remove_object_from_coap(); + _instance_list.clear(); + } +} + +M2MObject& M2MObject::operator=(const M2MObject& other) +{ + if (this != &other) { // protect against invalid self-assignment + if(!other._instance_list.empty()){ + M2MObjectInstance* ins = NULL; + M2MObjectInstanceList::const_iterator it; + it = other._instance_list.begin(); + for (; it!=other._instance_list.end(); it++ ) { + ins = *it; + _instance_list.push_back(new M2MObjectInstance(*ins)); + } + } + } + return *this; +} + +M2MObject::M2MObject(const M2MObject& other) +: M2MBase(other), + _max_instance_count(MAX_UNINT_16_COUNT) +{ + this->operator=(other); +} + +M2MObjectInstance* M2MObject::create_object_instance(uint16_t instance_id) +{ + tr_debug("M2MObject::create_object_instance - id: %d", instance_id); + M2MObjectInstance *instance = NULL; + if(!object_instance(instance_id)) { + instance = new M2MObjectInstance(this->name(),*this); + if(instance) { + instance->add_observation_level(observation_level()); + instance->set_instance_id(instance_id); + if(M2MBase::name_id() != -1) { + instance->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE); + } + _instance_list.push_back(instance); + } + } + return instance; +} + +bool M2MObject::remove_object_instance(uint16_t inst_id) +{ + tr_debug("M2MObject::remove_object_instance(inst_id %d)", inst_id); + bool success = false; + if(!_instance_list.empty()) { + M2MObjectInstance* obj = NULL; + M2MObjectInstanceList::const_iterator it; + it = _instance_list.begin(); + int pos = 0; + for ( ; it != _instance_list.end(); it++, pos++ ) { + if((*it)->instance_id() == inst_id) { + // Instance found and deleted. + obj = *it; + String obj_name = name(); + obj_name.push_back('/'); + obj_name.append_int(obj->instance_id()); + obj->remove_resource_from_coap(obj_name); + _instance_list.erase(pos); + delete obj; + success = true; + break; + } + } + } + return success; +} + +M2MObjectInstance* M2MObject::object_instance(uint16_t inst_id) const +{ + tr_debug("M2MObject::object_instance(inst_id %d)", inst_id); + M2MObjectInstance *obj = NULL; + if(!_instance_list.empty()) { + M2MObjectInstanceList::const_iterator it; + it = _instance_list.begin(); + for ( ; it != _instance_list.end(); it++ ) { + if((*it)->instance_id() == inst_id) { + // Instance found. + obj = *it; + break; + } + } + } + return obj; +} + +const M2MObjectInstanceList& M2MObject::instances() const +{ + return _instance_list; +} + +uint16_t M2MObject::instance_count() const +{ + return (uint16_t)_instance_list.size(); +} + +M2MBase::BaseType M2MObject::base_type() const +{ + return M2MBase::base_type(); +} + +void M2MObject::add_observation_level(M2MBase::Observation observation_level) +{ + M2MBase::add_observation_level(observation_level); + if(!_instance_list.empty()) { + M2MObjectInstanceList::const_iterator it; + it = _instance_list.begin(); + for ( ; it != _instance_list.end(); it++ ) { + (*it)->add_observation_level(observation_level); + } + } +} + +void M2MObject::remove_observation_level(M2MBase::Observation observation_level) +{ + M2MBase::remove_observation_level(observation_level); + if(!_instance_list.empty()) { + M2MObjectInstanceList::const_iterator it; + it = _instance_list.begin(); + for ( ; it != _instance_list.end(); it++ ) { + (*it)->remove_observation_level(observation_level); + } + } +} + +sn_coap_hdr_s* M2MObject::handle_get_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler) +{ + tr_debug("M2MObject::handle_get_request()"); + sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CONTENT; + sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl, + received_coap_header, + msg_code); + uint8_t * data = NULL; + uint32_t data_length = 0; + if(received_coap_header) { + // process the GET if we have registered a callback for it + if ((operation() & SN_GRS_GET_ALLOWED) != 0) { + if(coap_response) { + uint16_t coap_content_type = 0; + bool content_type_present = false; + if(received_coap_header->content_type_ptr) { + content_type_present = true; + coap_response->content_type_ptr = alloc_copy(received_coap_header->content_type_ptr, + received_coap_header->content_type_len); + if(coap_response->content_type_ptr) { + coap_response->content_type_len = received_coap_header->content_type_len; + for(uint8_t i = 0; i < coap_response->content_type_len; i++) { + coap_content_type = (coap_content_type << 8) + + (coap_response->content_type_ptr[i] & 0xFF); + } + } + } + if(!content_type_present && + M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE) { + coap_content_type = COAP_CONTENT_OMA_TLV_TYPE; + } + + tr_debug("M2MObject::handle_get_request() - Request Content-Type %d", coap_content_type); + if (!coap_response->content_type_ptr) { + coap_response->content_type_ptr = + m2m::String::convert_integer_to_array(coap_content_type, + coap_response->content_type_len); + if (coap_response->content_type_ptr) { + set_coap_content_type(coap_content_type); + } + } + // fill in the CoAP response payload + if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type) { + M2MTLVSerializer *serializer = new M2MTLVSerializer(); + data = serializer->serialize(_instance_list, data_length); + delete serializer; + + } else { // TOD0: Implement JSON Format. + msg_code = COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; // Content format not supported + } + + coap_response->payload_len = data_length; + coap_response->payload_ptr = data; + + coap_response->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(coap_response->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + + coap_response->options_list_ptr->max_age_ptr = + m2m::String::convert_integer_to_array(max_age(), + coap_response->options_list_ptr->max_age_len); + + if(data){ + if(received_coap_header->options_list_ptr) { + if(received_coap_header->options_list_ptr->observe) { + if (is_observable()) { + uint32_t number = 0; + uint8_t observe_option = 0; + if(received_coap_header->options_list_ptr->observe_ptr) { + observe_option = *received_coap_header->options_list_ptr->observe_ptr; + } + if(START_OBSERVATION == observe_option) { + tr_debug("M2MObject::handle_get_request - Starts Observation"); + // If the observe length is 0 means register for observation. + if(received_coap_header->options_list_ptr->observe_len != 0) { + for(int i=0;i < received_coap_header->options_list_ptr->observe_len; i++) { + number = (*(received_coap_header->options_list_ptr->observe_ptr + i) & 0xff) << + 8*(received_coap_header->options_list_ptr->observe_len- 1 - i); + } + } + if(received_coap_header->token_ptr) { + tr_debug("M2MObject::handle_get_request - Sets Observation Token to resource"); + set_observation_token(received_coap_header->token_ptr, + received_coap_header->token_len); + } + + // If the observe value is 0 means register for observation. + if(number == 0) { + tr_debug("M2MObject::handle_get_request - Put Resource under Observation"); + set_under_observation(true,observation_handler); + add_observation_level(M2MBase::O_Attribute); + tr_debug("M2MObject::handle_get_request - Observation Number %d", observation_number()); + coap_response->options_list_ptr->observe_ptr = + m2m::String::convert_integer_to_array(observation_number(), + coap_response->options_list_ptr->observe_len); + } + } else if (STOP_OBSERVATION == observe_option) { + tr_debug("M2MObject::handle_get_request - Stops Observation"); + // If the observe options_list_ptr->observe_ptr value is 1 means de-register from observation. + set_under_observation(false,NULL); + remove_observation_level(M2MBase::O_Attribute); + } + msg_code = COAP_MSG_CODE_RESPONSE_CONTENT; + } + else { + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + } + } + } else { + msg_code = COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; // Content format not supported + } + } + }else { + tr_error("M2MResource::handle_get_request - Return COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED"); + // Operation is not allowed. + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + } else { + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + if(coap_response) { + coap_response->msg_code = msg_code; + } + return coap_response; +} + +sn_coap_hdr_s* M2MObject::handle_put_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler */*observation_handler*/, + bool &/*execute_value_updated*/) +{ + tr_debug("M2MObject::handle_put_request()"); + sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04 + sn_coap_hdr_s *coap_response = sn_nsdl_build_response(nsdl, + received_coap_header, + msg_code); + if(received_coap_header) { + if(received_coap_header->options_list_ptr && + received_coap_header->options_list_ptr->uri_query_ptr) { + char *query = (char*)alloc_string_copy(received_coap_header->options_list_ptr->uri_query_ptr, + received_coap_header->options_list_ptr->uri_query_len); + if (query){ + tr_debug("M2MObject::handle_put_request() - Query %s", query); + // if anything was updated, re-initialize the stored notification attributes + if (!handle_observation_attribute(query)){ + tr_debug("M2MObject::handle_put_request() - Invalid query"); + msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // 4.00 + } + free(query); + } + } else { + tr_error("M2MObject::handle_put_request() - COAP_MSG_CODE_RESPONSE_BAD_REQUEST - Empty URI_QUERY"); + msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; + } + } else { + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + if(coap_response) { + coap_response->msg_code = msg_code; + } + return coap_response; +} + + +sn_coap_hdr_s* M2MObject::handle_post_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler, + bool &execute_value_updated) +{ + tr_debug("M2MObject::handle_post_request()"); + sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04 + // process the POST if we have registered a callback for it + sn_coap_hdr_s *coap_response = sn_nsdl_build_response(nsdl, + received_coap_header, + msg_code); + + if(received_coap_header) { + if ((operation() & SN_GRS_POST_ALLOWED) != 0) { + if(received_coap_header->payload_ptr) { + tr_debug("M2MObject::handle_post_request() - Update Object with new values"); + uint16_t coap_content_type = 0; + bool content_type_present = false; + if(received_coap_header->content_type_ptr) { + content_type_present = true; + if(coap_response) { + coap_response->content_type_ptr = (uint8_t*)alloc_copy(received_coap_header->content_type_ptr, + received_coap_header->content_type_len); + if(coap_response->content_type_ptr) { + coap_response->content_type_len = received_coap_header->content_type_len; + for(uint8_t i = 0; i < coap_response->content_type_len; i++) { + coap_content_type = (coap_content_type << 8) + + (coap_response->content_type_ptr[i] & 0xFF); + } + } + } + } // if(received_coap_header->content_type_ptr) + if(!content_type_present && + M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE) { + coap_content_type = COAP_CONTENT_OMA_TLV_TYPE; + } + + tr_debug("M2MObject::handle_post_request() - Request Content-Type %d", coap_content_type); + + if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type) { + uint16_t instance_id = 0; + // Check next free instance id + for(instance_id = 0; instance_id <= _max_instance_count; instance_id++) { + if(NULL == object_instance(instance_id)) { + break; + } + if(instance_id == _max_instance_count) { + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + break; + } + } + if(COAP_MSG_CODE_RESPONSE_CHANGED == msg_code) { + M2MTLVDeserializer *deserializer = new M2MTLVDeserializer(); + bool is_obj_instance = false; + bool obj_instance_exists = false; + if (deserializer) { + is_obj_instance = deserializer->is_object_instance(received_coap_header->payload_ptr); + if (is_obj_instance) { + instance_id = deserializer->instance_id(received_coap_header->payload_ptr); + tr_debug("M2MObject::handle_post_request() - instance id in TLV: %d", instance_id); + // Check if instance id already exists + if (object_instance(instance_id)){ + obj_instance_exists = true; + } + } + } + if (!obj_instance_exists) { + M2MObjectInstance *obj_instance = create_object_instance(instance_id); + if(obj_instance) { + obj_instance->set_operation(M2MBase::GET_PUT_ALLOWED); + } + + if(deserializer) { + String obj_name = ""; + M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; + if(is_obj_instance) { + tr_debug("M2MObject::handle_post_request() - TLV data contains ObjectInstance"); + error = deserializer->deserialise_object_instances(received_coap_header->payload_ptr, + received_coap_header->payload_len, + *this, + M2MTLVDeserializer::Post); + } else if(deserializer->is_resource(received_coap_header->payload_ptr) || + deserializer->is_multiple_resource(received_coap_header->payload_ptr)) { + tr_debug("M2MObject::handle_post_request() - TLV data contains Resources"); + error = deserializer->deserialize_resources(received_coap_header->payload_ptr, + received_coap_header->payload_len, + *obj_instance, + M2MTLVDeserializer::Post); + } else { + error = M2MTLVDeserializer::NotValid; + } + switch(error) { + case M2MTLVDeserializer::None: + if(observation_handler) { + execute_value_updated = true; + } + coap_response->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + if (coap_response->options_list_ptr) { + memset(coap_response->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + + obj_name = M2MBase::name(); + obj_name.push_back('/'); + obj_name.append_int(instance_id); + + coap_response->options_list_ptr->location_path_len = obj_name.length(); + if (coap_response->options_list_ptr->location_path_len != 0) { + coap_response->options_list_ptr->location_path_ptr = + (uint8_t*)malloc(coap_response->options_list_ptr->location_path_len); + if (coap_response->options_list_ptr->location_path_ptr) { + memcpy(coap_response->options_list_ptr->location_path_ptr, + obj_name.c_str(), + coap_response->options_list_ptr->location_path_len); + } + } + } + msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + break; + case M2MTLVDeserializer::NotAllowed: + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + break; + case M2MTLVDeserializer::NotValid: + msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; + break; + case M2MTLVDeserializer::NotFound: + msg_code = COAP_MSG_CODE_RESPONSE_NOT_FOUND; + break; + } + } + } else { + tr_debug("M2MObject::handle_post_request() - COAP_MSG_CODE_RESPONSE_BAD_REQUEST"); + msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; + } + delete deserializer; + } + } else { + msg_code =COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; + } // if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type) + } else { + tr_error("M2MObject::handle_post_request - COAP_MSG_CODE_RESPONSE_BAD_REQUEST - Missing Payload"); + msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // + } + } else { // if ((object->operation() & SN_GRS_POST_ALLOWED) != 0) + tr_error("M2MObject::handle_post_request - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED"); + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; // 4.05 + } + } else { //if(received_coap_header) + tr_error("M2MObject::handle_post_request - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED"); + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; // 4.05 + } + + if(coap_response) { + coap_response->msg_code = msg_code; + } + return coap_response; +} + +void M2MObject::notification_update(uint16_t obj_instance_id) +{ + tr_debug("M2MObject::notification_update - id: %d", obj_instance_id); + M2MReportHandler *report_handler = M2MBase::report_handler(); + if(report_handler && is_under_observation()) { + report_handler->set_notification_trigger(obj_instance_id); + } +} + diff --git a/features/FEATURE_CLIENT/mbed-client/source/m2mobjectinstance.cpp b/features/FEATURE_CLIENT/mbed-client/source/m2mobjectinstance.cpp new file mode 100644 index 0000000000..60f0288815 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/m2mobjectinstance.cpp @@ -0,0 +1,693 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client/m2mobjectinstance.h" +#include "mbed-client/m2mobject.h" +#include "mbed-client/m2mconstants.h" +#include "mbed-client/m2mresource.h" +#include "mbed-client/m2mresource.h" +#include "mbed-client/m2mobservationhandler.h" +#include "mbed-client/m2mstring.h" +#include "include/m2mtlvserializer.h" +#include "include/m2mtlvdeserializer.h" +#include "include/nsdllinker.h" +#include "include/m2mreporthandler.h" +#include "mbed-trace/mbed_trace.h" + +#define BUFFER_SIZE 10 +#define TRACE_GROUP "mClt" + +M2MObjectInstance& M2MObjectInstance::operator=(const M2MObjectInstance& other) +{ + if (this != &other) { // protect against invalid self-assignment + if(!other._resource_list.empty()){ + M2MResource* ins = NULL; + M2MResourceList::const_iterator it; + it = other._resource_list.begin(); + for (; it!=other._resource_list.end(); it++ ) { + ins = *it; + _resource_list.push_back(new M2MResource(*ins)); + } + } + } + return *this; +} + +M2MObjectInstance::M2MObjectInstance(const M2MObjectInstance& other) +: M2MBase(other), + _object_callback(other._object_callback) +{ + this->operator=(other); +} + +M2MObjectInstance::M2MObjectInstance(const String &object_name, + M2MObjectCallback &object_callback) +: M2MBase(object_name,M2MBase::Dynamic), + _object_callback(object_callback) +{ + M2MBase::set_base_type(M2MBase::ObjectInstance); + M2MBase::set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE); +} + +M2MObjectInstance::~M2MObjectInstance() +{ + if(!_resource_list.empty()) { + M2MResource* res = NULL; + M2MResourceList::const_iterator it; + it = _resource_list.begin(); + for (; it!=_resource_list.end(); it++ ) { + //Free allocated memory for resources. + res = *it; + String obj_name = name(); + obj_name.push_back('/'); + obj_name.append_int(instance_id()); + obj_name.push_back('/'); + obj_name += (*it)->name(); + (*it)->remove_resource_from_coap(obj_name); + delete res; + } + _resource_list.clear(); + } +} + +M2MResource* M2MObjectInstance::create_static_resource(const String &resource_name, + const String &resource_type, + M2MResourceInstance::ResourceType type, + const uint8_t *value, + const uint8_t value_length, + bool multiple_instance) +{ + tr_debug("M2MObjectInstance::create_static_resource(resource_name %s)",resource_name.c_str()); + M2MResource *res = NULL; + if( resource_name.empty() || resource_name.size() > MAX_ALLOWED_STRING_LENGTH){ + return res; + } + if(!resource(resource_name)) { + res = new M2MResource(*this,resource_name, resource_type, type, + value, value_length, M2MBase::instance_id(), + M2MBase::name(), multiple_instance); + if(res) { + res->add_observation_level(observation_level()); + if (multiple_instance) { + res->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE); + } + _resource_list.push_back(res); + } + } + return res; +} + +M2MResource* M2MObjectInstance::create_dynamic_resource(const String &resource_name, + const String &resource_type, + M2MResourceInstance::ResourceType type, + bool observable, + bool multiple_instance) +{ + tr_debug("M2MObjectInstance::create_dynamic_resource(resource_name %s)",resource_name.c_str()); + M2MResource *res = NULL; + if( resource_name.empty() || resource_name.size() > MAX_ALLOWED_STRING_LENGTH){ + return res; + } + if(!resource(resource_name)) { + res = new M2MResource(*this,resource_name, resource_type, type, + observable, M2MBase::instance_id(), + M2MBase::name(), multiple_instance); + if(res) { + if (multiple_instance) { + res->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE); + } + res->add_observation_level(observation_level()); + _resource_list.push_back(res); + } + } + return res; +} + +M2MResourceInstance* M2MObjectInstance::create_static_resource_instance(const String &resource_name, + const String &resource_type, + M2MResourceInstance::ResourceType type, + const uint8_t *value, + const uint8_t value_length, + uint16_t instance_id) +{ + tr_debug("M2MObjectInstance::create_static_resource_instance(resource_name %s)",resource_name.c_str()); + M2MResourceInstance *instance = NULL; + if(resource_name.empty() || resource_name.size() > MAX_ALLOWED_STRING_LENGTH){ + return instance; + } + M2MResource *res = resource(resource_name); + if(!res) { + res = new M2MResource(*this,resource_name, resource_type, type, + value, value_length, M2MBase::instance_id(), + M2MBase::name(), true); + _resource_list.push_back(res); + res->set_operation(M2MBase::GET_ALLOWED); + res->set_observable(false); + res->set_register_uri(false); + } + if(res->supports_multiple_instances()&& (res->resource_instance(instance_id) == NULL)) { + instance = new M2MResourceInstance(resource_name, resource_type, type, + value, value_length, *this, + M2MBase::instance_id(), M2MBase::name()); + if(instance) { + instance->set_operation(M2MBase::GET_ALLOWED); + instance->set_instance_id(instance_id); + res->add_resource_instance(instance); + } + } + return instance; +} + +M2MResourceInstance* M2MObjectInstance::create_dynamic_resource_instance(const String &resource_name, + const String &resource_type, + M2MResourceInstance::ResourceType type, + bool observable, + uint16_t instance_id) +{ + tr_debug("M2MObjectInstance::create_dynamic_resource_instance(resource_name %s)",resource_name.c_str()); + M2MResourceInstance *instance = NULL; + if(resource_name.empty() || resource_name.size() > MAX_ALLOWED_STRING_LENGTH){ + return instance; + } + M2MResource *res = resource(resource_name); + if(!res) { + res = new M2MResource(*this,resource_name, resource_type, type, + false, M2MBase::instance_id(), M2MBase::name(), true); + _resource_list.push_back(res); + res->set_register_uri(false); + res->set_operation(M2MBase::GET_ALLOWED); + } + if(res->supports_multiple_instances() && (res->resource_instance(instance_id) == NULL)) { + instance = new M2MResourceInstance(resource_name, resource_type, type, *this, + M2MBase::instance_id(), M2MBase::name()); + if(instance) { + instance->set_operation(M2MBase::GET_ALLOWED); + instance->set_observable(observable); + instance->set_instance_id(instance_id); + res->add_resource_instance(instance); + } + } + return instance; +} + +bool M2MObjectInstance::remove_resource(const String &resource_name) +{ + tr_debug("M2MObjectInstance::remove_resource(resource_name %s)", + resource_name.c_str()); + bool success = false; + if(!_resource_list.empty()) { + M2MResource* res = NULL; + M2MResourceList::const_iterator it; + it = _resource_list.begin(); + int pos = 0; + for ( ; it != _resource_list.end(); it++, pos++ ) { + if(((*it)->name() == resource_name)) { + // Resource found and deleted. + res = *it; + + String obj_name = name(); + obj_name.push_back('/'); + obj_name.append_int(instance_id()); + obj_name.push_back('/'); + obj_name += res->name(); + res->remove_resource_from_coap(obj_name); + delete res; + res = NULL; + _resource_list.erase(pos); + success = true; + break; + } + } + } + return success; +} + +bool M2MObjectInstance::remove_resource_instance(const String &resource_name, + uint16_t inst_id) +{ + tr_debug("M2MObjectInstance::remove_resource_instance(resource_name %s inst_id %d)", + resource_name.c_str(), inst_id); + bool success = false; + M2MResource *res = resource(resource_name); + if(res) { + M2MResourceInstanceList list = res->resource_instances(); + M2MResourceInstanceList::const_iterator it; + it = list.begin(); + for ( ; it != list.end(); it++) { + if((*it)->instance_id() == inst_id) { + String obj_name = name(); + obj_name.push_back('/'); + obj_name.append_int(instance_id()); + obj_name.push_back('/'); + obj_name += resource_name; + obj_name.push_back('/'); + obj_name.append_int(inst_id); + remove_resource_from_coap(obj_name); + success = res->remove_resource_instance(inst_id); + if(res->resource_instance_count() == 0) { + M2MResourceList::const_iterator itr; + itr = _resource_list.begin(); + int pos = 0; + for ( ; itr != _resource_list.end(); itr++, pos++ ) { + if(((*itr)->name() == resource_name)) { + delete res; + res = NULL; + _resource_list.erase(pos); + break; + } + } + } + break; + } + } + } + return success; +} + +M2MResource* M2MObjectInstance::resource(const String &resource) const +{ + M2MResource *res = NULL; + if(!_resource_list.empty()) { + M2MResourceList::const_iterator it; + it = _resource_list.begin(); + for (; it!=_resource_list.end(); it++ ) { + if((*it)->name() == resource) { + res = *it; + break; + } + } + } + return res; +} + +const M2MResourceList& M2MObjectInstance::resources() const +{ + return _resource_list; +} + +uint16_t M2MObjectInstance::resource_count() const +{ + uint16_t count = 0; + if(!_resource_list.empty()) { + M2MResourceList::const_iterator it; + it = _resource_list.begin(); + for ( ; it != _resource_list.end(); it++ ) { + if((*it)->supports_multiple_instances()) { + count += (*it)->resource_instance_count(); + } else { + count++; + } + } + } + return count; +} + +uint16_t M2MObjectInstance::resource_count(const String& resource) const +{ + uint16_t count = 0; + if(!_resource_list.empty()) { + M2MResourceList::const_iterator it; + it = _resource_list.begin(); + for ( ; it != _resource_list.end(); it++ ) { + if((*it)->name() == resource) { + if((*it)->supports_multiple_instances()) { + count += (*it)->resource_instance_count(); + } else { + count++; + } + } + } + } + return count; +} + +M2MBase::BaseType M2MObjectInstance::base_type() const +{ + return M2MBase::base_type(); +} + +void M2MObjectInstance::add_observation_level(M2MBase::Observation observation_level) +{ + M2MBase::add_observation_level(observation_level); + if(!_resource_list.empty()) { + M2MResourceList::const_iterator it; + it = _resource_list.begin(); + for ( ; it != _resource_list.end(); it++ ) { + (*it)->add_observation_level(observation_level); + } + } +} + +void M2MObjectInstance::remove_observation_level(M2MBase::Observation observation_level) +{ + M2MBase::remove_observation_level(observation_level); + if(!_resource_list.empty()) { + M2MResourceList::const_iterator it; + it = _resource_list.begin(); + for ( ; it != _resource_list.end(); it++ ) { + (*it)->remove_observation_level(observation_level); + } + } +} + +sn_coap_hdr_s* M2MObjectInstance::handle_get_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler) +{ + tr_debug("M2MObjectInstance::handle_get_request()"); + sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CONTENT; + sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl, + received_coap_header, + msg_code); + uint8_t * data = NULL; + uint32_t data_length = 0; + if(received_coap_header) { + // process the GET if we have registered a callback for it + if ((operation() & SN_GRS_GET_ALLOWED) != 0) { + if(coap_response) { + uint16_t coap_content_type = 0; + bool content_type_present = false; + if(received_coap_header->content_type_ptr) { + content_type_present = true; + coap_response->content_type_ptr = alloc_copy(received_coap_header->content_type_ptr, + received_coap_header->content_type_len); + if(coap_response->content_type_ptr) { + coap_response->content_type_len = received_coap_header->content_type_len; + for(uint8_t i = 0; i < coap_response->content_type_len; i++) { + coap_content_type = (coap_content_type << 8) + + (coap_response->content_type_ptr[i] & 0xFF); + } + } + } + if(!content_type_present && + M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE) { + coap_content_type = COAP_CONTENT_OMA_TLV_TYPE; + } + + tr_debug("M2MObjectInstance::handle_get_request() - Request Content-Type %d", coap_content_type); + if (!coap_response->content_type_ptr) { + coap_response->content_type_ptr = + m2m::String::convert_integer_to_array(coap_content_type, + coap_response->content_type_len); + if (coap_response->content_type_ptr) { + set_coap_content_type(coap_content_type); + } + } + // fill in the CoAP response payload + if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type) { + M2MTLVSerializer serializer; + data = serializer.serialize(_resource_list, data_length); + } else { + msg_code = COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; // Content format not supported + } + + coap_response->payload_len = data_length; + coap_response->payload_ptr = data; + + if(data) { + coap_response->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(coap_response->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + + coap_response->options_list_ptr->max_age_ptr = + m2m::String::convert_integer_to_array(max_age(), + coap_response->options_list_ptr->max_age_len); + + if(received_coap_header->options_list_ptr) { + if(received_coap_header->options_list_ptr->observe) { + if (is_observable()) { + uint32_t number = 0; + uint8_t observe_option = 0; + if(received_coap_header->options_list_ptr->observe_ptr) { + observe_option = *received_coap_header->options_list_ptr->observe_ptr; + } + if(START_OBSERVATION == observe_option) { + tr_debug("M2MObjectInstance::handle_get_request - Starts Observation"); + // If the observe length is 0 means register for observation. + if(received_coap_header->options_list_ptr->observe_len != 0) { + for(int i=0;i < received_coap_header->options_list_ptr->observe_len; i++) { + number = (*(received_coap_header->options_list_ptr->observe_ptr + i) & 0xff) << + 8*(received_coap_header->options_list_ptr->observe_len- 1 - i); + } + } + if(received_coap_header->token_ptr) { + tr_debug("M2MObjectInstance::handle_get_request - Sets Observation Token to resource"); + set_observation_token(received_coap_header->token_ptr, + received_coap_header->token_len); + } + + // If the observe value is 0 means register for observation. + if(number == 0) { + tr_debug("M2MObjectInstance::handle_get_request - Put Resource under Observation"); + set_under_observation(true,observation_handler); + add_observation_level(M2MBase::OI_Attribute); + coap_response->options_list_ptr->observe_ptr = + m2m::String::convert_integer_to_array(observation_number(), + coap_response->options_list_ptr->observe_len); + } + } else if (STOP_OBSERVATION == observe_option) { + tr_debug("M2MObjectInstance::handle_get_request - Stops Observation"); + set_under_observation(false,NULL); + remove_observation_level(M2MBase::OI_Attribute); + + } + msg_code = COAP_MSG_CODE_RESPONSE_CONTENT; + } + else { + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + } + } + } else { + msg_code = COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; // Content format not supported + } + } + }else { + tr_error("M2MObjectInstance::handle_get_request - Return COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED"); + // Operation is not allowed. + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + } else { + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + if(coap_response) { + coap_response->msg_code = msg_code; + } + return coap_response; +} + +sn_coap_hdr_s* M2MObjectInstance::handle_put_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler, + bool &/*execute_value_updated*/) +{ + tr_debug("M2MObjectInstance::handle_put_request()"); + sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04 + sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl, + received_coap_header, + msg_code);; + if(received_coap_header) { + uint16_t coap_content_type = 0; + bool content_type_present = false; + if(received_coap_header->content_type_ptr) { + content_type_present = true; + if(coap_response) { + coap_response->content_type_ptr = alloc_copy(received_coap_header->content_type_ptr, + received_coap_header->content_type_len); + if(coap_response->content_type_ptr) { + coap_response->content_type_len = received_coap_header->content_type_len; + for(uint8_t i = 0; i < coap_response->content_type_len; i++) { + coap_content_type = (coap_content_type << 8) + + (coap_response->content_type_ptr[i] & 0xFF); + } + } + } + } + if(received_coap_header->options_list_ptr && + received_coap_header->options_list_ptr->uri_query_ptr) { + char *query = (char*)alloc_string_copy(received_coap_header->options_list_ptr->uri_query_ptr, + received_coap_header->options_list_ptr->uri_query_len); + if (query){ + tr_debug("M2MObjectInstance::handle_put_request() - Query %s", query); + // if anything was updated, re-initialize the stored notification attributes + if (!handle_observation_attribute(query)){ + tr_debug("M2MObjectInstance::handle_put_request() - Invalid query"); + msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // 4.00 + } else { + msg_code =COAP_MSG_CODE_RESPONSE_CHANGED; + } + free(query); + } + } else if ((operation() & SN_GRS_PUT_ALLOWED) != 0) { + if(!content_type_present && + M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE) { + coap_content_type = COAP_CONTENT_OMA_TLV_TYPE; + } + + tr_debug("M2MObjectInstance::handle_put_request() - Request Content-Type %d", coap_content_type); + + if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type) { + M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; + M2MTLVDeserializer *deserializer = new M2MTLVDeserializer(); + if(deserializer && received_coap_header->payload_ptr) { + error = deserializer->deserialize_resources(received_coap_header->payload_ptr, + received_coap_header->payload_len, + *this, + M2MTLVDeserializer::Put); + switch(error) { + case M2MTLVDeserializer::None: + if(observation_handler) { + observation_handler->value_updated(this); + } + msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; + break; + case M2MTLVDeserializer::NotFound: + msg_code = COAP_MSG_CODE_RESPONSE_NOT_FOUND; + break; + case M2MTLVDeserializer::NotAllowed: + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + break; + case M2MTLVDeserializer::NotValid: + msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; + break; + } + } + delete deserializer; + } else { + msg_code =COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; + } // if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type) + } else { + // Operation is not allowed. + tr_error("M2MObjectInstance::handle_put_request() - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED"); + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + } else { + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + if(coap_response) { + coap_response->msg_code = msg_code; + } + return coap_response; +} + +sn_coap_hdr_s* M2MObjectInstance::handle_post_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler, + bool &execute_value_updated) +{ + tr_debug("M2MObjectInstance::handle_post_request()"); + sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04 + sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl, + received_coap_header, + msg_code); + if(received_coap_header) { + if ((operation() & SN_GRS_POST_ALLOWED) != 0) { + uint16_t coap_content_type = 0; + bool content_type_present = false; + if(received_coap_header->content_type_ptr) { + content_type_present = true; + if(coap_response) { + coap_response->content_type_ptr = alloc_copy(received_coap_header->content_type_ptr, + received_coap_header->content_type_len); + if(coap_response->content_type_ptr) { + coap_response->content_type_len = received_coap_header->content_type_len; + for(uint8_t i = 0; i < coap_response->content_type_len; i++) { + coap_content_type = (coap_content_type << 8) + + (coap_response->content_type_ptr[i] & 0xFF); + } + } + } + } + if(!content_type_present && + M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE) { + coap_content_type = COAP_CONTENT_OMA_TLV_TYPE; + } + + tr_debug("M2MObjectInstance::handle_post_request() - Request Content-Type %d", coap_content_type); + + if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type) { + M2MTLVDeserializer *deserializer = new M2MTLVDeserializer(); + if(deserializer) { + String obj_name = ""; + M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; + error = deserializer->deserialize_resources(received_coap_header->payload_ptr, + received_coap_header->payload_len, + *this, + M2MTLVDeserializer::Post); + + uint16_t instance_id = deserializer->instance_id(received_coap_header->payload_ptr); + switch(error) { + case M2MTLVDeserializer::None: + if(observation_handler) { + execute_value_updated = true; + } + coap_response->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + if (coap_response->options_list_ptr) { + memset(coap_response->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + + obj_name += M2MBase::name(); + obj_name += "/"; + obj_name.append_int(M2MBase::instance_id()); + obj_name += "/"; + obj_name.append_int(instance_id); + + coap_response->options_list_ptr->location_path_len = obj_name.length(); + if (coap_response->options_list_ptr->location_path_len != 0) { + coap_response->options_list_ptr->location_path_ptr = + alloc_string_copy((uint8_t*)obj_name.c_str(), + coap_response->options_list_ptr->location_path_len); + } + } + msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + break; + case M2MTLVDeserializer::NotAllowed: + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + break; + case M2MTLVDeserializer::NotValid: + msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; + break; + default: + break; + } + delete deserializer; + } + } else { + msg_code =COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; + } // if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type) + } else { + // Operation is not allowed. + tr_error("M2MObjectInstance::handle_post_request() - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED"); + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + } else { + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + if(coap_response) { + coap_response->msg_code = msg_code; + } + return coap_response; +} + +void M2MObjectInstance::notification_update(M2MBase::Observation observation_level) +{ + tr_debug("M2MObjectInstance::notification_update() - level(%d)", observation_level); + if(M2MBase::O_Attribute == observation_level) { + _object_callback.notification_update(instance_id()); + } else { + M2MReportHandler *report_handler = M2MBase::report_handler(); + if(report_handler && is_under_observation()) { + report_handler->set_notification_trigger(); + } + } +} diff --git a/features/FEATURE_CLIENT/mbed-client/source/m2mreporthandler.cpp b/features/FEATURE_CLIENT/mbed-client/source/m2mreporthandler.cpp new file mode 100644 index 0000000000..08eb60d8c5 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/m2mreporthandler.cpp @@ -0,0 +1,487 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client/m2mreportobserver.h" +#include "mbed-client/m2mconstants.h" +#include "mbed-client/m2mtimer.h" +#include "include/m2mreporthandler.h" +#include "mbed-trace/mbed_trace.h" +#include +#include + +#define TRACE_GROUP "mClt" + +M2MReportHandler::M2MReportHandler(M2MReportObserver &observer) +: _observer(observer), + _pmax(-1.0f), + _pmin(1.0f), + _gt(0.0f), + _lt(0.0f), + _st(0.0f), + _pmin_exceeded(false), + _pmax_exceeded(false), + _pmin_timer(NULL), + _pmax_timer(NULL), + _high_step(0.0f), + _low_step(0.0f), + _current_value(0.0f), + _last_value(-1.0f), + _attribute_state(0), + _notify(false) +{ + tr_debug("M2MReportHandler::M2MReportHandler()"); +} + +M2MReportHandler::~M2MReportHandler() +{ + tr_debug("M2MReportHandler::~M2MReportHandler()"); + + delete _pmax_timer; + delete _pmin_timer; +} + +void M2MReportHandler::set_under_observation(bool observed) +{ + tr_debug("M2MReportHandler::set_under_observation(observed %d)", (int)observed); + stop_timers(); + if(observed) { + handle_timers(); + } + else { + set_default_values(); + } +} + +void M2MReportHandler::set_value(float value) +{ + tr_debug("M2MReportHandler::set_value() - current %f, last %f", value, _last_value); + _current_value = value; + if(_current_value != _last_value) { + tr_debug("M2MReportHandler::set_value() - UNDER OBSERVATION"); + if (check_threshold_values()) { + schedule_report(); + } + else { + tr_debug("M2MReportHandler::set_value - value not in range"); + _notify = false; + _last_value = _current_value; + if ((_attribute_state & M2MReportHandler::Lt) == M2MReportHandler::Lt || + (_attribute_state & M2MReportHandler::Gt) == M2MReportHandler::Gt || + (_attribute_state & M2MReportHandler::St) == M2MReportHandler::St) { + tr_debug("M2MReportHandler::set_value - stop pmin timer"); + if (_pmin_timer) { + _pmin_timer->stop_timer(); + _pmin_exceeded = true; + } + } + } + _high_step = _current_value + _st; + _low_step = _current_value - _st; + } +} + +void M2MReportHandler::set_notification_trigger(uint16_t obj_instance_id) +{ + tr_debug("M2MReportHandler::set_notification_trigger(): %d", obj_instance_id); + // Add to array if not there yet + m2m::Vector::const_iterator it; + it = _changed_instance_ids.begin(); + bool found = false; + for ( ; it != _changed_instance_ids.end(); it++) { + if ((*it) == obj_instance_id) { + found = true; + break; + } + } + if (!found) { + _changed_instance_ids.push_back(obj_instance_id); + } + + _current_value = 0.0f; + _last_value = 1.0f; + schedule_report(); +} + +bool M2MReportHandler::parse_notification_attribute(char *&query, + M2MBase::BaseType type, + M2MResourceInstance::ResourceType resource_type) +{ + tr_debug("M2MReportHandler::parse_notification_attribute(Query %s, Base type %d)", query, (int)type); + bool success = false; + char* sep_pos = strchr(query, '&'); + char* rest = query; + if( sep_pos != NULL ){ + char query_options[5][20]; + float pmin = _pmin; + float pmax = _pmax; + float lt = _lt; + float gt = _gt; + float st = _st; + float high = _high_step; + float low = _low_step; + uint8_t attr = _attribute_state; + + memset(query_options, 0, sizeof(query_options[0][0]) * 5 * 20); + uint8_t num_options = 0; + while( sep_pos != NULL && num_options < 5){ + size_t len = (size_t)(sep_pos-rest); + if( len > 19 ){ + len = 19; + } + memcpy(query_options[num_options], rest, len); + sep_pos++; + rest = sep_pos; + sep_pos = strchr(rest, '&'); + num_options++; + } + if( num_options < 5 && strlen(rest) > 0){ + size_t len = (size_t)strlen(rest); + if( len > 19 ){ + len = 19; + } + memcpy(query_options[num_options++], rest, len); + } + + for (int option = 0; option < num_options; option++) { + success = set_notification_attribute(query_options[option],type, resource_type); + if (!success) { + tr_debug("M2MReportHandler::parse_notification_attribute - break"); + break; + } + } + + if(success) { + success = check_attribute_validity(); + } + else { + tr_debug("M2MReportHandler::parse_notification_attribute - not valid query"); + _pmin = pmin; + _pmax = pmax; + _st = st; + _lt = lt; + _gt = gt; + _high_step = high; + _low_step = low; + _attribute_state = attr; + } + } + else { + if(set_notification_attribute(query, type, resource_type)) { + success = check_attribute_validity(); + } + } + + return success; +} + +void M2MReportHandler::timer_expired(M2MTimerObserver::Type type) +{ + switch(type) { + case M2MTimerObserver::PMinTimer: { + tr_debug("M2MReportHandler::timer_expired - PMIN"); + if (_notify || + (_pmin > 0 && + (_attribute_state & M2MReportHandler::Pmax) != M2MReportHandler::Pmax)){ + report(); + } + else{ + _pmin_exceeded = true; + } + } + break; + case M2MTimerObserver::PMaxTimer: { + tr_debug("M2MReportHandler::timer_expired - PMAX"); + _pmax_exceeded = true; + if (_pmin_exceeded || + (_attribute_state & M2MReportHandler::Pmin) != M2MReportHandler::Pmin ) { + report(); + } + } + break; + default: + break; + } +} + +bool M2MReportHandler::set_notification_attribute(char* option, + M2MBase::BaseType type, + M2MResourceInstance::ResourceType resource_type) +{ + tr_debug("M2MReportHandler::set_notification_attribute()"); + bool success = false; + char attribute[20]; + char value[20]; + memset(&attribute, 0, 20); + memset(&value, 0, 20); + + char* pos = strstr(option, EQUAL); + if( pos != NULL ){ + memcpy(attribute, option, (size_t)(pos-option)); + pos++; + memcpy(value, pos, strlen(pos)); + }else{ + memcpy(attribute, option, (size_t)strlen(option) + 1); + } + + if (strlen(value)) { + if (strcmp(attribute, PMIN) == 0) { + _pmin = atoi(value); + success = true; + _attribute_state |= M2MReportHandler::Pmin; + tr_debug("M2MReportHandler::set_notification_attribute %s to %d", attribute, _pmin); + } + else if(strcmp(attribute, PMAX) == 0) { + _pmax = atoi(value); + success = true; + _attribute_state |= M2MReportHandler::Pmax; + tr_debug("M2MReportHandler::set_notification_attribute %s to %d", attribute, _pmax); + } + else if(strcmp(attribute, GT) == 0 && + (M2MBase::Resource == type)){ + _gt = atof(value); + success = true; + _attribute_state |= M2MReportHandler::Gt; + tr_debug("M2MReportHandler::set_notification_attribute %s to %f", attribute, _gt); + } + else if(strcmp(attribute, LT) == 0 && + (M2MBase::Resource == type)){ + _lt = atof(value); + success = true; + _attribute_state |= M2MReportHandler::Lt; + tr_debug("M2MReportHandler::set_notification_attribute %s to %f", attribute, _lt); + } + else if((strcmp(attribute, ST_SIZE) == 0 || (strcmp(attribute, STP) == 0)) + && (M2MBase::Resource == type)){ + _st = atof(value); + success = true; + _high_step = _current_value + _st; + _low_step = _current_value - _st; + _attribute_state |= M2MReportHandler::St; + tr_debug("M2MReportHandler::set_notification_attribute %s to %f", attribute, _st); + } + // Return false if try to set gt,lt or st when the resource type is something else than numerical + if ((resource_type != M2MResourceInstance::INTEGER && + resource_type != M2MResourceInstance::FLOAT) && + ((_attribute_state & M2MReportHandler::Gt) == M2MReportHandler::Gt || + (_attribute_state & M2MReportHandler::Lt) == M2MReportHandler::Lt || + (_attribute_state & M2MReportHandler::St) == M2MReportHandler::St)) { + tr_debug("M2MReportHandler::set_notification_attribute - not numerical resource"); + success = false; + } + } + return success; +} + +void M2MReportHandler::schedule_report() +{ + tr_debug("M2MReportHandler::schedule_report()"); + _notify = true; + if ((_attribute_state & M2MReportHandler::Pmin) != M2MReportHandler::Pmin || + _pmin_exceeded) { + report(); + } +} + +void M2MReportHandler::report() +{ + tr_debug("M2MReportHandler::report()"); + if(_current_value != _last_value && _notify) { + tr_debug("M2MReportHandler::report()- send with PMIN"); + _pmin_exceeded = false; + _pmax_exceeded = false; + _notify = false; + _observer.observation_to_be_sent(_changed_instance_ids); + _changed_instance_ids.clear(); + if (_pmax_timer) { + _pmax_timer->stop_timer(); + } + } + else { + if (_pmax_exceeded) { + tr_debug("M2MReportHandler::report()- send with PMAX"); + _observer.observation_to_be_sent(_changed_instance_ids, true); + _changed_instance_ids.clear(); + } + else { + tr_debug("M2MReportHandler::report()- no need to send"); + } + } + handle_timers(); + _last_value = _current_value; +} + +void M2MReportHandler::handle_timers() +{ + tr_debug("M2MReportHandler::handle_timers()"); + uint64_t time_interval = 0; + if ((_attribute_state & M2MReportHandler::Pmin) == M2MReportHandler::Pmin) { + if (_pmin == _pmax) { + _pmin_exceeded = true; + } else { + _pmin_exceeded = false; + time_interval = (uint64_t)(_pmin * 1000); + tr_debug("M2MReportHandler::handle_timers() - Start PMIN interval: %d", (int)time_interval); + if (!_pmin_timer) { + _pmin_timer = new M2MTimer(*this); + } + _pmin_timer->start_timer(time_interval, + M2MTimerObserver::PMinTimer, + true); + } + } + if ((_attribute_state & M2MReportHandler::Pmax) == M2MReportHandler::Pmax) { + if (_pmax > 0) { + if (!_pmax_timer) { + _pmax_timer = new M2MTimer(*this); + } + time_interval = (uint64_t)(_pmax * 1000); + tr_debug("M2MReportHandler::handle_timers() - Start PMAX interval: %d", (int)time_interval); + _pmax_timer->start_timer(time_interval, + M2MTimerObserver::PMaxTimer, + true); + } + } +} + +bool M2MReportHandler::check_attribute_validity() +{ + bool success = true; + if ((_attribute_state & M2MReportHandler::Pmax) == M2MReportHandler::Pmax && + ((_pmax >= -1.0f) && (_pmin > _pmax))) { + success = false; + } + float low = _lt + 2 * _st; + if ((_attribute_state & M2MReportHandler::Gt) == M2MReportHandler::Gt && + (low >= _gt)) { + success = false; + } + return success; +} + +void M2MReportHandler::stop_timers() +{ + tr_debug("M2MReportHandler::stop_timers()"); + if (_pmin_timer) { + _pmin_exceeded = false; + _pmin_timer->stop_timer(); + + delete _pmin_timer; + _pmin_timer = NULL; + } + if (_pmax_timer) { + _pmax_exceeded = false; + _pmax_timer->stop_timer(); + delete _pmax_timer; + _pmax_timer = NULL; + } + tr_debug("M2MReportHandler::stop_timers() - out"); +} + +void M2MReportHandler::set_default_values() +{ + tr_debug("M2MReportHandler::set_default_values"); + _pmax = -1.0f; + _pmin = 1.0f; + _gt = 0.0f; + _lt = 0.0f; + _st = 0.0f; + _high_step = 0.0f; + _low_step = 0.0f; + _pmin_exceeded = false; + _pmax_exceeded = false; + _last_value = -1.0f; + _attribute_state = 0; + _changed_instance_ids.clear(); +} + +bool M2MReportHandler::check_threshold_values() +{ + tr_debug("M2MReportHandler::check_threshold_values"); + tr_debug("Current value: %f", _current_value); + tr_debug("High step: %f", _high_step); + tr_debug("Low step: %f", _low_step); + tr_debug("Less than: %f", _lt); + tr_debug("Greater than: %f", _gt); + tr_debug("Step: %f", _st); + bool can_send = false; + // Check step condition + if ((_attribute_state & M2MReportHandler::St) == M2MReportHandler::St) { + if ((_current_value >= _high_step || + _current_value <= _low_step)) { + can_send = true; + } + else { + if ((_attribute_state & M2MReportHandler::Lt) == M2MReportHandler::Lt || + (_attribute_state & M2MReportHandler::Gt) == M2MReportHandler::Gt ) { + can_send = check_gt_lt_params(); + } + else { + can_send = false; + } + } + } + else { + can_send = check_gt_lt_params(); + } + tr_debug("M2MReportHandler::check_threshold_values - value in range = %d", (int)can_send); + return can_send; +} + +bool M2MReportHandler::check_gt_lt_params() +{ + tr_debug("M2MReportHandler::check_gt_lt_params"); + bool can_send = false; + // GT & LT set. + if ((_attribute_state & (M2MReportHandler::Lt | M2MReportHandler::Gt)) + == (M2MReportHandler::Lt | M2MReportHandler::Gt)) { + if (_current_value > _gt || _current_value < _lt) { + can_send = true; + } + else { + can_send = false; + } + } + // Only LT + else if ((_attribute_state & M2MReportHandler::Lt) == M2MReportHandler::Lt && + (_attribute_state & M2MReportHandler::Gt) == 0 ) { + if (_current_value < _lt) { + can_send = true; + } + else { + can_send = false; + } + } + // Only GT + else if ((_attribute_state & M2MReportHandler::Gt) == M2MReportHandler::Gt && + (_attribute_state & M2MReportHandler::Lt) == 0 ) { + if (_current_value > _gt) { + can_send = true; + } + else { + can_send = false; + } + } + // GT & LT not set. + else { + can_send = true; + } + tr_debug("M2MReportHandler::check_gt_lt_params - value in range = %d", (int)can_send); + return can_send; +} + +uint8_t M2MReportHandler::attribute_flags() +{ + return _attribute_state; +} diff --git a/features/FEATURE_CLIENT/mbed-client/source/m2mresource.cpp b/features/FEATURE_CLIENT/mbed-client/source/m2mresource.cpp new file mode 100644 index 0000000000..a88afeb53c --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/m2mresource.cpp @@ -0,0 +1,633 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client/m2mconstants.h" +#include "mbed-client/m2mresource.h" +#include "mbed-client/m2mobservationhandler.h" +#include "include/m2mreporthandler.h" +#include "include/m2mtlvserializer.h" +#include "include/m2mtlvdeserializer.h" +#include "include/nsdllinker.h" +#include "mbed-trace/mbed_trace.h" + +#define TRACE_GROUP "mClt" + +M2MResource& M2MResource::operator=(const M2MResource& other) +{ + if (this != &other) { // protect against invalid self-assignment + _has_multiple_instances = other._has_multiple_instances; + if(!other._resource_instance_list.empty()){ + M2MResourceInstance* ins = NULL; + M2MResourceInstanceList::const_iterator it; + it = other._resource_instance_list.begin(); + for (; it!=other._resource_instance_list.end(); it++ ) { + ins = *it; + _resource_instance_list.push_back(new M2MResourceInstance(*ins)); + } + } + if(other._delayed_token) { + _delayed_token = (uint8_t*)alloc_copy(other._delayed_token,other._delayed_token_len); + if(_delayed_token) { + _delayed_token_len = other._delayed_token_len; + } + } + } + return *this; +} + +M2MResource::M2MResource(const M2MResource& other) +: M2MResourceInstance(other), + _delayed_token(NULL), + _delayed_token_len(0), + _delayed_response(false) +{ + this->operator=(other); +} + +M2MResource::M2MResource(M2MObjectInstanceCallback &object_instance_callback, + const String &resource_name, + const String &resource_type, + M2MResourceInstance::ResourceType type, + const uint8_t *value, + const uint8_t value_length, + const uint16_t object_instance_id, + const String &object_name, + bool multiple_instance) +: M2MResourceInstance(resource_name, resource_type, type, value, value_length, + object_instance_callback, object_instance_id, object_name), + _delayed_token(NULL), + _delayed_token_len(0), + _has_multiple_instances(multiple_instance), + _delayed_response(false) +{ + M2MBase::set_base_type(M2MBase::Resource); + M2MBase::set_operation(M2MBase::GET_ALLOWED); + M2MBase::set_observable(false); +} + +M2MResource::M2MResource(M2MObjectInstanceCallback &object_instance_callback, + const String &resource_name, + const String &resource_type, + M2MResourceInstance::ResourceType type, + bool observable, + const uint16_t object_instance_id, + const String &object_name, + bool multiple_instance) +: M2MResourceInstance(resource_name, resource_type, type, + object_instance_callback, object_instance_id, object_name), + _delayed_token(NULL), + _delayed_token_len(0), + _has_multiple_instances(multiple_instance), + _delayed_response(false) +{ + M2MBase::set_base_type(M2MBase::Resource); + M2MBase::set_operation(M2MBase::GET_PUT_ALLOWED); + M2MBase::set_observable(observable); +} + +M2MResource::~M2MResource() +{ + if(!_resource_instance_list.empty()) { + M2MResourceInstance* res = NULL; + M2MResourceInstanceList::const_iterator it; + it = _resource_instance_list.begin(); + for (; it!=_resource_instance_list.end(); it++ ) { + //Free allocated memory for resources. + res = *it; + delete res; + } + _resource_instance_list.clear(); + } + free(_delayed_token); +} + +bool M2MResource::supports_multiple_instances() const +{ + return _has_multiple_instances; +} + +void M2MResource::set_delayed_response(bool delayed_response) +{ + _delayed_response = delayed_response; +} + +bool M2MResource::send_delayed_post_response() +{ + bool success = false; + if(_delayed_response) { + success = true; + observation_handler()->send_delayed_response(this); + } + return success; +} + +void M2MResource::get_delayed_token(uint8_t *&token, uint8_t &token_length) +{ + token = _delayed_token; + token_length = _delayed_token_len; +} + +bool M2MResource::remove_resource_instance(uint16_t inst_id) +{ + tr_debug("M2MResource::remove_resource(inst_id %d)", inst_id); + bool success = false; + if(!_resource_instance_list.empty()) { + M2MResourceInstance* res = NULL; + M2MResourceInstanceList::const_iterator it; + it = _resource_instance_list.begin(); + int pos = 0; + for ( ; it != _resource_instance_list.end(); it++, pos++ ) { + if(((*it)->instance_id() == inst_id)) { + // Resource found and deleted. + res = *it; + delete res; + _resource_instance_list.erase(pos); + success = true; + break; + } + } + } + return success; +} + +M2MResourceInstance* M2MResource::resource_instance(uint16_t inst_id) const +{ + tr_debug("M2MResource::resource(resource_name inst_id %d)", inst_id); + M2MResourceInstance *res = NULL; + if(!_resource_instance_list.empty()) { + M2MResourceInstanceList::const_iterator it; + it = _resource_instance_list.begin(); + for ( ; it != _resource_instance_list.end(); it++ ) { + if(((*it)->instance_id() == inst_id)) { + // Resource found. + res = *it; + break; + } + } + } + return res; +} + +const M2MResourceInstanceList& M2MResource::resource_instances() const +{ + return _resource_instance_list; +} + +uint16_t M2MResource::resource_instance_count() const +{ + return (uint16_t)_resource_instance_list.size(); +} + +bool M2MResource::delayed_response() const +{ + return _delayed_response; +} + +bool M2MResource::handle_observation_attribute(char *&query) +{ + tr_debug("M2MResource::handle_observation_attribute - is_under_observation(%d)", is_under_observation()); + bool success = false; + M2MReportHandler *handler = M2MBase::report_handler(); + if (handler) { + success = handler->parse_notification_attribute(query, + M2MBase::base_type(), _resource_type); + if (success) { + if (is_under_observation()) { + handler->set_under_observation(true); + } + } + else { + handler->set_default_values(); + } + + if (success) { + if(!_resource_instance_list.empty()) { + M2MResourceInstanceList::const_iterator it; + it = _resource_instance_list.begin(); + for ( ; it != _resource_instance_list.end(); it++ ) { + M2MReportHandler *report_handler = (*it)->report_handler(); + if(report_handler && is_under_observation()) { + report_handler->set_notification_trigger(); + } + } + } + } + } + return success; +} + +void M2MResource::add_observation_level(M2MBase::Observation observation_level) +{ + M2MBase::add_observation_level(observation_level); + if(!_resource_instance_list.empty()) { + M2MResourceInstanceList::const_iterator inst; + inst = _resource_instance_list.begin(); + for ( ; inst != _resource_instance_list.end(); inst++ ) { + (*inst)->add_observation_level(observation_level); + } + } +} + +void M2MResource::remove_observation_level(M2MBase::Observation observation_level) +{ + M2MBase::remove_observation_level(observation_level); + if(!_resource_instance_list.empty()) { + M2MResourceInstanceList::const_iterator inst; + inst = _resource_instance_list.begin(); + for ( ; inst != _resource_instance_list.end(); inst++ ) { + (*inst)->remove_observation_level(observation_level); + } + } +} + +void M2MResource::add_resource_instance(M2MResourceInstance *res) +{ + tr_debug("M2MResource::add_resource_instance()"); + if(res) { + _resource_instance_list.push_back(res); + } +} + +sn_coap_hdr_s* M2MResource::handle_get_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler) +{ + tr_debug("M2MResource::handle_get_request()"); + sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CONTENT; + sn_coap_hdr_s * coap_response = NULL; + if(_has_multiple_instances) { + coap_response = sn_nsdl_build_response(nsdl, + received_coap_header, + msg_code); + if(received_coap_header) { + // process the GET if we have registered a callback for it + if ((operation() & SN_GRS_GET_ALLOWED) != 0) { + if(coap_response) { + uint16_t coap_content_type = 0; + bool content_type_present = false; + if(received_coap_header->content_type_ptr){ + content_type_present = true; + coap_response->content_type_ptr = alloc_copy(received_coap_header->content_type_ptr, + received_coap_header->content_type_len); + if(coap_response->content_type_ptr) { + coap_response->content_type_len = received_coap_header->content_type_len; + for(uint8_t i = 0; i < coap_response->content_type_len; i++) { + coap_content_type = (coap_content_type << 8) + + (coap_response->content_type_ptr[i] & 0xFF); + } + } + } + + if(!content_type_present && + M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE) { + coap_content_type = COAP_CONTENT_OMA_TLV_TYPE; + } + + tr_debug("M2MResource::handle_get_request() - Request Content-Type %d", coap_content_type); + if (!coap_response->content_type_ptr) { + coap_response->content_type_ptr = + m2m::String::convert_integer_to_array(coap_content_type, + coap_response->content_type_len); + if (coap_response->content_type_ptr) { + set_coap_content_type(coap_content_type); + } + } + uint8_t *data = NULL; + uint32_t data_length = 0; + // fill in the CoAP response payload + if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type) { + M2MTLVSerializer *serializer = new M2MTLVSerializer(); + if(serializer) { + data = serializer->serialize(this, data_length); + delete serializer; + } + } else { + msg_code = COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; // Content format not supported + } + + coap_response->payload_len = data_length; + coap_response->payload_ptr = data; + + coap_response->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(coap_response->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + + coap_response->options_list_ptr->max_age_ptr = + m2m::String::convert_integer_to_array(max_age(), + coap_response->options_list_ptr->max_age_len); + + if(received_coap_header->options_list_ptr) { + if(received_coap_header->options_list_ptr->observe) { + if (is_observable()) { + uint32_t number = 0; + uint8_t observe_option = 0; + if(received_coap_header->options_list_ptr->observe_ptr) { + observe_option = *received_coap_header->options_list_ptr->observe_ptr; + } + if(START_OBSERVATION == observe_option) { + tr_debug("M2MResource::handle_get_request - Starts Observation"); + // If the observe length is 0 means register for observation. + if(received_coap_header->options_list_ptr->observe_len != 0) { + for(int i=0;i < received_coap_header->options_list_ptr->observe_len; i++) { + number = (*(received_coap_header->options_list_ptr->observe_ptr + i) & 0xff) << + 8*(received_coap_header->options_list_ptr->observe_len- 1 - i); + } + } + if(received_coap_header->token_ptr) { + tr_debug("M2MResource::handle_get_request - Sets Observation Token to resource"); + set_observation_token(received_coap_header->token_ptr, + received_coap_header->token_len); + } + + // If the observe value is 0 means register for observation. + if(number == 0) { + tr_debug("M2MResource::handle_get_request - Put Resource under Observation"); + M2MResourceInstanceList::const_iterator it; + it = _resource_instance_list.begin(); + for (; it!=_resource_instance_list.end(); it++ ) { + tr_debug("M2MResource::handle_get_request - set_resource_observer"); + (*it)->set_resource_observer(this); + (*it)->add_observation_level(M2MBase::R_Attribute); + } + set_under_observation(true,observation_handler); + M2MBase::add_observation_level(M2MBase::R_Attribute); + coap_response->options_list_ptr->observe_ptr = + m2m::String::convert_integer_to_array(observation_number(), + coap_response->options_list_ptr->observe_len); + } + } else if (STOP_OBSERVATION == observe_option) { + tr_debug("M2MResource::handle_get_request - Stops Observation"); + set_under_observation(false,NULL); + M2MBase::remove_observation_level(M2MBase::R_Attribute); + M2MResourceInstanceList::const_iterator it; + it = _resource_instance_list.begin(); + for (; it!=_resource_instance_list.end(); it++ ) { + (*it)->set_resource_observer(NULL); + } + } + msg_code = COAP_MSG_CODE_RESPONSE_CONTENT; + } + else { + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + } + } + } + } else { + tr_error("M2MResource::handle_get_request - Return COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED"); + // Operation is not allowed. + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + } + if(coap_response) { + coap_response->msg_code = msg_code; + } + } else { + coap_response = M2MResourceInstance::handle_get_request(nsdl, + received_coap_header, + observation_handler); + } + return coap_response; +} + +sn_coap_hdr_s* M2MResource::handle_put_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler, + bool &execute_value_updated) +{ + tr_debug("M2MResource::handle_put_request()"); + sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04 + sn_coap_hdr_s * coap_response = NULL; + if(_has_multiple_instances) { + coap_response = sn_nsdl_build_response(nsdl, + received_coap_header, + msg_code); + // process the PUT if we have registered a callback for it + if(received_coap_header) { + uint16_t coap_content_type = 0; + bool content_type_present = false; + if(received_coap_header->content_type_ptr) { + if(coap_response) { + content_type_present = true; + coap_response->content_type_ptr = alloc_copy(received_coap_header->content_type_ptr, + received_coap_header->content_type_len); + if(coap_response->content_type_ptr) { + coap_response->content_type_len = received_coap_header->content_type_len; + for(uint8_t i = 0; i < coap_response->content_type_len; i++) { + coap_content_type = (coap_content_type << 8) + + (coap_response->content_type_ptr[i] & 0xFF); + } + } + } + } + if(received_coap_header->options_list_ptr && + received_coap_header->options_list_ptr->uri_query_ptr) { + char *query = (char*)alloc_string_copy(received_coap_header->options_list_ptr->uri_query_ptr, + received_coap_header->options_list_ptr->uri_query_len); + if (query){ + msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; + tr_debug("M2MResource::handle_put_request() - Query %s", query); + // if anything was updated, re-initialize the stored notification attributes + if (!handle_observation_attribute(query)){ + tr_debug("M2MResource::handle_put_request() - Invalid query"); + msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // 4.00 + } + free(query); + } + } else if ((operation() & SN_GRS_PUT_ALLOWED) != 0) { + if(!content_type_present && + M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE) { + coap_content_type = COAP_CONTENT_OMA_TLV_TYPE; + } + + tr_debug("M2MResource::handle_put_request() - Request Content-Type %d", coap_content_type); + + if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type) { + M2MTLVDeserializer *deserializer = new M2MTLVDeserializer(); + if(deserializer) { + M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; + error = deserializer->deserialize_resource_instances(received_coap_header->payload_ptr, + received_coap_header->payload_len, + *this, + M2MTLVDeserializer::Put); + switch(error) { + case M2MTLVDeserializer::None: + if(observation_handler) { + String value = ""; + if (received_coap_header->uri_path_ptr != NULL && + received_coap_header->uri_path_len > 0) { + + value.append_raw((char*)received_coap_header->uri_path_ptr,received_coap_header->uri_path_len); + } + execute_value_updated = true; + } + msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; + break; + case M2MTLVDeserializer::NotFound: + msg_code = COAP_MSG_CODE_RESPONSE_NOT_FOUND; + break; + case M2MTLVDeserializer::NotAllowed: + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + break; + case M2MTLVDeserializer::NotValid: + msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; + break; + } + delete deserializer; + } + } else { + msg_code =COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; + } // if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type) + } else { + // Operation is not allowed. + tr_error("M2MResource::handle_put_request() - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED"); + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + } else { + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + if(coap_response) { + coap_response->msg_code = msg_code; + } + } else { + coap_response = M2MResourceInstance::handle_put_request(nsdl, + received_coap_header, + observation_handler, + execute_value_updated); + } + return coap_response; +} + +sn_coap_hdr_s* M2MResource::handle_post_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler */*observation_handler*/, + bool &/*execute_value_updated*/) +{ + tr_debug("M2MResource::handle_post_request()"); + sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04 + sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl, + received_coap_header, + msg_code); + // process the POST if we have registered a callback for it + if(received_coap_header) { + if ((operation() & SN_GRS_POST_ALLOWED) != 0) { + M2MResource::M2MExecuteParameter *exec_params = new M2MResource::M2MExecuteParameter(); + if (exec_params) { + exec_params->_object_name = object_name(); + exec_params->_resource_name = name(); + exec_params->_object_instance_id = object_instance_id(); + } + uint16_t coap_content_type = 0; + if(received_coap_header->payload_ptr) { + if(received_coap_header->content_type_ptr) { + for(uint8_t i = 0; i < received_coap_header->content_type_len; i++) { + coap_content_type = (coap_content_type << 8) + (received_coap_header->content_type_ptr[i] & 0xFF); + } + } + if(coap_content_type == 0) { + if (exec_params){ + exec_params->_value = alloc_string_copy(received_coap_header->payload_ptr, + received_coap_header->payload_len); + if (exec_params->_value) { + exec_params->_value_length = received_coap_header->payload_len; + } + } + } else { + msg_code = COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; + } + } + if(COAP_MSG_CODE_RESPONSE_CHANGED == msg_code) { + tr_debug("M2MResource::handle_post_request - Execute resource function"); + execute(exec_params); + if(_delayed_response) { + coap_response->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; + coap_response->msg_code = COAP_MSG_CODE_EMPTY; + coap_response->msg_id = received_coap_header->msg_id; + if(received_coap_header->token_len) { + free(_delayed_token); + _delayed_token_len = 0; + + _delayed_token = alloc_copy(received_coap_header->token_ptr, received_coap_header->token_len); + if(_delayed_token) { + _delayed_token_len = received_coap_header->token_len; + } + } + } else { + uint32_t length = 0; + get_value(coap_response->payload_ptr, length); + coap_response->payload_len = length; + } + } + delete exec_params; + } else { // if ((object->operation() & SN_GRS_POST_ALLOWED) != 0) + tr_error("M2MResource::handle_post_request - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED"); + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; // 4.05 + } + } else { //if(object && received_coap_header) + tr_error("M2MResource::handle_post_request - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED"); + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; // 4.01 + } + if(coap_response) { + coap_response->msg_code = msg_code; + } + return coap_response; +} + +void M2MResource::notification_update() +{ + tr_debug("M2MResource::notification_update()"); + M2MReportHandler *report_handler = M2MBase::report_handler(); + if(report_handler && is_observable()) { + report_handler->set_notification_trigger(); + } +} + +M2MResource::M2MExecuteParameter::M2MExecuteParameter() +{ + _value = NULL; + _value_length = 0; + _object_name = ""; + _resource_name = ""; + _object_instance_id = 0; +} + +M2MResource::M2MExecuteParameter::~M2MExecuteParameter() +{ + free(_value); +} + +uint8_t *M2MResource::M2MExecuteParameter::get_argument_value() const +{ + return _value; +} + +uint16_t M2MResource::M2MExecuteParameter::get_argument_value_length() const +{ + return _value_length; +} + +const String& M2MResource::M2MExecuteParameter::get_argument_object_name() const +{ + return _object_name; +} + +const String& M2MResource::M2MExecuteParameter::get_argument_resource_name() const +{ + return _resource_name; +} + +uint16_t M2MResource::M2MExecuteParameter::get_argument_object_instance_id() const +{ + return _object_instance_id; +} diff --git a/features/FEATURE_CLIENT/mbed-client/source/m2mresourceinstance.cpp b/features/FEATURE_CLIENT/mbed-client/source/m2mresourceinstance.cpp new file mode 100644 index 0000000000..38108e546b --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/m2mresourceinstance.cpp @@ -0,0 +1,507 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client/m2mresource.h" +#include "mbed-client/m2mconstants.h" +#include "mbed-client/m2mobservationhandler.h" +#include "mbed-client/m2mobjectinstance.h" +#include "include/m2mreporthandler.h" +#include "include/nsdllinker.h" +#include "mbed-trace/mbed_trace.h" + +#define TRACE_GROUP "mClt" + +M2MResourceInstance& M2MResourceInstance::operator=(const M2MResourceInstance& other) +{ + if (this != &other) { // protect against invalid self-assignment + + free(_value); + _value = NULL; + + _value_length = other._value_length; + if(other._value) { + _value = (uint8_t *)alloc_string_copy(other._value, other._value_length); + } + } + return *this; +} + +M2MResourceInstance::M2MResourceInstance(const M2MResourceInstance& other) +: M2MBase(other), + _object_instance_callback(other._object_instance_callback), + _execute_callback(NULL), + _value(NULL), + _value_length(0), + _resource_callback(NULL), + _object_name(other._object_name), + _function_pointer(NULL), + _object_instance_id(other._object_instance_id), + _resource_type(M2MResourceInstance::STRING) +{ + this->operator=(other); +} + +M2MResourceInstance::M2MResourceInstance(const String &res_name, + const String &resource_type, + M2MResourceInstance::ResourceType type, + M2MObjectInstanceCallback &object_instance_callback, + const uint16_t object_instance_id, + const String &object_name) +: M2MBase(res_name, + M2MBase::Dynamic), + _object_instance_callback(object_instance_callback), + _execute_callback(NULL), + _value(NULL), + _value_length(0), + _resource_callback(NULL), + _object_name(object_name), + _function_pointer(NULL), + _object_instance_id(object_instance_id), + _resource_type(type) +{ + M2MBase::set_resource_type(resource_type); + M2MBase::set_base_type(M2MBase::ResourceInstance); +} + +M2MResourceInstance::M2MResourceInstance(const String &res_name, + const String &resource_type, + M2MResourceInstance::ResourceType type, + const uint8_t *value, + const uint8_t value_length, + M2MObjectInstanceCallback &object_instance_callback, + const uint16_t object_instance_id, + const String &object_name) +: M2MBase(res_name, + M2MBase::Static), + _object_instance_callback(object_instance_callback), + _execute_callback(NULL), + _value(NULL), + _value_length(0), + _resource_callback(NULL), + _object_name(object_name), + _function_pointer(NULL), + _object_instance_id(object_instance_id), + _resource_type(type) +{ + M2MBase::set_resource_type(resource_type); + M2MBase::set_base_type(M2MBase::Resource); + if( value != NULL && value_length > 0 ) { + _value = alloc_string_copy(value, value_length); + if(_value) { + _value_length = value_length; + } + } +} + +M2MResourceInstance::~M2MResourceInstance() +{ + free(_value); + delete _function_pointer; +} + +M2MBase::BaseType M2MResourceInstance::base_type() const +{ + return M2MBase::base_type(); +} + +M2MResourceInstance::ResourceType M2MResourceInstance::resource_instance_type() const +{ + return _resource_type; +} + +bool M2MResourceInstance::handle_observation_attribute(char *&query) +{ + tr_debug("M2MResourceInstance::handle_observation_attribute - is_under_observation(%d)", is_under_observation()); + bool success = false; + M2MReportHandler *handler = M2MBase::report_handler(); + if (handler) { + success = handler->parse_notification_attribute(query, + M2MBase::base_type(), _resource_type); + if(success) { + if (is_under_observation()) { + handler->set_under_observation(true); + } + } else { + handler->set_default_values(); + } + } + return success; +} + +void M2MResourceInstance::set_execute_function(execute_callback callback) +{ + _execute_callback = callback; +} + +void M2MResourceInstance::set_execute_function(execute_callback_2 callback) +{ + delete _function_pointer; + + _function_pointer = new FP1(callback); + set_execute_function(execute_callback(_function_pointer, &FP1::call)); +} + +void M2MResourceInstance::clear_value() +{ + tr_debug("M2MResourceInstance::clear_value"); + + free(_value); + _value = NULL; + _value_length = 0; + + report(); +} + +bool M2MResourceInstance::set_value(int64_t value) +{ + bool success; + // max len of "-9223372036854775808" plus zero termination + char buffer[20+1]; + uint32_t size = m2m::itoa_c(value, buffer); + + success = set_value((const uint8_t*)buffer, size); + + return success; +} + +bool M2MResourceInstance::set_value(const uint8_t *value, + const uint32_t value_length) +{ + tr_debug("M2MResourceInstance::set_value()"); + bool success = false; + bool value_changed = false; + if(is_value_changed(value,value_length)) { + value_changed = true; + } + if( value != NULL && value_length > 0 ) { + success = true; + + free(_value); + _value_length = 0; + + _value = alloc_string_copy(value, value_length); + if(_value) { + _value_length = value_length; + if( value_changed ) { // + if (_resource_type == M2MResourceInstance::STRING) { + M2MReportHandler *report_handler = M2MBase::report_handler(); + if(report_handler && is_under_observation()) { + report_handler->set_notification_trigger(); + } + } + else { + report(); + } + } + } + } + return success; +} + +void M2MResourceInstance::report() +{ + tr_debug("M2MResourceInstance::report()"); + M2MBase::Observation observation_level = M2MBase::observation_level(); + if(M2MBase::R_Attribute != observation_level) { + tr_debug("M2MResourceInstance::report() -- object level"); + _object_instance_callback.notification_update(observation_level); + } + if(M2MBase::Dynamic == mode() && M2MBase::R_Attribute == observation_level) { + tr_debug("M2MResourceInstance::report() - resource level"); + if(!_resource_callback && _resource_type != M2MResourceInstance::STRING) { + M2MReportHandler *report_handler = M2MBase::report_handler(); + if (report_handler && is_observable()) { + if(_value) { + report_handler->set_value(atof((const char*)_value)); + } else { + report_handler->set_value(0); + } + } + } + else { + if (_resource_callback && base_type() == M2MBase::ResourceInstance) { + _resource_callback->notification_update(); + } + } + } else if(M2MBase::Static == mode()) { + M2MObservationHandler *observation_handler = M2MBase::observation_handler(); + if(observation_handler) { + observation_handler->value_updated(this); + } + } else { + tr_debug("M2MResourceInstance::report() - mode = %d, is_observable = %d", mode(), is_observable()); + } +} + +bool M2MResourceInstance::is_value_changed(const uint8_t* value, const uint32_t value_len) +{ + bool changed = false; + if(value_len != _value_length) { + changed = true; + } else if(value && !_value) { + changed = true; + } else if(_value && !value) { + changed = true; + } else { + if (_value) { + if (strcmp((char*)value, (char*)_value) != 0) { + changed = true; + } + } + } + tr_debug("M2MResourceInstance::is_value_changed() -- %s", changed ? "true" : "false"); + return changed; +} + +void M2MResourceInstance::execute(void *arguments) +{ + tr_debug("M2MResourceInstance::execute"); + if(_execute_callback) { + _execute_callback(arguments); + } +} + +void M2MResourceInstance::get_value(uint8_t *&value, uint32_t &value_length) +{ + value_length = 0; + if(value) { + free(value); + value = NULL; + } + if(_value && _value_length > 0) { + value = alloc_string_copy(_value, _value_length); + if(value) { + value_length = _value_length; + } + } +} + +int M2MResourceInstance::get_value_int() +{ + int value_int = 0; + // Get the value and convert it into integer. This is not the most + // efficient way, as it takes pointless heap copy to get the zero termination. + uint8_t* buffer = NULL; + uint32_t length; + get_value(buffer,length); + if(buffer) { + value_int = atoi((const char*)buffer); + free(buffer); + } + return value_int; +} + +String M2MResourceInstance::get_value_string() const +{ + // XXX: do a better constructor to avoid pointless malloc + String value; + if (_value) { + value.append_raw((char*)_value, _value_length); + } + + return value; +} + +uint8_t* M2MResourceInstance::value() const +{ + return _value; +} + +uint32_t M2MResourceInstance::value_length() const +{ + return _value_length; +} + +sn_coap_hdr_s* M2MResourceInstance::handle_get_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler) +{ + tr_debug("M2MResourceInstance::handle_get_request()"); + sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CONTENT; + sn_coap_hdr_s *coap_response = sn_nsdl_build_response(nsdl, + received_coap_header, + msg_code); + if(received_coap_header) { + // process the GET if we have registered a callback for it + if ((operation() & SN_GRS_GET_ALLOWED) != 0) { + if(coap_response) { + if(_resource_type == M2MResourceInstance::OPAQUE) { + coap_response->content_type_ptr = + m2m::String::convert_integer_to_array(COAP_CONTENT_OMA_OPAQUE_TYPE, + coap_response->content_type_len); + } else { + coap_response->content_type_ptr = + m2m::String::convert_integer_to_array(0, + coap_response->content_type_len); + } + + // fill in the CoAP response payload + coap_response->payload_ptr = NULL; + uint32_t payload_len = 0; + get_value(coap_response->payload_ptr,payload_len); + coap_response->payload_len = payload_len; + + coap_response->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(coap_response->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + + coap_response->options_list_ptr->max_age_ptr = + m2m::String::convert_integer_to_array(max_age(), + coap_response->options_list_ptr->max_age_len); + + if(received_coap_header->options_list_ptr) { + if(received_coap_header->options_list_ptr->observe) { + if (is_observable()) { + uint32_t number = 0; + uint8_t observe_option = 0; + if(received_coap_header->options_list_ptr->observe_ptr) { + observe_option = *received_coap_header->options_list_ptr->observe_ptr; + } + if(START_OBSERVATION == observe_option) { + tr_debug("M2MResourceInstance::handle_get_request - Starts Observation"); + // If the observe length is 0 means register for observation. + if(received_coap_header->options_list_ptr->observe_len != 0) { + for(int i=0;i < received_coap_header->options_list_ptr->observe_len; i++) { + number = (*(received_coap_header->options_list_ptr->observe_ptr + i) & 0xff) << + 8*(received_coap_header->options_list_ptr->observe_len- 1 - i); + } + } + if(received_coap_header->token_ptr) { + tr_debug("M2MResourceInstance::handle_get_request - Sets Observation Token to resource"); + set_observation_token(received_coap_header->token_ptr, + received_coap_header->token_len); + } + // If the observe value is 0 means register for observation. + if(number == 0) { + tr_debug("M2MResourceInstance::handle_get_request - Put Resource under Observation"); + set_under_observation(true,observation_handler); + M2MBase::add_observation_level(M2MBase::R_Attribute); + coap_response->options_list_ptr->observe_ptr = + m2m::String::convert_integer_to_array(observation_number(), + coap_response->options_list_ptr->observe_len); + } + } else if (STOP_OBSERVATION == observe_option) { + tr_debug("M2MResourceInstance::handle_get_request - Stops Observation"); + set_under_observation(false,NULL); + M2MBase::remove_observation_level(M2MBase::R_Attribute); + } + } else { + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + } + } + } + }else { + tr_error("M2MResourceInstance::handle_get_request - Return COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED"); + // Operation is not allowed. + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + } else { + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + if(coap_response) { + coap_response->msg_code = msg_code; + } + return coap_response; +} + +sn_coap_hdr_s* M2MResourceInstance::handle_put_request(nsdl_s *nsdl, + sn_coap_hdr_s *received_coap_header, + M2MObservationHandler *observation_handler, + bool &execute_value_updated) +{ + tr_debug("M2MResourceInstance::handle_put_request()"); + sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04 + sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl, + received_coap_header, + msg_code); + // process the PUT if we have registered a callback for it + if(received_coap_header) { + uint16_t coap_content_type = 0; + if(received_coap_header->content_type_ptr) { + if(coap_response) { + coap_response->content_type_ptr = alloc_copy(received_coap_header->content_type_ptr, + received_coap_header->content_type_len); + if(coap_response->content_type_ptr) { + coap_response->content_type_len = received_coap_header->content_type_len; + for(uint8_t i = 0; i < coap_response->content_type_len; i++) { + coap_content_type = (coap_content_type << 8) + + (coap_response->content_type_ptr[i] & 0xFF); + } + } + } + } + if(received_coap_header->options_list_ptr && + received_coap_header->options_list_ptr->uri_query_ptr) { + char *query = (char*)alloc_string_copy(received_coap_header->options_list_ptr->uri_query_ptr, + received_coap_header->options_list_ptr->uri_query_len); + if (query){ + tr_debug("M2MResourceInstance::handle_put_request() - Query %s", query); + + // if anything was updated, re-initialize the stored notification attributes + if (!handle_observation_attribute(query)){ + tr_debug("M2MResourceInstance::handle_put_request() - Invalid query"); + msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // 4.00 + } + free(query); + } + } else if ((operation() & SN_GRS_PUT_ALLOWED) != 0) { + tr_debug("M2MResourceInstance::handle_put_request() - Request Content-Type %d", coap_content_type); + + if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type) { + msg_code = COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; + } else { + set_value(received_coap_header->payload_ptr, received_coap_header->payload_len); + if(received_coap_header->payload_ptr) { + tr_debug("M2MResourceInstance::handle_put_request() - Update Resource with new values"); + if(observation_handler) { + String value = ""; + if (received_coap_header->uri_path_ptr != NULL && + received_coap_header->uri_path_len > 0) { + + value.append_raw((char*)received_coap_header->uri_path_ptr, received_coap_header->uri_path_len); + } + execute_value_updated = true; + } + } + } + } else { + // Operation is not allowed. + tr_error("M2MResourceInstance::handle_put_request() - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED"); + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + } else { + msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + } + if(coap_response) { + coap_response->msg_code = msg_code; + } + return coap_response; +} + +void M2MResourceInstance::set_resource_observer(M2MResourceCallback *resource) +{ + _resource_callback = resource; +} + +const String& M2MResourceInstance::object_name() const +{ + return _object_name; +} + +uint16_t M2MResourceInstance::object_instance_id() const +{ + return _object_instance_id; +} diff --git a/features/FEATURE_CLIENT/mbed-client/source/m2msecurity.cpp b/features/FEATURE_CLIENT/mbed-client/source/m2msecurity.cpp new file mode 100644 index 0000000000..1f53307286 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/m2msecurity.cpp @@ -0,0 +1,369 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client/m2msecurity.h" +#include "mbed-client/m2mconstants.h" +#include "mbed-client/m2mobject.h" +#include "mbed-client/m2mobjectinstance.h" +#include "mbed-client/m2mresource.h" +#include "mbed-client/m2mstring.h" +#include "mbed-trace/mbed_trace.h" +#define TRACE_GROUP "mClt" + +#define BUFFER_SIZE 21 + +M2MSecurity::M2MSecurity(ServerType ser_type) +: M2MObject(M2M_SECURITY_ID), + _server_instance(NULL), + _server_type(ser_type) +{ + _server_instance = M2MObject::create_object_instance(); + + if(_server_instance) { + M2MResource* res = _server_instance->create_dynamic_resource(SECURITY_M2M_SERVER_URI, + OMA_RESOURCE_TYPE, + M2MResourceInstance::STRING, + false); + if(res) { + res->set_operation(M2MBase::NOT_ALLOWED); + } + res = _server_instance->create_dynamic_resource(SECURITY_BOOTSTRAP_SERVER, + OMA_RESOURCE_TYPE, + M2MResourceInstance::BOOLEAN, + false); + if(res) { + res->set_operation(M2MBase::NOT_ALLOWED); + } + res = _server_instance->create_dynamic_resource(SECURITY_SECURITY_MODE, + OMA_RESOURCE_TYPE, + M2MResourceInstance::INTEGER, + false); + if(res) { + res->set_operation(M2MBase::NOT_ALLOWED); + } + res = _server_instance->create_dynamic_resource(SECURITY_PUBLIC_KEY, + OMA_RESOURCE_TYPE, + M2MResourceInstance::OPAQUE, + false); + if(res) { + res->set_operation(M2MBase::NOT_ALLOWED); + } + res = _server_instance->create_dynamic_resource(SECURITY_SERVER_PUBLIC_KEY, + OMA_RESOURCE_TYPE, + M2MResourceInstance::OPAQUE, + false); + if(res) { + res->set_operation(M2MBase::NOT_ALLOWED); + } + res = _server_instance->create_dynamic_resource(SECURITY_SECRET_KEY, + OMA_RESOURCE_TYPE, + M2MResourceInstance::OPAQUE, + false); + if(res) { + res->set_operation(M2MBase::NOT_ALLOWED); + } + if(M2MSecurity::M2MServer == ser_type) { + res = _server_instance->create_dynamic_resource(SECURITY_SHORT_SERVER_ID, + OMA_RESOURCE_TYPE, + M2MResourceInstance::INTEGER, + false); + if(res) { + res->set_operation(M2MBase::NOT_ALLOWED); + } + } + } +} + +M2MSecurity::~M2MSecurity() +{ +} + +M2MResource* M2MSecurity::create_resource(SecurityResource resource, uint32_t value) +{ + M2MResource* res = NULL; + const char* security_id_ptr = ""; + if(!is_resource_present(resource)) { + switch(resource) { + case SMSSecurityMode: + security_id_ptr = SECURITY_SMS_SECURITY_MODE; + break; + case M2MServerSMSNumber: + security_id_ptr = SECURITY_M2M_SERVER_SMS_NUMBER; + break; + case ShortServerID: + security_id_ptr = SECURITY_SHORT_SERVER_ID; + break; + case ClientHoldOffTime: + security_id_ptr = SECURITY_CLIENT_HOLD_OFF_TIME; + break; + default: + break; + } + } + + const String security_id(security_id_ptr); + + if(!security_id.empty()) { + if(_server_instance) { + res = _server_instance->create_dynamic_resource(security_id,OMA_RESOURCE_TYPE, + M2MResourceInstance::INTEGER, + false); + + if(res) { + res->set_operation(M2MBase::NOT_ALLOWED); + res->set_value(value); + } + } + } + return res; +} + +bool M2MSecurity::delete_resource(SecurityResource resource) +{ + bool success = false; + const char* security_id_ptr = ""; + switch(resource) { + case SMSSecurityMode: + security_id_ptr = SECURITY_SMS_SECURITY_MODE; + break; + case M2MServerSMSNumber: + security_id_ptr = SECURITY_M2M_SERVER_SMS_NUMBER; + break; + case ShortServerID: + if(M2MSecurity::Bootstrap == _server_type) { + security_id_ptr = SECURITY_SHORT_SERVER_ID; + } + break; + case ClientHoldOffTime: + security_id_ptr = SECURITY_CLIENT_HOLD_OFF_TIME; + break; + default: + // Others are mandatory resources hence cannot be deleted. + break; + } + + const String security_id(security_id_ptr); + + if(!security_id.empty()) { + if(_server_instance) { + success = _server_instance->remove_resource(security_id); + } + } + return success; +} + +bool M2MSecurity::set_resource_value(SecurityResource resource, + const String &value) +{ + bool success = false; + if(M2MSecurity::M2MServerUri == resource) { + M2MResource* res = get_resource(resource); + if(res) { + success = res->set_value((const uint8_t*)value.c_str(),(uint32_t)value.length()); + } + } + return success; +} + +bool M2MSecurity::set_resource_value(SecurityResource resource, + uint32_t value) +{ + bool success = false; + M2MResource* res = get_resource(resource); + if(res) { + if(M2MSecurity::SecurityMode == resource || + M2MSecurity::SMSSecurityMode == resource || + M2MSecurity::M2MServerSMSNumber == resource || + M2MSecurity::ShortServerID == resource || + M2MSecurity::ClientHoldOffTime == resource) { + // If it is any of the above resource + // set the value of the resource. + uint8_t size = 0; + uint8_t *buffer = String::convert_integer_to_array(value, size); + success = res->set_value(buffer,size); + free(buffer); + } + } + return success; +} + +bool M2MSecurity::set_resource_value(SecurityResource resource, + const uint8_t *value, + const uint16_t length) +{ + bool success = false; + M2MResource* res = get_resource(resource); + if(res) { + if(M2MSecurity::PublicKey == resource || + M2MSecurity::ServerPublicKey == resource || + M2MSecurity::Secretkey == resource) { + success = res->set_value(value,length); + } + } + return success; +} + +String M2MSecurity::resource_value_string(SecurityResource resource) const +{ + String value = ""; + M2MResource* res = get_resource(resource); + if(res) { + if(M2MSecurity::M2MServerUri == resource) { + value = res->get_value_string(); + } + } + return value; +} + +uint32_t M2MSecurity::resource_value_buffer(SecurityResource resource, + uint8_t *&data) const +{ + uint32_t size = 0; + M2MResource* res = get_resource(resource); + if(res) { + if(M2MSecurity::PublicKey == resource || + M2MSecurity::ServerPublicKey == resource || + M2MSecurity::Secretkey == resource) { + res->get_value(data,size); + } + } + return size; +} + +uint32_t M2MSecurity::resource_value_buffer(SecurityResource resource, + const uint8_t *&data) const +{ + uint32_t size = 0; + M2MResource* res = get_resource(resource); + if(res) { + if(M2MSecurity::PublicKey == resource || + M2MSecurity::ServerPublicKey == resource || + M2MSecurity::Secretkey == resource) { + data = res->value(); + size = res->value_length(); + } + } + return size; +} + + +uint32_t M2MSecurity::resource_value_int(SecurityResource resource) const +{ + uint32_t value = 0; + M2MResource* res = get_resource(resource); + if(res) { + if(M2MSecurity::SecurityMode == resource || + M2MSecurity::SMSSecurityMode == resource || + M2MSecurity::M2MServerSMSNumber == resource || + M2MSecurity::ShortServerID == resource || + M2MSecurity::ClientHoldOffTime == resource) { + // Get the value and convert it into integer. This is not the most + // efficient way, as it takes pointless heap copy to get the zero termination. + uint8_t* buffer = NULL; + uint32_t length = 0; + res->get_value(buffer,length); + if(buffer) { + value = String::convert_array_to_integer(buffer,length); + free(buffer); + } + } + } + return value; +} + +bool M2MSecurity::is_resource_present(SecurityResource resource) const +{ + bool success = false; + M2MResource *res = get_resource(resource); + if(res) { + success = true; + } + return success; +} + +uint16_t M2MSecurity::total_resource_count() const +{ + uint16_t count = 0; + if(_server_instance) { + count = _server_instance->resources().size(); + } + return count; +} + +M2MSecurity::ServerType M2MSecurity::server_type() const +{ + return _server_type; +} + +M2MResource* M2MSecurity::get_resource(SecurityResource res) const +{ + M2MResource* res_object = NULL; + if(_server_instance) { + const char* res_name_ptr = ""; + switch(res) { + case M2MServerUri: + res_name_ptr = SECURITY_M2M_SERVER_URI; + break; + case BootstrapServer: + res_name_ptr = SECURITY_BOOTSTRAP_SERVER; + break; + case SecurityMode: + res_name_ptr = SECURITY_SECURITY_MODE; + break; + case PublicKey: + res_name_ptr = SECURITY_PUBLIC_KEY; + break; + case ServerPublicKey: + res_name_ptr = SECURITY_SERVER_PUBLIC_KEY; + break; + case Secretkey: + res_name_ptr = SECURITY_SECRET_KEY; + break; + case SMSSecurityMode: + res_name_ptr = SECURITY_SMS_SECURITY_MODE; + break; + case SMSBindingKey: + res_name_ptr = SECURITY_SMS_BINDING_KEY; + break; + case SMSBindingSecretKey: + res_name_ptr = SECURITY_SMS_BINDING_SECRET_KEY; + break; + case M2MServerSMSNumber: + res_name_ptr = SECURITY_M2M_SERVER_SMS_NUMBER; + break; + case ShortServerID: + res_name_ptr = SECURITY_SHORT_SERVER_ID; + break; + case ClientHoldOffTime: + res_name_ptr = SECURITY_CLIENT_HOLD_OFF_TIME; + break; + } + const String res_name(res_name_ptr); + + res_object = _server_instance->resource(res_name); + } + return res_object; +} + +void M2MSecurity::clear_resources() +{ + for(int i = 0; i <= M2MSecurity::ClientHoldOffTime; i++) { + M2MResource *res = get_resource((SecurityResource) i); + if (res) { + res->clear_value(); + } + } +} diff --git a/features/FEATURE_CLIENT/mbed-client/source/m2mserver.cpp b/features/FEATURE_CLIENT/mbed-client/source/m2mserver.cpp new file mode 100644 index 0000000000..b2a4943847 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/m2mserver.cpp @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client/m2mserver.h" +#include "mbed-client/m2mconstants.h" +#include "mbed-client/m2mobject.h" +#include "mbed-client/m2mobjectinstance.h" +#include "mbed-client/m2mresource.h" +#include "mbed-client/m2mstring.h" + +#define TRACE_GROUP "mClt" + +#define BUFFER_SIZE 21 + +M2MServer::M2MServer() +: M2MObject(M2M_SERVER_ID) +{ + M2MObject::create_object_instance(); + + _server_instance = object_instance(); + + if(_server_instance) { + + M2MResource* res = _server_instance->create_dynamic_resource(SERVER_SHORT_SERVER_ID, + OMA_RESOURCE_TYPE, + M2MResourceInstance::INTEGER, + true); + if(res) { + res->set_operation(M2MBase::GET_PUT_ALLOWED); + } + res = _server_instance->create_dynamic_resource(SERVER_LIFETIME, + OMA_RESOURCE_TYPE, + M2MResourceInstance::INTEGER, + true); + if(res) { + res->set_operation(M2MBase::GET_PUT_POST_ALLOWED); + } + res = _server_instance->create_dynamic_resource(SERVER_NOTIFICATION_STORAGE, + OMA_RESOURCE_TYPE, + M2MResourceInstance::BOOLEAN, + true); + if(res) { + res->set_operation(M2MBase::GET_PUT_POST_ALLOWED); + } + res = _server_instance->create_dynamic_resource(SERVER_BINDING, + OMA_RESOURCE_TYPE, + M2MResourceInstance::STRING, + true); + if(res) { + res->set_operation(M2MBase::GET_PUT_POST_ALLOWED); + } + res = _server_instance->create_dynamic_resource(SERVER_REGISTRATION_UPDATE, + OMA_RESOURCE_TYPE, + M2MResourceInstance::OPAQUE, + false); + if(res) { + res->set_operation(M2MBase::POST_ALLOWED); + } + } +} + +M2MServer::~M2MServer() +{ + +} + +M2MResource* M2MServer::create_resource(ServerResource resource, uint32_t value) +{ + M2MResource* res = NULL; + const char* server_id_ptr = ""; + if(!is_resource_present(resource)) { + switch(resource) { + case DefaultMinPeriod: + server_id_ptr = SERVER_DEFAULT_MIN_PERIOD; + break; + case DefaultMaxPeriod: + server_id_ptr = SERVER_DEFAULT_MAX_PERIOD; + break; + case DisableTimeout: + server_id_ptr = SERVER_DISABLE_TIMEOUT; + break; + default: + break; + } + } + String server_id(server_id_ptr); + + if(!server_id.empty()) { + if(_server_instance) { + res = _server_instance->create_dynamic_resource(server_id, + OMA_RESOURCE_TYPE, + M2MResourceInstance::INTEGER, + true); + if(res) { + res->set_operation(M2MBase::GET_PUT_POST_ALLOWED); + + res->set_value(value); + } + } + } + return res; +} + +M2MResource* M2MServer::create_resource(ServerResource resource) +{ + M2MResource* res = NULL; + if(!is_resource_present(resource)) { + if(M2MServer::Disable == resource) { + if(_server_instance) { + res = _server_instance->create_dynamic_resource(SERVER_DISABLE, + OMA_RESOURCE_TYPE, + M2MResourceInstance::OPAQUE, + false); + if(res) { + res->set_operation(M2MBase::POST_ALLOWED); + } + } + } + } + return res; +} + +bool M2MServer::delete_resource(ServerResource resource) +{ + bool success = false; + const char* server_id_ptr; + switch(resource) { + case DefaultMinPeriod: + server_id_ptr = SERVER_DEFAULT_MIN_PERIOD; + break; + case DefaultMaxPeriod: + server_id_ptr = SERVER_DEFAULT_MAX_PERIOD; + break; + case Disable: + server_id_ptr = SERVER_DISABLE; + break; + case DisableTimeout: + server_id_ptr = SERVER_DISABLE_TIMEOUT; + break; + default: + server_id_ptr = ""; + break; + } + String server_id(server_id_ptr); + + if(!server_id.empty()) { + if(_server_instance) { + success = _server_instance->remove_resource(server_id); + } + } + return success; +} + +bool M2MServer::set_resource_value(ServerResource resource, + const String &value) +{ + bool success = false; + M2MResource* res = get_resource(resource); + if(res && (M2MServer::Binding == resource)) { + success = res->set_value((const uint8_t*)value.c_str(),(uint32_t)value.length()); + } + return success; +} + +bool M2MServer::set_resource_value(ServerResource resource, + uint32_t value) +{ + bool success = false; + M2MResource* res = get_resource(resource); + if(res) { + if(M2MServer::ShortServerID == resource || + M2MServer::Lifetime == resource || + M2MServer::DefaultMinPeriod == resource || + M2MServer::DefaultMaxPeriod == resource || + M2MServer::DisableTimeout == resource || + M2MServer::NotificationStorage == resource) { + // If it is any of the above resource + // set the value of the resource. + + success = res->set_value(value); + } + } + return success; +} + +String M2MServer::resource_value_string(ServerResource resource) const +{ + String value = ""; + M2MResource* res = get_resource(resource); + if(res && (M2MServer::Binding == resource)) { + + value = res->get_value_string(); + } + return value; +} + + +uint32_t M2MServer::resource_value_int(ServerResource resource) const +{ + uint32_t value = 0; + M2MResource* res = get_resource(resource); + if(res) { + if(M2MServer::ShortServerID == resource || + M2MServer::Lifetime == resource || + M2MServer::DefaultMinPeriod == resource || + M2MServer::DefaultMaxPeriod == resource || + M2MServer::DisableTimeout == resource || + M2MServer::NotificationStorage == resource) { + + value = res->get_value_int(); + } + } + return value; +} + +bool M2MServer::is_resource_present(ServerResource resource) const +{ + bool success = false; + M2MResource *res = get_resource(resource); + if(res) { + success = true; + } + return success; +} + +uint16_t M2MServer::total_resource_count() const +{ + uint16_t total_count = 0; + if(_server_instance) { + total_count = _server_instance->resources().size(); + } + return total_count; +} + +M2MResource* M2MServer::get_resource(ServerResource res) const +{ + M2MResource* res_object = NULL; + const char* res_name_ptr = ""; + switch(res) { + case ShortServerID: + res_name_ptr = SERVER_SHORT_SERVER_ID; + break; + case Lifetime: + res_name_ptr = SERVER_LIFETIME; + break; + case DefaultMinPeriod: + res_name_ptr = SERVER_DEFAULT_MIN_PERIOD; + break; + case DefaultMaxPeriod: + res_name_ptr = SERVER_DEFAULT_MAX_PERIOD; + break; + case Disable: + res_name_ptr = SERVER_DISABLE; + break; + case DisableTimeout: + res_name_ptr = SERVER_DISABLE_TIMEOUT; + break; + case NotificationStorage: + res_name_ptr = SERVER_NOTIFICATION_STORAGE; + break; + case Binding: + res_name_ptr = SERVER_BINDING; + break; + case RegistrationUpdate: + res_name_ptr = SERVER_REGISTRATION_UPDATE; + break; + } + + const String res_name(res_name_ptr); + + if(!res_name.empty()) { + if(_server_instance) { + res_object = _server_instance->resource(res_name); + } + } + return res_object; +} diff --git a/features/FEATURE_CLIENT/mbed-client/source/m2mstring.cpp b/features/FEATURE_CLIENT/mbed-client/source/m2mstring.cpp new file mode 100644 index 0000000000..fe01143415 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/m2mstring.cpp @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client/m2mstring.h" +#include // strlen +#include // malloc, realloc +#include +#include // min + +namespace m2m { + +const String::size_type String::npos = static_cast(-1); + +char* String::strdup(const char* s) +{ + const size_t len = strlen(s)+1; + char *p2 = static_cast(malloc(len)); + memcpy(p2, s, len); + allocated_ = len; + size_ = len-1; + return p2; +} + +String::String() + : p( strdup("") ) +{ +} + +String::~String() +{ + free(p); + p = 0; +} + +String::String(const String& s) + : p(0) +{ + if( &s != NULL ) { + p = static_cast(malloc(s.size_ + 1)); + + allocated_ = s.size_ + 1; + size_ = s.size_; + memcpy(p, s.p, size_ + 1); + } +} + +String::String(const char* s) + : p(strdup(s)) +{ +} + +String& String::operator=(const char* s) +{ + if ( p != s ) { + // s could point into our own string, so we have to allocate a new string + const size_t len = strlen(s); + char* copy = (char*) malloc( len + 1); + memmove(copy, s, len+1); // trailing 0 + free( p ); + p = copy; + size_ = len; + allocated_ = len+1; + } + return *this; +} + +String& String::operator=(const String& s) +{ + return operator=(s.p); +} + +String& String::operator+=(const String& s) +{ + if (s.size_ > 0) { + this->reserve(size_ + s.size_); + memmove(p+size_, s.p, s.size_+1); // trailing 0 + size_ += s.size_; + } + return *this; +} + +// since p and s may overlap, we have to copy our own string first +String& String::operator+=(const char* s) +{ + const size_type lens = strlen(s); + if (lens > 0) { + if (size_ + lens + 1 <= allocated_) { + memmove(p+size_, s, lens+1); // trailing 0 + size_ += lens; + } else { + String s2( *this ); // copy own data + s2.reserve(size_ + lens); + memmove(s2.p+size_, s, lens+1); // trailing 0 + s2.size_ = size_ + lens; + this->swap( s2 ); + } + } + return *this; +} + +String& String::operator+=(const char c) +{ + push_back(c); + return *this; +} + +void String::push_back(const char c) { + + if (size_ == allocated_ - 1) { + size_t more = (allocated_* 3) / 2; // factor 1.5 + if ( more < 4 ) more = 4; + reserve( size_ + more ); + } + + p[size_] = c; + size_++; + p[size_] = 0; +} + +bool String::operator==(const char* s) const +{ + if( s == NULL ) { + if( p == NULL ) { + return true; + } + return false; + } + bool ret = strcmp(p, s); + return !ret; +} + +bool String::operator==(const String& s) const +{ + bool ret = strcmp(p, s.p); + return !ret; +} + +void String::clear() +{ + size_ = 0; + p[0] = 0; +} + +String String::substr(const size_type pos, size_type length) const +{ + String s; + const size_type len = size_; + + if ( pos <= len ) { + + size_type remain = len - pos; + + if ( length > remain ) + length = remain; + + s.reserve( length ); + + memcpy(s.p, p + pos, length); + s.p[length] = '\0'; + s.size_ = length; + } + return s; +} + + +// checked access, accessing the NUL at end is allowed +char String::at(const size_type i) const +{ + if ( i <= strlen(p) ) { + return p[i]; + } else { + return '\0'; + } +} + +String& String::erase(size_type pos, size_type len) +{ + if (len > 0) { + + if ( pos < size_ ) { // user must not remove trailing 0 + + size_type s2 = size_; + size_type remain = s2 - pos - len; + + if (remain > 0) { + // erase by overwriting + memmove(p + pos, p + pos + len, remain); + } + + //if ( remain < 0 ) remain = 0; + + // remove unused space + this->resize( pos+remain ); + + } + } + return *this; +} + +String& String::append( const char* str, size_type n) { + if (str && n > 0) { + size_t lens = strlen(str); + if (n > lens) + n = lens; + size_t newlen = size_ + n; + this->reserve( newlen ); + memmove(p+size_, str, n); // p and s.p MAY overlap + p[newlen] = 0; // add NUL termination + size_ = newlen; + } + return *this; +} + +String& String::append_raw( const char* str, size_type n) { + if (str && n > 0) { + size_t newlen = size_ + n; + this->reserve( newlen ); + memmove(p+size_, str, n); // p and s.p MAY overlap + p[newlen] = 0; // add NUL termination + size_ = newlen; + } + return *this; +} + +void String::append_int(int param) { + + // max len of "-9223372036854775808" plus zero termination + char conv_buff[20+1]; + + int len = itoa_c(param, conv_buff); + append_raw(conv_buff, len); +} + +int String::compare( size_type pos, size_type len, const String& str ) const { + int r = -1; + if (pos <= size_) { + if ( len > size_ - pos) + len = size_ - pos; // limit len to available length + + const size_type osize = str.size(); + const size_type len2 = std::min(len, osize); + r = strncmp( p + pos, str.p, len2); + if (r==0) // equal so far, now compare sizes + r = len < osize ? -1 : ( len == osize ? 0 : +1 ); + } + return r; +} + +int String::compare( size_type pos, size_type len, const char* str ) const { + int r = -1; + if (pos <= size_) { + + if ( len > size_ - pos) + len = size_ - pos; // limit len to available length + + const size_type osize = strlen(str); + const size_type len2 = std::min(len, osize); + r = strncmp( p + pos, str, len2); + if (r==0) // equal so far, now compare sizes + r = len < osize ? -1 : ( len == osize ? 0 : +1 ); + } + return r; +} + +int String::find_last_of(char c) const { + int r = -1; + char *v; + v = strrchr(p,c); + if (v != NULL) { + r = 0; + char* i = p; + while (v != i) { + i++; + r++; + } + } + return r; +} + +void String::new_realloc( size_type n) { + if (n > 0 ) { + char* pnew = static_cast(realloc(p, n)); // could return NULL + if (pnew) + p = pnew; + } +} + +void String::reserve( const size_type n) { + if (n >= allocated_ ) { + this->new_realloc(n + 1); + allocated_ = n + 1; + } +} + +void String::resize( const size_type n) { + this->resize( n, 0 ); +} + +void String::resize( const size_type n, const char c) { + if (n < size_ ) { + p[n] = 0; + size_ = n; + } + else if (n > size_ ) { + this->reserve( n ); + for (size_type i=size_; i < n; ++i ) + p[i] = c; + p[n] = 0; + size_ = n; + } +} + +void String::swap( String& s ) { + std::swap( allocated_, s.allocated_ ); + std::swap( size_, s.size_ ); + std::swap( p, s.p ); +} + + +// Comparison +bool operator<( const String& s1, const String& s2 ) { + return strcmp( s1.c_str(), s2.c_str() ) < 0; +} + +void reverse(char s[], uint32_t length) +{ + uint32_t i, j; + char c; + + for (i = 0, j = length-1; i 0); + + if (sign < 0) + s[i++] = '-'; + + s[i] = '\0'; + + m2m::reverse(s, i); + return i; +} + +uint8_t* String::convert_integer_to_array(int64_t value, uint8_t &size, uint8_t *array, uint32_t array_size) +{ + uint8_t* buffer = NULL; + size = 0; + if (array) { + value = String::convert_array_to_integer(array, array_size); + } + + if(value < 0xFF) { + size = 1; + } else if(value < 0xFFFF) { + size = 2; + } else if(value < 0xFFFFFF) { + size = 3; + } else if(value < 0xFFFFFFFF) { + size = 4; + } else if(value < 0xFFFFFFFFFF) { + size = 5; + } else if(value < 0xFFFFFFFFFFFF) { + size = 6; + } else if(value < 0xFFFFFFFFFFFFFF) { + size = 7; + } else { + size = 8; + } + + buffer = (uint8_t*)malloc(size); + if (buffer) { + for (int i = 0; i < size; i++) { + buffer[i] = (value >> ((size - i - 1) * 8)); + } + } else { + size = 0; + } + return buffer; +} + +int64_t String::convert_array_to_integer(uint8_t *value, uint32_t size) +{ + int64_t temp_64 = 0; + for (int i = size - 1; i >= 0; i--) { + temp_64 += (uint64_t)(*value++) << i * 8; + } + return temp_64; +} + +} // namespace diff --git a/features/FEATURE_CLIENT/mbed-client/source/m2mtlvdeserializer.cpp b/features/FEATURE_CLIENT/mbed-client/source/m2mtlvdeserializer.cpp new file mode 100644 index 0000000000..5b70526a7b --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/m2mtlvdeserializer.cpp @@ -0,0 +1,431 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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/m2mtlvdeserializer.h" +#include "mbed-client/m2mconstants.h" +#include "include/nsdllinker.h" +#include "mbed-trace/mbed_trace.h" + +#define TRACE_GROUP "mClt" +#define BUFFER_SIZE 10 + +M2MTLVDeserializer::M2MTLVDeserializer() +{ +} + +M2MTLVDeserializer::~M2MTLVDeserializer() +{ +} + +bool M2MTLVDeserializer::is_object_instance(uint8_t *tlv) +{ + return is_object_instance(tlv, 0); +} + +bool M2MTLVDeserializer::is_resource(uint8_t *tlv) +{ + return is_resource(tlv, 0); +} + +bool M2MTLVDeserializer::is_multiple_resource(uint8_t *tlv) +{ + return is_multiple_resource(tlv, 0); +} + +bool M2MTLVDeserializer::is_resource_instance(uint8_t *tlv) +{ + return is_resource_instance(tlv, 0); +} + +M2MTLVDeserializer::Error M2MTLVDeserializer::deserialise_object_instances(uint8_t* tlv, + uint32_t tlv_size, + M2MObject &object, + M2MTLVDeserializer::Operation operation) +{ + M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; + if (is_object_instance(tlv) ) { + tr_debug("M2MTLVDeserializer::deserialise_object_instances"); + error = deserialize_object_instances(tlv, tlv_size, 0, object,operation,false); + if(M2MTLVDeserializer::None == error) { + error = deserialize_object_instances(tlv, tlv_size, 0, object,operation,true); + } + } else { + tr_debug("M2MTLVDeserializer::deserialise_object_instances ::NotValid"); + error = M2MTLVDeserializer::NotValid; + } + return error; +} + +M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resources(uint8_t *tlv, + uint32_t tlv_size, + M2MObjectInstance &object_instance, + M2MTLVDeserializer::Operation operation) +{ + M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; + if (!is_resource(tlv) && !is_multiple_resource(tlv)) { + error = M2MTLVDeserializer::NotValid; + } else { + error = deserialize_resources(tlv, tlv_size, 0, object_instance, operation,false); + if(M2MTLVDeserializer::None == error) { + error = deserialize_resources(tlv, tlv_size, 0, object_instance, operation,true); + } + } + return error; +} + +M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(uint8_t *tlv, + uint32_t tlv_size, + M2MResource &resource, + M2MTLVDeserializer::Operation operation) +{ + M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; + if (!is_multiple_resource(tlv)) { + error = M2MTLVDeserializer::NotValid; + } else { + tr_debug("M2MTLVDeserializer::deserialize_resource_instances()"); + uint8_t offset = 2; + + ((tlv[0] & 0x20) == 0) ? offset : offset++; + + uint8_t length = tlv[0] & 0x18; + if(length == 0x08) { + offset+= 1; + } else if(length == 0x10) { + offset+= 2; + } else if(length == 0x18) { + offset+= 3; + } + + tr_debug("M2MTLVDeserializer::deserialize_resource_instances() Offset %d", offset); + error = deserialize_resource_instances(tlv, tlv_size, offset, resource, operation,false); + if(M2MTLVDeserializer::None == error) { + error = deserialize_resource_instances(tlv, tlv_size, offset, resource, operation,true); + } + } + return error; +} + +M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_object_instances(uint8_t *tlv, + uint32_t tlv_size, + uint32_t offset, + M2MObject &object, + M2MTLVDeserializer::Operation operation, + bool update_value) +{ + tr_debug("M2MTLVDeserializer::deserialize_object_instances()"); + M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; + TypeIdLength *til = TypeIdLength::createTypeIdLength(tlv, offset)->deserialize(); + offset = til->_offset; + + M2MObjectInstanceList list = object.instances(); + M2MObjectInstanceList::const_iterator it; + it = list.begin(); + + if (TYPE_OBJECT_INSTANCE == til->_type) { + for (; it!=list.end(); it++) { + if((*it)->instance_id() == til->_id) { + error = deserialize_resources(tlv, tlv_size, offset, (**it),operation, update_value); + } + } + offset += til->_length; + + if(offset < tlv_size) { + error = deserialize_object_instances(tlv, tlv_size, offset, object, operation, update_value); + } + delete til; + } + return error; +} + +M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resources(uint8_t *tlv, + uint32_t tlv_size, + uint32_t offset, + M2MObjectInstance &object_instance, + M2MTLVDeserializer::Operation operation, + bool update_value) +{ + tr_debug("M2MTLVDeserializer::deserialize_resources()"); + M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; + TypeIdLength *til = TypeIdLength::createTypeIdLength(tlv, offset)->deserialize(); + offset = til->_offset; + + M2MResourceList list = object_instance.resources(); + M2MResourceList::const_iterator it; + it = list.begin(); + + if (TYPE_RESOURCE == til->_type || TYPE_RESOURCE_INSTANCE == til->_type) { + bool found = false; + for (; it!=list.end(); it++) { + if((*it)->name_id() == til->_id){ + tr_debug("M2MTLVDeserializer::deserialize_resources() - Resource ID %d ", til->_id); + found = true; + if(update_value) { + if(til->_length > 0) { + tr_debug("M2MTLVDeserializer::deserialize_resources() - Update value"); + (*it)->set_value(tlv+offset, til->_length); + } else { + tr_debug("M2MTLVDeserializer::deserialize_resources() - Clear Value"); + (*it)->clear_value(); + } + break; + } else if(0 == ((*it)->operation() & SN_GRS_PUT_ALLOWED)) { + tr_debug("M2MTLVDeserializer::deserialize_resources() - NOT_ALLOWED"); + error = M2MTLVDeserializer::NotAllowed; + break; + } + } + } + if(!found) { + if(M2MTLVDeserializer::Post == operation) { + //Create a new Resource + String id; + id.append_int(til->_id); + M2MResource *resource = object_instance.create_dynamic_resource(id,"",M2MResourceInstance::INTEGER,true,false); + if(resource) { + resource->set_operation(M2MBase::GET_PUT_POST_DELETE_ALLOWED); + } + } else if(M2MTLVDeserializer::Put == operation) { + error = M2MTLVDeserializer::NotFound; + } + } + } else if (TYPE_MULTIPLE_RESOURCE == til->_type) { + for (; it!=list.end(); it++) { + if((*it)->supports_multiple_instances()) { + error = deserialize_resource_instances(tlv, tlv_size-offset, offset, (**it), object_instance, operation, update_value); + } + } + + } else { + delete til; + error = M2MTLVDeserializer::NotValid; + return error; + } + offset += til->_length; + + delete til; + if(offset < tlv_size) { + error = deserialize_resources(tlv, tlv_size, offset, object_instance, operation, update_value); + } + return error; +} + +M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(uint8_t *tlv, + uint32_t tlv_size, + uint32_t offset, + M2MResource &resource, + M2MObjectInstance &object_instance, + M2MTLVDeserializer::Operation operation, + bool update_value) +{ + M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; + TypeIdLength *til = TypeIdLength::createTypeIdLength(tlv, offset)->deserialize(); + offset = til->_offset; + + if (TYPE_MULTIPLE_RESOURCE == til->_type || TYPE_RESOURCE_INSTANCE == til->_type) { + M2MResourceInstanceList list = resource.resource_instances(); + M2MResourceInstanceList::const_iterator it; + it = list.begin(); + bool found = false; + for (; it!=list.end(); it++) { + if((*it)->instance_id() == til->_id) { + found = true; + if(update_value) { + if(til->_length > 0) { + (*it)->set_value(tlv+offset, til->_length); + } else { + (*it)->clear_value(); + } + break; + } else if(0 == ((*it)->operation() & SN_GRS_PUT_ALLOWED)) { + error = M2MTLVDeserializer::NotAllowed; + break; + } + } + } + if(!found) { + if(M2MTLVDeserializer::Post == operation) { + // Create a new Resource Instance + M2MResourceInstance *res_instance = object_instance.create_dynamic_resource_instance(resource.name(),"", + M2MResourceInstance::INTEGER, + true, + til->_id); + if(res_instance) { + res_instance->set_operation(M2MBase::GET_PUT_POST_DELETE_ALLOWED); + } + } else if(M2MTLVDeserializer::Put == operation) { + error = M2MTLVDeserializer::NotFound; + } + } + } else { + delete til; + error = M2MTLVDeserializer::NotValid; + return error; + } + + offset += til->_length; + + delete til; + if(offset < tlv_size) { + error = deserialize_resource_instances(tlv, tlv_size-offset, offset, resource, object_instance, operation, update_value); + } + return error; +} + +M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(uint8_t *tlv, + uint32_t tlv_size, + uint32_t offset, + M2MResource &resource, + M2MTLVDeserializer::Operation operation, + bool update_value) +{ + M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; + TypeIdLength *til = TypeIdLength::createTypeIdLength(tlv, offset)->deserialize(); + offset = til->_offset; + + if (TYPE_RESOURCE_INSTANCE == til->_type) { + M2MResourceInstanceList list = resource.resource_instances(); + M2MResourceInstanceList::const_iterator it; + it = list.begin(); + bool found = false; + for (; it!=list.end(); it++) { + if((*it)->instance_id() == til->_id) { + found = true; + if(update_value) { + if(til->_length > 0) { + (*it)->set_value(tlv+offset, til->_length); + } else { + (*it)->clear_value(); + } + break; + } else if(0 == ((*it)->operation() & SN_GRS_PUT_ALLOWED)) { + error = M2MTLVDeserializer::NotAllowed; + break; + } + } + } + if(!found) { + if(M2MTLVDeserializer::Post == operation) { + error = M2MTLVDeserializer::NotAllowed; + } else if(M2MTLVDeserializer::Put == operation) { + error = M2MTLVDeserializer::NotFound; + } + } + } else { + delete til; + error = M2MTLVDeserializer::NotValid; + return error; + } + + offset += til->_length; + + delete til; + if(offset < tlv_size) { + error = deserialize_resource_instances(tlv, tlv_size-offset, offset, resource, operation, update_value); + } + return error; +} + +bool M2MTLVDeserializer::is_object_instance(uint8_t *tlv, uint32_t offset) +{ + bool ret = false; + if (tlv) { + uint8_t value = tlv[offset]; + ret = (TYPE_OBJECT_INSTANCE == (value & TYPE_RESOURCE)); + } + return ret; +} + +uint16_t M2MTLVDeserializer::instance_id(uint8_t *tlv) +{ + TypeIdLength *til = TypeIdLength::createTypeIdLength(tlv, 0)->deserialize(); + uint16_t id = til->_id; + delete til; + return id; +} + +bool M2MTLVDeserializer::is_resource(uint8_t *tlv, uint32_t offset) +{ + bool ret = false; + if (tlv) { + ret = (TYPE_RESOURCE == (tlv[offset] & TYPE_RESOURCE)); + } + return ret; +} + +bool M2MTLVDeserializer::is_multiple_resource(uint8_t *tlv, uint32_t offset) +{ + bool ret = false; + if (tlv) { + ret = (TYPE_MULTIPLE_RESOURCE == (tlv[offset] & TYPE_RESOURCE)); + } + return ret; +} + +bool M2MTLVDeserializer::is_resource_instance(uint8_t *tlv, uint32_t offset) +{ + bool ret = false; + if (tlv) { + ret = (TYPE_RESOURCE_INSTANCE == (tlv[offset] & TYPE_RESOURCE)); + } + return ret; +} + +TypeIdLength* TypeIdLength::createTypeIdLength(uint8_t *tlv, uint32_t offset) +{ + TypeIdLength *til = new TypeIdLength(); + til->_tlv = tlv; + til->_offset = offset; + til->_type = tlv[offset] & 0xC0; + til->_id = 0; + til->_length = 0; + return til; +} + +TypeIdLength* TypeIdLength::deserialize() +{ + uint32_t idLength = _tlv[_offset] & ID16; + uint32_t lengthType = _tlv[_offset] & LENGTH24; + if (0 == lengthType) { + _length = _tlv[_offset] & 0x07; + } + _offset++; + + deserialiseID(idLength); + deserialiseLength(lengthType); + + return this; +} + +void TypeIdLength::deserialiseID(uint32_t idLength) +{ + _id = _tlv[_offset++] & 0xFF; + if (ID16 == idLength) { + _id = (_id << 8) + (_tlv[_offset++] & 0xFF); + } +} + +void TypeIdLength::deserialiseLength(uint32_t lengthType) +{ + if (lengthType > 0) { + _length = _tlv[_offset++] & 0xFF; + } + if (lengthType > LENGTH8) { + _length = (_length << 8) + (_tlv[_offset++] & 0xFF); + } + if (lengthType > LENGTH16) { + _length = (_length << 8) + (_tlv[_offset++] & 0xFF); + } +} diff --git a/features/FEATURE_CLIENT/mbed-client/source/m2mtlvserializer.cpp b/features/FEATURE_CLIENT/mbed-client/source/m2mtlvserializer.cpp new file mode 100644 index 0000000000..5e73c7b244 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/m2mtlvserializer.cpp @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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/m2mtlvserializer.h" +#include "include/nsdllinker.h" +#include "mbed-client/m2mconstants.h" + +#define TRACE_GROUP "mClt" + +M2MTLVSerializer::M2MTLVSerializer() +{ +} + +M2MTLVSerializer::~M2MTLVSerializer() +{ +} + +uint8_t* M2MTLVSerializer::serialize(M2MObjectInstanceList object_instance_list, uint32_t &size) +{ + return serialize_object_instances(object_instance_list, size); +} + +uint8_t* M2MTLVSerializer::serialize(M2MResourceList resource_list, uint32_t &size) +{ + bool valid = true; + return serialize_resources(resource_list, size,valid); +} + +uint8_t* M2MTLVSerializer::serialize(M2MResource *resource, uint32_t &size) +{ + uint8_t* data = NULL; + serialize(resource, data, size); + return data; +} + +uint8_t* M2MTLVSerializer::serialize_object_instances(M2MObjectInstanceList object_instance_list, uint32_t &size) +{ + uint8_t *data = NULL; + + if(!object_instance_list.empty()) { + M2MObjectInstanceList::const_iterator it; + it = object_instance_list.begin(); + for (; it!=object_instance_list.end(); it++) { + uint16_t id = (*it)->instance_id(); + serialize(id, *it, data, size); + } + } + return data; +} + +uint8_t* M2MTLVSerializer::serialize_resources(M2MResourceList resource_list, uint32_t &size, bool &valid) +{ + uint8_t *data = NULL; + + if(!resource_list.empty()) { + M2MResourceList::const_iterator it; + it = resource_list.begin(); + for (; it!=resource_list.end(); it++) { + if((*it)->name_id() == -1) { + valid = false; + break; + } + } + if(valid) { + it = resource_list.begin(); + for (; it!=resource_list.end(); it++) { + serialize(*it, data, size); + } + } + } + return data; +} + +void M2MTLVSerializer::serialize(uint16_t id, M2MObjectInstance *object_instance, uint8_t *&data, uint32_t &size) +{ + uint8_t *resource_data = NULL; + uint32_t resource_size = 0; + + bool valid = true; + resource_data = serialize_resources(object_instance->resources(),resource_size,valid); + if(valid) { + serialize_TILV(TYPE_OBJECT_INSTANCE, id, resource_data, resource_size, data, size); + } + free(resource_data); +} + +bool M2MTLVSerializer::serialize(M2MResource *resource, uint8_t *&data, uint32_t &size) +{ + bool success = false; + if(resource->name_id() != -1) { + success = resource->supports_multiple_instances() ? + serialize_multiple_resource(resource, data, size) : + serialize_resource(resource, data, size); + } + return success; +} + +bool M2MTLVSerializer::serialize_resource(M2MResource *resource, uint8_t *&data, uint32_t &size) +{ + bool success = false; + if(resource->name_id() != -1) { + success = true; + serialize_TILV(TYPE_RESOURCE, resource->name_id(), resource->value(), resource->value_length(), data, size); + } + return success; +} + +bool M2MTLVSerializer::serialize_multiple_resource(M2MResource *resource, uint8_t *&data, uint32_t &size) +{ + bool success = false; + uint8_t *nested_data = NULL; + uint32_t nested_data_size = 0; + + M2MResourceInstanceList instance_list = resource->resource_instances(); + if(!instance_list.empty()) { + M2MResourceInstanceList::const_iterator it; + it = instance_list.begin(); + for (; it!=instance_list.end(); it++) { + uint16_t id = (*it)->instance_id(); + serialize_resource_instance(id, (*it), nested_data, nested_data_size); + } + } + if(resource->name_id() != -1) { + success = true; + serialize_TILV(TYPE_MULTIPLE_RESOURCE, resource->name_id(), nested_data, nested_data_size, data, size); + } + + free(nested_data); + nested_data = NULL; + return success; +} + +void M2MTLVSerializer::serialize_resource_instance(uint16_t id, M2MResourceInstance *resource, uint8_t *&data, uint32_t &size) +{ + serialize_TILV(TYPE_RESOURCE_INSTANCE, id, resource->value(), resource->value_length(), data, size); +} + +void M2MTLVSerializer::serialize_TILV(uint8_t type, uint16_t id, uint8_t *value, uint32_t value_length, uint8_t *&data, uint32_t &size) +{ + uint8_t *tlv = 0; + uint32_t type_length = 1; + type += id < 256 ? 0 : ID16; + type += value_length < 8 ? value_length : + value_length < 256 ? LENGTH8 : + value_length < 65536 ? LENGTH16 : LENGTH24; + uint8_t *tlv_type = (uint8_t*)malloc(type_length+1); + memset(tlv_type,0,type_length+1); + *tlv_type = type & 0xFF; + + uint32_t id_size = 0; + uint8_t* id_ptr = serialize_id(id, id_size); + + uint32_t length_size = 0; + uint8_t* length_ptr = serialize_length(value_length, length_size); + + tlv = (uint8_t*)malloc(size + type_length + id_size + length_size + value_length+1); + memset(tlv,0,size + type_length + id_size + length_size + value_length+1); + if(data) { + memcpy(tlv, data, size); + } + memcpy(tlv+size, tlv_type, type_length); + memcpy(tlv+size+type_length, id_ptr, id_size); + memcpy(tlv+size+type_length+id_size, length_ptr, length_size); + memcpy(tlv+size+type_length+id_size+length_size, value, value_length); + + free(tlv_type) ; + free(length_ptr); + free(id_ptr); + free(data); + + data = tlv; + size += type_length + id_size + length_size + value_length; +} + +uint8_t* M2MTLVSerializer::serialize_id(uint16_t id, uint32_t &size) +{ + uint32_t id_size = id > 255 ? 2 : 1; + uint8_t *id_ptr = (uint8_t*)malloc(id_size); + memset(id_ptr, 0 , id_size); + size += id_size; + if(id > 255) { + *id_ptr = (id & 0xFF00) >> 8; + id_ptr++; + *id_ptr = id & 0xFF; + id_ptr--; + } else { + *id_ptr = id & 0xFF; + } + return id_ptr; +} + +uint8_t* M2MTLVSerializer::serialize_length(uint32_t length, uint32_t &size) +{ + uint8_t *length_ptr = 0; + uint32_t length_size = 0; + if (length > 65535) { + length_size = 3; + length_ptr = (uint8_t*)malloc(length_size+1); + memset(length_ptr,0,length_size+1); + *length_ptr = (length & 0xFF0000) >> 16; + length_ptr++; + *length_ptr = (length & 0xFF00) >> 8; + length_ptr++; + *length_ptr = length & 0xFF; + length_ptr--; + length_ptr--; + } else if (length > 255) { + length_size = 2; + length_ptr = (uint8_t*)malloc(length_size+1); + memset(length_ptr,0,length_size+1); + *length_ptr = (length & 0xFF00) >> 8; + length_ptr++; + *length_ptr = length & 0xFF; + length_ptr--; + } else if (length > 7) { + length_size = 1; + length_ptr = (uint8_t*)malloc(length_size+1); + memset(length_ptr,0,length_size+1); + *length_ptr = length & 0xFF; + } + size += length_size; + return length_ptr; +} + diff --git a/features/FEATURE_CLIENT/mbed-client/source/nsdlaccesshelper.cpp b/features/FEATURE_CLIENT/mbed-client/source/nsdlaccesshelper.cpp new file mode 100644 index 0000000000..aa535296d0 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/source/nsdlaccesshelper.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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/nsdlaccesshelper.h" +#include "include/m2mnsdlinterface.h" + +M2MNsdlInterfaceList __nsdl_interface_list; + +// callback function for NSDL library to call into + +M2MConnectionHandler *__connection_handler = NULL; + + +uint8_t __nsdl_c_callback(struct nsdl_s *nsdl_handle, + sn_coap_hdr_s *received_coap_ptr, + sn_nsdl_addr_s *address, + sn_nsdl_capab_e nsdl_capab) +{ + uint8_t status = 0; + M2MNsdlInterface *interface = get_interface(nsdl_handle); + if(interface) { + status = interface->resource_callback(nsdl_handle,received_coap_ptr, + address, nsdl_capab); + // Payload freeing must be done in app level if blockwise message + if (received_coap_ptr && + received_coap_ptr->options_list_ptr && + received_coap_ptr->options_list_ptr->block1_len > 0) { + free(received_coap_ptr->payload_ptr); + received_coap_ptr->payload_ptr = NULL; + } + } + return status; +} + +void* __nsdl_c_memory_alloc(uint16_t size) +{ + if(size) + return malloc(size); + else + return 0; +} + +void __nsdl_c_memory_free(void *ptr) +{ + if(ptr) + free(ptr); +} + +uint8_t __nsdl_c_send_to_server(struct nsdl_s * nsdl_handle, + sn_nsdl_capab_e protocol, + uint8_t *data_ptr, + uint16_t data_len, + sn_nsdl_addr_s *address_ptr) +{ + uint8_t status = 0; + M2MNsdlInterface *interface = get_interface(nsdl_handle); + if(interface) { + status = interface->send_to_server_callback(nsdl_handle, + protocol, data_ptr, + data_len, address_ptr); + } + return status; +} + +uint8_t __nsdl_c_received_from_server(struct nsdl_s * nsdl_handle, + sn_coap_hdr_s *coap_header, + sn_nsdl_addr_s *address_ptr) +{ + uint8_t status = 0; + M2MNsdlInterface *interface = get_interface(nsdl_handle); + if(interface) { + status = interface->received_from_server_callback(nsdl_handle, + coap_header, + address_ptr); + // Payload freeing must be done in app level if blockwise message + if (coap_header && + coap_header->options_list_ptr && + coap_header->options_list_ptr->block1_len > 0) { + free(coap_header->payload_ptr); + coap_header->payload_ptr = NULL; + } + } + return status; +} + +void* __socket_malloc( void * context, size_t size) +{ + (void) context; + return malloc(size); +} + +void __socket_free(void * context, void * ptr) +{ + (void) context; + free(ptr); +} + +M2MNsdlInterface* get_interface(struct nsdl_s* nsdl_handle) +{ + M2MNsdlInterfaceList::const_iterator it; + it = __nsdl_interface_list.begin(); + M2MNsdlInterface* obj = NULL; + if (nsdl_handle) { + for (; it!=__nsdl_interface_list.end(); it++) { + if ((*it)->get_nsdl_handle() == nsdl_handle) { + obj = *it; + break; + } + } + } + return obj; +} + +void __mutex_claim() +{ + if(__connection_handler) { + __connection_handler->claim_mutex(); + } +} + +void __mutex_release() +{ + if(__connection_handler) { + __connection_handler->release_mutex(); + } +} diff --git a/features/FEATURE_CLIENT/mbed-client/sources.mk b/features/FEATURE_CLIENT/mbed-client/sources.mk new file mode 100644 index 0000000000..fc3fcfec77 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/sources.mk @@ -0,0 +1,23 @@ +SRCS += \ + source/m2mbase.cpp \ + source/m2mdevice.cpp \ + source/m2mfirmware.cpp \ + source/m2minterfacefactory.cpp \ + source/m2minterfaceimpl.cpp \ + source/m2mnsdlinterface.cpp \ + source/m2mobject.cpp \ + source/m2mobjectinstance.cpp \ + source/m2mreporthandler.cpp \ + source/m2mresource.cpp \ + source/m2mresourceinstance.cpp \ + source/m2msecurity.cpp \ + source/m2mserver.cpp \ + source/m2mstring.cpp \ + source/m2mtlvdeserializer.cpp \ + source/m2mtlvserializer.cpp \ + source/nsdlaccesshelper.cpp \ + source/m2mfirmware.cpp \ + + + + diff --git a/features/FEATURE_CLIENT/mbed-client/test/CMakeLists.txt b/features/FEATURE_CLIENT/mbed-client/test/CMakeLists.txt new file mode 100644 index 0000000000..5ff8a73b75 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/CMakeLists.txt @@ -0,0 +1,108 @@ +if(TARGET_LIKE_X86_LINUX_NATIVE_COVERAGE) +SET(CMAKE_CXX_FLAGS "") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage -Wall -Wextra -include /usr/include/CppUTest/MemoryLeakDetectorMallocMacros.h -include /usr/include/CppUTest/MemoryLeakDetectorNewMacros.h -D__thumb2__ -w") +include_directories($ENV{CPPUTEST_HOME}/include) +link_directories($ENV{CPPUTEST_HOME}/lib) +MACRO(SUBDIRLIST result curdir) + FILE(GLOB children RELATIVE ${curdir} ${curdir}/*) + SET(dirlist "") + FOREACH(child ${children}) + IF(IS_DIRECTORY ${curdir}/${child}) + if(EXISTS "${curdir}/${child}/CMakeLists.txt") + LIST(APPEND dirlist ${curdir}/${child}) + endif() + ENDIF() + ENDFOREACH() + SET(${result} ${dirlist}) +ENDMACRO() + +SUBDIRLIST(SUBDIRS ${CMAKE_CURRENT_SOURCE_DIR}/mbedclient/utest) + +FOREACH(subdir ${SUBDIRS}) + ADD_SUBDIRECTORY(${subdir}) +ENDFOREACH() + +endif() + +if(TARGET_LIKE_LINUX AND NOT TARGET_LIKE_X86_LINUX_NATIVE_COVERAGE) +add_executable(mbed-client-test-mbedclient_linux + "mbedclient_linux/main.cpp" +) +target_link_libraries(mbed-client-test-mbedclient_linux + mbed-client-c + mbed-client-linux + mbed-client +) +#add_test(mbed-client-test-mbedclient_linux mbed-client-test-mbedclient_linux) +add_dependencies(all_tests mbed-client-test-mbedclient_linux) + +add_executable(mbed-client-test-helloworld-mbedclient + "helloworld-mbedclient/main.cpp" + "helloworld-mbedclient/mbedclient.cpp" + "helloworld-mbedclient/to_be_ported.c" +) +target_link_libraries(mbed-client-test-helloworld-mbedclient + mbed-client-c + mbed-client-linux + mbed-client +) +#add_test(mbed-client-test-helloworld-mbedclient mbed-client-test-helloworld-mbedclient) +add_dependencies(all_tests mbed-client-test-helloworld-mbedclient) + +endif() + +if(TARGET_LIKE_MBED) + +add_executable(mbed-client-test-mbedclient-smokeTest EXCLUDE_FROM_ALL + "mbedclient-smokeTest/main.cpp" + "mbedclient-smokeTest/testconfig.cpp" + "mbedclient-smokeTest/testconfig.h" +) +target_link_libraries(mbed-client-test-mbedclient-smokeTest + mbed-client-c + mbed-client-mbed-os + mbed-client +) + +#add_test(mbed-client-test-mbedclient-smokeTest mbed-client-test-mbedclient-smokeTest) +add_dependencies(all_tests mbed-client-test-mbedclient-smokeTest) + +# if the target has defined a post-processing step, perform it: +if(YOTTA_POSTPROCESS_COMMAND) + string(REPLACE YOTTA_CURRENT_EXE_NAME "mbed-client-test-mbedclient-smokeTest" LOCAL_POSTPROCESS_COMMAND "${YOTTA_POSTPROCESS_COMMAND}") + separate_arguments(LOCAL_POSTPROCESS_COMMAND_SEPARATED UNIX_COMMAND ${LOCAL_POSTPROCESS_COMMAND}) + add_custom_command( + TARGET mbed-client-test-mbedclient-smokeTest + POST_BUILD + COMMAND ${LOCAL_POSTPROCESS_COMMAND_SEPARATED} + ) +endif() + +add_executable(mbed-client-test-helloworld-mbedclient EXCLUDE_FROM_ALL + "helloworld-mbedclient/main.cpp" + "helloworld-mbedclient/mbedclient.cpp" + "helloworld-mbedclient/to_be_ported.c" +) +target_link_libraries(mbed-client-test-helloworld-mbedclient + mbed-client-c + mbed-client-mbed-os + mbed-client +) +# if the target has defined a post-processing step, perform it: +if(YOTTA_POSTPROCESS_COMMAND) + string(REPLACE YOTTA_CURRENT_EXE_NAME "mbed-client-test-helloworld-mbedclient" LOCAL_POSTPROCESS_COMMAND "${YOTTA_POSTPROCESS_COMMAND}") + separate_arguments(LOCAL_POSTPROCESS_COMMAND_SEPARATED UNIX_COMMAND ${LOCAL_POSTPROCESS_COMMAND}) + add_custom_command( + TARGET mbed-client-test-helloworld-mbedclient + POST_BUILD + COMMAND ${LOCAL_POSTPROCESS_COMMAND_SEPARATED} + ) +endif() + +#add_test(mbed-client-test-helloworld-mbedclient mbed-client-test-helloworld-mbedclient) +add_dependencies(all_tests mbed-client-test-helloworld-mbedclient) + +endif() + + + diff --git a/features/FEATURE_CLIENT/mbed-client/test/helloworld-mbedclient/main.cpp b/features/FEATURE_CLIENT/mbed-client/test/helloworld-mbedclient/main.cpp new file mode 100755 index 0000000000..5079737541 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/helloworld-mbedclient/main.cpp @@ -0,0 +1,445 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbedclient.h" + +#ifdef TARGET_LIKE_LINUX +#include +#include +#include +#include +#include /* For SIGIGN and SIGINT */ +#else +#include "sockets/UDPSocket.h" +#ifdef SIXLOWPAN_INTERFACE +#include "atmel-rf-driver/driverRFPhy.h" // rf_device_register +#include "mbed-mesh-api/Mesh6LoWPAN_ND.h" +#endif +#include "EthernetInterface.h" +#include "test_env.h" +// TODO: Remove when yotta supports init. +#include "lwipv4_init.h" +using namespace mbed::util; +#endif + +#include "mbed-client/m2minterfacefactory.h" +#include "mbed-client/m2mdevice.h" +#include "mbed-client/m2minterfaceobserver.h" +#include "mbed-client/m2minterface.h" +#include "mbed-client/m2mobjectinstance.h" +#include "mbed-client/m2mresource.h" +#include "mbed-trace/mbed_trace.h" + +#ifdef TARGET_LIKE_LINUX +static void ctrl_c_handle_function(void); +typedef void (*signalhandler_t)(int); /* Function pointer type for ctrl-c */ +#else +#if defined(TARGET_K64F) +#define OBS_BUTTON SW2 +#define UNREG_BUTTON SW3 +#endif +#endif + +bool _have_secure_conn = false; + +const unsigned char psk[] = {0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x30,0x31,0x32,0x33,0x34,0x35,0x36}; +const size_t psk_len = sizeof( psk ); +const unsigned char psk_identity[] = {0x0F,0x0F}; +const size_t psk_identity_len = sizeof( psk_identity ); + +const uint8_t server_cert[] = "-----BEGIN CERTIFICATE-----\r\n" +"MIIBmDCCAT6gAwIBAgIEVUCA0jAKBggqhkjOPQQDAjBLMQswCQYDVQQGEwJGSTEN\r\n" +"MAsGA1UEBwwET3VsdTEMMAoGA1UECgwDQVJNMQwwCgYDVQQLDANJb1QxETAPBgNV\r\n" +"BAMMCEFSTSBtYmVkMB4XDTE1MDQyOTA2NTc0OFoXDTE4MDQyOTA2NTc0OFowSzEL\r\n" +"MAkGA1UEBhMCRkkxDTALBgNVBAcMBE91bHUxDDAKBgNVBAoMA0FSTTEMMAoGA1UE\r\n" +"CwwDSW9UMREwDwYDVQQDDAhBUk0gbWJlZDBZMBMGByqGSM49AgEGCCqGSM49AwEH\r\n" +"A0IABLuAyLSk0mA3awgFR5mw2RHth47tRUO44q/RdzFZnLsAsd18Esxd5LCpcT9w\r\n" +"0tvNfBv4xJxGw0wcYrPDDb8/rjujEDAOMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0E\r\n" +"AwIDSAAwRQIhAPAonEAkwixlJiyYRQQWpXtkMZax+VlEiS201BG0PpAzAiBh2RsD\r\n" +"NxLKWwf4O7D6JasGBYf9+ZLwl0iaRjTjytO+Kw==\r\n" +"-----END CERTIFICATE-----\r\n"; + +const uint8_t cert[] = "-----BEGIN CERTIFICATE-----\r\n" +"MIICTDCCAbWgAwIBAgIJAKI3S+LGklSGMA0GCSqGSIb3DQEBCwUAMD8xCzAJBgNV\r\n" +"BAYTAkZJMRMwEQYDVQQIDApTb21lLVN0YXRlMQ0wCwYDVQQHDARPdWx1MQwwCgYD\r\n" +"VQQKDANBUk0wHhcNMTUwNjExMTI0NTU1WhcNMTYwNjEwMTI0NTU1WjA/MQswCQYD\r\n" +"VQQGEwJGSTETMBEGA1UECAwKU29tZS1TdGF0ZTENMAsGA1UEBwwET3VsdTEMMAoG\r\n" +"A1UECgwDQVJNMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBt8ag12ILm2pn\r\n" +"RHUc2yMBXpdzspDwVV3VDaNTRXypVUOq/nxJc6zr8yG/Pvga2/XVijWQDLABHVhV\r\n" +"PoeulzXVSEHRR2bR2lhqulLzdUzPYJ+yJd4+082akoxdzoom8ms2LFlgiXO7lyBg\r\n" +"1t74xjEQapCkr7Tdl2pD9OTUrcfoEwIDAQABo1AwTjAdBgNVHQ4EFgQUHK0O4iK7\r\n" +"Rv8AsxAqRDlY3TSHWtUwHwYDVR0jBBgwFoAUHK0O4iK7Rv8AsxAqRDlY3TSHWtUw\r\n" +"DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQAPVLihYN65DEeYdf7gDAdP\r\n" +"MNH5RxsQlHdktQkYWcUewe3hvOf8yZUBbmO5OeEQmy5Ca2H1QhUuw+kWHo1l/K9g\r\n" +"DpR1xoDACeycBd/6tAHfaFzTEEDC9Ug839EAHDrbI4ihrPEbP6hyRIaUIM4IojXf\r\n" +"zuqwOcobS3idv8a9Npuohw==\r\n" +"-----END CERTIFICATE-----\r\n"; + +const uint8_t key[] = "-----BEGIN PRIVATE KEY-----\r\n" +"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMG3xqDXYgubamdE\r\n" +"dRzbIwFel3OykPBVXdUNo1NFfKlVQ6r+fElzrOvzIb8++Brb9dWKNZAMsAEdWFU+\r\n" +"h66XNdVIQdFHZtHaWGq6UvN1TM9gn7Il3j7TzZqSjF3OiibyazYsWWCJc7uXIGDW\r\n" +"3vjGMRBqkKSvtN2XakP05NStx+gTAgMBAAECgYEAlRimNxsu6jIXJh4paSk8ewxb\r\n" +"0v+n0GJT0uwpPakotofaihxOepYejIfX/IMxoDKVtmImsZUiTelRGGMFORpGomS7\r\n" +"3Pb9awfn1yWiYja9MF7+pgFtXj6LxcB5rcxrP8s9rCs+kEq8yl/khGXmlwlpacUm\r\n" +"Pdg1rEHriykk/5dlyKkCQQD9zpgQKN87bQNOVSgFSNsrwCjEN2MvVUC6ycqVYqQd\r\n" +"oQZrO2lJuf57Jn7kRKJgfqqImwLYaohn5A9gKiqszo+fAkEAw2REr8L9aLoRPe5Q\r\n" +"4+lYCmNmxJjBbJoRviSlxx+p5dxK+8H4J+bnFUWzORFJP0+Bjhii2UHGBoMjuP2s\r\n" +"e8xDDQJADm0IrZp1Hb6TeodSkAJVGsaASq7PP2h8FmHT1uvVYi293Khy0pL0yPEm\r\n" +"MzlHdW6dqMgOwFhFyonm6dNbu5i+BwJBALSPKfIKDMcEev5yBgo3Dga7iLJQPx4u\r\n" +"2gqOLyvtlME3a4tu2fV1qUG9ITuxP7DjteMr3QFLiMVn1lETCpt0TNkCQGIvyjdV\r\n" +"RzYnzLDMulXCsuRBjs0C75KoZrcPPQ416SZFtYASsOl3P0Ih5jgt/1aPmth3Yson\r\n" +"GdnBOWyKzadLmz8=\r\n" +"-----END PRIVATE KEY-----\r\n"; + +const size_t server_cert_len = sizeof( server_cert ); +const size_t cert_len = sizeof( cert ); +const size_t key_len = sizeof( key ); + +#ifdef TARGET_LIKE_LINUX + +#if defined (BOOTSTRAP_ENABLED) +void* wait_for_bootstrap(void* arg) { + MbedClient *client; + client = (MbedClient*) arg; + if(client->bootstrap_successful()) { + printf("Registering endpoint\n"); + + // Create LWM2M device object specifying device resources + // as per OMA LWM2M specification. + M2MDevice* device_object = client->create_device_object(); + + M2MObject* object = client->create_generic_object(); + + // Add all the objects that you would like to register + // into the list and pass the list for register API. + M2MObjectList object_list; + object_list.push_back(device_object); + object_list.push_back(object); + + // Issue register command. + client->test_register(object_list); + } + return NULL; +} +#endif + +void* wait_for_unregister(void* arg) { + MbedClient *client; + client = (MbedClient*) arg; + if(client->unregister_successful()) { + printf("Unregistered done --> exiting\n"); + exit(1); + } + return NULL; +} + +void* send_observation(void* arg) { + MbedClient *client; + client = (MbedClient*) arg; + static uint8_t counter = 0; + while(1) { + sleep(1); + if(counter >= 10 && + client->register_successful()) { + printf("Sending observation\n"); + client->update_resource(); + counter = 0; + } + else + counter++; + } + return NULL; +} + +static MbedClient *m2mclient = NULL; + +static void ctrl_c_handle_function(void) +{ + if(m2mclient && m2mclient->register_successful()) { + printf("Unregistering endpoint\n"); + m2mclient->test_unregister(); + } +} +#else +#ifdef SIXLOWPAN_INTERFACE +volatile uint8_t mesh_network_state = MESH_DISCONNECTED; + +void mesh_network_callback(mesh_connection_status_t mesh_state) +{ + tr_info("Network established"); + mesh_network_state = mesh_state; +} +#endif +#endif + +void trace_printer(const char* str) +{ + printf("%s\r\n", str); +} + +#ifdef TARGET_LIKE_MBED +void app_start(int /*argc*/, char* /*argv*/[]) { +#else +int main() { +#endif + + // Instantiate the class which implements + // mbed Client API + MbedClient mbed_client; + +#ifdef TARGET_LIKE_LINUX + pthread_t unregister_thread; + pthread_t observation_thread; + + m2mclient = &mbed_client; + + mbed_trace_init(); + mbed_trace_print_function_set( trace_printer ); + mbed_trace_config_set(TRACE_MODE_COLOR|TRACE_ACTIVE_LEVEL_DEBUG|TRACE_CARRIAGE_RETURN); + + signal(SIGINT, (signalhandler_t)ctrl_c_handle_function); + +#else + // This sets up the network interface configuration which will be used + // by LWM2M Client API to communicate with mbed Device server. + +#ifdef SIXLOWPAN_INTERFACE + + Mesh6LoWPAN_ND *mesh_api = Mesh6LoWPAN_ND::getInstance(); + int8_t status; + + status = mesh_api->init(rf_device_register(), mesh_network_callback); + if (status != MESH_ERROR_NONE) + { + tr_error("Mesh network initialization failed %d!", status); + return 1; + } + + status = mesh_api->connect(); + if (status != MESH_ERROR_NONE) + { + tr_error("Can't connect to mesh network!"); + return 1; + } + + do + { + mesh_api->processEvent(); + } while(mesh_network_state != MESH_CONNECTED); + + +#else + EthernetInterface eth; + eth.init(); //Use DHCP + eth.connect(); + + lwipv4_socket_init(); +#endif + + // Set up Hardware interrupt button. + InterruptIn obs_button(OBS_BUTTON); + InterruptIn unreg_button(UNREG_BUTTON); + + // On press of SW3 button on K64F board, example application + // will call unregister API towards mbed Device Server + unreg_button.fall(&mbed_client,&MbedClient::test_unregister); + + // On press of SW2 button on K64F board, example application + // will send observation towards mbed Device Server + obs_button.fall(&mbed_client,&MbedClient::update_resource); + + +#endif + + // Create LWM2M Client API interface to manage bootstrap, + // register and unregister + + //These 2 are defining the secure connection usage + M2MSecurity::SecurityModeType mode = M2MSecurity::NoSecurity; + _have_secure_conn = (mode == M2MSecurity::Certificate || mode == M2MSecurity::Psk); + // SecurityNotSet, + // Psk = 0, + // Certificate = 2, + // NoSecurity = 3 + + mbed_client.create_interface(); + +#ifdef TARGET_LIKE_LINUX + +#if defined (BOOTSTRAP_ENABLED) + pthread_t bootstrap_thread; + // Create LWM2M bootstrap object specifying bootstrap server + // information. + M2MSecurity* security_object = mbed_client.create_bootstrap_object(_have_secure_conn); + // Issue bootstrap command. + mbed_client.test_bootstrap(security_object); + + pthread_create(&bootstrap_thread, NULL, &wait_for_bootstrap, (void*) &mbed_client); + pthread_join(bootstrap_thread, NULL); + +#else + M2MSecurity *register_object = mbed_client.create_register_object(_have_secure_conn); + + if( mode == M2MSecurity::Certificate ){ + register_object->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::Certificate); + register_object->set_resource_value(M2MSecurity::ServerPublicKey,server_cert,server_cert_len); + register_object->set_resource_value(M2MSecurity::PublicKey,cert,cert_len); + register_object->set_resource_value(M2MSecurity::Secretkey,key,key_len); + }else if( mode == M2MSecurity::Psk ){ + register_object->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::Psk); + register_object->set_resource_value(M2MSecurity::ServerPublicKey,psk_identity,psk_identity_len); + register_object->set_resource_value(M2MSecurity::PublicKey,psk_identity,psk_identity_len); + register_object->set_resource_value(M2MSecurity::Secretkey,psk,psk_len); + }else{ + register_object->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::NoSecurity); + } + + mbed_client.set_register_object(register_object); + M2MDevice* device_object = mbed_client.create_device_object(); + + M2MObject* object = mbed_client.create_generic_object(); + + M2MObjectList object_list; + object_list.push_back(device_object); + object_list.push_back(object); + + mbed_client.test_register(object_list); +#endif + + pthread_create(&observation_thread, NULL, &send_observation, (void*) &mbed_client); + pthread_create(&unregister_thread, NULL, &wait_for_unregister, (void*) &mbed_client); + pthread_join(unregister_thread, NULL); + +#else + +#if defined (BOOTSTRAP_ENABLED) + // Create LWM2M bootstrap object specifying bootstrap server + // information. + M2MSecurity* security_object = mbed_client.create_bootstrap_object(_have_secure_conn); + + // Issue bootstrap command. + mbed_client.test_bootstrap(security_object); + + // Wait till the bootstrap callback is called successfully. + // Callback comes in bootstrap_done() +#ifdef SIXLOWPAN_INTERFACE + /* wait network to be established */ + do { + mesh_interface_run(); + } while(!mbed_client.bootstrap_successful()); +#else + while (!mbed_client.bootstrap_successful()) { __WFI(); } +#endif + +#else + + M2MSecurity *register_object = mbed_client.create_register_object(_have_secure_conn); + + if( mode == M2MSecurity::Certificate ){ + register_object->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::Certificate); + register_object->set_resource_value(M2MSecurity::ServerPublicKey,server_cert,server_cert_len); + register_object->set_resource_value(M2MSecurity::PublicKey,cert,cert_len); + register_object->set_resource_value(M2MSecurity::Secretkey,key,key_len); + }else if( mode == M2MSecurity::Psk ){ + register_object->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::Psk); + register_object->set_resource_value(M2MSecurity::ServerPublicKey,psk_identity,psk_identity_len); + register_object->set_resource_value(M2MSecurity::PublicKey,psk_identity,psk_identity_len); + register_object->set_resource_value(M2MSecurity::Secretkey,psk,psk_len); + }else{ + register_object->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::NoSecurity); + } + + mbed_client.set_register_object(register_object); + +#endif + + // Create LWM2M device object specifying device resources + // as per OMA LWM2M specification. + M2MDevice* device_object = mbed_client.create_device_object(); + + M2MObject* object = mbed_client.create_generic_object(); + + // Add all the objects that you would like to register + // into the list and pass the list for register API. + M2MObjectList object_list; + object_list.push_back(device_object); + object_list.push_back(object); + + // Issue register command. + + FunctionPointer1 fp(&mbed_client, &MbedClient::test_register); + minar::Scheduler::postCallback(fp.bind(object_list)); + + minar::Scheduler::start(); + + // Wait till the register callback is called successfully. + // Callback comes in object_registered() +#ifdef SIXLOWPAN_INTERFACE + /* wait network to be established */ + do { + mesh_api->processEvent(); + } while(!mbed_client.register_successful()); +#endif + + // Wait for the unregister successful callback, + // Callback comes in object_unregsitered(), this will be + // waiting for user to press SW2 button on K64F board. +#ifdef SIXLOWPAN_INTERFACE + /* wait network to be established */ + do { + mesh_api->processEvent(); + } while(!mbed_client.unregister_successful()); +#endif + + +#if defined(BOOTSTRAP_ENABLED) + // This will turn on the LED on the board specifying that + // the application has run successfully. + notify_completion(mbed_client.unregister_successful() && + mbed_client.register_successful() && + mbed_client.bootstrap_successful()); + + // Delete security object created for bootstrapping + if(security_object) { + delete security_object; + } + +#else + + // Disconnect the connect and teardown the network interface +#ifdef SIXLOWPAN_INTERFACE + mesh_api->disconnect(); +#else + eth.disconnect(); +#endif +#endif //BOOTSTRAP_ENABLED + + // Delete device object created for registering device + // resources. + if(device_object) { + M2MDevice::delete_instance(); + } + if(object) { + delete object; + } + +#endif //TARGET_LIKE_LINUX + +#ifndef TARGET_LIKE_MBED +return 0; +#endif +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/helloworld-mbedclient/mbedclient.cpp b/features/FEATURE_CLIENT/mbed-client/test/helloworld-mbedclient/mbedclient.cpp new file mode 100644 index 0000000000..200b048844 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/helloworld-mbedclient/mbedclient.cpp @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbedclient.h" + +#include "mbed-client/m2minterfacefactory.h" +#include "mbed-client/m2mdevice.h" +#include "mbed-client/m2mobjectinstance.h" +#include "mbed-client/m2mresource.h" + +#ifdef TARGET_LIKE_MBED +#include "minar/minar.h" +#include "test_env.h" +#endif + +// Enter your mbed Device Server's IPv4 address and Port number in +// mentioned format like 192.168.0.1:5693 +const String &BOOTSTRAP_SERVER_ADDRESS = "coap://10.45.3.10:5693"; +const String &BOOTSTRAP_SERVER_DTLS_ADDRESS = "coap://10.45.3.10:5694"; + +#ifdef SIXLOWPAN_INTERFACE +const String &MBED_SERVER_ADDRESS = "coap://FD00:FF1:CE0B:A5E1:1068:AF13:9B61:D557:5683"; +const String &MBED_SERVER_DTLS_ADDRESS = "coap://FD00:FF1:CE0B:A5E1:1068:AF13:9B61:D557:5684"; +#else +const String &MBED_SERVER_ADDRESS = "coap://10.45.3.10:5683"; +//const String &MBED_SERVER_ADDRESS = "coap://10.45.0.152:5683"; +const String &MBED_SERVER_DTLS_ADDRESS = "coap://10.45.3.10:5684"; +#endif +const String CLIENT_NAME = "secure-client"; + +const String &MANUFACTURER = "ARM"; +const String &TYPE = "type"; +const String &MODEL_NUMBER = "2015"; +const String &SERIAL_NUMBER = "12345"; +const uint8_t STATIC_VALUE[] = "Static value"; + +#ifdef TARGET_LIKE_LINUX +#include +#else + +#endif + +MbedClient::MbedClient() +#ifndef TARGET_LIKE_LINUX +:_led(LED3) +#endif +{ + _security = NULL; + _interface = NULL; + _register_security = NULL; + _device = NULL; + _object = NULL; + _bootstrapped = false; + _error = false; + _registered = false; + _unregistered = false; + _registration_updated = false; + _value = 0; +} + +MbedClient::~MbedClient() { + if(_security) { + delete _security; + } + if(_register_security){ + delete _register_security; + } + if(_device) { + M2MDevice::delete_instance(); + } + if(_object) { + delete _object; + } + if(_interface) { + delete _interface; + } +} + +bool MbedClient::create_interface() { + + M2MInterface::NetworkStack stack = M2MInterface::LwIP_IPv4; + #ifdef SIXLOWPAN_INTERFACE + stack = M2MInterface::Nanostack_IPv6; + #endif + + /* From http://www.iana.org/assignments/port-numbers: + "The Dynamic and/or Private Ports are those from 49152 through 65535" */ + srand(time(NULL)); + uint16_t port = (rand() % (65535-49152)) + 49152; + + _interface = M2MInterfaceFactory::create_interface(*this, + CLIENT_NAME, + "test", + 60, + port, + "", + M2MInterface::UDP, + stack, + ""); + + return (_interface == NULL) ? false : true; +} + +bool MbedClient::bootstrap_successful() { +#ifdef TARGET_LIKE_LINUX + while(!_bootstrapped && !_error) { + sleep(1); + } +#endif + return _bootstrapped; +} + +bool MbedClient::register_successful() { +#ifdef TARGET_LIKE_LINUX + while(!_registered && !_error) { + sleep(1); + } +#endif + return _registered; +} + +bool MbedClient::unregister_successful() { +#ifdef TARGET_LIKE_LINUX + while(!_unregistered && !_error) { + sleep(1); + } +#endif + return _unregistered; +} + +bool MbedClient::registration_update_successful() { +#ifdef TARGET_LIKE_LINUX + while(!_registration_updated && !_error) { + sleep(1); + } +#endif + return _registration_updated; +} + +M2MSecurity* MbedClient::create_bootstrap_object(bool useSecureConnection) { + // Creates bootstrap server object with Bootstrap server address and other parameters + // required for client to connect to bootstrap server. + M2MSecurity *security = M2MInterfaceFactory::create_security(M2MSecurity::Bootstrap); + if(security) { + if(useSecureConnection){ + security->set_resource_value(M2MSecurity::M2MServerUri, BOOTSTRAP_SERVER_DTLS_ADDRESS); + //TODO: remove these, when bootstrapping server supports DTLS + delete security; + return NULL; + }else{ + security->set_resource_value(M2MSecurity::M2MServerUri, BOOTSTRAP_SERVER_ADDRESS); + //TODO: refactor this out + security->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::NoSecurity); + } + } + return security; +} + +M2MSecurity* MbedClient::create_register_object(bool useSecureConnection) { + // Creates bootstrap server object with Bootstrap server address and other parameters + // required for client to connect to bootstrap server. + M2MSecurity *security = M2MInterfaceFactory::create_security(M2MSecurity::M2MServer); + if(security) { + if(useSecureConnection){ + security->set_resource_value(M2MSecurity::M2MServerUri, MBED_SERVER_DTLS_ADDRESS); + }else{ + security->set_resource_value(M2MSecurity::M2MServerUri, MBED_SERVER_ADDRESS); + } + } + return security; +} + +void MbedClient::test_bootstrap(M2MSecurity *security) { + if(_interface) { + // Bootstrap function. + _interface->bootstrap(security); + } +} + +M2MDevice* MbedClient::create_device_object() { + // Creates device object which contains mandatory resources linked with + // device endpoint. + M2MDevice *device = M2MInterfaceFactory::create_device(); + if(device) { + device->create_resource(M2MDevice::Manufacturer,MANUFACTURER); + device->create_resource(M2MDevice::DeviceType,TYPE); + device->create_resource(M2MDevice::ModelNumber,MODEL_NUMBER); + device->create_resource(M2MDevice::SerialNumber,SERIAL_NUMBER); + } + return device; +} + +void MbedClient::execute_function(void *argument) { +#ifdef TARGET_LIKE_LINUX + if(argument) { + char* arguments = (char*)argument; + printf("Received %s!!\n", arguments); + } + printf("I am executed !!\n"); +#else + _led == 0 ? _led = 1 : _led = 0; +#endif +} + +M2MObject* MbedClient::create_generic_object() { + _object = M2MInterfaceFactory::create_object("Test"); + if(_object) { + M2MObjectInstance* inst = _object->create_object_instance(); + if(inst) { + inst->set_operation(M2MBase::GET_ALLOWED); + + M2MResource* res = inst->create_dynamic_resource("Dynamic", + "ResourceTest", + M2MResourceInstance::INTEGER, + true); + + char buffer[20]; + int size = sprintf(buffer,"%d",_value); + res->set_operation(M2MBase::GET_PUT_POST_ALLOWED); + res->set_value((const uint8_t*)buffer, + (const uint32_t)size); + res->set_execute_function(execute_callback(this,&MbedClient::execute_function)); + _value++; + + inst->create_static_resource("Static", + "ResourceTest", + M2MResourceInstance::STRING, + STATIC_VALUE, + sizeof(STATIC_VALUE)-1); + } + } + return _object; +} + +void MbedClient::update_resource() { + if(_object) { + M2MObjectInstance* inst = _object->object_instance(); + if(inst) { + M2MResource* res = inst->resource("Dynamic"); + if( res ){ + char buffer[20]; + int size = sprintf(buffer,"%d",_value); + res->set_value((const uint8_t*)buffer, + (const uint32_t)size); + _value++; + } + } + } +} + +void MbedClient::test_register(M2MObjectList object_list){ + if(_interface) { + _interface->register_object(_register_security, object_list); + } +} + +void MbedClient::set_register_object(M2MSecurity *®ister_object){ + if(_register_security) { + delete _register_security; + _register_security = NULL; + } + _register_security = register_object; + +} + +void MbedClient::test_update_register() { + uint32_t updated_lifetime = 20; + _registered = false; + _unregistered = false; + if(_interface){ + _interface->update_registration(_register_security,updated_lifetime); + } +} + +void MbedClient::test_unregister() { + if(_interface) { + _interface->unregister_object(NULL); + } +} + +void MbedClient::bootstrap_done(M2MSecurity *server_object){ + if(server_object) { + set_register_object(server_object); + _bootstrapped = true; + _error = false; + printf("\nBootstrapped\n"); + } +} + +void MbedClient::object_registered(M2MSecurity */*security_object*/, const M2MServer &/*server_object*/){ + _registered = true; + _unregistered = false; + printf("\nRegistered\n"); +} + +void MbedClient::object_unregistered(M2MSecurity */*server_object*/){ + _unregistered = true; + _registered = false; + +#ifdef TARGET_LIKE_MBED + notify_completion(_unregistered); + minar::Scheduler::stop(); +#endif + printf("\nUnregistered\n"); +} + +void MbedClient::registration_updated(M2MSecurity */*security_object*/, const M2MServer & /*server_object*/){ + _registration_updated = true; + printf("\nregistration updated\n"); +} + +void MbedClient::error(M2MInterface::Error error){ + _error = true; + printf("\nError occured Error code %d\n", (int)error); +} + +void MbedClient::value_updated(M2MBase *base, M2MBase::BaseType type) { + printf("\nValue updated of Object name %s and Type %d\n", + base->name().c_str(), type); +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/helloworld-mbedclient/mbedclient.h b/features/FEATURE_CLIENT/mbed-client/test/helloworld-mbedclient/mbedclient.h new file mode 100644 index 0000000000..ec3557e8ae --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/helloworld-mbedclient/mbedclient.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 __MBED_CLIENT_H__ +#define __MBED_CLIENT_H__ + +#undef SIXLOWPAN_INTERFACE + +#include "mbed-client/m2minterfaceobserver.h" + +#ifndef TARGET_LIKE_LINUX +#include "mbed/DigitalOut.h" +#endif + + +//#define BOOTSTRAP_ENABLED + +class M2MDevice; +class M2MSecurity; +class M2MObject; + +class MbedClient: public M2MInterfaceObserver { +public: + MbedClient(); + + ~MbedClient(); + + bool create_interface(); + + bool bootstrap_successful(); + + bool register_successful(); + + bool unregister_successful(); + + bool registration_update_successful(); + + M2MSecurity* create_bootstrap_object(bool useSecureConnection); + + M2MSecurity* create_register_object(bool useSecureConnection); + + void test_bootstrap(M2MSecurity *security); + + M2MDevice* create_device_object(); + + void execute_function(void *argument); + + M2MObject* create_generic_object(); + + void update_resource(); + + void test_register(M2MObjectList object_list); + + void set_register_object(M2MSecurity *®ister_object); + + void test_update_register(); + + void test_unregister(); + + //Callback from mbed client stack when the bootstrap + // is successful, it returns the mbed Device Server object + // which will be used for registering the resources to + // mbed Device server. + void bootstrap_done(M2MSecurity *server_object); + + //Callback from mbed client stack when the registration + // is successful, it returns the mbed Device Server object + // to which the resources are registered and registered objects. + void object_registered(M2MSecurity */*security_object*/, const M2MServer &/*server_object*/); + + //Callback from mbed client stack when the unregistration + // is successful, it returns the mbed Device Server object + // to which the resources were unregistered. + void object_unregistered(M2MSecurity */*server_object*/); + + void registration_updated(M2MSecurity */*security_object*/, const M2MServer & /*server_object*/); + + //Callback from mbed client stack if any error is encountered + // during any of the LWM2M operations. Error type is passed in + // the callback. + void error(M2MInterface::Error error); + + //Callback from mbed client stack if any value has changed + // during PUT operation. Object and its type is passed in + // the callback. + void value_updated(M2MBase *base, M2MBase::BaseType type); + +private: + +#ifndef TARGET_LIKE_LINUX + mbed::DigitalOut _led; +#endif + M2MInterface *_interface; + M2MSecurity *_security; + M2MSecurity *_register_security; + M2MDevice *_device; + M2MObject *_object; + bool _bootstrapped; + bool _error; + bool _registered; + bool _unregistered; + bool _registration_updated; + int _value; +}; + + + +#endif //__MBED_CLIENT_H__ diff --git a/features/FEATURE_CLIENT/mbed-client/test/helloworld-mbedclient/to_be_ported.c b/features/FEATURE_CLIENT/mbed-client/test/helloworld-mbedclient/to_be_ported.c new file mode 100644 index 0000000000..0171d1e315 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/helloworld-mbedclient/to_be_ported.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 + +void arm_random_module_init(void) +{ +} + +uint32_t arm_random_seed_get(void) +{ + return 0; +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/cmd_commands.cpp b/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/cmd_commands.cpp new file mode 100644 index 0000000000..f2afacf6a8 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/cmd_commands.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2014-2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "ns_types.h" +#include "eventOS_event.h" +#include "eventOS_event_timer.h" +#include "net_interface.h" +#include "socket_api.h" +#include "mbed-trace/mbed_trace.h" +#include "common_functions.h" + +#include "ns_cmdline.h" +#include "cmd_commands.h" +#include "cmd_lwm2m.h" + +#define TRACE_GROUP "cApp" + +#define ESC 0x03 +#define EVENT_DATA_COMMAND_EXECUTED 6 + +// Prototypes +void cmd_ready_cb(int retcode); + +static void cmdline_event(arm_event_s *event); + +/** +* Callback function for thread handling. +*/ +void* __thread_poll_function(void*); + +typedef struct { + uint8_t tasklet_id; +} cmd_commands_t; + +cmd_commands_t cmd_commands; +pthread_t input_thread; /* Thread for input_terminal-function */ + +void initialize_app_commands(int8_t /*rf_driver_id*/) +{ + //initialize ready cb + cmd_set_ready_cb( cmd_ready_cb ); + lwm2m_command_init(); + + cmd_commands.tasklet_id = eventOS_event_handler_create(&cmdline_event, EVENT_TYPE_CMDLINE); + pthread_create(&input_thread, NULL,__thread_poll_function, NULL); +} + +void cmd_ready_cb(int retcode) +{ + tr_debug("cmd_ready_cb(%d)", retcode); + arm_event_s event; + event.sender = cmd_commands.tasklet_id; + event.receiver = cmd_commands.tasklet_id; + event.event_type = APPLICATION_EVENT; + event.event_id = EVENT_DATA_COMMAND_EXECUTED; + event.event_data = retcode; + eventOS_event_send(&event); +} + +static void cmdline_event(arm_event_s *event) +{ + switch( event->event_type ) + { + case ARM_LIB_TASKLET_INIT_EVENT: + //tasklet up and running + tr_warning("cmdline_event-ARM_LIB_TASKLET_INIT_EVENT"); + break; + + case APPLICATION_EVENT: + if( event->event_id == EVENT_DATA_COMMAND_EXECUTED ) + { + int retcode = event->event_data; + cmd_next( retcode ); + } + break; + default: + tr_warning("Unknown event type (type: %i, id: %i)", event->event_type, event->event_id); + break; + } +} + +void* __thread_poll_function(void*) +{ + int16_t c = getchar(); + while( c >= 0 ) { + cmd_char_input(c); + c = getchar(); + } + return NULL; +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/cmd_commands.h b/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/cmd_commands.h new file mode 100644 index 0000000000..544671803a --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/cmd_commands.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 CMD_COMMANDS_H_ +#define CMD_COMMANDS_H_ + +#include + +#define EVENT_TYPE_CMDLINE 5 +#define EVENT_CMDLINE_CONSOLE 5 + +void initialize_app_commands(int8_t rf_driver_id); + +#endif diff --git a/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/cmd_lwm2m.cpp b/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/cmd_lwm2m.cpp new file mode 100644 index 0000000000..edc0526be7 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/cmd_lwm2m.cpp @@ -0,0 +1,875 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 + +//libServices +#include "ns_types.h" +#include "ns_cmdline.h" +#include "cmd_lwm2m.h" +#include "lwm2mtest.h" + +#define CMD_MAN_LWM2M_CLIENT "lwm2m-client [options] LWM2M mbed Client API\n"\ + "setup

[options] Set up the LWM2M Interface\n"\ + "

:\n"\ + " Options for setup command\n"\ + " --endpoint Endpoint Name (mandatory)\n"\ + " --type Resource Type\n"\ + " --lifetime Lifetime in seconds, default is -1 means not included\n"\ + " --port Listen port, default is 5683\n"\ + " --domain Domain for mbed Device Server, default is empty\n"\ + " --binding_mode Binding Mode, NOT_SET = 0|UDP = 1(default)|QUEUE = 2|SMS = 4\n"\ + " --network_interface Network Interface, Uninitialized = 0 ,LwIP_IPv4 = 1(default), LwIP_IPv6 = 2, Nanostack_IPv6 = 4\n"\ + "bootstrap_object

[options]\n"\ + "

:\n"\ + " Options for bootstrap object command\n"\ + " --address Bootstrap server address, format is coap://192.168.0.1:5683\n"\ + "bootstrap Issues Bootstrap command\n"\ + "object

[options]\n"\ + "

:\n"\ + " Options for custom object\n"\ + " --name Object name\n"\ + " --new_instance If you need new instance 0=false(default), 1=true\n"\ + " --object_observable Object is observable false=0(default), true=1\n"\ + " --object_instance_observable Object Instance is observable false=0(default), true=1\n"\ + " --object_instance_id Instance id of object instance 0=(default)\n"\ + " --object_operation Operation Mode, Default is 0, NOT_ALLOWED = 0, GET_ALLOWED = 1,\n"\ + "PUT_ALLOWED = 2, GET_PUT_ALLOWED = 3, POST_ALLOWED = 4,GET_POST_ALLOWED = 5,\n"\ + "PUT_POST_ALLOWED = 6, GET_PUT_POST_ALLOWED = 7, DELETE_ALLOWED = 8\n"\ + " --object_instance_operation Operation Mode, Default is 0, NOT_ALLOWED = 0, GET_ALLOWED = 1,\n"\ + "PUT_ALLOWED = 2, GET_PUT_ALLOWED = 3, POST_ALLOWED = 4,GET_POST_ALLOWED = 5,\n"\ + "PUT_POST_ALLOWED = 6, GET_PUT_POST_ALLOWED = 7, DELETE_ALLOWED = 8\n"\ + "static_resource

[options]\n"\ + "

:\n"\ + " Options for static resource\n"\ + " --object_instance Instance Id of the object this resource is associated with, default is 0\n"\ + " --name Resource name\n"\ + " --value Resource value\n"\ + " --value_type Value Type String=0, Integer=1\n"\ + " --multiple_instance Supports multiple instances, false=0(default), true=1\n"\ + "dynamic_resource

[options]\n"\ + "

:\n"\ + " Options for dynamic resource\n"\ + " --object_instance Instance Id of the object this resource is associated with, default is 0\n"\ + " --name Resource name\n"\ + " --observable Resource is observable false=0(default), true=1\n"\ + " --multiple_instance Supports multiple instances, false=0(default), true=1\n"\ + " --resource_operation Operation Mode, Default is 1, NOT_ALLOWED = 0, GET_ALLOWED = 1,\n"\ + "PUT_ALLOWED = 2, GET_PUT_ALLOWED = 3, POST_ALLOWED = 4,GET_POST_ALLOWED = 5,\n"\ + "PUT_POST_ALLOWED = 6, GET_PUT_POST_ALLOWED = 7, DELETE_ALLOWED = 8\n"\ + "dynamic_resource

[options]\n"\ + "static_resource_instance

[options]\n"\ + "

:\n"\ + " Options for static resource instance\n"\ + " --object_instance Instance Id of the object this resource is associated with, default is 0\n"\ + " --resource_instance Instance Id of the resource associated with, default is 0\n"\ + " --name Resource name\n"\ + " --value Resource value\n"\ + " --value_type Value Type String=0, Integer=1\n"\ + " --multiple_instance Supports multiple instances, false=0(default), true=1\n"\ + "dynamic_resource

[options]\n"\ + "dynamic_resource_instance

[options]\n"\ + "

:\n"\ + " Options for dynamic resource instance\n"\ + " --object_instance Instance Id of the object this resource is associated with, default is 0\n"\ + " --resource_instance Instance Id of the resource associated with, default is 0\n"\ + " --name Resource name\n"\ + " --value_type Value Type String=0, Integer=1(default)\n"\ + " --observable Resource is observable false=0(default), true=1\n"\ + " --multiple_instance Supports multiple instances, false=0(default), true=1\n"\ + " --resource_instance_operation Operation Mode, Default is 1, NOT_ALLOWED = 0, GET_ALLOWED = 1,\n"\ + "PUT_ALLOWED = 2, GET_PUT_ALLOWED = 3, POST_ALLOWED = 4,GET_POST_ALLOWED = 5,\n"\ + "PUT_POST_ALLOWED = 6, GET_PUT_POST_ALLOWED = 7, DELETE_ALLOWED = 8\n"\ + "dynamic_resource

[options]\n"\ + "device

[options]\n"\ + "

:\n"\ + " Options for device object \n"\ + " --manufacturer Manufacturer name\n"\ + " --model_number Model number\n"\ + " --serial_number Serial number\n"\ + " --device_type Device Type\n"\ + " --hardware_version Hardware version\n"\ + " --software_version Software version\n"\ + " --firmware_version Firmware version\n"\ + " --available_power_sources Number of available power sources, Must have Instance ID\n"\ + " --power_source_voltage Power source voltage, Must have Instance ID\n"\ + " --power_source_current Power source current, Must have Instance ID\n"\ + " --battery_level Battery level\n"\ + " --battery_status Battery status\n"\ + " --memory_free Free memory, in bytes\n"\ + " --memory_total Free memory in bytes\n"\ + " --error_code Error Code, Must have Instance ID\n"\ + " --current_time Current Time, EPOCH format\n"\ + " --utc_offset UTC Format\n"\ + " --timezone Time zone \n"\ + " --instance_id Instance ID for multiple resources \n"\ + "firmware

[options]\n"\ + "

:\n"\ + " Options for firmware object \n"\ + " --package Firmware package\n"\ + " --package_uri URI from where the device can download package\n"\ + " --state State of firmware update\n"\ + " --update_supported_objects Send update registration message after fw update\n"\ + " --update_results Result of downloading or updating firmware\n"\ + " --package_name Package name\n"\ + " --package_version Package version\n"\ + "register_object

[options]\n"\ + "

:\n"\ + " Options for register command\n"\ + " --address mbed Device Server address, format is coap://192.168.0.1:5683\n"\ + " --secure 1 == secure mode, non-secure otherwise (remember: secure port is 5684)\n"\ + "register Issues Register command\n"\ + "update-register

[options] Issues Update registration command\n"\ + "

:\n"\ + " Options for update-register command\n"\ + " --lifetime Lifetime value in seconds\n"\ + "unregister Issues Un-register command\n"\ + "set_value

[options]\n"\ + "

:\n"\ + " Options for set_value command \n"\ + " --name Resource name (Mandatory)\n"\ + " --value Resource value (Mandatory)\n"\ + " --object_instance Instance ID of object this resource is associated with, default is 0\n"\ + "set_value_instance

[options]\n"\ + "

:\n"\ + " Options for set_value_instance command for Resource Instances\n"\ + " --name Resource name (Mandatory)\n"\ + " --value Resource value (Mandatory)\n"\ + " --object_instance Instance ID of object this resource is associated with, default is 0\n"\ + " --resource_instance Instance ID of object of the resource, default is 0\n"\ + "resource_value

[options]\n"\ + "

:\n"\ + " Options for resource_value command\n"\ + " --firmware Resource instance id in Firmware object\n"\ + +#define EXIT_MANUAL "exit :closes the application\n" + + +int lwm2m_client_command(int argc, char *argv[]); +int lwm2m_client_setup_command(int argc, char *argv[]); +int lwm2m_client_device_command(int argc, char *argv[]); +int lwm2m_client_object_command(int argc, char *argv[]); +int lwm2m_client_static_resource_command(int argc, char *argv[]); +int lwm2m_client_dynamic_resource_command(int argc, char *argv[]); +int lwm2m_client_static_resource_instance_command(int argc, char *argv[]); +int lwm2m_client_dynamic_resource_instance_command(int argc, char *argv[]); +int lwm2m_client_bootstrap_object_command(int argc, char *argv[]); +int lwm2m_client_bootstrap_command(); +int lwm2m_client_register_object_command(int argc, char *argv[]); +int lwm2m_client_register_command(); +int lwm2m_client_update_register_command(int argc, char *argv[]); +int lwm2m_client_unregister_command(); +int lwm2m_client_set_value_command(int argc, char *argv[]); +int lwm2m_client_set_value_instance_command(int argc, char *argv[]); +int lwm2m_client_firmware_command(int argc, char *argv[]); +int lwm2m_client_resource_value(int argc, char *argv[]); +int exit_command(int argc, char *argv[]); + +void lwm2m_command_init(void) +{ + cmd_add("lwm2m-client", lwm2m_client_command, "LWM2M Client specific command", CMD_MAN_LWM2M_CLIENT); + cmd_alias_add("lwm2m-client-test-setup", "lwm2m-client setup --endpoint lwm2m-endpoint --type test --lifetime 3600"); + cmd_alias_add("lwm2m-client-test-device", "lwm2m-client device --manufacturer ARM --model_number 2015 --serial_number 12345"); + cmd_alias_add("lwm2m-client-test-bootstrap-object", "lwm2m-client bootstrap_object --address coap://10.45.3.10:5693"); + cmd_alias_add("lwm2m-client-test-register-object", "lwm2m-client register_object --address coap://10.45.3.10:5683"); + cmd_alias_add("lwm2m-client-test-object", "lwm2m-client object --name 10 --object_observable 1 --object_instance_observable 1 --object_operation 3 --object_instance_operation 3"); + cmd_alias_add("lwm2m-client-test-dynamic_resource", "lwm2m-client dynamic_resource --name 1 --resource_operation 3 --observable 0"); + cmd_alias_add("lwm2m-client-test-secure-register-object", "lwm2m-client register_object --address coap://10.45.3.10:5684 --secure 1"); + cmd_add("exit", exit_command, "exit command", EXIT_MANUAL); +} +char *test_mem_block = 0; +int test_timer; +M2MLWClient lwm2m_client; + +int lwm2m_client_command(int argc, char *argv[]) +{ + if( strcmp(argv[1], "setup") == 0 ) + { + return lwm2m_client_setup_command(argc, argv); + } + else if( strcmp(argv[1], "bootstrap_object") == 0 ) + { + return lwm2m_client_bootstrap_object_command(argc, argv); + } + else if( strcmp(argv[1], "bootstrap") == 0 ) + { + return lwm2m_client_bootstrap_command(); + } + else if( strcmp(argv[1], "device") == 0 ) + { + return lwm2m_client_device_command(argc, argv); + } + else if( strcmp(argv[1], "firmware") == 0 ) + { + return lwm2m_client_firmware_command(argc, argv); + } + else if( strcmp(argv[1], "resource_value") == 0 ) + { + return lwm2m_client_resource_value(argc, argv); + } + else if( strcmp(argv[1], "object") == 0 ) + { + return lwm2m_client_object_command(argc, argv); + } + else if( strcmp(argv[1], "static_resource") == 0 ) + { + return lwm2m_client_static_resource_command(argc, argv); + } + else if( strcmp(argv[1], "dynamic_resource") == 0 ) + { + return lwm2m_client_dynamic_resource_command(argc, argv); + } + else if( strcmp(argv[1], "static_resource_instance") == 0 ) + { + return lwm2m_client_static_resource_instance_command(argc, argv); + } + else if( strcmp(argv[1], "dynamic_resource_instance") == 0 ) + { + return lwm2m_client_dynamic_resource_instance_command(argc, argv); + } + else if( strcmp(argv[1], "register_object") == 0 ) + { + return lwm2m_client_register_object_command(argc, argv); + } + else if( strcmp(argv[1], "register") == 0 ) + { + return lwm2m_client_register_command(); + } + else if( strcmp(argv[1], "update-register") == 0 ) + { + return lwm2m_client_update_register_command(argc, argv); + } + else if( strcmp(argv[1], "unregister") == 0 ) + { + return lwm2m_client_unregister_command(); + } + else if ( strcmp(argv[1], "set_value") == 0) + { + return lwm2m_client_set_value_command(argc, argv); + } + else if ( strcmp(argv[1], "set_value_instance") == 0) + { + return lwm2m_client_set_value_instance_command(argc, argv); + } + //:TODO what another commands should be there ? + return CMDLINE_RETCODE_COMMAND_NOT_IMPLEMENTED; +} + +int lwm2m_client_setup_command(int argc, char *argv[]) +{ + char *endpoint = 0; + char *type = 0; + int lifetime = -1; + int32_t port = 5683; + char *domain = 0; + int32_t binding_mode = 1; + int32_t network_interface = 1; + + if (!cmd_parameter_val(argc, argv, "--endpoint", &endpoint)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + int opt_params = 0; + cmd_parameter_val(argc, argv, "--type", &type); + if (cmd_parameter_int(argc, argv, "--lifetime", &lifetime)) { + if (opt_params != 0) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + else { + opt_params += 1; + } + } + if (cmd_parameter_int(argc, argv, "--port", &port)) { + if (port > UINT16_MAX || opt_params != 1) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + else { + opt_params += 1; + } + } + if (cmd_parameter_val(argc, argv, "--domain", &domain)) { + if (opt_params != 2) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + else { + opt_params += 1; + } + } + if (cmd_parameter_int(argc, argv, "--binding_mode", &binding_mode)) { + if (opt_params != 3) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + else { + opt_params += 1; + } + } + if (cmd_parameter_int(argc, argv, "--network_interface", &network_interface)) { + if (opt_params != 4) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + else { + opt_params += 1; + } + } + + bool success = false; + if (lwm2m_client.create_interface(opt_params, + endpoint, + type, + lifetime, + port, + domain, + binding_mode, + network_interface)) { + return CMDLINE_RETCODE_SUCCESS; + } + + return CMDLINE_RETCODE_FAIL; +} + +int lwm2m_client_device_command(int argc, char *argv[]) +{ + int return_code = CMDLINE_RETCODE_SUCCESS;// CMDLINE_RETCODE_INVALID_PARAMETERS; + char *manufacturer = 0; + char *model_number = 0; + char *serial_number = 0; + char *device_type = 0; + char *hardware_version = 0; + char *software_version = 0; + char *firmware_version = 0; + char *utc_offset = 0; + char *timezone = 0; + int32_t current_time = 0; + int32_t available_power_sources = 0; + int32_t power_source_voltage = 0; + int32_t power_source_current = 0; + int32_t battery_status = 0; + int32_t battery_level = 0; + int32_t memory_free = 0; + int32_t memory_total = 0; + int32_t error_code = 0; + int32_t instance_id = 0; + + lwm2m_client.create_device_object(); + + if(cmd_parameter_val(argc, argv, "--manufacturer", &manufacturer)) { + if(!lwm2m_client.create_device_object(M2MDevice::Manufacturer, + manufacturer)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if(cmd_parameter_val(argc, argv, "--model_number", &model_number)) { + if(!lwm2m_client.create_device_object(M2MDevice::ModelNumber, + model_number)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if(cmd_parameter_val(argc, argv, "--serial_number", &serial_number)){ + if(!lwm2m_client.create_device_object(M2MDevice::SerialNumber, + serial_number)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if(cmd_parameter_val(argc, argv, "--device_type", &device_type)){ + if(!lwm2m_client.create_device_object(M2MDevice::DeviceType, + device_type)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if(cmd_parameter_val(argc, argv, "--hardware_version", &hardware_version)){ + if(!lwm2m_client.create_device_object(M2MDevice::HardwareVersion, + hardware_version)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if(cmd_parameter_val(argc, argv, "--software_version", &software_version)){ + if(!lwm2m_client.create_device_object(M2MDevice::SoftwareVersion, + software_version)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if(cmd_parameter_val(argc, argv, "--firmware_version", &firmware_version)){ + if(!lwm2m_client.create_device_object(M2MDevice::FirmwareVersion, + firmware_version)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if(cmd_parameter_int(argc, argv, "--available_power_sources", &available_power_sources)){ + if(cmd_parameter_int(argc, argv, "--instance_id", &instance_id)) { + if(!lwm2m_client.create_device_object(M2MDevice::AvailablePowerSources, + available_power_sources,instance_id)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + } + if(cmd_parameter_int(argc, argv, "--power_source_voltage", &power_source_voltage)){ + if(cmd_parameter_int(argc, argv, "--instance_id", &instance_id)) { + if(!lwm2m_client.create_device_object(M2MDevice::PowerSourceVoltage, + power_source_voltage,instance_id)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + } + if(cmd_parameter_int(argc, argv, "--power_source_current", &power_source_current)){ + if(cmd_parameter_int(argc, argv, "--instance_id", &instance_id)) { + if(!lwm2m_client.create_device_object(M2MDevice::PowerSourceCurrent, + power_source_current,instance_id)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + } + if(cmd_parameter_int(argc, argv, "--battery_level", &battery_level)){ + if(!lwm2m_client.create_device_object(M2MDevice::BatteryLevel, + battery_level)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if(cmd_parameter_int(argc, argv, "--battery_status", &battery_status)){ + if(!lwm2m_client.create_device_object(M2MDevice::BatteryStatus, + battery_status)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if(cmd_parameter_int(argc, argv, "--memory_free", &memory_free)){ + if(!lwm2m_client.create_device_object(M2MDevice::MemoryFree, + memory_free)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if(cmd_parameter_int(argc, argv, "--memory_total", &memory_total)){ + if(!lwm2m_client.create_device_object(M2MDevice::MemoryTotal, + memory_total)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if(cmd_parameter_int(argc, argv, "--error_code", &error_code)){ + if(cmd_parameter_int(argc, argv, "--instance_id", &instance_id)) { + if(!lwm2m_client.create_device_object(M2MDevice::ErrorCode, + error_code,instance_id)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + } + if(cmd_parameter_int(argc, argv, "--current_time", ¤t_time)){ + if(!lwm2m_client.create_device_object(M2MDevice::CurrentTime, + current_time)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if(cmd_parameter_val(argc, argv, "--utc_offset", &utc_offset)){ + if(!lwm2m_client.create_device_object(M2MDevice::UTCOffset, + utc_offset)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if(cmd_parameter_val(argc, argv, "--timezone", &timezone)){ + if(!lwm2m_client.create_device_object(M2MDevice::Timezone, + timezone)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + + return return_code; +} + +int lwm2m_client_firmware_command(int argc, char *argv[]) +{ + int return_code = CMDLINE_RETCODE_SUCCESS;// CMDLINE_RETCODE_INVALID_PARAMETERS; + char *package = 0; + char *package_uri = 0; + char *package_name = 0; + char *package_version = 0; + int32_t state = 1; + int32_t update_result = 0; + int32_t update_supported_objects = 0; + + lwm2m_client.create_firmware_object(); + + if(cmd_parameter_val(argc, argv, "--package", &package)) { + uint16_t length = (uint16_t)sizeof(package); + if(!lwm2m_client.create_firmware_object(M2MFirmware::Package, + (const uint8_t*)package, length)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + + if(cmd_parameter_val(argc, argv, "--package_uri", &package_uri)) { + if(!lwm2m_client.create_firmware_object(M2MFirmware::PackageUri, + package_uri)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if(cmd_parameter_int(argc, argv, "--state", &state)) { + if(!lwm2m_client.create_firmware_object(M2MFirmware::State, + state)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if(cmd_parameter_int(argc, argv, "--update_supported_objects", &update_supported_objects)) { + if(!lwm2m_client.create_firmware_object(M2MFirmware::UpdateSupportedObjects, + update_supported_objects)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if(cmd_parameter_int(argc, argv, "--update_results", &update_result)) { + if(!lwm2m_client.create_firmware_object(M2MFirmware::UpdateResult, + update_result)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if(cmd_parameter_val(argc, argv, "--package_name", &package_name)) { + if(!lwm2m_client.create_firmware_object(M2MFirmware::PackageName, + package_name)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + if(cmd_parameter_val(argc, argv, "--package_version", &package_version)) { + if(!lwm2m_client.create_firmware_object(M2MFirmware::PackageVersion, + package_version)) { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + lwm2m_client.set_fw_execute_function(); + return return_code; +} + +int lwm2m_client_resource_value(int argc, char *argv[]) +{ + int resource = 0; + if(cmd_parameter_int(argc, argv, "--firmware", &resource)) { + if (resource == 3 || resource == 4 || resource == 5) { + lwm2m_client.firmware_resource_int(resource); + } + else if (resource == 0) { + lwm2m_client.firmware_resource_buffer(); + } + else { + lwm2m_client.firmware_resource_string(resource); + } + } + return CMDLINE_RETCODE_SUCCESS; +} + +int lwm2m_client_object_command(int argc, char *argv[]) +{ + int return_code = CMDLINE_RETCODE_SUCCESS;// CMDLINE_RETCODE_INVALID_PARAMETERS; + char *object_name = 0; + int32_t new_instance = 0; + int32_t object_operation = 0; + int32_t object_instance_operation = 0; + int32_t object_instance_id = 0; + int32_t object_observable = 0; + int32_t object_instance_observable = 0; + + if(cmd_parameter_val(argc, argv, "--name", &object_name)) { + cmd_parameter_int(argc, argv, "--new_instance", &new_instance); + cmd_parameter_int(argc, argv, "--object_operation", &object_operation); + cmd_parameter_int(argc, argv, "--object_instance_operation", &object_instance_operation); + cmd_parameter_int(argc, argv, "--object_instance_id", &object_instance_id); + cmd_parameter_int(argc, argv, "--object_observable", &object_observable); + cmd_parameter_int(argc, argv, "--object_instance_observable", &object_instance_observable); + + if(!lwm2m_client.create_object(object_name, + new_instance, + object_operation, + object_instance_operation, + object_instance_id, + object_observable, + object_instance_observable)) { + return_code = CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } + return return_code; +} + +int lwm2m_client_static_resource_command(int argc, char *argv[]) +{ + int return_code = CMDLINE_RETCODE_INVALID_PARAMETERS; + char *name = 0; + char *value_string = 0; + int32_t value_int = 0; + int32_t value_type = -1; + int32_t multiple_instance = 0; + int32_t object_instance = 0; + + cmd_parameter_int(argc, argv, "--multiple_instance", &multiple_instance); + cmd_parameter_int(argc, argv, "--object_instance", &object_instance); + + + if(cmd_parameter_int(argc, argv, "--value_type", &value_type)) { + if(0 == value_type){ + if(cmd_parameter_val(argc, argv, "--name", &name) && + cmd_parameter_val(argc, argv, "--value", &value_string)) { + if(lwm2m_client.create_static_resource_string(name,value_string, + multiple_instance,object_instance)) { + return_code = CMDLINE_RETCODE_SUCCESS; + } + } + } else if(1 == value_type){ + if(cmd_parameter_val(argc, argv, "--name", &name) && + cmd_parameter_int(argc, argv, "--value", &value_int)) { + if(lwm2m_client.create_static_resource_int(name,value_int, + multiple_instance,object_instance)) { + return_code = CMDLINE_RETCODE_SUCCESS; + } + } + } + } + return return_code; +} + +int lwm2m_client_dynamic_resource_command(int argc, char *argv[]) +{ + int return_code = CMDLINE_RETCODE_INVALID_PARAMETERS; + char *name = 0; + int32_t multiple_instance = 0; + int32_t object_instance = 0; + int32_t observable = 0; + int32_t resource_operation = 1; + int32_t value_type = -1; + + cmd_parameter_int(argc, argv, "--value_type", &value_type); + cmd_parameter_int(argc, argv, "--multiple_instance", &multiple_instance); + cmd_parameter_int(argc, argv, "--object_instance", &object_instance); + cmd_parameter_int(argc, argv, "--observable", &observable); + cmd_parameter_int(argc, argv, "--resource_operation", &resource_operation); + if(-1 == value_type){ + value_type = 1; + } + + if(cmd_parameter_val(argc, argv, "--name", &name)) { + if(0 == value_type) { + if(lwm2m_client.create_dynamic_resource_string(name,observable, + multiple_instance, + object_instance, + resource_operation)) { + return_code = CMDLINE_RETCODE_SUCCESS; + } + } + else if(1 == value_type){ + if(lwm2m_client.create_dynamic_resource_int(name,observable, + multiple_instance, + object_instance, + resource_operation)) { + return_code = CMDLINE_RETCODE_SUCCESS; + } + } + + } + return return_code; +} + +int lwm2m_client_static_resource_instance_command(int argc, char *argv[]) +{ + int return_code = CMDLINE_RETCODE_INVALID_PARAMETERS; + char *name = 0; + char *value_string = 0; + int32_t value_int = 0; + int32_t value_type = -1; + int32_t multiple_instance = 0; + int32_t object_instance = 0; + int32_t resource_instance = 0; + + cmd_parameter_int(argc, argv, "--multiple_instance", &multiple_instance); + cmd_parameter_int(argc, argv, "--object_instance", &object_instance); + cmd_parameter_int(argc, argv, "--resource_instance", &resource_instance); + + if(cmd_parameter_int(argc, argv, "--value_type", &value_type)) { + if(0 == value_type){ + if(cmd_parameter_val(argc, argv, "--name", &name) && + cmd_parameter_val(argc, argv, "--value", &value_string)) { + if(lwm2m_client.create_static_resource_instance_string(name,value_string, + multiple_instance, + object_instance, + resource_instance)) { + return_code = CMDLINE_RETCODE_SUCCESS; + } + } + } else if(1 == value_type){ + if(cmd_parameter_val(argc, argv, "--name", &name) && + cmd_parameter_int(argc, argv, "--value", &value_int)) { + if(lwm2m_client.create_static_resource_instance_int(name,value_int, + multiple_instance, + object_instance, + resource_instance)) { + return_code = CMDLINE_RETCODE_SUCCESS; + } + } + } + } + return return_code; +} + +int lwm2m_client_dynamic_resource_instance_command(int argc, char *argv[]) +{ + int return_code = CMDLINE_RETCODE_INVALID_PARAMETERS; + char *name = 0; + int32_t multiple_instance = 0; + int32_t object_instance = 0; + int32_t resource_instance = 0; + int32_t observable = 0; + int32_t resource_instance_operation = 1; + int32_t value_type = -1; + + cmd_parameter_int(argc, argv, "--value_type", &value_type); + cmd_parameter_int(argc, argv, "--multiple_instance", &multiple_instance); + cmd_parameter_int(argc, argv, "--object_instance", &object_instance); + cmd_parameter_int(argc, argv, "--resource_instance", &resource_instance); + cmd_parameter_int(argc, argv, "--observable", &observable); + cmd_parameter_int(argc, argv, "--resource_instance_operation", &resource_instance_operation); + if(-1 == value_type){ + value_type = 1; + } + + if(cmd_parameter_val(argc, argv, "--name", &name)) { + if(0 == value_type){ + if(lwm2m_client.create_dynamic_resource_instance_string(name,observable, + multiple_instance, + object_instance, + resource_instance, + resource_instance_operation)) { + return_code = CMDLINE_RETCODE_SUCCESS; + } + } + else if(1 == value_type){ + if(lwm2m_client.create_dynamic_resource_instance_int(name,observable, + multiple_instance, + object_instance, + resource_instance, + resource_instance_operation)) { + return_code = CMDLINE_RETCODE_SUCCESS; + } + } + } + return return_code; +} + +int lwm2m_client_bootstrap_object_command(int argc, char *argv[]) +{ + int return_code = CMDLINE_RETCODE_FAIL; + char *address = 0; + + if( cmd_parameter_val(argc, argv, "--address", &address) ){ + if(lwm2m_client.create_bootstrap_object(address)){ + return_code = CMDLINE_RETCODE_SUCCESS; + } + } else { + return_code = CMDLINE_RETCODE_INVALID_PARAMETERS; + } + return return_code; +} + +int lwm2m_client_bootstrap_command() +{ + int return_code = CMDLINE_RETCODE_FAIL; + + if(lwm2m_client.test_bootstrap()){ + return_code = CMDLINE_RETCODE_EXCUTING_CONTINUE; + } + return return_code; +} + +int lwm2m_client_register_object_command(int argc, char *argv[]) +{ + char *address = 0; + cmd_parameter_val(argc, argv, "--address", &address); + + int useSecureConn = 0; + if( !cmd_parameter_int(argc, argv, "--secure", &useSecureConn) ){ + useSecureConn = 0; + } + + if(lwm2m_client.create_register_object(address, useSecureConn == 1)) { + return CMDLINE_RETCODE_SUCCESS; + } + return CMDLINE_RETCODE_INVALID_PARAMETERS; +} + +int lwm2m_client_register_command() +{ + if(lwm2m_client.test_register()) { + return CMDLINE_RETCODE_EXCUTING_CONTINUE; + } + return CMDLINE_RETCODE_INVALID_PARAMETERS; +} + +int lwm2m_client_update_register_command(int argc, char *argv[]) +{ + int ret_code = CMDLINE_RETCODE_INVALID_PARAMETERS; + int32_t lifetime = 0; + + cmd_parameter_int(argc, argv, "--lifetime", &lifetime); + + if(lifetime >= 0) { + if(lwm2m_client.test_update_register(lifetime)) { + ret_code = CMDLINE_RETCODE_EXCUTING_CONTINUE; + } + } + return ret_code; +} + +int lwm2m_client_unregister_command() +{ + if(lwm2m_client.test_unregister()) { + return CMDLINE_RETCODE_EXCUTING_CONTINUE; + } + return CMDLINE_RETCODE_INVALID_PARAMETERS; +} + +int lwm2m_client_set_value_command(int argc, char *argv[]) +{ + int return_code = CMDLINE_RETCODE_INVALID_PARAMETERS; + char *name = 0; + int32_t value = 0; + int32_t object_instance = 0; + + cmd_parameter_int(argc, argv, "--object_instance", &object_instance); + + if(cmd_parameter_val(argc, argv, "--name", &name) && + cmd_parameter_int(argc, argv, "--value", &value)) { + if(lwm2m_client.set_resource_value(name,value,object_instance)) { + return_code = CMDLINE_RETCODE_SUCCESS; + } + } + return return_code; +} + +int lwm2m_client_set_value_instance_command(int argc, char *argv[]) +{ + int return_code = CMDLINE_RETCODE_INVALID_PARAMETERS; + char *name = 0; + int32_t value = 0; + int32_t object_instance = 0; + int32_t resource_instance = 0; + + cmd_parameter_int(argc, argv, "--object_instance", &object_instance); + cmd_parameter_int(argc, argv, "--resource_instance", &resource_instance); + + if(cmd_parameter_val(argc, argv, "--name", &name) && + cmd_parameter_int(argc, argv, "--value", &value)) { + if(lwm2m_client.set_resource_instance_value(name,value, + object_instance, + resource_instance)) { + return_code = CMDLINE_RETCODE_SUCCESS; + } + } + return return_code; +} + +int exit_command(int argc, char *argv[]) +{ + exit(1); +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/cmd_lwm2m.h b/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/cmd_lwm2m.h new file mode 100644 index 0000000000..69d26df980 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/cmd_lwm2m.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 CMD_LWM2M_H_ +#define CMD_LWM2M_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void lwm2m_command_init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/generate_coverage.sh b/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/generate_coverage.sh new file mode 100644 index 0000000000..51b5d6af54 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/generate_coverage.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# Copyright (c) 2015 ARM Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +rm -rf coverage +lcov --base-directory ../../ --directory ../../output/gcc_linux/source -c -o testapp.info +lcov --base-directory ../../ --directory ../../output/lwm2m-client-linux/source -c -o lwm2mlinux.info +lcov --base-directory ../../ --directory ../../output/lwm2m-client-mbedtls/source -c -o mbedtls.info +lcov --base-directory ../../../../nsdl-c --directory ../../../../nsdl-c/output/gcc_/source/libCoap/src -c -o libcoap.info +lcov --base-directory ../../../../nsdl-c --directory ../../../../nsdl-c/output/gcc_/source/libNsdl/src -c -o libnsdl.info +genhtml -o coverage -t "lwm2mtestapplication coverage" --num-spaces 4 testapp.info libcoap.info libnsdl.info lwm2mlinux.info mbedtls.info +lcov --base-directory ../../ --directory ../../output/gcc_linux/source -z +lcov --base-directory ../../ --directory ../../output/lwm2m-client-linux/source -z +lcov --base-directory ../../ --directory ../../output/lwm2m-client-mbedtls/source -z +lcov --base-directory ../../../../nsdl-c --directory ../../../../nsdl-c/output/gcc_/source/libCoap/src -z +lcov --base-directory ../../../../nsdl-c --directory ../../../../nsdl-c/output/gcc_/source/libNsdl/src -z \ No newline at end of file diff --git a/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/lwm2mtest.cpp b/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/lwm2mtest.cpp new file mode 100644 index 0000000000..9f054bf4a4 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/lwm2mtest.cpp @@ -0,0 +1,859 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "lwm2mtest.h" +#include "ns_types.h" +#include "ns_cmdline.h" + +M2MLWClient::M2MLWClient() +: _security(NULL), + _interface(NULL), + _device(NULL), + _bootstrapped(false), + _error(false), + _registered(false), + _unregistered(false), + _registration_updated(false) +{ +} + +M2MLWClient::~M2MLWClient() +{ + if(_interface) { + delete _interface; + } + if(_security) { + delete _security; + } + if( _register_security){ + delete _register_security; + } +} + + +bool M2MLWClient::create_interface(int32_t param_count, + const char *endpoint, + const char *resource_type, + const int32_t lifetime, + const uint16_t listen_port, + const char *domain, + const uint8_t binding_mode, + const uint8_t network_interface) +{ + if(_interface) { + delete _interface; + _interface = NULL; + } + String ep; + String rt; + String dmn; + if(endpoint) { + ep += endpoint; + } + if(resource_type) { + rt += resource_type; + } + if(domain) { + dmn += domain; + } + + // Binding mode cannot be higher than 0x07 since it is an enum, check M2MInterface::BindingMode + if(binding_mode > 0x07) { + return false; + } + + switch (param_count) { + case 0: + _interface = M2MInterfaceFactory::create_interface(*this, ep, rt); + break; + case 1: + _interface = M2MInterfaceFactory::create_interface(*this, ep, rt, lifetime); + break; + case 2: + _interface = M2MInterfaceFactory::create_interface(*this, ep, rt, lifetime, listen_port); + break; + case 3: + _interface = M2MInterfaceFactory::create_interface(*this, ep, rt, lifetime, listen_port, dmn); + break; + case 4: + _interface = M2MInterfaceFactory::create_interface(*this, ep, rt, lifetime, listen_port, dmn, (M2MInterface::BindingMode)binding_mode); + break; + case 5: + _interface = M2MInterfaceFactory::create_interface(*this, ep, rt, lifetime, listen_port, dmn, (M2MInterface::BindingMode)binding_mode, (M2MInterface::NetworkStack)network_interface); + break; + } + return (_interface == NULL) ? false : true; +} + +bool M2MLWClient::create_bootstrap_object(const char *coap_bootstrap_address) +{ + bool success = false; + String address; + if(coap_bootstrap_address) { + address += coap_bootstrap_address; + } + if(_security) { + delete _security; + } + _security = M2MInterfaceFactory::create_security(M2MSecurity::Bootstrap); + if(_security) { + if(_security->set_resource_value(M2MSecurity::M2MServerUri, address) && + _security->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::NoSecurity)) { + success = true; + } + } + return success; +} + +bool M2MLWClient::create_register_object(const char *coap_register_address, bool useSecureConn) +{ + bool success = false; + String address; + if(coap_register_address) { + address += coap_register_address; + } + if(_register_security) { + delete _register_security; + } + _register_security = M2MInterfaceFactory::create_security(M2MSecurity::M2MServer); + if(_register_security) { + if( !useSecureConn ){ + if(_register_security->set_resource_value(M2MSecurity::M2MServerUri, address) && + _register_security->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::NoSecurity)) { + success = true; + } + }else{ + if(_register_security->set_resource_value(M2MSecurity::M2MServerUri, address) && + _register_security->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::Certificate) && + _register_security->set_resource_value(M2MSecurity::ServerPublicKey,server_cert,server_cert_len) && + _register_security->set_resource_value(M2MSecurity::PublicKey,cert,cert_len) && + _register_security->set_resource_value(M2MSecurity::Secretkey,key,key_len) ){ + success = true; + } + } + } + return success; +} + +bool M2MLWClient::test_bootstrap() +{ + bool success = false; + if(_interface) { + _interface->bootstrap(_security); + success = true; + } + return success; +} + +bool M2MLWClient::create_device_object(M2MDevice::DeviceResource resource, + const char *value) +{ + bool success = false; + String value_string; + if(value) { + value_string += value; + } + if(!_device) { + _device = M2MInterfaceFactory::create_device(); + } + if(_device) { + + if(_device->create_resource(resource,value_string)){ + success = true; + } else { + success = _device->set_resource_value(resource,value); + } + } + return success; +} + +bool M2MLWClient::create_device_object() +{ + bool success = false; + if(!_device) { + _device = M2MInterfaceFactory::create_device(); + success = true; + } + return success; +} + +bool M2MLWClient::create_device_object(M2MDevice::DeviceResource resource, + int64_t value) +{ + bool success = false; + if(!_device) { + _device = M2MInterfaceFactory::create_device(); + } + if(_device) { + if(_device->create_resource(resource,value)) { + success = true; + } else { + success = _device->set_resource_value(resource, value); + } + } + return success; +} + +bool M2MLWClient::create_device_object(M2MDevice::DeviceResource resource, + int64_t value, + uint16_t instance_id) +{ + bool success = false; + if(!_device) { + _device = M2MInterfaceFactory::create_device(); + } + if(_device) { + if(_device->create_resource_instance(resource,value,instance_id)) { + success = true; + } else { + success = _device->set_resource_value(resource, + value, + instance_id); + } + } + return success; +} + +bool M2MLWClient::create_firmware_object(M2MFirmware::FirmwareResource resource, + const char *value) +{ + bool success = false; + String value_string; + if(value) { + value_string += value; + } + if(!_firmware) { + _firmware = M2MInterfaceFactory::create_firmware(); + } + if(_firmware) { + if(_firmware->create_resource(resource,value_string)){ + success = true; + } else { + success = _firmware->set_resource_value(resource,value); + } + } + return success; +} + +bool M2MLWClient::create_firmware_object() +{ + bool success = false; + if(!_firmware) { + _firmware = M2MInterfaceFactory::create_firmware(); + success = true; + } + return success; +} + +bool M2MLWClient::create_firmware_object(M2MFirmware::FirmwareResource resource, + int64_t value) +{ + bool success = false; + if(!_firmware) { + _firmware = M2MInterfaceFactory::create_firmware(); + } + if(_firmware) { + if(_firmware->create_resource(resource,value)) { + success = true; + } else { + success = _firmware->set_resource_value(resource, value); + } + } + return success; +} + +bool M2MLWClient::create_firmware_object(M2MFirmware::FirmwareResource resource, + const uint8_t *value, + const uint32_t length) +{ + bool success = false; + if(!_firmware) { + _firmware = M2MInterfaceFactory::create_firmware(); + } + if(_firmware) { + success = _firmware->set_resource_value(resource, value, length); + } + return success; +} + +void M2MLWClient::set_fw_execute_function() +{ + if(_firmware) { + M2MObjectInstance *inst = _firmware->object_instance(0); + if(inst) { + M2MResource *res = inst->resource("2"); + if (res) { + res->set_execute_function(execute_callback( + this, + &M2MLWClient::fw_execute_function)); + } + } + } +} + +bool M2MLWClient::create_object(const char *name, + bool new_instance, + uint8_t object_operation, + uint8_t object_instance_operation, + uint16_t object_instance_id, + bool object_observable, + bool object_instance_observable) +{ + bool success = false; + M2MObjectInstance *inst = NULL; + if(!_object) { + _object = M2MInterfaceFactory::create_object(name); + if(_object) { + _object->set_operation(int_to_operation(object_operation)); + _object->set_observable(object_observable); + inst = _object->create_object_instance(object_instance_id); + if(inst) { + success = true; + inst->set_operation(int_to_operation(object_instance_operation)); + inst->set_observable(object_instance_observable); + } + } + } else { + if(new_instance) { + inst = _object->create_object_instance(object_instance_id); + if(inst) { + success = true; + inst->set_operation(int_to_operation(object_instance_operation)); + inst->set_observable(object_instance_observable); + } + } + } + return success; +} + +bool M2MLWClient::create_static_resource_string(const char *name, + const char *value, + bool multiple_instance, + uint16_t object_instance) +{ + bool success = false; + String name_string; + if(name) { + name_string += name; + } + String value_string; + if(value) { + value_string += value; + } + if(_object) { + M2MObjectInstance *inst = _object->object_instance(object_instance); + if(inst) { + if(inst->create_static_resource(name,"resource", + M2MResourceInstance::STRING, + (const uint8_t*)value_string.c_str(), + value_string.size()) != NULL) { + success = true; + } + } + } + return success; +} + +bool M2MLWClient::create_static_resource_int(const char *name, + int64_t value, + bool multiple_instance, + uint16_t object_instance) +{ + bool success = false; + String name_string; + String value_string; + + if(name) { + name_string += name; + } + + char value_buffer[20]; + sprintf(value_buffer,"%ld",value); + value_string += value_buffer; + + if(_object) { + M2MObjectInstance *inst = _object->object_instance(object_instance); + if(inst) { + if(inst->create_static_resource(name,"resource", + M2MResourceInstance::INTEGER, + (const uint8_t*)value_string.c_str(), + value_string.size()) != NULL) { + success = true; + } + } + } + return success; +} + +bool M2MLWClient::create_dynamic_resource_string(const char *name, + bool observable, + bool multiple_instance, + uint16_t object_instance, + uint8_t resource_operation) +{ + bool success = false; + String name_string; + if(name) { + name_string += name; + } + if(_object) { + M2MObjectInstance *inst = _object->object_instance(object_instance); + if(inst) { + M2MResource *res = inst->create_dynamic_resource(name,"resource", + M2MResourceInstance::STRING, + observable, multiple_instance); + if(res) { + success = true; + res->set_operation(int_to_operation(resource_operation)); + } + } + } + return success; +} + +bool M2MLWClient::create_dynamic_resource_int(const char *name, + bool observable, + bool multiple_instance, + uint16_t object_instance, + uint8_t resource_operation) +{ + bool success = false; + String name_string; + if(name) { + name_string += name; + } + if(_object) { + M2MObjectInstance *inst = _object->object_instance(object_instance); + if(inst) { + M2MResource *res = inst->create_dynamic_resource(name,"resource", + M2MResourceInstance::INTEGER, + observable, multiple_instance); + if(res) { + success = true; + res->set_operation(int_to_operation(resource_operation)); + } + } + } + return success; +} + +bool M2MLWClient::set_resource_value(const char *name, + int32_t value, + uint16_t object_instance) +{ + bool success = false; + String name_string; + String value_string; + if(name) { + name_string += name; + } + + char value_buffer[20]; + sprintf(value_buffer,"%d",value); + value_string += value_buffer; + + if(_object && name_string.length() > 0) { + M2MObjectInstance *inst = _object->object_instance(object_instance); + if(inst) { + M2MResource *res = inst->resource(name_string); + if (res) { + if (res->set_value((const uint8_t*)value_string.c_str(), value_string.size())) { + success = true; + } + } + } + } + return success; +} + +bool M2MLWClient::set_resource_value(const char *name, + const char *value, + uint16_t object_instance) +{ + bool success = false; + String name_string; + String value_string; + if(name) { + name_string += name; + } + if(value) { + value_string += value; + } + + if(_object && name_string.length() > 0) { + M2MObjectInstance *inst = _object->object_instance(object_instance); + if(inst) { + M2MResource *res = inst->resource(name_string); + if (res) { + if (res->set_value((const uint8_t*)value_string.c_str(), value_string.size())) { + success = true; + } + } + } + } + return success; +} + +bool M2MLWClient::create_static_resource_instance_string(const char *name, + const char *value, + bool multiple_instance, + uint16_t object_instance, + uint16_t resource_instance) +{ + bool success = false; + String name_string; + if(name) { + name_string += name; + } + String value_string; + if(value) { + value_string += value; + } + if(_object) { + M2MObjectInstance *inst = _object->object_instance(object_instance); + if(inst) { + if(inst->create_static_resource_instance(name,"resource", + M2MResourceInstance::STRING, + (const uint8_t*)value_string.c_str(), + value_string.size(), + resource_instance) != NULL) { + success = true; + } + } + } + return success; +} + +bool M2MLWClient::create_static_resource_instance_int(const char *name, + int32_t value, + bool multiple_instance, + uint16_t object_instance, + uint16_t resource_instance) +{ + bool success = false; + String name_string; + String value_string; + + if(name) { + name_string += name; + } + + char value_buffer[20]; + sprintf(value_buffer,"%ld",value); + value_string += value_buffer; + + if(_object) { + M2MObjectInstance *inst = _object->object_instance(object_instance); + if(inst) { + if(inst->create_static_resource_instance(name,"resource", + M2MResourceInstance::INTEGER, + (const uint8_t*)value_string.c_str(), + value_string.size(), + resource_instance) != NULL) { + success = true; + } + } + } + return success; +} + +bool M2MLWClient::create_dynamic_resource_instance_int(const char *name, + bool observable, + bool multiple_instance, + uint16_t object_instance, + uint16_t resource_instance, + uint8_t resource_instance_operation) +{ + bool success = false; + String name_string; + if(name) { + name_string += name; + } + if(_object) { + M2MObjectInstance *inst = _object->object_instance(object_instance); + if(inst) { + M2MResourceInstance *res = inst->create_dynamic_resource_instance(name,"resource", + M2MResourceInstance::INTEGER, + observable, + resource_instance); + if( res) { + success = true; + res->set_operation(int_to_operation(resource_instance_operation)); + } + } + } + return success; +} + +bool M2MLWClient::create_dynamic_resource_instance_string(const char *name, + bool observable, + bool multiple_instance, + uint16_t object_instance, + uint16_t resource_instance, + uint8_t resource_instance_operation) +{ + bool success = false; + String name_string; + if(name) { + name_string += name; + } + if(_object) { + M2MObjectInstance *inst = _object->object_instance(object_instance); + if(inst) { + M2MResourceInstance *res = inst->create_dynamic_resource_instance(name,"resource", + M2MResourceInstance::STRING, + observable, + resource_instance); + if( res) { + success = true; + res->set_operation(int_to_operation(resource_instance_operation)); + } + } + } + return success; +} + +bool M2MLWClient::set_resource_instance_value(const char *name, + int32_t value, + uint16_t object_instance, + uint16_t resource_instance) +{ + bool success = false; + String name_string; + String value_string; + if(name) { + name_string += name; + } + + char value_buffer[20]; + sprintf(value_buffer,"%d",value); + value_string += value_buffer; + + if(_object && name_string.length() > 0) { + M2MObjectInstance *inst = _object->object_instance(object_instance); + if(inst) { + M2MResource *res = inst->resource(name_string); + if (res) { + M2MResourceInstance *res_inst = res->resource_instance(resource_instance); + if(res_inst) { + if (res_inst->set_value((const uint8_t*)value_string.c_str(), value_string.size())) { + success = true; + } + } + } + } + } + return success; +} + +bool M2MLWClient::set_resource_instance_value(const char *name, + const char *value, + uint16_t object_instance, + uint16_t resource_instance) +{ + bool success = false; + String name_string; + String value_string; + if(name) { + name_string += name; + } + if(value) { + value_string += value; + } + + if(_object && name_string.length() > 0) { + M2MObjectInstance *inst = _object->object_instance(object_instance); + if(inst) { + M2MResource *res = inst->resource(name_string); + if (res) { + M2MResourceInstance *res_inst = res->resource_instance(resource_instance); + if(res_inst) { + if (res_inst->set_value((const uint8_t*)value_string.c_str(), value_string.size())) { + success = true; + } + } + } + } + } + return success; +} + +bool M2MLWClient::test_register() +{ + bool success = false; + M2MObjectList object_list; + if(_device) { + object_list.push_back(_device); + } + if(_firmware) { + object_list.push_back(_firmware); + } + if(_object) { + object_list.push_back(_object); + } + if(_interface) { + _interface->register_object(_register_security,object_list); + success = true; + } + return success; +} + +bool M2MLWClient::test_update_register(const uint32_t lifetime) +{ + bool success = false; + if(_interface && _register_security) { + success = true; + _interface->update_registration(_register_security,lifetime); + } + return success; +} + +bool M2MLWClient::test_unregister() +{ + bool success = false; + if(_interface) { + success = true; + _interface->unregister_object(_register_security); + } + return success; +} + +void M2MLWClient::bootstrap_done(M2MSecurity *server_object) +{ + if(server_object) { + _register_security = server_object; + _bootstrapped = true; + cmd_printf("\nBootstrapped\n"); + cmd_ready( CMDLINE_RETCODE_SUCCESS ); + } +} + +void M2MLWClient::object_registered(M2MSecurity *security_object, const M2MServer &server_object) +{ + _registered = true; + cmd_printf("\nRegistered\n"); + cmd_ready( CMDLINE_RETCODE_SUCCESS ); +} + +void M2MLWClient::object_unregistered(M2MSecurity *server_object) +{ + _unregistered = true; + if(_device) { + M2MDevice::delete_instance(); + _device = NULL; + } + if(_object) { + delete _object; + _object = NULL; + } + if(_security) { + delete _security; + _security = NULL; + } + if(_register_security) { + delete _register_security; + _register_security = NULL; + } + cmd_printf("\nUnregistered\n"); + cmd_ready( CMDLINE_RETCODE_SUCCESS ); +} + +void M2MLWClient::registration_updated(M2MSecurity *security_object, + const M2MServer &server_object) +{ + _registration_updated = true; + cmd_printf("\nregistration updated\n"); + cmd_ready( CMDLINE_RETCODE_SUCCESS ); +} + +void M2MLWClient::error(M2MInterface::Error error) +{ + _error = true; + cmd_printf("\nError occured Error Code : %d\n", (int8_t)error); + cmd_ready( CMDLINE_RETCODE_SUCCESS ); +} + +void M2MLWClient::value_updated(M2MBase *base, M2MBase::BaseType type) +{ + cmd_printf("\nValue updated of Object name %s and Type \n", + base->name().c_str(), type); +} + +M2MBase::Operation M2MLWClient::int_to_operation(uint8_t operation) +{ + M2MBase::Operation op = M2MBase::NOT_ALLOWED; + switch(operation) { + case 0: + op = M2MBase::NOT_ALLOWED; + break; + case 1: + op = M2MBase::GET_ALLOWED; + break; + case 2: + op = M2MBase::PUT_ALLOWED; + break; + case 3: + op = M2MBase::GET_PUT_ALLOWED; + break; + case 4: + op = M2MBase::POST_ALLOWED; + break; + case 5: + op = M2MBase::GET_POST_ALLOWED; + break; + case 6: + op = M2MBase::PUT_POST_ALLOWED; + break; + case 7: + op = M2MBase::GET_PUT_POST_ALLOWED; + break; + case 8: + op = M2MBase::DELETE_ALLOWED; + break; + default: + break; + } + return op; +} + +void M2MLWClient::fw_execute_function(void *argument) +{ + if(argument) { + char* arguments = (char*)argument; + cmd_printf("Received %s!!\n", arguments); + } + cmd_printf("Firmware update executed\n"); +} + +void M2MLWClient::firmware_resource_int(int resource) +{ + cmd_printf("Firmware resource value int\n"); + cmd_printf("%ld\n", _firmware->resource_value_int(static_cast(resource))); +} + +void M2MLWClient::firmware_resource_string(int resource) +{ + cmd_printf("Firmware resource value string\n"); + cmd_printf("%s\n", _firmware->resource_value_string(static_cast(resource)).c_str()); +} + +void M2MLWClient::firmware_resource_buffer() +{ + cmd_printf("Firmware resource value buffer\n"); + uint8_t *value = 0; + uint32_t valueSize = _firmware->resource_value_buffer(M2MFirmware::Package, value); + cmd_printf("%s\n", value); + free(value); +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/lwm2mtest.h b/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/lwm2mtest.h new file mode 100644 index 0000000000..a38538787d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/lwm2mtest.h @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client/m2minterfacefactory.h" +#include "mbed-client/m2minterface.h" +#include "mbed-client/m2mdevice.h" +#include "mbed-client/m2minterfaceobserver.h" +#include "mbed-client/m2mobjectinstance.h" +#include "mbed-client/m2mresource.h" +#include "mbed-client/m2mfirmware.h" + +class M2MLWClient: public M2MInterfaceObserver { +public: + M2MLWClient(); + + ~M2MLWClient(); + + bool create_interface(int32_t param_count, + const char *endpoint, + const char *resource_type, + const int32_t lifetime, + const uint16_t listen_port, + const char *domain, + const uint8_t binding_mode, + const uint8_t network_interface); + + bool create_bootstrap_object(const char *coap_bootstrap_address); + + bool create_register_object(const char *coap_register_address, bool useSecureConn); + + bool test_bootstrap(); + + bool create_device_object(); + + bool create_device_object(M2MDevice::DeviceResource resource, + const char *value); + + bool create_device_object(M2MDevice::DeviceResource resource, + int64_t value, + uint16_t instance_id); + + bool create_device_object(M2MDevice::DeviceResource resource, + int64_t value); + + bool create_firmware_object(); + + bool create_firmware_object(M2MFirmware::FirmwareResource resource, + const char *value); + + bool create_firmware_object(M2MFirmware::FirmwareResource resource, + int64_t value); + + bool create_firmware_object(M2MFirmware::FirmwareResource resource, + const uint8_t *value, + const uint32_t length); + + void firmware_resource_int(int resource); + void firmware_resource_string(int resource); + + void firmware_resource_buffer(); + + bool create_object(const char *name, + bool new_instance, + uint8_t object_operation, + uint8_t object_instance_operation, + uint16_t object_instance_id, + bool object_observable, + bool object_instance_observable); + + bool create_static_resource_string(const char *name, + const char *value, + bool multiple_instance, + uint16_t object_instance = 0); + + bool create_static_resource_int(const char *name, + int64_t value, + bool multiple_instance, + uint16_t object_instance = 0); + + bool create_dynamic_resource_int(const char *name, + bool observable, + bool multiple_instance, + uint16_t object_instance = 0, + uint8_t resource_operation = 1); + bool create_dynamic_resource_string(const char *name, + bool observable, + bool multiple_instance, + uint16_t object_instance = 0, + uint8_t resource_operation = 1); + + bool set_resource_value(const char *name, + int32_t value, + uint16_t object_instance = 0); + + bool set_resource_value(const char *name, + const char *value, + uint16_t object_instance = 0); + + bool create_static_resource_instance_string(const char *name, + const char *value, + bool multiple_instance, + uint16_t object_instance = 0, + uint16_t resource_instance = 0); + + bool create_static_resource_instance_int(const char *name, + int32_t value, + bool multiple_instance, + uint16_t object_instance = 0, + uint16_t resource_instance = 0); + + bool create_dynamic_resource_instance_int(const char *name, + bool observable, + bool multiple_instance, + uint16_t object_instance = 0, + uint16_t resource_instance = 0, + uint8_t resource_instance_operation = 1); + bool create_dynamic_resource_instance_string(const char *name, + bool observable, + bool multiple_instance, + uint16_t object_instance = 0, + uint16_t resource_instance = 0, + uint8_t resource_instance_operation = 1); + + bool set_resource_instance_value(const char *name, + int32_t value, + uint16_t object_instance = 0, + uint16_t resource_instance = 0); + + bool set_resource_instance_value(const char *name, + const char *value, + uint16_t object_instance = 0, + uint16_t resource_instance = 0); + + bool create_object_instance(); + + bool test_register(); + + bool test_update_register(const uint32_t lifetime); + + bool test_unregister(); + + void bootstrap_done(M2MSecurity *server_object); + + void object_registered(M2MSecurity *security_object, const M2MServer &server_object); + + void object_unregistered(M2MSecurity *server_object); + + void registration_updated(M2MSecurity *security_object, const M2MServer &server_object); + + void error(M2MInterface::Error error); + + void value_updated(M2MBase *base, M2MBase::BaseType type); + + void set_fw_execute_function(); + +private: + + M2MBase::Operation int_to_operation(uint8_t operation); + void fw_execute_function(void *argument); + + +private: + + M2MInterface *_interface; + M2MSecurity *_security; + M2MSecurity *_register_security; + M2MDevice *_device; + M2MFirmware *_firmware; + M2MObject *_object; + bool _bootstrapped; + bool _error; + bool _registered; + bool _unregistered; + bool _registration_updated; +}; + + +const unsigned char psk[] = {0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x30,0x31,0x32,0x33,0x34,0x35,0x36}; +const size_t psk_len = sizeof( psk ); +const unsigned char psk_identity[] = {0x0F,0x0F}; +const size_t psk_identity_len = sizeof( psk_identity ); + +const uint8_t server_cert[] = "-----BEGIN CERTIFICATE-----\r\n" +"MIIBmDCCAT6gAwIBAgIEVUCA0jAKBggqhkjOPQQDAjBLMQswCQYDVQQGEwJGSTEN\r\n" +"MAsGA1UEBwwET3VsdTEMMAoGA1UECgwDQVJNMQwwCgYDVQQLDANJb1QxETAPBgNV\r\n" +"BAMMCEFSTSBtYmVkMB4XDTE1MDQyOTA2NTc0OFoXDTE4MDQyOTA2NTc0OFowSzEL\r\n" +"MAkGA1UEBhMCRkkxDTALBgNVBAcMBE91bHUxDDAKBgNVBAoMA0FSTTEMMAoGA1UE\r\n" +"CwwDSW9UMREwDwYDVQQDDAhBUk0gbWJlZDBZMBMGByqGSM49AgEGCCqGSM49AwEH\r\n" +"A0IABLuAyLSk0mA3awgFR5mw2RHth47tRUO44q/RdzFZnLsAsd18Esxd5LCpcT9w\r\n" +"0tvNfBv4xJxGw0wcYrPDDb8/rjujEDAOMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0E\r\n" +"AwIDSAAwRQIhAPAonEAkwixlJiyYRQQWpXtkMZax+VlEiS201BG0PpAzAiBh2RsD\r\n" +"NxLKWwf4O7D6JasGBYf9+ZLwl0iaRjTjytO+Kw==\r\n" +"-----END CERTIFICATE-----\r\n"; + +const uint8_t cert[] = "-----BEGIN CERTIFICATE-----\r\n" +"MIICTDCCAbWgAwIBAgIJAKI3S+LGklSGMA0GCSqGSIb3DQEBCwUAMD8xCzAJBgNV\r\n" +"BAYTAkZJMRMwEQYDVQQIDApTb21lLVN0YXRlMQ0wCwYDVQQHDARPdWx1MQwwCgYD\r\n" +"VQQKDANBUk0wHhcNMTUwNjExMTI0NTU1WhcNMTYwNjEwMTI0NTU1WjA/MQswCQYD\r\n" +"VQQGEwJGSTETMBEGA1UECAwKU29tZS1TdGF0ZTENMAsGA1UEBwwET3VsdTEMMAoG\r\n" +"A1UECgwDQVJNMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBt8ag12ILm2pn\r\n" +"RHUc2yMBXpdzspDwVV3VDaNTRXypVUOq/nxJc6zr8yG/Pvga2/XVijWQDLABHVhV\r\n" +"PoeulzXVSEHRR2bR2lhqulLzdUzPYJ+yJd4+082akoxdzoom8ms2LFlgiXO7lyBg\r\n" +"1t74xjEQapCkr7Tdl2pD9OTUrcfoEwIDAQABo1AwTjAdBgNVHQ4EFgQUHK0O4iK7\r\n" +"Rv8AsxAqRDlY3TSHWtUwHwYDVR0jBBgwFoAUHK0O4iK7Rv8AsxAqRDlY3TSHWtUw\r\n" +"DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQAPVLihYN65DEeYdf7gDAdP\r\n" +"MNH5RxsQlHdktQkYWcUewe3hvOf8yZUBbmO5OeEQmy5Ca2H1QhUuw+kWHo1l/K9g\r\n" +"DpR1xoDACeycBd/6tAHfaFzTEEDC9Ug839EAHDrbI4ihrPEbP6hyRIaUIM4IojXf\r\n" +"zuqwOcobS3idv8a9Npuohw==\r\n" +"-----END CERTIFICATE-----\r\n"; + +const uint8_t key[] = "-----BEGIN PRIVATE KEY-----\r\n" +"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMG3xqDXYgubamdE\r\n" +"dRzbIwFel3OykPBVXdUNo1NFfKlVQ6r+fElzrOvzIb8++Brb9dWKNZAMsAEdWFU+\r\n" +"h66XNdVIQdFHZtHaWGq6UvN1TM9gn7Il3j7TzZqSjF3OiibyazYsWWCJc7uXIGDW\r\n" +"3vjGMRBqkKSvtN2XakP05NStx+gTAgMBAAECgYEAlRimNxsu6jIXJh4paSk8ewxb\r\n" +"0v+n0GJT0uwpPakotofaihxOepYejIfX/IMxoDKVtmImsZUiTelRGGMFORpGomS7\r\n" +"3Pb9awfn1yWiYja9MF7+pgFtXj6LxcB5rcxrP8s9rCs+kEq8yl/khGXmlwlpacUm\r\n" +"Pdg1rEHriykk/5dlyKkCQQD9zpgQKN87bQNOVSgFSNsrwCjEN2MvVUC6ycqVYqQd\r\n" +"oQZrO2lJuf57Jn7kRKJgfqqImwLYaohn5A9gKiqszo+fAkEAw2REr8L9aLoRPe5Q\r\n" +"4+lYCmNmxJjBbJoRviSlxx+p5dxK+8H4J+bnFUWzORFJP0+Bjhii2UHGBoMjuP2s\r\n" +"e8xDDQJADm0IrZp1Hb6TeodSkAJVGsaASq7PP2h8FmHT1uvVYi293Khy0pL0yPEm\r\n" +"MzlHdW6dqMgOwFhFyonm6dNbu5i+BwJBALSPKfIKDMcEev5yBgo3Dga7iLJQPx4u\r\n" +"2gqOLyvtlME3a4tu2fV1qUG9ITuxP7DjteMr3QFLiMVn1lETCpt0TNkCQGIvyjdV\r\n" +"RzYnzLDMulXCsuRBjs0C75KoZrcPPQ416SZFtYASsOl3P0Ih5jgt/1aPmth3Yson\r\n" +"GdnBOWyKzadLmz8=\r\n" +"-----END PRIVATE KEY-----\r\n"; + +const size_t server_cert_len = sizeof( server_cert ); +const size_t cert_len = sizeof( cert ); +const size_t key_len = sizeof( key ); + diff --git a/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/main.cpp b/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/main.cpp new file mode 100644 index 0000000000..e3cf12b3f7 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/lwm2mtestapplication/main.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 + +//stack +#include "eventOS_event.h" +#include "eventOS_scheduler.h" + +//mbed-client-libservice +#include "randLIB.h" +#include "nsdynmemLIB.h" +#include "mbed-trace/mbed_trace.h" +#include "ns_cmdline.h" + + +//application +#include "cmd_commands.h" + +#define APP_DEV_HEAP_SIZE 30000 + +void eventOS_scheduler_idle(void) +{ + eventOS_scheduler_wait(); +} + +/*Global variables*/ + +uint8_t app_defined_stack_heap[APP_DEV_HEAP_SIZE]; + +void app_heap_error_handler(heap_fail_t event) +{ + switch (event) + { + case NS_DYN_MEM_NULL_FREE: + tracef(TRACE_LEVEL_ERROR, "mem", "Dyn mem error:NULL_FREE"); + break; + case NS_DYN_MEM_DOUBLE_FREE: + tracef(TRACE_LEVEL_ERROR, "mem", "Dyn mem error:DOUBLE_FREE"); + break; + + case NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID: + tracef(TRACE_LEVEL_ERROR, "mem", "Dyn mem error:SIZE_NOT_VALID"); + break; + case NS_DYN_MEM_POINTER_NOT_VALID: + tracef(TRACE_LEVEL_ERROR, "mem", "Dyn mem error:POINTER_NOT_VALID"); + break; + + case NS_DYN_MEM_HEAP_SECTOR_CORRUPTED: + tracef(TRACE_LEVEL_ERROR, "mem", "Dyn mem error:SECTOR_CORRUPTED"); + break; + + case NS_DYN_MEM_HEAP_SECTOR_UNITIALIZED: + tracef(TRACE_LEVEL_ERROR, "mem", "Dyn mem error:SECTOR_UNITIALIZED"); + break; + default: + tracef(TRACE_LEVEL_ERROR, "mem", "Dyn mem error:UNKNOWN!"); + break; + } + while(1); +} + +int app_time_i=0; +char* time_now(size_t size) +{ + static char str[10] = {0}; + sprintf(str, "[%04d]", app_time_i++); + return str; +} + +void trace_printer(const char* str) +{ + printf("%s\r\n", str); + cmd_output(); + fflush(stdout); +} +void cmd_printer(const char *str) +{ + cmd_printf("%s", str); + fflush(stdout); +} + +void custom_cmd_response_out(const char* fmt, va_list ap) +{ + vprintf(fmt, ap); + fflush(stdout); +} + +mem_stat_t memory_heap_stat; +/** + * \brief Application infinite loop. + */ +int main(void) +{ + ns_dyn_mem_init(app_defined_stack_heap, APP_DEV_HEAP_SIZE, app_heap_error_handler, &memory_heap_stat); + eventOS_scheduler_init(); + mbed_trace_init(); + mbed_trace_print_function_set( trace_printer ); + mbed_trace_cmdprint_function_set( cmd_printer ); + mbed_trace_prefix_function_set( time_now ); + mbed_trace_config_set(TRACE_MODE_COLOR|TRACE_ACTIVE_LEVEL_DEBUG|TRACE_CARRIAGE_RETURN); + cmd_init( &custom_cmd_response_out ); + + initialize_app_commands(0); + + eventOS_scheduler_run(); + return 0; +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient-smokeTest/main.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient-smokeTest/main.cpp new file mode 100644 index 0000000000..52a3b54405 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient-smokeTest/main.cpp @@ -0,0 +1,497 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "sockets/UDPSocket.h" +#include "EthernetInterface.h" +#include "test_env.h" +#include "mbed-client/m2minterfacefactory.h" +#include "mbed-client/m2minterfaceobserver.h" +#include "mbed-client/m2mdevice.h" +#include "mbed-client/m2mobjectinstance.h" +#include "mbed-client/m2minterface.h" +#include "testconfig.h" + +// TODO: Remove when yotta supports init. +#include "lwipv4_init.h" + +// Minar for event scheduling +#include "minar/minar.h" + +using namespace mbed::util; +const String &MANUFACTURER = "ARM"; +const String &TYPE = "type"; + +static bool test_result = false; + +// Dynamic resource variables +const String &DYNAMIC_RESOURCE_NAME = "Dynamic"; +const String &DYNAMIC_RESOURCE_TYPE = "DynamicType"; +const String &STATIC_RESOURCE_NAME = "Static"; +const String &STATIC_RESOURCE_TYPE = "StaticType"; +const uint8_t STATIC_VALUE[] = "Static value"; + +//TODO: should this be configured in .json conf file, and communicated via host test to here? +int CALLBACK_TIMEOUT = 5; +int MINAR_DELAY = 10000; + +#define SUITE_TEST_INFO(test_name, info) printf("Suite-%s: %s\n", test_name, info) +#define SUITE_TEST_RESULT(test_name, result) printf("Suite-%s: result %s\n", test_name, result ? "PASSED" : "FAILED") +#define SUITE_RESULT(result) printf("Suite: result %s\n", result ? "success" : "failure") + + +class MbedClient: public M2MInterfaceObserver { +public: + MbedClient(TestConfig *test_config){ + _interface = NULL; + _register_security = NULL; + _resource_object = NULL; + _bootstrapped = false; + _error = false; + _registered = false; + _unregistered = false; + _registration_updated = false; + _resource_value = 0; + _object = NULL; + _test_config = test_config; + } + + virtual ~MbedClient() { + if(_interface) { + delete _interface; + } + if( _register_security){ + delete _register_security; + } + } + + bool create_interface() { + bool success = false; + // Creates M2MInterface using which endpoint can + // setup its name, resource type, life time, connection mode, + // Currently only LwIPv4 is supported. + _interface = M2MInterfaceFactory::create_interface( *this, + _test_config->get_endpoint_name(), + _test_config->get_endpoint_type(), + _test_config->get_lifetime(), + _test_config->get_port(), + _test_config->get_domain(), + M2MInterface::UDP, + M2MInterface::LwIP_IPv4, + ""); + if (_interface) { + success = true; + } + + return success; + } + + bool bootstrap_successful() { + return _bootstrapped; + } + + M2MSecurity* create_bootstrap_object() { + // Creates bootstrap server object with Bootstrap server address and other parameters + // required for client to connect to bootstrap server. + M2MSecurity *security = M2MInterfaceFactory::create_security(M2MSecurity::Bootstrap); + if(security) { + security->set_resource_value(M2MSecurity::M2MServerUri, _test_config->get_bootstrap_server()); + security->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::NoSecurity); + } + return security; + } + + void test_bootstrap(M2MSecurity *security) { + if(_interface) { + // Bootstrap function. + _interface->bootstrap(security); + } + } + + bool register_successful() { + return _registered; + } + + bool unregister_successful() { + return _unregistered; + } + + bool update_register_successful() { + return _registration_updated; + } + + void check_result(const char* result) { + if(_registered && _registration_updated && _unregistered) { + SUITE_TEST_RESULT(result, true); + test_result = true; + } else { + SUITE_TEST_RESULT(result, false); + test_result = false; + } + minar::Scheduler::stop(); + } + + M2MSecurity* create_register_object() { + // Creates server object with LWM2M server address and other parameters + // required for client to connect to LWM2M server. + M2MSecurity *security = M2MInterfaceFactory::create_security(M2MSecurity::M2MServer); + if(security) { + security->set_resource_value(M2MSecurity::M2MServerUri, _test_config->get_mds_server()); + //security->set_resource_value(M2MSecurity::M2MServerUri, "ds-test.dev.mbed.com"); + security->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::NoSecurity); + } + return security; + } + + void test_register(M2MObjectList object_list){ + if(_interface) { + // Register function + _interface->register_object(_register_security, object_list); + } + } + + void test_update_register(const uint32_t lifetime) + { + if(_interface && _register_security) { + _interface->update_registration(_register_security,lifetime); + } + } + + void test_unregister(){ + if(_interface) { + // Unregister function + _interface->unregister_object(NULL); + } + } + + void set_register_object(M2MSecurity *®ister_object){ + if(_register_security) { + delete _register_security; + _register_security = NULL; + } + _register_security = register_object; + } + + M2MDevice* create_device_object() { + M2MDevice *device = M2MInterfaceFactory::create_device(); + if (device) { + device->create_resource(M2MDevice::Manufacturer, MANUFACTURER); + device->create_resource(M2MDevice::DeviceType, TYPE); + } + return device; + } + + M2MObject* create_generic_object() { + _object = M2MInterfaceFactory::create_object("Test"); + if(_object) { + M2MObjectInstance* inst = _object->create_object_instance(); + if(inst) { + M2MResource* res = inst->create_dynamic_resource("D","ResourceTest", + M2MResourceInstance::INTEGER, + true); + char buffer[20]; + int size = sprintf(buffer,"%d",_resource_value); + res->set_operation(M2MBase::GET_PUT_POST_ALLOWED); + res->set_value((const uint8_t*)buffer, + (const uint32_t)size); + _resource_value++; + + inst->create_static_resource("S", + "ResourceTest", + M2MResourceInstance::STRING, + STATIC_VALUE, + sizeof(STATIC_VALUE)-1); + } + } + return _object; + } + + //Callback from mbed client stack when the bootstrap + // is successful, it returns the mbed Device Server object + // which will be used for registering the resources to + // mbed Device server. + void bootstrap_done(M2MSecurity *server_object){ + if(server_object) { + _bootstrapped = true; + _error = false; + } + } + + //Callback from mbed client stack when the registration + // is successful, it returns the mbed Device Server object + // to which the resources are registered and registered objects. + void object_registered(M2MSecurity */*security_object*/, const M2MServer &/*server_object*/){ + _registered = true; + } + + //Callback from mbed client stack when the registration update + // is successful, it returns the mbed Device Server object + // to which the resources are registered and registered objects. + void registration_updated(M2MSecurity */*security_object*/, const M2MServer &/*server_object*/){ + _registration_updated = true; + } + + //Callback from mbed client stack when the unregistration + // is successful, it returns the mbed Device Server object + // to which the resources were unregistered. + void object_unregistered(M2MSecurity */*server_object*/){ + _unregistered = true; + } + + //Callback from mbed client stack if any value has changed + // during PUT operation. Object and its type is passed in + // the callback. + void value_updated(M2MBase *base, M2MBase::BaseType type) { + printf("\nValue updated of Object name %s and Type %d\n", + base->name().c_str(), type); + } + + //Callback from mbed client stack if any error is encountered + // during any of the LWM2M operations. Error type is passed in + // the callback. + void error(M2MInterface::Error error){ + _error = true; + printf("\nError occured %d\n", error); + } + +private: + + M2MInterface *_interface; + M2MSecurity *_register_security; + M2MObject *_resource_object; + M2MObject *_object; + volatile bool _bootstrapped; + volatile bool _error; + volatile bool _registered; + volatile bool _unregistered; + volatile bool _registration_updated; + int _resource_value; + TestConfig *_test_config; +}; + +#define WAIT_CALLBACK(X, TIMEOUT) \ +{int _timer = 0;\ +while ( 1 ) \ + { \ + _result &= (X); \ + if (_result) { \ + SUITE_TEST_INFO(_tn, "callback done"); \ + break; \ + } \ + wait_ms(1000); _timer+=1; \ + if (_timer >= TIMEOUT) { \ + SUITE_TEST_INFO(_tn, "ERROR: callback timeout");\ + break; \ + } \ + }} + +bool test_bootStrap(TestConfig *test_config) { + bool _result = true; + const char* _tn = "TC1_bootStrap"; + + SUITE_TEST_INFO(_tn, "STARTED"); + + // Instantiate the class which implements + // mbed Client API + MbedClient *mbed_client = new MbedClient(test_config); + + SUITE_TEST_INFO(_tn, "client done"); + + // Create LWM2M Client API interface to manage bootstrap, + // register and unregister + _result &= mbed_client->create_interface(); + + // Create LWM2M bootstrap object specifying bootstrap server + // information. + M2MSecurity* security_object = mbed_client->create_bootstrap_object(); + + // Issue bootstrap command. + mbed_client->test_bootstrap(security_object); + SUITE_TEST_INFO(_tn, "bootstrap done"); + + SUITE_TEST_INFO(_tn, "waiting bootstrap callback..."); + // Wait till the bootstrap callback is called successfully. + // Callback comes in bootstrap_done() + WAIT_CALLBACK(mbed_client->bootstrap_successful(), CALLBACK_TIMEOUT); + + // Delete security object created for bootstrapping + if(security_object) { + delete security_object; + } + + if (mbed_client) { + delete mbed_client; + } + + SUITE_TEST_RESULT(_tn, _result); + return _result; +} + +void test_deviceObject(TestConfig *test_config) { + const char* _tn = "TC2_deviceObject"; + + SUITE_TEST_INFO(_tn, "STARTED"); + + // Instantiate the class which implements + // LWM2M Client API + MbedClient mbed_client(test_config);// = new MbedClient(test_config); + + SUITE_TEST_INFO(_tn, "client done"); + + // Create LWM2M Client API interface for M2M server + mbed_client.create_interface(); + + M2MSecurity *register_object = mbed_client.create_register_object(); + + mbed_client.set_register_object(register_object); + + // Create LWM2M device object specifying device resources + // as per OMA LWM2M specification. + M2MDevice* device_object = mbed_client.create_device_object(); + + // Add the device object that we want to register + // into the list and pass the list for register API. + M2MObjectList object_list; + object_list.push_back(device_object); + + // Issue register command. + + FunctionPointer1 tr(&mbed_client, &MbedClient::test_register); + minar::Scheduler::postCallback(tr.bind(object_list)); + + // Issue update register command. + + uint32_t lifetime = 2222; + + FunctionPointer1 ur(&mbed_client, &MbedClient::test_update_register); + minar::Scheduler::postCallback(ur.bind(lifetime)).delay(MINAR_DELAY); + + // Issue unregister command. + + FunctionPointer0 tur(&mbed_client, &MbedClient::test_unregister); + minar::Scheduler::postCallback(tur.bind()).delay(MINAR_DELAY*2); + + FunctionPointer1 cus(&mbed_client, &MbedClient::check_result); + minar::Scheduler::postCallback(cus.bind(_tn)).delay(MINAR_DELAY*3); + + minar::Scheduler::start(); + + // Delete device object created for registering device + // resources. + + if(device_object) { + M2MDevice::delete_instance(); + } +} + +bool test_resource(TestConfig *test_config) { + bool _result = true; + const char* _tn = "TC3_resource"; + SUITE_TEST_INFO(_tn, "STARTED"); + + // Instantiate the class which implements LWM2M Client API + MbedClient mbed_client(test_config); + SUITE_TEST_INFO(_tn, "client done"); + + // Create LWM2M Client API interface for M2M server + _result &= mbed_client.create_interface(); + + M2MSecurity *register_object = mbed_client.create_register_object(); + + mbed_client.set_register_object(register_object); + + // Create LWM2M device object specifying device resources + // as per OMA LWM2M specification. + M2MDevice* device_object = mbed_client.create_device_object(); + + // Create LWM2M generic object for resource + M2MObject* resource_object = mbed_client.create_generic_object(); + + // Add the device object that we want to register + // into the list and pass the list for register API. + M2MObjectList object_list; + object_list.push_back(device_object); + object_list.push_back(resource_object); + + // Issue register command. + + FunctionPointer1 tr(&mbed_client, &MbedClient::test_register); + minar::Scheduler::postCallback(tr.bind(object_list)); + + // Issue update register command. + + uint32_t lifetime = 2222; + + FunctionPointer1 ur(&mbed_client, &MbedClient::test_update_register); + minar::Scheduler::postCallback(ur.bind(lifetime)).delay(MINAR_DELAY); + + // Issue unregister command. + + FunctionPointer0 tur(&mbed_client, &MbedClient::test_unregister); + minar::Scheduler::postCallback(tur.bind()).delay(MINAR_DELAY*2); + + FunctionPointer1 cus(&mbed_client, &MbedClient::check_result); + minar::Scheduler::postCallback(cus.bind(_tn)).delay(MINAR_DELAY*3); + + minar::Scheduler::start(); + + // Delete device object created for registering device resources. + if(device_object) { + M2MDevice::delete_instance(); + } + + // Delete resource object for registering resources. + if(resource_object) { + delete resource_object; + } +} + + + +void app_start(int /*argc*/, char* /*argv*/[]) { + DigitalOut _led = DigitalOut(LED3); + _led = 1; + + MBED_HOSTTEST_TIMEOUT(40); + MBED_HOSTTEST_SELECT(mbed_client_auto); + MBED_HOSTTEST_DESCRIPTION(LWM2MClient Smoke Test); + MBED_HOSTTEST_START("LWM2MClientSmokeTest"); + + // This sets up the network interface configuration which will be used + // by LWM2M Client API to communicate with mbed Device server. + EthernetInterface eth; + eth.init(); //Use DHCP + eth.connect(); + + lwipv4_socket_init(); + + // Create test config object, and setup with unique MAC address + TestConfig test_config; + test_config.setup(); + + _led = 0; + + // Bootstrap test is uncommented, until it will be supported. + //result &= test_bootStrap(&test_config); + test_deviceObject(&test_config); + test_resource(&test_config); + + _led = 1; + + // Disconnect and teardown the network interface + eth.disconnect(); + + SUITE_RESULT(test_result); +} + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient-smokeTest/security.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient-smokeTest/security.h new file mode 100644 index 0000000000..a952623d31 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient-smokeTest/security.h @@ -0,0 +1,115 @@ + + +/* + + * Copyright (c) 2015 ARM Limited. All rights reserved. + + * SPDX-License-Identifier: Apache-2.0 + + * Licensed under the Apache License, Version 2.0 (the License); you may + + * not use this file except in compliance with the License. + + * You may obtain a copy of the License at + + * + + * http://www.apache.org/licenses/LICENSE-2.0 + + * + + * Unless required by applicable law or agreed to in writing, software + + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + + * 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 __SECURITY_H__ + +#define __SECURITY_H__ + + + +#include + + + +#define MBED_DOMAIN "eeforester" + +#define MBED_ENDPOINT_NAME "a3e4593c-4e03-492a-9e32-320550fe442e" + + + +const unsigned char PSK[] = {0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x30,0x31,0x32,0x33,0x34,0x35,0x36}; + +const unsigned char PSK_IDENTITY[] = {0x0F,0x0F}; + + + +const uint8_t SERVER_CERT[] = "-----BEGIN CERTIFICATE-----\r\n" + +"MIIBmDCCAT6gAwIBAgIEVUCA0jAKBggqhkjOPQQDAjBLMQswCQYDVQQGEwJGSTEN\r\n" + +"MAsGA1UEBwwET3VsdTEMMAoGA1UECgwDQVJNMQwwCgYDVQQLDANJb1QxETAPBgNV\r\n" + +"BAMMCEFSTSBtYmVkMB4XDTE1MDQyOTA2NTc0OFoXDTE4MDQyOTA2NTc0OFowSzEL\r\n" + +"MAkGA1UEBhMCRkkxDTALBgNVBAcMBE91bHUxDDAKBgNVBAoMA0FSTTEMMAoGA1UE\r\n" + +"CwwDSW9UMREwDwYDVQQDDAhBUk0gbWJlZDBZMBMGByqGSM49AgEGCCqGSM49AwEH\r\n" + +"A0IABLuAyLSk0mA3awgFR5mw2RHth47tRUO44q/RdzFZnLsAsd18Esxd5LCpcT9w\r\n" + +"0tvNfBv4xJxGw0wcYrPDDb8/rjujEDAOMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0E\r\n" + +"AwIDSAAwRQIhAPAonEAkwixlJiyYRQQWpXtkMZax+VlEiS201BG0PpAzAiBh2RsD\r\n" + +"NxLKWwf4O7D6JasGBYf9+ZLwl0iaRjTjytO+Kw==\r\n" + +"-----END CERTIFICATE-----\r\n"; + + + +const uint8_t CERT[] = "-----BEGIN CERTIFICATE-----\r\n" + +"MIIBjDCCATCgAwIBAgIEFGtTOzAMBggqhkjOPQQDAgUAMBAxDjAMBgNVBAMTBW5z\r\n" + +"cDAxMB4XDTE1MDkwMjE0MjE0MVoXDTE2MDkwMTE0MjE0MVowgYcxODA2BgNVBAMT\r\n" + +"L2EzZTQ1OTNjLTRlMDMtNDkyYS05ZTMyLTMyMDU1MGZlNDQyZS9lZWZvcmVzdGVy\r\n" + +"MQwwCgYDVQQLEwNBUk0xEjAQBgNVBAoTCW1iZWQgdXNlcjENMAsGA1UEBxMET3Vs\r\n" + +"dTENMAsGA1UECBMET3VsdTELMAkGA1UEBhMCRkkwWTATBgcqhkjOPQIBBggqhkjO\r\n" + +"PQMBBwNCAAQuxHp1a1V8pCVziDMhuuSt5zbrduEe+0y+UXuPMj2k6uoEuVCYI4+k\r\n" + +"JU6WSfVYAFSVVka0JhIMKB289xU2G5+EMAwGCCqGSM49BAMCBQADSAAwRQIgeWQK\r\n" + +"su17hcY+fQxY8H8BgrGy0z+RKJr51WZl2LR9ZSwCIQDKPx9LYzwSw8y1hugpcsc/\r\n" + +"ul5++FNrYwLE44l3pW87yw==\r\n" + +"-----END CERTIFICATE-----\r\n"; + + + +const uint8_t KEY[] = "-----BEGIN PRIVATE KEY-----\r\n" + +"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg9RFcAVbOKG1LbIF8\r\n" + +"kNqA8dznz4wnD+B/ghYNQMHtL/qhRANCAAQuxHp1a1V8pCVziDMhuuSt5zbrduEe\r\n" + +"+0y+UXuPMj2k6uoEuVCYI4+kJU6WSfVYAFSVVka0JhIMKB289xU2G5+E\r\n" + +"-----END PRIVATE KEY-----\r\n"; + + + +#endif //__SECURITY_H__ diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient-smokeTest/testconfig.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient-smokeTest/testconfig.cpp new file mode 100644 index 0000000000..6c50c44f93 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient-smokeTest/testconfig.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "mbed-client/m2mstring.h" +#include "testconfig.h" +#include "security.h" + +TestConfig::TestConfig() { } + +TestConfig::~TestConfig() { } + +/*void TestConfig::set_endpoint_name(const char *name) { + _endpointName = m2m::String("lwm2mtest-"); + _endpointName += name; + + printf("MBED: endpoint=%s", _endpointName.c_str()); +}*/ + +void TestConfig::setup() { + _bootstrapAddress = m2m::String("dummy"); + _mdsAddress = m2m::String("coap://ds-test.dev.mbed.com:5683"); + _endpointName = m2m::String(MBED_ENDPOINT_NAME); + _endpointType = m2m::String("test2"); + _domain = m2m::String(MBED_DOMAIN); + _port = 5683; + _lifetime = 2222; + + printf("MBED: test configuration \n"); + printf("mds_server=%s\n", _mdsAddress.c_str()); + printf("endpoint name=%s\n", _endpointName.c_str()); + printf("endpoint type=%s\n", _endpointType.c_str()); + printf("domain=%s\n", _domain.c_str()); + printf("port=%d\n", _port); + printf("lifetime=%d\n\n", _lifetime); +} + +m2m::String& TestConfig::get_domain() { + return _domain; +} + +m2m::String& TestConfig::get_bootstrap_server() { + return _bootstrapAddress; +} + +m2m::String& TestConfig::get_mds_server() { + return _mdsAddress; +} + +m2m::String& TestConfig::get_endpoint_name() { + return _endpointName; +} + +m2m::String& TestConfig::get_endpoint_type() { + return _endpointType; +} + +int TestConfig::get_port() { + //return _port++; + return _port; +} + +int TestConfig::get_lifetime() { + return _lifetime; +} + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient-smokeTest/testconfig.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient-smokeTest/testconfig.h new file mode 100644 index 0000000000..7e32d4fc82 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient-smokeTest/testconfig.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TESTCONFIG_H_ +#define TESTCONFIG_H_ + +class TestConfig { + +public: + + TestConfig(); + ~TestConfig(); + + void setup(); + void set_endpoint_name(const char *name); + + m2m::String& get_domain(); + m2m::String& get_bootstrap_server(); + m2m::String& get_mds_server(); + m2m::String& get_endpoint_name(); + m2m::String& get_endpoint_type(); + int get_port(); + int get_lifetime(); + +private: + + int _port; + int _lifetime; + m2m::String _domain; + m2m::String _endpointName; + m2m::String _endpointType; + m2m::String _bootstrapAddress; + m2m::String _mdsAddress; + +}; + +#endif /* TESTCONFIG_H_ */ diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/CThunk.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/CThunk.h new file mode 100644 index 0000000000..4fd91033e0 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/CThunk.h @@ -0,0 +1,202 @@ +/* General C++ Object Thunking class + * + * - allows direct callbacks to non-static C++ class functions + * - keeps track for the corresponding class instance + * - supports an optional context parameter for the called function + * - ideally suited for class object receiving interrupts (NVIC_SetVector) + * + * Copyright (c) 2014-2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __CTHUNK_H__ +#define __CTHUNK_H__ + +#define CTHUNK_ADDRESS 1 + +#if defined(__CORTEX_M3) || defined(__CORTEX_M4) || defined(__thumb2__) +#define CTHUNK_VARIABLES volatile uint32_t code[1] +/** +* CTHUNK disassembly for Cortex-M3/M4 (thumb2): +* * ldm.w pc,{r0,r1,r2,pc} +* +* This instruction loads the arguments for the static thunking function to r0-r2, and +* branches to that function by loading its address into PC. +* +* This is safe for both regular calling and interrupt calling, since it only touches scratch registers +* which should be saved by the caller, and are automatically saved as part of the IRQ context switch. +*/ +#define CTHUNK_ASSIGMENT m_thunk.code[0] = 0x8007E89F + +#elif defined(__CORTEX_M0PLUS) || defined(__CORTEX_M0) +/* +* CTHUNK disassembly for Cortex M0 (thumb): +* * push {r0,r1,r2,r3,r4,lr} save touched registers and return address +* * movs r4,#4 set up address to load arguments from (immediately following this code block) (1) +* * add r4,pc set up address to load arguments from (immediately following this code block) (2) +* * ldm r4!,{r0,r1,r2,r3} load arguments for static thunk function +* * blx r3 call static thunk function +* * pop {r0,r1,r2,r3,r4,pc} restore scratch registers and return from function +*/ +#define CTHUNK_VARIABLES volatile uint32_t code[3] +#define CTHUNK_ASSIGMENT do { \ + m_thunk.code[0] = 0x2404B51F; \ + m_thunk.code[1] = 0xCC0F447C; \ + m_thunk.code[2] = 0xBD1F4798; \ + } while (0) + +#else +#error "Target is not currently suported." +#endif + +/* IRQ/Exception compatible thunk entry function */ +typedef void (*CThunkEntry)(void); + +template +class CThunk +{ + public: + typedef void (T::*CCallbackSimple)(void); + typedef void (T::*CCallback)(void* context); + + inline CThunk(T *instance) + { + init(instance, NULL, NULL); + } + + inline CThunk(T *instance, CCallback cb) + { + init(instance, cb, NULL); + } + + ~CThunk() { + + } + + inline CThunk(T *instance, CCallbackSimple cb) + { + init(instance, (CCallback)cb, NULL); + } + + inline CThunk(T &instance, CCallback cb) + { + init(instance, cb, NULL); + } + + inline CThunk(T &instance, CCallbackSimple cb) + { + init(instance, (CCallback)cb, NULL); + } + + inline CThunk(T &instance, CCallback cb, void* ctx) + { + init(instance, cb, ctx); + } + + inline void callback(CCallback cb) + { + m_callback = cb; + } + + inline void callback(CCallbackSimple cb) + { + m_callback = (CCallback)cb; + } + + inline void context(void* ctx) + { + m_thunk.context = (uint32_t)ctx; + } + + inline void context(uint32_t ctx) + { + m_thunk.context = ctx; + } + + inline uint32_t entry(void) + { + return (((uint32_t)&m_thunk)|CTHUNK_ADDRESS); + } + + /* get thunk entry point for connecting rhunk to an IRQ table */ + inline operator CThunkEntry(void) + { + return (CThunkEntry)entry(); + } + + /* get thunk entry point for connecting rhunk to an IRQ table */ + inline operator uint32_t(void) + { + return entry(); + } + + /* simple test function */ + inline void call(void) + { + (((CThunkEntry)(entry()))()); + } + + private: + T* m_instance; + volatile CCallback m_callback; + +// TODO: this needs proper fix, to refactor toolchain header file and all its use +// PACKED there is not defined properly for IAR +#if defined (__ICCARM__) + typedef __packed struct + { + CTHUNK_VARIABLES; + volatile uint32_t instance; + volatile uint32_t context; + volatile uint32_t callback; + volatile uint32_t trampoline; + } CThunkTrampoline; +#else + typedef struct + { + CTHUNK_VARIABLES; + volatile uint32_t instance; + volatile uint32_t context; + volatile uint32_t callback; + volatile uint32_t trampoline; + } __attribute__((__packed__)) CThunkTrampoline; +#endif + + static void trampoline(T* instance, void* ctx, CCallback* cb) + { + if(instance && *cb) { + (static_cast(instance)->**cb)(ctx); + } + } + + volatile CThunkTrampoline m_thunk; + + inline void init(T *instance, CCallback cb, void* ctx) + { + /* remember callback - need to add this level of redirection + as pointer size for member functions differs between platforms */ + m_callback = cb; + + /* populate thunking trampoline */ +// CTHUNK_ASSIGMENT; +// m_thunk.context = (uint32_t)ctx; +// m_thunk.instance = (uint32_t)instance; +// m_thunk.callback = (uint32_t)&m_callback; +// m_thunk.trampoline = (uint32_t)&trampoline; + +// __ISB(); +// __DSB(); + } +}; + +#endif/*__CTHUNK_H__*/ diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/FunctionPointer.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/FunctionPointer.h new file mode 100644 index 0000000000..b8a7e89448 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/FunctionPointer.h @@ -0,0 +1,604 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 MBED_FUNCTIONPOINTER_H +#define MBED_FUNCTIONPOINTER_H + +#include +#include +#include +#include +#include +#include "FunctionPointerBase.h" +#include "FunctionPointerBind.h" + +namespace mbed { +/** A class for storing and calling a pointer to a static or member void function without arguments + */ +template +class FunctionPointer0 : public FunctionPointerBase{ +public: + typedef R(*static_fp)(void); + typedef struct arg_struct{ + } ArgStruct; + /** Create a FunctionPointer, attaching a static function + * + * @param function The void static function to attach (default is none) + */ + FunctionPointer0(static_fp function = 0): + FunctionPointerBase() + { + attach(function); + } + + /** Create a FunctionPointer, attaching a member function + * + * @param object The object pointer to invoke the member function on (i.e. the this pointer) + * @param function The address of the void member function to attach + */ + template + FunctionPointer0(T *object, R (T::*member)(void)): + FunctionPointerBase() + { + attach(object, member); + } + + /** Attach a static function + * + * @param function The void static function to attach (default is none) + */ + void attach(static_fp function) { + FunctionPointerBase::_object = reinterpret_cast(function); + FunctionPointerBase::_membercaller = &FunctionPointer0::staticcaller; + } + + /** Attach a member function + * + * @param object The object pointer to invoke the member function on (i.e. the this pointer) + * @param function The address of the void member function to attach + */ + template + void attach(T *object, R (T::*member)(void)) { + FunctionPointerBase::_object = static_cast(object); + *reinterpret_cast(FunctionPointerBase::_member) = member; + FunctionPointerBase::_membercaller = &FunctionPointer0::membercaller; + } + + /** Call the attached static or member function + */ + R call(){ + return FunctionPointerBase::call(NULL); + } + + FunctionPointerBind bind() { + FunctionPointerBind fp; + fp.bind(&FunctionPointerBase::_nullops, (ArgStruct *) NULL, this); + return fp; + } + + static_fp get_function()const { + return reinterpret_cast(FunctionPointerBase::_object); + } + + R operator ()(void) { + return call(); + } + +private: + template + static R membercaller(void *object, uintptr_t *member, void *arg) { + (void) arg; + T* o = static_cast(object); + R (T::**m)(void) = reinterpret_cast(member); + return (o->**m)(); + } + static R staticcaller(void *object, uintptr_t *member, void *arg) { + (void) arg; + (void) member; + static_fp f = reinterpret_cast(object); + return f(); + } +}; + +/* If we had variaditic templates, this wouldn't be a problem, but until C++11 is enabled, we are stuck with multiple classes... */ + +/** A class for storing and calling a pointer to a static or member void function with one argument + */ +template +class FunctionPointer1 : public FunctionPointerBase { +protected: + typedef struct arg_struct{ + A1 a1; + arg_struct(const A1 *b1) { + a1 = *b1; + } + } ArgStruct; + +public: + typedef R(*static_fp)(A1); + /** Create a FunctionPointer, attaching a static function + * + * @param function The void static function to attach (default is none) + */ + FunctionPointer1(static_fp function = 0) { + attach(function); + } + + /** Create a FunctionPointer, attaching a member function + * + * @param object The object pointer to invoke the member function on (i.e. the this pointer) + * @param function The address of the void member function to attach + */ + template + FunctionPointer1(T *object, R (T::*member)(A1)) { + attach(object, member); + } + + /** Attach a static function + * + * @param function The void static function to attach (default is none) + */ + void attach(static_fp function) { + FunctionPointerBase::_object = reinterpret_cast(function); + FunctionPointerBase::_membercaller = &FunctionPointer1::staticcaller; + } + + /** Attach a member function + * + * @param object The object pointer to invoke the member function on (i.e. the this pointer) + * @param function The address of the void member function to attach + */ + template + void attach(T *object, R (T::*member)(A1)) + { + FunctionPointerBase::_object = static_cast(object); + *reinterpret_cast(FunctionPointerBase::_member) = member; + FunctionPointerBase::_membercaller = &FunctionPointer1::membercaller; + } + + FunctionPointerBind bind(const A1 &a1) { + FunctionPointerBind fp; + fp.bind(&_fp1_ops, (ArgStruct *) NULL, this, &a1); + return fp; + } + + + /** Call the attached static or member function + */ + R call(A1 a1) + { + ArgStruct Args(&a1); + return FunctionPointerBase::call(&Args); + } + + static_fp get_function()const + { + return reinterpret_cast(FunctionPointerBase::_object); + } + + R operator ()(A1 a) { + return call(a); + } + +private: + template + static R membercaller(void *object, uintptr_t *member, void *arg) { + ArgStruct *Args = static_cast(arg); + T* o = static_cast(object); + R (T::**m)(A1) = reinterpret_cast(member); + return (o->**m)(Args->a1); + } + static R staticcaller(void *object, uintptr_t *member, void *arg) { + ArgStruct *Args = static_cast(arg); + (void) member; + static_fp f = reinterpret_cast(object); + return f(Args->a1); + } +/* static void constructor(void * dest, va_list args) { + new(dest) ArgStruct(va_arg(args,A1*)); + } + static void copy_constructor(void *dest , void* src) { + ArgStruct *src_args = static_cast(src); + new(dest) ArgStruct(&(src_args->a1)); + } + static void destructor(void *args) { + ArgStruct *argstruct = static_cast(args); + argstruct->~arg_struct(); + } +*/ +protected: + static const struct FunctionPointerBase::ArgOps _fp1_ops; +}; + +template +const struct FunctionPointerBase::ArgOps FunctionPointer1::_fp1_ops = { + FunctionPointer1::constructor, + FunctionPointer1::copy_constructor, + FunctionPointer1::destructor +}; + + +/** A class for storing and calling a pointer to a static or member void function with two arguments + */ +template +class FunctionPointer2 : public FunctionPointerBase { +protected: + typedef struct arg_struct{ + A1 a1; + A2 a2; + arg_struct(const A1 *b1, const A2 *b2) { + a1 = *b1; + a2 = *b2; + } + } ArgStruct; + +public: + typedef R(*static_fp)(A1, A2); + /** Create a FunctionPointer, attaching a static function + * + * @param function The void static function to attach (default is none) + */ + FunctionPointer2(static_fp function = 0) { + attach(function); + } + + /** Create a FunctionPointer, attaching a member function + * + * @param object The object pointer to invoke the member function on (i.e. the this pointer) + * @param function The address of the void member function to attach + */ + template + FunctionPointer2(T *object, R (T::*member)(A1, A2)) { + attach(object, member); + } + + /** Attach a static function + * + * @param function The void static function to attach (default is none) + */ + void attach(static_fp function) { + FunctionPointerBase::_object = reinterpret_cast(function); + FunctionPointerBase::_membercaller = &FunctionPointer2::staticcaller; + } + + /** Attach a member function + * + * @param object The object pointer to invoke the member function on (i.e. the this pointer) + * @param function The address of the void member function to attach + */ + template + void attach(T *object, R (T::*member)(A1, A2)) + { + FunctionPointerBase::_object = static_cast(object); + *reinterpret_cast(FunctionPointerBase::_member) = member; + FunctionPointerBase::_membercaller = &FunctionPointer2::membercaller; + } + + FunctionPointerBind bind(const A1 &a1, const A2 &a2) { + FunctionPointerBind fp; + fp.bind(&_fp2_ops, (ArgStruct *) NULL, this, &a1, &a2); + return fp; + } + + + /** Call the attached static or member function + */ + R call(A1 a1, A2 a2) + { + ArgStruct Args(&a1, &a2); + return FunctionPointerBase::call(&Args); + } + + static_fp get_function()const + { + return reinterpret_cast(FunctionPointerBase::_object); + } + + R operator ()(A1 a1, A2 a2) { + return call(a1, a2); + } + +private: + template + static R membercaller(void *object, uintptr_t *member, void *arg) { + ArgStruct *Args = static_cast(arg); + T* o = static_cast(object); + R (T::**m)(A1, A2) = reinterpret_cast(member); + return (o->**m)(Args->a1, Args->a2); + } + static R staticcaller(void *object, uintptr_t *member, void *arg) { + ArgStruct *Args = static_cast(arg); + (void) member; + static_fp f = reinterpret_cast(object); + return f(Args->a1, Args->a2); + } +/* static void constructor(void * dest, va_list args) { + A1 *a1 = va_arg(args, A1*); + A2 *a2 = va_arg(args, A2*); + new(dest) ArgStruct(a1, a2); + } + static void copy_constructor(void *dest , void* src) { + ArgStruct *src_args = static_cast(src); + new(dest) ArgStruct(&(src_args->a1), &(src_args->a2)); + } + static void destructor(void *args) { + ArgStruct *argstruct = static_cast(args); + argstruct->~arg_struct(); + } +*/ +protected: + static const struct FunctionPointerBase::ArgOps _fp2_ops; +}; + +template +const struct FunctionPointerBase::ArgOps FunctionPointer2::_fp2_ops = { + FunctionPointer2::constructor, + FunctionPointer2::copy_constructor, + FunctionPointer2::destructor +}; + +/** A class for storing and calling a pointer to a static or member void function with three arguments + */ +template +class FunctionPointer3 : public FunctionPointerBase { +protected: + typedef struct arg_struct{ + A1 a1; + A2 a2; + A3 a3; + arg_struct(const A1 *b1, const A2 *b2, const A3* b3) { + a1 = *b1; + a2 = *b2; + a3 = *b3; + } + } ArgStruct; + +public: + typedef R(*static_fp)(A1, A2, A3); + /** Create a FunctionPointer, attaching a static function + * + * @param function The void static function to attach (default is none) + */ + FunctionPointer3(static_fp function = 0) { + attach(function); + } + + /** Create a FunctionPointer, attaching a member function + * + * @param object The object pointer to invoke the member function on (i.e. the this pointer) + * @param function The address of the void member function to attach + */ + template + FunctionPointer3(T *object, R (T::*member)(A1, A2, A3)) { + attach(object, member); + } + + /** Attach a static function + * + * @param function The void static function to attach (default is none) + */ + void attach(static_fp function) { + FunctionPointerBase::_object = reinterpret_cast(function); + FunctionPointerBase::_membercaller = &FunctionPointer3::staticcaller; + } + + /** Attach a member function + * + * @param object The object pointer to invoke the member function on (i.e. the this pointer) + * @param function The address of the void member function to attach + */ + template + void attach(T *object, R (T::*member)(A1, A2, A3)) + { + FunctionPointerBase::_object = static_cast(object); + *reinterpret_cast(FunctionPointerBase::_member) = member; + FunctionPointerBase::_membercaller = &FunctionPointer3::membercaller; + } + + FunctionPointerBind bind(const A1 &a1, const A2 &a2, const A3 &a3) { + FunctionPointerBind fp; + fp.bind(&_fp3_ops, (ArgStruct *) NULL, this, &a1, &a2, &a3); + return fp; + } + + + /** Call the attached static or member function + */ + R call(A1 a1, A2 a2, A3 a3) + { + ArgStruct Args(&a1, &a2, &a3); + return FunctionPointerBase::call(&Args); + } + + static_fp get_function()const + { + return reinterpret_cast(FunctionPointerBase::_object); + } + + R operator ()(A1 a1, A2 a2, A3 a3) { + return call(a1, a2, a3); + } + +private: + template + static R membercaller(void *object, uintptr_t *member, void *arg) { + ArgStruct *Args = static_cast(arg); + T* o = static_cast(object); + R (T::**m)(A1, A2, A3) = reinterpret_cast(member); + return (o->**m)(Args->a1, Args->a2, Args->a3); + } + static R staticcaller(void *object, uintptr_t *member, void *arg) { + ArgStruct *Args = static_cast(arg); + (void) member; + static_fp f = reinterpret_cast(object); + return f(Args->a1, Args->a2, Args->a3); + } +/* static void constructor(void * dest, va_list args) { + A1 *a1 = va_arg(args, A1*); + A2 *a2 = va_arg(args, A2*); + A3 *a3 = va_arg(args, A3*); + new(dest) ArgStruct(a1, a2, a3); + } + static void copy_constructor(void *dest , void* src) { + ArgStruct *src_args = static_cast(src); + new(dest) ArgStruct(&(src_args->a1), &(src_args->a2), &(src_args->a3)); + } + static void destructor(void *args) { + ArgStruct *argstruct = static_cast(args); + argstruct->~arg_struct(); + } +*/ +protected: + static const struct FunctionPointerBase::ArgOps _fp3_ops; +}; + +template +const struct FunctionPointerBase::ArgOps FunctionPointer3::_fp3_ops = { + FunctionPointer3::constructor, + FunctionPointer3::copy_constructor, + FunctionPointer3::destructor +}; + +/** A class for storing and calling a pointer to a static or member void function with four arguments + */ +template +class FunctionPointer4 : public FunctionPointerBase { +protected: + typedef struct arg_struct{ + A1 a1; + A2 a2; + A3 a3; + A4 a4; + arg_struct(const A1 *b1, const A2 *b2, const A3* b3, const A4* b4) { + a1 = *b1; + a2 = *b2; + a3 = *b3; + a4 = *b4; + } + } ArgStruct; + +public: + typedef R(*static_fp)(A1, A2, A3, A4); + /** Create a FunctionPointer, attaching a static function + * + * @param function The void static function to attach (default is none) + */ + FunctionPointer4(static_fp function = 0) { + attach(function); + } + + /** Create a FunctionPointer, attaching a member function + * + * @param object The object pointer to invoke the member function on (i.e. the this pointer) + * @param function The address of the void member function to attach + */ + template + FunctionPointer4(T *object, R (T::*member)(A1, A2, A3, A4)) { + attach(object, member); + } + + /** Attach a static function + * + * @param function The void static function to attach (default is none) + */ + void attach(static_fp function) { + FunctionPointerBase::_object = reinterpret_cast(function); + FunctionPointerBase::_membercaller = &FunctionPointer4::staticcaller; + } + + /** Attach a member function + * + * @param object The object pointer to invoke the member function on (i.e. the this pointer) + * @param function The address of the void member function to attach + */ + template + void attach(T *object, R (T::*member)(A1, A2, A3, A4)) + { + FunctionPointerBase::_object = static_cast(object); + *reinterpret_cast(FunctionPointerBase::_member) = member; + FunctionPointerBase::_membercaller = &FunctionPointer4::membercaller; + } + + FunctionPointerBind bind(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) { + FunctionPointerBind fp; + fp.bind(&_fp4_ops, (ArgStruct *) NULL, this, &a1, &a2, &a3, &a4); + return fp; + } + + + /** Call the attached static or member function + */ + R call(A1 a1, A2 a2, A3 a3, A4 a4) + { + ArgStruct Args(&a1, &a2, &a3, &a4); + return FunctionPointerBase::call(&Args); + } + + static_fp get_function()const + { + return reinterpret_cast(FunctionPointerBase::_object); + } + + R operator ()(A1 a1, A2 a2, A3 a3, A4 a4) { + return call(a1, a2, a3, a4); + } + +private: + template + static R membercaller(void *object, uintptr_t *member, void *arg) { + ArgStruct *Args = static_cast(arg); + T* o = static_cast(object); + R (T::**m)(A1, A2, A3, A4) = reinterpret_cast(member); + return (o->**m)(Args->a1, Args->a2, Args->a3, Args->a4); + } + static R staticcaller(void *object, uintptr_t *member, void *arg) { + ArgStruct *Args = static_cast(arg); + (void) member; + static_fp f = reinterpret_cast(object); + return f(Args->a1, Args->a2, Args->a3, Args->a4); + } +/* static void constructor(void * dest, va_list args) { + A1 *a1 = va_arg(args, A1*); + A2 *a2 = va_arg(args, A2*); + A3 *a3 = va_arg(args, A3*); + A4 *a4 = va_arg(args, A4*); + new(dest) ArgStruct(a1, a2, a3, a4); + } + static void copy_constructor(void *dest , void* src) { + ArgStruct *src_args = static_cast(src); + new(dest) ArgStruct(&(src_args->a1), &(src_args->a2), &(src_args->a3), &(src_args->a4)); + } + static void destructor(void *args) { + ArgStruct *argstruct = static_cast(args); + argstruct->~arg_struct(); + } +*/ +protected: + static const struct FunctionPointerBase::ArgOps _fp4_ops; +}; + +template +const struct FunctionPointerBase::ArgOps FunctionPointer4::_fp4_ops = { + FunctionPointer4::constructor, + FunctionPointer4::copy_constructor, + FunctionPointer4::destructor +}; + +typedef FunctionPointer0 FunctionPointer; +//typedef FunctionPointer1 event_callback_t; + +} // namespace mbed + +#endif diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/FunctionPointerBase.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/FunctionPointerBase.h new file mode 100644 index 0000000000..02a6dbd30f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/FunctionPointerBase.h @@ -0,0 +1,89 @@ +/* mbed Microcontroller Library + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 MBED_FUNCTIONPOINTERBASE_H +#define MBED_FUNCTIONPOINTERBASE_H + +#include +#include +#include +#include +namespace mbed { + +template +class FunctionPointerBase { +public: + operator bool(void) const { + return (_membercaller != NULL) && (_object != NULL); + } + + /** + * Clears the current function pointer assignment + * After clear(), this instance will point to nothing (NULL) + */ + virtual void clear() { + _membercaller = NULL; + _object = NULL; + } + +protected: + struct ArgOps { + void (*constructor)(void *, va_list); + void (*copy_args)(void *, void *); + void (*destructor)(void *); + }; + void * _object; // object Pointer/function pointer + R (*_membercaller)(void *, uintptr_t *, void *); + // aligned raw member function pointer storage - converted back by registered _membercaller + uintptr_t _member[4]; + static const struct ArgOps _nullops; + +protected: + FunctionPointerBase():_object(NULL), _membercaller(NULL) {} + FunctionPointerBase(const FunctionPointerBase & fp) { + copy(&fp); + } + virtual ~FunctionPointerBase() { + } + + /** + * Calls the member pointed to by object::member or (function)object + * @param arg + * @return + */ + inline R call(void* arg) { + return _membercaller(_object, _member, arg); + } + + void copy(const FunctionPointerBase * fp) { + _object = fp->_object; + memcpy (_member, fp->_member, sizeof(_member)); + _membercaller = fp->_membercaller; + } +private: + static void _null_constructor(void * dest, va_list args) {(void) dest;(void) args;} + static void _null_copy_args(void *dest , void* src) {(void) dest; (void) src;} + static void _null_destructor(void *args) {(void) args;} + +}; +template +const struct FunctionPointerBase::ArgOps FunctionPointerBase::_nullops = { + FunctionPointerBase::_null_constructor, + FunctionPointerBase::_null_copy_args, + FunctionPointerBase::_null_destructor +}; + +} +#endif diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/FunctionPointerBind.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/FunctionPointerBind.h new file mode 100644 index 0000000000..f90f187f4c --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/FunctionPointerBind.h @@ -0,0 +1,112 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 MBED_FUNCTIONPOINTERBIND_H__ +#define MBED_FUNCTIONPOINTERBIND_H__ + +#include +#include +#include +#include +#include +#include "FunctionPointerBase.h" + +#ifndef EVENT_STORAGE_SIZE +#define EVENT_STORAGE_SIZE 32 +#endif + +#define MBED_STATIC_ASSERT(MBED_STATIC_ASSERT_FAILED,MSG)\ + switch(0){\ + case 0:case (MBED_STATIC_ASSERT_FAILED): \ + break;} + +namespace mbed{ + +template +class FunctionPointerBind : public FunctionPointerBase { +public: + // Call the Event + inline R call() { + return FunctionPointerBase::call(static_cast(_storage)); + } + FunctionPointerBind(): + FunctionPointerBase(), + _ops(&FunctionPointerBase::_nullops) + {} + + FunctionPointerBind(const FunctionPointerBind & fp): + FunctionPointerBase(), + _ops(&FunctionPointerBase::_nullops) { + *this = fp; + } + + virtual ~FunctionPointerBind() { + _ops->destructor(_storage); + } + + FunctionPointerBind & operator=(const FunctionPointerBind& rhs) { + if (_ops != &FunctionPointerBase::_nullops) { + _ops->destructor(_storage); + } + FunctionPointerBase::copy(&rhs); + _ops = rhs._ops; + _ops->copy_args(_storage, (void *)rhs._storage); + return *this; + } + + /** + * Clears the current binding, making this instance unbound + */ + virtual void clear() { + if (_ops != &FunctionPointerBase::_nullops) { + _ops->destructor(_storage); + } + _ops = &FunctionPointerBase::_nullops; + FunctionPointerBase::clear(); + } + + template + FunctionPointerBind & bind(const struct FunctionPointerBase::ArgOps * ops , S * argStruct, FunctionPointerBase *fp, ...) { + MBED_STATIC_ASSERT(sizeof(S) <= sizeof(_storage), ERROR: Arguments too large for FunctionPointerBind internal storage) + if (_ops != &FunctionPointerBase::_nullops) { + _ops->destructor(_storage); + } + _ops = ops; + FunctionPointerBase::copy(fp); + assert(this->_ops != NULL); + assert(this->_ops->constructor != NULL); + if (argStruct) { + this->_ops->copy_args(this->_storage, (void *)argStruct); + } else { + va_list args; + va_start(args, fp); + this->_ops->constructor(_storage, args); + va_end(args); + } + return *this; + } + + R operator()() { + return call(); + } + +protected: + const struct FunctionPointerBase::ArgOps * _ops; + uint32_t _storage[(EVENT_STORAGE_SIZE+sizeof(uint32_t)-1)/sizeof(uint32_t)]; +}; +} + +#endif // MBED_FUNCTIONPOINTERBIND_H__ diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/Ticker.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/Ticker.h new file mode 100644 index 0000000000..54611a3c32 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/Ticker.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TICKER_H +#define TICKER_H + +namespace mbed +{ +typedef uint64_t timestamp_t; + + class Ticker{ + public : + Ticker() {} + ~Ticker(){} + + // Ticker + template + void attach_us(T* tptr, void (T::*mptr)(void), timestamp_t){} + + void detach(); + }; +} + +#endif // TICKER_H diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/mbed-net-socket-abstract/socket_api.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/mbed-net-socket-abstract/socket_api.h new file mode 100644 index 0000000000..8c61d39eed --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/mbed-net-socket-abstract/socket_api.h @@ -0,0 +1,164 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKET_ABSTRACT_SOCKET_API_H__ +#define __MBED_NET_SOCKET_ABSTRACT_SOCKET_API_H__ + +#include +#include "socket_types.h" +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef SOCKET_MAX_STACKS +#define SOCKET_MAX_STACKS 2 +#endif + +typedef socket_error_t (*socket_init)(); +typedef socket_error_t (*socket_create)(struct socket *socket, + const socket_address_family_t af, const socket_proto_family_t pf, + socket_api_handler_t const handler); +typedef socket_error_t (*socket_destroy)(struct socket *socket); +typedef socket_error_t (*socket_close)(struct socket *socket); +typedef socket_api_handler_t (*socket_periodic_task)(const struct socket * socket); +typedef uint32_t (*socket_periodic_interval)(const struct socket * socket); +typedef socket_error_t (*socket_resolve)(struct socket *socket, const char *address); +typedef socket_error_t (*socket_connect)(struct socket *sock, const struct socket_addr *address, const uint16_t port); +typedef socket_error_t (*socket_bind)(struct socket *socket, const struct socket_addr *address, const uint16_t port); +typedef socket_error_t (*socket_str2addr)(const struct socket *socket, struct socket_addr *addr, const char *address); +typedef socket_error_t (*socket_start_listen)(struct socket *socket, const uint32_t backlog); +typedef socket_error_t (*socket_stop_listen)(struct socket *socket); +typedef socket_error_t (*socket_accept)(struct socket *sock, socket_api_handler_t handler); +typedef socket_error_t (*socket_reject)(struct socket *sock); +typedef socket_error_t (*socket_send)(struct socket *socket, const void * buf, const size_t len); +typedef socket_error_t (*socket_send_to)(struct socket *socket, const void * buf, const size_t len, const struct socket_addr *addr, const uint16_t port); +typedef socket_error_t (*socket_recv)(struct socket *socket, void * buf, size_t *len); +typedef socket_error_t (*socket_recv_from)(struct socket *socket, void * buf, size_t *len, struct socket_addr *addr, uint16_t *port); + +typedef socket_error_t (*socket_get_local_addr)(const struct socket *socket, struct socket_addr *addr); +typedef socket_error_t (*socket_get_remote_addr)(const struct socket *socket, struct socket_addr *addr); +typedef socket_error_t (*socket_get_local_port)(const struct socket *socket, uint16_t *port); +typedef socket_error_t (*socket_get_remote_port)(const struct socket *socket, uint16_t *port); + +typedef uint8_t (*socket_is_connected)(const struct socket *socket); +typedef uint8_t (*socket_is_bound)(const struct socket *socket); + +struct socket_api { + socket_stack_t stack; + uint32_t version; + socket_init init; + socket_create create; + socket_destroy destroy; + socket_close close; + socket_periodic_task periodic_task; + socket_periodic_interval periodic_interval; + socket_resolve resolve; + socket_connect connect; + socket_str2addr str2addr; + socket_bind bind; + socket_start_listen start_listen; + socket_stop_listen stop_listen; + socket_accept accept; + socket_reject reject; + socket_send send; + socket_send_to send_to; + socket_recv recv; + socket_recv_from recv_from; + socket_is_connected is_connected; + socket_is_bound is_bound; + socket_get_local_addr get_local_addr; + socket_get_remote_addr get_remote_addr; + socket_get_local_port get_local_port; + socket_get_remote_port get_remote_port; +}; +#define SOCKET_API_FIRST_PTR init +#define SOCKET_API_LAST_PTR get_remote_port + +socket_error_t socket_register_stack(const struct socket_api * api); +const char * socket_strerror(const socket_error_t err); +const struct socket_api * socket_get_api(const socket_stack_t stack); + +static inline int socket_addr_is_ipv4(const struct socket_addr *addr) +{ + if ((addr->ipv6be[0] == 0) && + (addr->ipv6be[1] == 0) && + (addr->ipv6be[2] == 0)) { + return 1; + } else { + return 0; + } +} +static inline int socket_addr_is_any(const struct socket_addr *addr) +{ + if ((addr->ipv6be[0] == 0) && + (addr->ipv6be[1] == 0) && + (addr->ipv6be[2] == 0) && + (addr->ipv6be[3] == 0)) { + return 1; + } else { + return 0; + } +} +static inline void socket_addr_set_ipv4_addr(struct socket_addr *addr, uint32_t ipv4addr) +{ + addr->ipv6be[0] = 0; + addr->ipv6be[1] = 0; + addr->ipv6be[2] = 0; + addr->ipv6be[3] = ipv4addr; +} +static inline uint32_t socket_addr_get_ipv4_addr(const struct socket_addr *addr) +{ + if (!socket_addr_is_ipv4(addr)) { + return 0; + } + return addr->ipv6be[3]; +} +static inline const uint32_t * socket_addr_get_ipv4_addrp(const struct socket_addr *addr) +{ + if (!socket_addr_is_ipv4(addr)) { + return NULL; + } + return &addr->ipv6be[3]; +} +static inline void socket_addr_set_any(struct socket_addr *addr) +{ + addr->ipv6be[0] = 0; + addr->ipv6be[1] = 0; + addr->ipv6be[2] = 0; + addr->ipv6be[3] = 0; +} + +static inline void socket_addr_copy(struct socket_addr *dest, const struct socket_addr *src) +{ + (dest)->ipv6be[0] = (src)->ipv6be[0]; + (dest)->ipv6be[1] = (src)->ipv6be[1]; + (dest)->ipv6be[2] = (src)->ipv6be[2]; + (dest)->ipv6be[3] = (src)->ipv6be[3]; +} +static inline int socket_addr_cmp(const struct socket_addr *a, const struct socket_addr *b) +{ + return + a->ipv6be[0] != b->ipv6be[0] || + a->ipv6be[1] != b->ipv6be[1] || + a->ipv6be[2] != b->ipv6be[2] || + a->ipv6be[3] != b->ipv6be[3]; +} + +#ifdef __cplusplus +} +#endif + +#endif /* __MBED_NET_SOCKET_ABSTRACT_SOCKET_API_H__ */ diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/mbed-net-socket-abstract/socket_types.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/mbed-net-socket-abstract/socket_types.h new file mode 100644 index 0000000000..0ffb822d9b --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/mbed-net-socket-abstract/socket_types.h @@ -0,0 +1,181 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKET_ABSTRACT_SOCKET_TYPES_H__ +#define __MBED_NET_SOCKET_ABSTRACT_SOCKET_TYPES_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MBED_NET_LWIP +#define MBED_NET_LWIP 1 +#endif + +typedef enum { + SOCKET_ERROR_NONE = 0, + SOCKET_ERROR_UNKNOWN, + SOCKET_ERROR_UNIMPLEMENTED, + SOCKET_ERROR_BUSY, + SOCKET_ERROR_NULL_PTR, + SOCKET_ERROR_BAD_FAMILY, + SOCKET_ERROR_TIMEOUT, + SOCKET_ERROR_BAD_ALLOC, + SOCKET_ERROR_NO_CONNECTION, + SOCKET_ERROR_SIZE, + SOCKET_ERROR_STACK_EXISTS, + SOCKET_ERROR_STACKS, + SOCKET_ERROR_BAD_STACK, + SOCKET_ERROR_BAD_ADDRESS, + SOCKET_ERROR_DNS_FAILED, + SOCKET_ERROR_WOULD_BLOCK, + SOCKET_ERROR_CLOSED, + SOCKET_ERROR_VALUE, + SOCKET_ERROR_ADDRESS_IN_USE, + SOCKET_ERROR_ALREADY_CONNECTED, + SOCKET_ERROR_ABORT, + SOCKET_ERROR_RESET, + SOCKET_ERROR_BAD_ARGUMENT, + SOCKET_ERROR_INTERFACE_ERROR, + SOCKET_ERROR_API_VERSION, + SOCKET_ERROR_NOT_BOUND, + +} socket_error_t; + +typedef enum { + SOCKET_ALLOC_HEAP = 0, + SOCKET_ALLOC_POOL_BEST, +} socket_alloc_pool_t; + +typedef enum { + SOCKET_AF_UNINIT, + SOCKET_AF_INET4, + SOCKET_AF_INET6, + SOCKET_AF_MAX, +} socket_address_family_t; + +typedef enum { + SOCKET_PROTO_UNINIT = 0, + SOCKET_DGRAM, + SOCKET_STREAM, + SOCKET_PROTO_MAX, +} socket_proto_family_t; + +typedef enum { + SOCKET_EVENT_NONE = 0, + SOCKET_EVENT_ERROR, + SOCKET_EVENT_RX_DONE, + SOCKET_EVENT_TX_DONE, + SOCKET_EVENT_RX_ERROR, + SOCKET_EVENT_TX_ERROR, + SOCKET_EVENT_CONNECT, + SOCKET_EVENT_DISCONNECT, + SOCKET_EVENT_DNS, + SOCKET_EVENT_ACCEPT, +} event_flag_t; + +typedef enum { + SOCKET_STATUS_IDLE = 0, + SOCKET_STATUS_RX_BUSY = 1 << 0, + SOCKET_STATUS_TX_BUSY = 1 << 1, + SOCKET_STATUS_CONNECTED = 1 << 2, + SOCKET_STATUS_BOUND = 1 << 3, +} socket_status_t; + +typedef enum { + SOCKET_STACK_UNINIT = 0, + SOCKET_STACK_LWIP_IPV4, + SOCKET_STACK_LWIP_IPV6, + SOCKET_STACK_RESERVED, + SOCKET_STACK_NANOSTACK_IPV6, + SOCKET_STACK_PICOTCP, + SOCKET_STACK_MAX, +} socket_stack_t; + +typedef enum { + SOCKET_BUFFER_UNINITIALISED = 0, + SOCKET_BUFFER_RAW, + SOCKET_BUFFER_LWIP_PBUF, + SOCKET_BUFFER_NANOSTACK_PBUF, +} socket_buffer_type_t; + +struct socket_addr { + uint32_t ipv6be[4]; +}; + +struct socket_buffer { + socket_buffer_type_t type; + const struct socket_buf_api *api; + void *impl; +}; + +struct socket_rawbuf { + void * buf; + size_t size; + size_t pos; +}; + +typedef void (*socket_api_handler_t)(void); +typedef struct { + void * (*alloc)(void *,const size_t); + void (*dealloc)(void *, void *); + void *context; +} socket_allocator_t; + +struct socket_tx_info { + uint16_t sentbytes; +}; + +struct socket_dns_info { + struct socket_addr addr; // A stack-specific socket address struct + const char *domain; +}; + +struct socket_accept_info { + void * newimpl; + uint8_t reject; +}; + +struct socket_event { + event_flag_t event; + struct socket *sock; + union { + struct socket_tx_info t; + socket_error_t e; + struct socket_dns_info d; + struct socket_accept_info a; + } i; +}; +typedef struct socket_event socket_event_t; + +struct socket { + socket_api_handler_t handler; + socket_event_t *event; // TODO: (CThunk upgrade/Alpha3) + const struct socket_api *api; + void *impl; + socket_status_t status; + uint8_t family; + socket_stack_t stack; + void *rxBufChain; // TODO: Only required in some stacks, which do not support BSD-style buffering +}; + +#ifdef __cplusplus +} +#endif +#endif /* __MBED_NET_SOCKET_ABSTRACT_SOCKET_TYPES_H__ */ diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/mbed.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/mbed.h new file mode 100644 index 0000000000..9a1b1fbce9 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/mbed.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 MBED_H +#define MBED_H + +#include +#include + +#endif // MBED_H diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/Socket.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/Socket.h new file mode 100644 index 0000000000..e4dfda504f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/Socket.h @@ -0,0 +1,32 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKETS_SOCKET_H__ +#define __MBED_NET_SOCKETS_SOCKET_H__ + +/* Include all versions of the API */ +#include "v0/Socket.h" + +/* Set the current namespace */ +namespace mbed { + namespace Sockets { + namespace current { + using namespace mbed::Sockets::v0; + } + } +} + +#endif // __MBED_NET_SOCKETS_SOCKET_H__ diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/SocketAddr.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/SocketAddr.h new file mode 100644 index 0000000000..99f2943e9d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/SocketAddr.h @@ -0,0 +1,32 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKETS_SOCKETADDR_H__ +#define __MBED_NET_SOCKETS_SOCKETADDR_H__ + +/* Include all versions of the API */ +#include "v0/SocketAddr.h" + +/* Set the current namespace */ +namespace mbed { + namespace Sockets { + namespace current { + using namespace mbed::Sockets::v0; + } + } +} + +#endif // __MBED_NET_SOCKETS_SOCKETADDR_H__ diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/UDPSocket.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/UDPSocket.h new file mode 100644 index 0000000000..d2d2046650 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/UDPSocket.h @@ -0,0 +1,32 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKETS_UDPSOCKET_H__ +#define __MBED_NET_SOCKETS_UDPSOCKET_H__ + +/* Include all versions of the API */ +#include "v0/UDPSocket.h" + +/* Set the current namespace */ +namespace mbed { + namespace Sockets { + namespace current { + using namespace mbed::Sockets::v0; + } + } +} + +#endif // __MBED_NET_SOCKETS_UDPSOCKET_H__ diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/Socket.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/Socket.h new file mode 100644 index 0000000000..8335ad2b94 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/Socket.h @@ -0,0 +1,268 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKETS_V0_SOCKET_H__ +#define __MBED_NET_SOCKETS_V0_SOCKET_H__ + + +#include +#include +#include "mbed.h" +#include "FunctionPointer.h" +#include "CThunk.h" +#include "mbed-net-socket-abstract/socket_types.h" +#include "SocketAddr.h" + +namespace mbed { +namespace Sockets { +namespace v0 { + +/** + * \brief Socket implements most of the interfaces required for sockets. + * Socket is a pure virtual class; it should never be instantiated directly, but it provides + * common functionality for derived classes. + */ +class Socket { +public: + typedef FunctionPointer3 DNSHandler_t; + typedef FunctionPointer2 ErrorHandler_t; + typedef FunctionPointer1 ReadableHandler_t; + typedef FunctionPointer2 SentHandler_t; +protected: + /** + * Socket constructor + * Initializes the Socket object. Initializes the underlying struct socket. Does not instantiate + * an underlying network stack socket. + * Since it is somewhat awkward to provide the network stack, a future change will provide + * a way to pass the network interface to the socket constructor, which will extract the stack from + * the interface. + * @param[in] stack The network stack to use for this socket. + */ + Socket(const socket_stack_t stack); + /** + * Socket destructor + * Frees the underlying socket implementation. + */ + virtual ~Socket(); +public: + /** + * Start the process of resolving a domain name. + * If the input is a text IP address, an event is queued immediately; otherwise, onDNS is + * queued as soon as DNS is resolved. + * The socket must have been opened before resolve is called + * @param[in] address The domain name to resolve + * @param[in] onDNS The handler to call when the name is resolved + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + virtual socket_error_t resolve(const char* address, const DNSHandler_t &onDNS); + /** + * Open the socket. + * Instantiates and initializes the underlying socket. Receive is started immediately after + * the socket is opened. + * @param[in] af Address family (SOCKET_AF_INET4 or SOCKET_AF_INET6), currently only IPv4 is supported + * @param[in] pf Protocol family (SOCKET_DGRAM or SOCKET_STREAM) + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + virtual socket_error_t open(const socket_address_family_t af, const socket_proto_family_t pf); + /** + * Binds the socket's local address and IP. + * 0.0.0.0 is accepted as a local address if only the port is meant to be bound. + * The behaviour of bind("0.0.0.0",...) is undefined where two or more stacks are in use. + * + * @param[in] address The string representation of the address to bind + * @param[in] port The local port to bind + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + virtual socket_error_t bind(const char *address, const uint16_t port); + /** + * bind(const SocketAddr *, const uint16_t) is the same as bind(const char *, const uint16_t), + * except that the address passed in is a SocketAddr. + * @param[in] address The address to bind + * @param[in] port The local port to bind + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + virtual socket_error_t bind(const SocketAddr *address, const uint16_t port); + /** + * Set the error handler. + * Errors are ignored if onError is not set. + * @param[in] onError + */ + virtual void setOnError(const ErrorHandler_t &onError); + /** + * Set the received data handler + * Received data is queued until it is read using recv or recv_from. + * @param[in] onReadable the handler to use for receive events + */ + virtual void setOnReadable(const ReadableHandler_t &onReadable); + /** + * Receive a message + * @param[out] buf The buffer to fill + * @param[in,out] len A pointer to the size of the receive buffer. Sets the maximum number of bytes + * to read but is updated with the actual number of bytes copied on success. len is not changed on + * failure + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + virtual socket_error_t recv(void * buf, size_t *len); + /** + * Receive a message with the sender address and port + * This API is not valid for SOCK_STREAM + * @param[out] buf The buffer to fill + * @param[in,out] len A pointer to the size of the receive buffer. Sets the maximum number of bytes + * to read but is updated with the actual number of bytes copied on success. len is not changed on + * failure + * @param[out] remote_addr Pointer to an address structure to fill with the sender address + * @param[out] remote_port Pointer to a uint16_t to fill with the sender port + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + virtual socket_error_t recv_from(void * buf, size_t *len, SocketAddr *remote_addr, uint16_t *remote_port); + /** + * Set the onSent handler. + * The exact moment this handler is called varies from implementation to implementation. + * On LwIP, onSent is called when the remote host ACK's data in TCP sockets, or when the message enters + * the network stack in UDP sockets. + * @param[in] onSent The handler to call when a send completes + */ + virtual void setOnSent(const SentHandler_t &onSent); + /** + * Send a message + * Sends a message over an open connection. This call is valid for UDP sockets, provided that connect() + * has been called. + * @param[in] buf The payload to send + * @param[in] len The size of the payload + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + virtual socket_error_t send(const void * buf, const size_t len); + /** + * Send a message to a specific address and port + * This API is not valid for SOCK_STREAM + * @param[in] buf The payload to send + * @param[in] len The size of the payload + * @param[in] address The address to send to + * @param[in] port The remote port to send to + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + virtual socket_error_t send_to(const void * buf, const size_t len, const SocketAddr *remote_addr, uint16_t remote_port); + /** + * Shuts down a socket. + * Sending and receiving are no longer possible after close() is called. + * The socket is not deallocated on close. A socket must not be reopened, it should be + * destroyed (either with delete, or by going out of scope) after calling close. + * Calling open on a closed socket can result in a memory leak. + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + virtual socket_error_t close(); + /** + * Error checking utility + * Generates an event on error, does nothing on SOCKET_ERROR_NONE + * @param[in] err the error code to check + * @return false if err is SOCKET_ERROR_NONE, true otherwise + */ + virtual bool error_check(socket_error_t err); + + /** + * Checks the socket status to determine whether it is still connected. + * @return true if the socket is connected, false if it is not + */ + virtual bool isConnected() const; + + /** + * Get the local address of the socket if bound. + * There are several failing conditions for this method: + * 1. If the socket has not been opened, returns SOCKET_ERROR_NULL_PTR + * 2. If the socket has not been bound, returns SOCKET_ERROR_NOT_BOUND + * 3. If addr is NULL, returns SOCKET_ERROR_NULL_PTR + * + * Otherwise, populates the SocketAddr object with the local address + * + * @param[out] addr a pointer to a SocketAddr object + * @return SOCKET_ERROR_NONE on success, or an error code on failure (see description) + */ + virtual socket_error_t getLocalAddr(SocketAddr *addr) const; + + /** + * Get the local port of the socket if bound. + * There are several failing conditions for this method: + * 1. If the socket has not been opened, returns SOCKET_ERROR_NULL_PTR + * 2. If the socket has not been bound, returns SOCKET_ERROR_NOT_BOUND + * 3. If port is NULL, returns SOCKET_ERROR_NULL_PTR + * + * Otherwise, populates the uint16_t object with the local port + * + * @param[out] port a pointer to a uint16_t + * @return SOCKET_ERROR_NONE on success, or an error code on failure (see description) + */ + virtual socket_error_t getLocalPort(uint16_t *port) const; + + /** + * Get the remote address of the socket if connected. + * There are several failing conditions for this method: + * 1. If the socket has not been opened, returns SOCKET_ERROR_NULL_PTR + * 2. If the socket has not been connected, returns SOCKET_ERROR_NO_CONNECTION + * 3. If addr is NULL, returns SOCKET_ERROR_NULL_PTR + * + * Otherwise, populates the SocketAddr object with the remote address + * + * @param[out] addr a pointer to a SocketAddr object + * @return SOCKET_ERROR_NONE on success, or an error code on failure (see description) + */ + virtual socket_error_t getRemoteAddr(SocketAddr *addr) const; + /** + * Get the remote port of the socket if connected. + * There are several failing conditions for this method: + * 1. If the socket has not been opened, returns SOCKET_ERROR_NULL_PTR + * 2. If the socket has not been connected, returns SOCKET_ERROR_NO_CONNECTION + * 3. If port is NULL, returns SOCKET_ERROR_NULL_PTR + * + * Otherwise, populates the uint16_t object with the remote port + * + * @param[out] port a pointer to a uint16_t + * @return SOCKET_ERROR_NONE on success, or an error code on failure (see description) + */ + virtual socket_error_t getRemotePort(uint16_t *port) const; + +#if 0 // not implemented yet + static long ntohl(long); + static short ntohs(short); + static long long ntohll(long long); +#endif + +protected: + /** + * The internal event handler + * @param[in] ev The event to handle + */ + virtual void _eventHandler(struct socket_event *ev); + +protected: + DNSHandler_t _onDNS; + ErrorHandler_t _onError; + ReadableHandler_t _onReadable; + SentHandler_t _onSent; + + CThunk _irq; + struct socket _socket; +private: + socket_event_t *_event; + /** + * Internal event handler. + * @param[in] arg + */ + void _nvEventHandler(void * arg); +}; +} // namespace v0 +} // namespace Sockets +} // namespace mbed +#endif // __MBED_NET_SOCKETS_V0_SOCKET_H__ diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/SocketAddr.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/SocketAddr.h new file mode 100644 index 0000000000..753cd432c3 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/SocketAddr.h @@ -0,0 +1,43 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKETS_V0_SOCKETADDR_H__ +#define __MBED_NET_SOCKETS_V0_SOCKETADDR_H__ + +#include "mbed-net-socket-abstract/socket_types.h" + +namespace mbed { +namespace Sockets { +namespace v0 { + +class SocketAddr { +public: + struct socket_addr * getAddr() {return &_addr;} + const struct socket_addr * getAddr() const {return &_addr;} + void setAddr(const struct socket_addr *addr); + void setAddr(const SocketAddr *addr); + size_t getAddrSize() const {return sizeof(_addr.ipv6be);} + bool is_v4(); + + int fmtIPv4(char *buf, size_t size); + int fmtIPv6(char *buf, size_t size); +protected: + struct socket_addr _addr; +}; +} // namespace v0 +} // namespace Sockets +} // namespace mbed +#endif // __MBED_NET_SOCKETS_V0_SOCKETADDR_H__ diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/TCPAsynch.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/TCPAsynch.h new file mode 100644 index 0000000000..a43e63655f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/TCPAsynch.h @@ -0,0 +1,47 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKETS_V0_TCP_ASYNCH__ +#define __MBED_NET_SOCKETS_V0_TCP_ASYNCH__ + +#include "Socket.h" +#include "mbed-net-socket-abstract/socket_api.h" + +#include "Ticker.h" + +namespace mbed { +namespace Sockets { +namespace v0 { +class TCPAsynch: public Socket { +protected: + TCPAsynch(const socket_stack_t stack); + ~TCPAsynch(); + +public: + virtual socket_error_t open(const socket_address_family_t af); +protected: + static Ticker _ticker; + static FunctionPointer0 _tick_handler; + // uintptr_t is used to guarantee that there will always be a large enough + // counter to avoid overflows. Memory allocation will always fail before + // counter overflow if the counter is the same size as the pointer type and + // sizeof(TCPAsynch) > 0 + static uintptr_t _TCPSockets; +}; +} // namespace v0 +} // namespace Sockets +} // namespace mbed +#endif // __MBED_NET_SOCKETS_V0_TCP_ASYNCH__ diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/TCPListener.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/TCPListener.h new file mode 100644 index 0000000000..98ab5cbfce --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/TCPListener.h @@ -0,0 +1,86 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKETS_V0_TCPLISTENER_H__ +#define __MBED_NET_SOCKETS_V0_TCPLISTENER_H__ + +#include +#include +#include "mbed/FunctionPointer.h" +#include "TCPAsynch.h" +#include "TCPStream.h" + +namespace mbed { +namespace Sockets { +namespace v0 { +/** \brief TCPListener: a TCP server socket + * The TCPListener listens for incoming connections. Prior to listening, the + * TCPListener must be bound to a port and, optionally, an address. + */ +class TCPListener: public TCPAsynch { +public: + typedef FunctionPointer2 IncomingHandler_t; + /** + * The TCP Listener constructor. + * @param[in] stack the network stack to use + */ + TCPListener(const socket_stack_t stack); + + /** + * The TCP Listener destructor + * This performs teardown of the listener + */ + ~TCPListener(); + + /** + * Begin listening for incoming connections. + * The supplied listenHandler will be called whenever an incoming connection arrives + * To reject a connection, the event handler needs to set the reject flag in the event. + * @param[in] listenHandler The event handler to call when an incoming connection arrives + * @param[in] backlog The number of connection requests to keep in the backlog + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + socket_error_t start_listening(IncomingHandler_t listenHandler, uint32_t backlog = 0); + /** + * Stop listening for incoming connections + * After this call, the server will reject incoming connections until start_listening is called again + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + socket_error_t stop_listening(); + + /** + * accept is a utility function for constructing a new TCPStream from an incoming connection + * The event passed to the listenHandler contains a pointer to a low level implementation of an + * already connected socket. This function + * @param new_impl + * @return + */ + virtual TCPStream * accept(void *new_impl); + virtual void reject(void *new_impl); + +protected: + /** + * Internal event handler + * @param[in] ev the event to handle + */ + void _eventHandler(struct socket_event *ev); + + IncomingHandler_t _onIncoming; +}; +} // namespace v0 +} // namespace Sockets +} // namespace mbed +#endif // __MBED_NET_SOCKETS_V0_TCPLISTENER_H__ diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/TCPStream.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/TCPStream.h new file mode 100644 index 0000000000..361d9c200f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/TCPStream.h @@ -0,0 +1,83 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKETS_V0_TCPSTREAM_H__ +#define __MBED_NET_SOCKETS_V0_TCPSTREAM_H__ +#include +#include +#include "Ticker.h" +#include "TCPAsynch.h" + +namespace mbed { +namespace Sockets { +namespace v0 { + +class TCPStream: public TCPAsynch { +public: + typedef FunctionPointer1 ConnectHandler_t; + typedef FunctionPointer1 DisconnectHandler_t; + /** + * TCP socket constructor. + * Does not allocate an underlying TCP Socket instance. + * @param[in] stack The network stack to use for this socket. + */ + TCPStream(const socket_stack_t stack); + /** + * TCP socket constructor. + * Does not allocate an underlying TCP Socket instance. This version is for use with + * TCPListener::accept(). The struct socket instance passed into this constructor should + * be a fully initialized socket, with an initialized impl field. TCPStream will copy + * the stack, API, protocol family, and impl pointer from sock. + * @param[in] sock The TCP socket instance to use for this TCP socket. + */ + TCPStream(const struct socket * sock); + /** + * TCP socket destructor + */ + ~TCPStream(); + /** + * Connect to a remote host. + * Initates the TCP Connection process. onConnect is called when the connection + * is acknowledged. + * @param[in] address The remote host to connect to + * @param[in] port The remote port to connect to + * @param[in] onConnect + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + virtual socket_error_t connect(const SocketAddr &address, const uint16_t port, + const ConnectHandler_t &onConnect); + /** + * Set a disconnect handler + * This handler only needs to be configured once onConnect has been called + * @param[in] h the handler to call when a connection is disconnected + */ + virtual void setOnDisconnect(const DisconnectHandler_t &h) { _onDisconnect = h; } + +protected: + /** + * Internal event handler + * @param[in] ev the event to handle + */ + void _eventHandler(struct socket_event *ev); + +protected: + ConnectHandler_t _onConnect; + DisconnectHandler_t _onDisconnect; +}; +} // namespace v0 +} // namespace Sockets +} // namespace mbed +#endif // __MBED_NET_SOCKETS_V0_TCPSTREAM_H__ diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/UDPSocket.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/UDPSocket.h new file mode 100644 index 0000000000..7b4ab1d3e8 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/common/sockets/v0/UDPSocket.h @@ -0,0 +1,64 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __MBED_NET_SOCKETS_V0_UDPSOCKET_H__ +#define __MBED_NET_SOCKETS_V0_UDPSOCKET_H__ + +#include +#include +#include "Socket.h" + +namespace mbed { +namespace Sockets { +namespace v0 { + +/* UDP socket class */ +class UDPSocket: public Socket { +public: + /** + * UDP socket constructor. + * Does not allocate an underlying UDP Socket instance. + * @param[in] stack The network stack to use for this socket. + */ + UDPSocket(socket_stack_t stack); + /** + * UDP Socket destructor + */ + ~UDPSocket(); + /** + * Open a UDP socket + * Instantiates and initializes the underlying socket. Receive is started immediately after + * the socket is opened. + * @param[in] af Address family (SOCKET_AF_INET4 or SOCKET_AF_INET6), currently only IPv4 is supported + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + socket_error_t inline open(const socket_address_family_t af) + { + return Socket::open(af,SOCKET_DGRAM); + } + /** + * Connect to a remote host. + * This is an internal configuration API only. No network traffic is generated. + * @param[in] address The remote host to connect to + * @param[in] port The remote port to connect to + * @return SOCKET_ERROR_NONE on success, or an error code on failure + */ + socket_error_t connect(const SocketAddr *address, const uint16_t port); +}; +} // namespace v0 +} // namespace Sockets +} // namespace mbed +#endif // __MBED_NET_SOCKETS_V0_UDPSOCKET_H__ diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/includes.txt b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/includes.txt new file mode 100644 index 0000000000..768bbbe625 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/includes.txt @@ -0,0 +1,17 @@ +if(TARGET_LIKE_LINUX) +include_directories( + "../common" + "../stub" + "../../../../mbed-client" + "../../../../source" + "../../../../source/include" + "../../../../yotta_modules/mbed-client-mbedtls" + "../../../../yotta_modules/mbedtls/include" + "../../../../yotta_modules/mbed-client-linux/mbed-client-linux" + "../../../../yotta_modules/mbed-client-mbed-os" + "../../../../yotta_modules/mbed-client-c" + "usr/include" + "$ENV{CPPUTEST_HOME}/include" +) +SET(UTEST_LINK_FLAGS "-fprofile-arcs") +endif() diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mbase/CMakeLists.txt b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mbase/CMakeLists.txt new file mode 100644 index 0000000000..e651848e9a --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mbase/CMakeLists.txt @@ -0,0 +1,22 @@ +if(TARGET_LIKE_LINUX) +include("../includes.txt") +add_executable(m2mbase + "../../../../source/m2mbase.cpp" + "main.cpp" + "../stub/m2mreporthandler_stub.cpp" + "../stub/m2mstring_stub.cpp" + "m2mbasetest.cpp" + "test_m2mbase.cpp" +) +target_link_libraries(m2mbase + CppUTest + CppUTestExt +) +set_target_properties(m2mbase +PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" + LINK_FLAGS "${UTEST_LINK_FLAGS}") +set(binary "m2mbase") +add_test(m2mbase ${binary}) + + +endif() diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mbase/m2mbasetest.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mbase/m2mbasetest.cpp new file mode 100644 index 0000000000..9e510ac904 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mbase/m2mbasetest.cpp @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//CppUTest includes should be after your and system includes +#include "CppUTest/TestHarness.h" +#include "test_m2mbase.h" + + +TEST_GROUP(M2MBase) +{ + Test_M2MBase* m2m_base; + + void setup() + { + m2m_base = new Test_M2MBase(); + } + void teardown() + { + delete m2m_base; + } +}; + +TEST(M2MBase, Create) +{ + CHECK(m2m_base != NULL); +} + +TEST(M2MBase, copy_constructor) +{ + m2m_base->test_copy_constructor(); +} + +TEST(M2MBase, test_assignment_operator) +{ + m2m_base->test_assignment_operator(); +} + +TEST(M2MBase, set_operation) +{ + m2m_base->test_set_operation(); +} + +TEST(M2MBase, test_set_base_type) +{ + m2m_base->test_set_base_type(); +} + +TEST(M2MBase, set_interface_description) +{ + m2m_base->test_set_interface_description(); +} + +TEST(M2MBase, set_uri_path) +{ + m2m_base->test_set_uri_path(); +} + +TEST(M2MBase, uri_path) +{ + m2m_base->test_uri_path(); +} + +TEST(M2MBase, set_resource_type) +{ + m2m_base->test_set_resource_type(); +} + +TEST(M2MBase, set_coap_content_type) +{ + m2m_base->test_set_coap_content_type(); +} + +TEST(M2MBase, set_instance_id) +{ + m2m_base->test_set_instance_id(); +} + +TEST(M2MBase, observation_number) +{ + m2m_base->test_observation_number(); +} + +TEST(M2MBase, mode) +{ + m2m_base->test_mode(); +} + +TEST(M2MBase, observation_token) +{ + m2m_base->test_get_observation_token(); +} + +TEST(M2MBase, is_observable) +{ + m2m_base->test_is_observable(); +} + +TEST(M2MBase, observation_level) +{ + m2m_base->test_observation_level(); +} + +TEST(M2MBase, set_observation_token) +{ + m2m_base->test_set_observation_token(); +} + +TEST(M2MBase, set_under_observation) +{ + m2m_base->test_set_under_observation(); +} + +TEST(M2MBase, set_observable) +{ + m2m_base->test_set_observable(); +} + +TEST(M2MBase, add_observation_level) +{ + m2m_base->test_add_observation_level(); +} + +TEST(M2MBase, remove_observation_level) +{ + m2m_base->test_remove_observation_level(); +} + +TEST(M2MBase, operation) +{ + m2m_base->test_operation(); +} + +TEST(M2MBase, name) +{ + m2m_base->test_name(); +} + +TEST(M2MBase, name_id) +{ + m2m_base->test_name_id(); +} + +TEST(M2MBase, instance_id) +{ + m2m_base->test_instance_id(); +} + +TEST(M2MBase, interface_description) +{ + m2m_base->test_interface_description(); +} + +TEST(M2MBase, resource_type) +{ + m2m_base->test_resource_type(); +} + +TEST(M2MBase, coap_content_type) +{ + m2m_base->test_coap_content_type(); +} + +TEST(M2MBase, test_base_type) +{ + m2m_base->test_base_type(); +} + +TEST(M2MBase, test_handle_observation_attribute) +{ + m2m_base->test_handle_observation_attribute(); +} + +TEST(M2MBase, test_observation_to_be_sent) +{ + m2m_base->test_observation_to_be_sent(); +} + +TEST(M2MBase, test_remove_resource_from_coap) +{ + m2m_base->test_remove_resource_from_coap(); +} + +TEST(M2MBase, test_remove_object_from_coap) +{ + m2m_base->test_remove_object_from_coap(); +} + +TEST(M2MBase, test_handle_get_request) +{ + m2m_base->test_handle_get_request(); +} + +TEST(M2MBase, test_handle_put_request) +{ + m2m_base->test_handle_put_request(); +} + +TEST(M2MBase, test_handle_post_request) +{ + m2m_base->test_handle_post_request(); +} + +TEST(M2MBase, test_memory_alloc) +{ + m2m_base->test_memory_alloc(); +} + +TEST(M2MBase, test_memory_free) +{ + m2m_base->test_memory_free(); +} + +TEST(M2MBase, test_report_handler) +{ + m2m_base->test_report_handler(); +} + +TEST(M2MBase, test_observation_handler) +{ + m2m_base->test_observation_handler(); +} + +TEST(M2MBase, test_id_number) +{ + m2m_base->test_id_number(); +} + +TEST(M2MBase, test_set_register_uri) +{ + m2m_base->test_set_register_uri(); +} + +TEST(M2MBase, test_register_uri) +{ + m2m_base->test_register_uri(); +} +TEST(M2MBase, test_set_observation_number) +{ + m2m_base->test_set_observation_number(); +} + +TEST(M2MBase, test_set_max_age) +{ + m2m_base->test_set_max_age(); +} + +TEST(M2MBase, test_max_age) +{ + m2m_base->test_max_age(); +} + +TEST(M2MBase, test_is_under_observation) +{ + m2m_base->test_is_under_observation(); +} + +TEST(M2MBase, test_value_updated_function) +{ + m2m_base->test_value_updated_function(); +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mbase/main.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mbase/main.cpp new file mode 100644 index 0000000000..8750b7ed97 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mbase/main.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP( M2MBase); diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mbase/test_m2mbase.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mbase/test_m2mbase.cpp new file mode 100755 index 0000000000..68390bacb0 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mbase/test_m2mbase.cpp @@ -0,0 +1,606 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include "test_m2mbase.h" +#include "m2mobservationhandler.h" +#include "m2mreportobserver.h" +#include "m2mreporthandler.h" +#include "m2mreporthandler_stub.h" +static bool value_update_called = false; +static void value_updated_function(const char* name) { + value_update_called = true; +} + +class MyTest{ +public: + void value_updated_function(const char* name) { + visited = true; + } + + bool visited; +}; + +class Handler : public M2MObservationHandler { + +public: + + Handler() : visited(false) {} + ~Handler(){} + void observation_to_be_sent(M2MBase *, uint16_t, m2m::Vector, bool){ + visited = true; + } + void send_delayed_response(M2MBase *){} + void resource_to_be_deleted(const String &){visited=true;} + void remove_object(M2MBase *){visited = true;} + void value_updated(M2MBase *,const String&){visited = true;} + + void clear() {visited = false;} + bool visited; +}; + +class Observer : public M2MReportObserver { +public: + Observer(){} + ~Observer(){} + + void observation_to_be_sent(m2m::Vector,bool){} +}; + +Test_M2MBase::Test_M2MBase() + :M2MBase("name",M2MBase::Static) +{ + +} + +Test_M2MBase::~Test_M2MBase() +{ +} + +void Test_M2MBase::test_copy_constructor() +{ + String test_string = "test"; + //Test stack constructor + Test_M2MBase b; + Test_M2MBase c(b); + Test_M2MBase a; + a = b; + + //Test heap constructor + Test_M2MBase* test = new Test_M2MBase(); + test->_interface_description = test_string; + + test->_token_length = 3; + test->_token = (u_int8_t *)malloc(test->_token_length); + + Observer obs; + test->_report_handler = new M2MReportHandler(obs); + + Test_M2MBase* copy = new Test_M2MBase(*test); + + CHECK(copy->_interface_description.compare(0,test_string.size(),test_string) == 0); + + CHECK(copy->_token != NULL); + + CHECK(copy->_report_handler != NULL); + + delete test; + delete copy; +} + +void Test_M2MBase::test_assignment_operator() +{ + //Test stack + M2MBase b("name", M2MBase::Static); + Test_M2MBase a; + M2MBase c = a; + c = b; + + //Test heap + Test_M2MBase* test = new Test_M2MBase(); + Test_M2MBase* test2 = new Test_M2MBase(); + Test_M2MBase* test3 = new Test_M2MBase(); + + test->operator=(*test3); + delete test3; + + test->_token_length = 3; + test->_token = (u_int8_t *)malloc(test->_token_length); + + Observer obs; + test->_report_handler = new M2MReportHandler(obs); + + test2->_token_length = 8; + test2->_token = (u_int8_t *)malloc(test2->_token_length); + + Observer obs2; + test2->_report_handler = new M2MReportHandler(obs2); + + *test = *test2; + + CHECK(test->_token != NULL); + + CHECK(test->_report_handler != NULL); + + delete test2; + delete test; +} + +void Test_M2MBase::test_set_operation() +{ + M2MBase::Operation test = M2MBase::GET_ALLOWED; + set_operation(test); + + CHECK(test == this->_operation); + + this->_mode = M2MBase::Dynamic; + test = M2MBase::PUT_ALLOWED; + set_operation(test); + + CHECK(test == this->_operation); +} + +void Test_M2MBase::test_set_base_type() +{ + set_base_type(M2MBase::ObjectInstance); + + CHECK(M2MBase::ObjectInstance == this->_base_type); +} + +void Test_M2MBase::test_set_interface_description() +{ + String test = "interface_description"; + set_interface_description(test); + + CHECK(test == this->_interface_description); +} + +void Test_M2MBase::test_set_uri_path() +{ + String test = "10/0/1"; + set_uri_path(test); + CHECK(test == this->_uri_path); +} + +void Test_M2MBase::test_uri_path() +{ + String test = "interface_description"; + this->_uri_path = test; + + CHECK(test == uri_path()); +} + +void Test_M2MBase::test_set_resource_type() +{ + String test = "resource_type"; + set_resource_type(test); + + CHECK(test == this->_resource_type); +} + +void Test_M2MBase::test_set_coap_content_type() +{ + u_int8_t test = 1; + set_coap_content_type(test); + + CHECK(test == this->_coap_content_type); +} + +void Test_M2MBase::test_set_instance_id() +{ + u_int16_t test = 1; + set_instance_id(test); + + CHECK(test == this->_instance_id); +} + +void Test_M2MBase::test_set_observable() +{ + bool test = true; + set_observable(test); + + CHECK(test == this->_observable); +} + +void Test_M2MBase::test_add_observation_level() +{ + add_observation_level(M2MBase::R_Attribute); + CHECK(M2MBase::R_Attribute == this->_observation_level); + + add_observation_level(M2MBase::O_Attribute); + CHECK(M2MBase::OR_Attribute == this->_observation_level); +} + +void Test_M2MBase::test_remove_observation_level() +{ + this->_observation_level = M2MBase::OR_Attribute; + remove_observation_level(M2MBase::R_Attribute); + CHECK(M2MBase::O_Attribute == this->_observation_level); + + remove_observation_level(M2MBase::O_Attribute); + CHECK(M2MBase::None == this->_observation_level); + + this->_observation_level = M2MBase::OI_Attribute; + remove_observation_level(M2MBase::R_Attribute); + CHECK(M2MBase::OI_Attribute == this->_observation_level); + + remove_observation_level(M2MBase::OI_Attribute); + CHECK(M2MBase::None == this->_observation_level); + remove_observation_level(M2MBase::OI_Attribute); + CHECK(M2MBase::None == this->_observation_level); +} + +void Test_M2MBase::test_set_under_observation() +{ + Handler handler; + + this->_base_type = M2MBase::ObjectInstance; + + bool test = true; + set_under_observation(test,NULL); + set_under_observation(test,&handler); + + CHECK(&handler == this->_observation_handler); + + set_under_observation(test,NULL); + + test = false; + set_under_observation(test,NULL); + + test = false; + set_under_observation(test,&handler); + + set_under_observation(test,&handler); +} + +void Test_M2MBase::test_set_observation_token() +{ + this->_token_length = 4; + this->_token = (u_int8_t *)malloc(this->_token_length); + String test = "token"; + set_observation_token((const u_int8_t*)test.c_str(), (u_int8_t)test.size()); + + CHECK(this->_token_length == 5); +} + +void Test_M2MBase::test_is_observable() +{ + bool test = false; + this->_observable = test; + + CHECK(test == is_observable()); +} + +void Test_M2MBase::test_observation_level() +{ + this->_observation_level = M2MBase::OR_Attribute; + CHECK(M2MBase::OR_Attribute == this->observation_level()); +} + +void Test_M2MBase::test_get_observation_token() +{ + u_int8_t test_value[] = {"val"}; + u_int32_t value_length((u_int32_t)sizeof(test_value)); + + u_int8_t* out_value = (u_int8_t *)malloc(value_length); + u_int32_t out_size = value_length; + memcpy((u_int8_t *)out_value, (u_int8_t *)test_value, value_length); + + u_int8_t test[] = {"token"}; + this->_token_length = (u_int8_t)sizeof(test); + this->_token = (u_int8_t *)malloc(this->_token_length); + memcpy((u_int8_t *)this->_token, (u_int8_t *)test, this->_token_length); + + get_observation_token(out_value,out_size); + + CHECK(out_size == 6); + + free(out_value); +} + +void Test_M2MBase::test_mode() +{ + CHECK(M2MBase::Static == mode()); +} + +void Test_M2MBase::test_observation_number() +{ + u_int8_t test = 1; + this->_observation_number = test; + + CHECK(test == observation_number()); +} + +void Test_M2MBase::test_operation() +{ + M2MBase::Operation test = M2MBase::DELETE_ALLOWED; + this->_operation = test; + + CHECK(test == operation()); +} + +void Test_M2MBase::test_name() +{ + String test = "name"; + this->_name = test; + + CHECK(test == name()); +} + +void Test_M2MBase::test_name_id() +{ + int id = 10; + this->_name_id = id; + + CHECK(id == name_id()); +} + +void Test_M2MBase::test_instance_id() +{ + u_int16_t test = 1; + this->_instance_id = test; + + CHECK(test == instance_id()); +} + +void Test_M2MBase::test_interface_description() +{ + String test = "interface_description"; + this->_interface_description = test; + + CHECK(test == interface_description()); +} + +void Test_M2MBase::test_resource_type() +{ + String test = "resource_type"; + this->_resource_type = test; + + CHECK(test == resource_type()); +} + +void Test_M2MBase::test_coap_content_type() +{ + u_int8_t test = 1; + this->_coap_content_type = test; + + CHECK(test == coap_content_type()); +} + +void Test_M2MBase::test_base_type() +{ + this->_base_type = M2MBase::ObjectInstance; + + CHECK(M2MBase::ObjectInstance == base_type()); +} + +//void Test_M2MBase::test_set_value() +//{ +// u_int8_t value[] = {"value2"}; +// this->_value = (u_int8_t*)malloc(sizeof(u_int8_t)); + +// CHECK(set_value(value,(u_int32_t)sizeof(value)) == true); +// CHECK( this->_value_length == sizeof(value)); +// CHECK( *this->_value == *value); + +// Observer obs; +// this->_report_handler = new M2MReportHandler(obs); + +// u_int8_t value2[] = {"12"}; +// CHECK(set_value(value2,(u_int32_t)sizeof(value2), true) == true); +//} + +//void Test_M2MBase::test_get_value() +//{ +// u_int8_t test_value[] = {"value3"}; +// u_int32_t value_length((u_int32_t)sizeof(test_value)); + +// u_int8_t* out_value = (u_int8_t *)malloc(1); +// u_int32_t out_size = 1; + +// this->_value = (u_int8_t *)malloc(value_length); +// this->_value_length = value_length; +// memcpy((u_int8_t *)this->_value, (u_int8_t *)test_value, value_length); + +// get_value(out_value,out_size); + +// CHECK(out_size == value_length); + +// free(out_value); +//} + +void Test_M2MBase::test_handle_observation_attribute() +{ + char query[] = "wrong"; + char* s = query; + bool ret = handle_observation_attribute(s); + CHECK(ret == false); + + Observer obs; + this->_report_handler = new M2MReportHandler(obs); + + m2mreporthandler_stub::bool_return = true; + ret = handle_observation_attribute(s); + CHECK(ret == true); + + this->_is_under_observation = true; + ret = handle_observation_attribute(s); + CHECK(ret == true); + + this->_is_under_observation = true; + m2mreporthandler_stub::bool_return = false; + ret = handle_observation_attribute(s); + CHECK(ret == false); + +} + +void Test_M2MBase::test_observation_to_be_sent() +{ + Handler handler; + Vector list; + observation_to_be_sent(list); + CHECK(handler.visited == false); + + this->_base_type = M2MBase::ObjectInstance; + + bool test = true; + set_under_observation(test,&handler); + + observation_to_be_sent(list); + + CHECK(handler.visited == true); +} + +void Test_M2MBase::test_remove_resource_from_coap() +{ + Handler handler; + + this->_base_type = M2MBase::ObjectInstance; + + const String s = "test"; + remove_resource_from_coap(s); + CHECK(handler.visited == false); + + bool test = true; + set_under_observation(test,&handler); + remove_resource_from_coap(s); + + CHECK(handler.visited == true); +} + +void Test_M2MBase::test_remove_object_from_coap() +{ + Handler handler; + + this->_base_type = M2MBase::ObjectInstance; + + remove_object_from_coap(); + CHECK(handler.visited == false); + + bool test = true; + set_under_observation(test,&handler); + remove_object_from_coap(); + + CHECK(handler.visited == true); +} + +void Test_M2MBase::test_handle_get_request() +{ + CHECK(this->handle_get_request(NULL,NULL,NULL) == NULL); +} + +void Test_M2MBase::test_handle_put_request() +{ + bool execute = false; + CHECK(this->handle_put_request(NULL,NULL,NULL, execute) == NULL); +} + +void Test_M2MBase::test_handle_post_request() +{ + bool execute = false; + CHECK(this->handle_post_request(NULL,NULL,NULL, execute) == NULL); +} + +void Test_M2MBase::test_memory_alloc() +{ + CHECK(memory_alloc(0) == 0); + uint8_t *ptr = 0; + ptr = (uint8_t*)memory_alloc(sizeof(uint8_t)); + CHECK(ptr != NULL); + memory_free(ptr); +} + +void Test_M2MBase::test_memory_free() +{ + uint8_t *ptr = (uint8_t*)memory_alloc(sizeof(uint8_t)); + memory_free((void*)ptr); + //memory leak test will fail, if there is a leak, so no need for CHECK +} + +void Test_M2MBase::test_report_handler() +{ + CHECK(report_handler() == NULL); +} + +void Test_M2MBase::test_observation_handler() +{ + CHECK(observation_handler() == NULL); +} + +void Test_M2MBase::test_id_number() +{ + M2MBase b("10", M2MBase::Static); + CHECK(b.name_id() == 10); + M2MBase * test1 = new M2MBase("66567",M2MBase::Static); + CHECK(test1->name_id() == -1); + delete test1; + +} + +void Test_M2MBase::test_set_register_uri() +{ + this->set_register_uri(false); + CHECK(this->_register_uri == false); +} + +void Test_M2MBase::test_register_uri() +{ + this->_register_uri = false; + CHECK(this->register_uri() == false); +} + +void Test_M2MBase::test_set_observation_number() +{ + set_observation_number(0); + CHECK(0 == this->_observation_number); +} + +void Test_M2MBase::test_set_max_age() +{ + this->set_max_age(10000); + CHECK(this->_max_age == 10000); +} + +void Test_M2MBase::test_max_age() +{ + this->_max_age = 10000; + CHECK(this->max_age() == 10000); +} + +void Test_M2MBase::test_is_under_observation() +{ + CHECK(false == is_under_observation()); + this->_is_under_observation = true; + CHECK(true == is_under_observation()); +} + +void Test_M2MBase::test_value_updated_function() +{ + MyTest test; + test.visited = false; + + CHECK(this->is_value_updated_function_set() == false); + + this->set_value_updated_function(value_updated_callback(&test,&MyTest::value_updated_function)); + this->execute_value_updated("test"); + CHECK(this->is_value_updated_function_set() == true); + CHECK(test.visited == true); + + value_update_called = false; + this->set_value_updated_function(value_updated_callback2(value_updated_function)); + this->execute_value_updated("test"); + CHECK(value_update_called == true); +} + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mbase/test_m2mbase.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mbase/test_m2mbase.h new file mode 100755 index 0000000000..59a0f55396 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mbase/test_m2mbase.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TEST_M2M_BASE_H +#define TEST_M2M_BASE_H + +#include "m2mbase.h" + +class Test_M2MBase : M2MBase +{ +public: + Test_M2MBase(); + + virtual ~Test_M2MBase(); + + void test_copy_constructor(); + + void test_assignment_operator(); + + void test_set_operation(); + + void test_set_base_type(); + + void test_set_interface_description(); + + void test_set_uri_path(); + + void test_uri_path(); + + void test_set_resource_type(); + + void test_set_coap_content_type(); + + void test_set_instance_id(); + + void test_set_observable(); + + void test_add_observation_level(); + + void test_remove_observation_level(); + + void test_set_under_observation(); + + void test_set_observation_token(); + + void test_is_observable(); + + void test_observation_level(); + + void test_get_observation_token(); + + void test_mode(); + + void test_observation_number(); + + void test_operation(); + + void test_name(); + + void test_name_id(); + + void test_instance_id(); + + void test_interface_description(); + + void test_resource_type(); + + void test_coap_content_type(); + + void test_base_type(); + + void test_handle_observation_attribute(); + + void test_observation_to_be_sent(); + + void test_remove_resource_from_coap(); + + void test_remove_object_from_coap(); + + void test_handle_get_request(); + + void test_handle_put_request(); + + void test_handle_post_request(); + + void test_memory_alloc(); + + void test_memory_free(); + + void test_report_handler(); + + void test_observation_handler(); + + void test_id_number(); + + void test_set_register_uri(); + + void test_register_uri(); + + void test_set_observation_number(); + + void test_set_max_age(); + + void test_max_age(); + + void test_is_under_observation(); + + void test_value_updated_function(); +}; + + +#endif // TEST_M2M_BASE_H diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mdevice/CMakeLists.txt b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mdevice/CMakeLists.txt new file mode 100644 index 0000000000..729cd0edec --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mdevice/CMakeLists.txt @@ -0,0 +1,25 @@ +if(TARGET_LIKE_LINUX) +include("../includes.txt") +add_executable(m2mdevice + "main.cpp" + "../stub/m2mobject_stub.cpp" + "../stub/m2mobjectinstance_stub.cpp" + "../stub/m2mresource_stub.cpp" + "../stub/m2mresourceinstance_stub.cpp" + "../stub/m2mbase_stub.cpp" + "../stub/m2mstring_stub.cpp" + "m2mdevicetest.cpp" + "test_m2mdevice.cpp" + "../../../../source/m2mdevice.cpp" +) +target_link_libraries(m2mdevice + CppUTest + CppUTestExt +) +set_target_properties(m2mdevice +PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" + LINK_FLAGS "${UTEST_LINK_FLAGS}") +set(binary "m2mdevice") +add_test(m2mdevice ${binary}) + +endif() diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mdevice/m2mdevicetest.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mdevice/m2mdevicetest.cpp new file mode 100644 index 0000000000..b9e48991a2 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mdevice/m2mdevicetest.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//CppUTest includes should be after your and system includes +#include "CppUTest/TestHarness.h" +#include "test_m2mdevice.h" + +TEST_GROUP(M2MDevice) +{ + Test_M2MDevice* m2m_device; + + void setup() + { + m2m_device = new Test_M2MDevice(); + } + void teardown() + { + delete m2m_device; + } +}; + +TEST(M2MDevice, Create) +{ + CHECK(m2m_device != NULL); +} + +TEST(M2MDevice, create_resource_instance) +{ + m2m_device->test_create_resource_instance(); +} + +TEST(M2MDevice, create_resource_string) +{ + m2m_device->test_create_resource_string(); +} + +TEST(M2MDevice, create_resource_int) +{ + m2m_device->test_create_resource_int(); +} + +TEST(M2MDevice, create_resource_no_param) +{ + m2m_device->test_create_resource_no_param(); +} + +TEST(M2MDevice, delete_resource) +{ + m2m_device->test_delete_resource(); +} + +TEST(M2MDevice, delete_resource_instance) +{ + m2m_device->test_delete_resource_instance(); +} + +TEST(M2MDevice, set_resource_value_int) +{ + m2m_device->test_set_resource_value_int(); +} + +TEST(M2MDevice, set_resource_value_string) +{ + m2m_device->test_set_resource_value_string(); +} + +TEST(M2MDevice, resource_value_int) +{ + m2m_device->test_resource_value_int(); +} + +TEST(M2MDevice, resource_value_string) +{ + m2m_device->test_resource_value_string(); +} + +TEST(M2MDevice, is_resource_present) +{ + m2m_device->test_is_resource_present(); +} + +TEST(M2MDevice, per_resource_count) +{ + m2m_device->test_per_resource_count(); +} + +TEST(M2MDevice, total_resource_count) +{ + m2m_device->test_total_resource_count(); +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mdevice/main.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mdevice/main.cpp new file mode 100644 index 0000000000..b6c971750d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mdevice/main.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP( M2MDevice); diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mdevice/test_m2mdevice.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mdevice/test_m2mdevice.cpp new file mode 100755 index 0000000000..085494c4f5 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mdevice/test_m2mdevice.cpp @@ -0,0 +1,500 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include "test_m2mdevice.h" +#include "m2mobject_stub.h" +#include "m2mobjectinstance_stub.h" +#include "m2mresource_stub.h" +#include "m2mresourceinstance_stub.h" +#include "m2mbase_stub.h" + +class Callback : public M2MObjectCallback { + +public: + + Callback(){} + ~Callback(){} + void notification_update(uint16_t obj_instance_id) { + visited = true; + } + + void clear() {visited = false;} + bool visited; +}; + + +Test_M2MDevice::Test_M2MDevice() +{ + callback = new Callback(); + m2mobject_stub::inst = new M2MObjectInstance("name",*callback); + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + m2mobjectinstance_stub::create_resource_instance= new M2MResourceInstance("name","type",M2MResourceInstance::STRING,*m2mobject_stub::inst); + m2mresource_stub::bool_value = true; + m2mobjectinstance_stub::create_resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + device = M2MDevice::get_instance(); + + delete m2mobjectinstance_stub::create_resource; + m2mobjectinstance_stub::create_resource = NULL; + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; + + delete m2mobjectinstance_stub::create_resource_instance; + m2mobjectinstance_stub::create_resource_instance = NULL; +} + +Test_M2MDevice::~Test_M2MDevice() +{ + delete m2mobject_stub::inst; + m2mobject_stub::inst = NULL; + + M2MDevice::delete_instance(); + device = NULL; + delete callback; +} + +void Test_M2MDevice::test_create_resource_instance() +{ + m2mobjectinstance_stub::create_resource_instance = new M2MResourceInstance("name","type",M2MResourceInstance::INTEGER,*m2mobject_stub::inst); + + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + + CHECK(device->create_resource_instance(M2MDevice::ErrorCode,5,1) != NULL); + CHECK(device->create_resource_instance(M2MDevice::ErrorCode,-1,1) == NULL); + CHECK(device->create_resource_instance(M2MDevice::ErrorCode,9,1) == NULL); + + m2mbase_stub::void_value = malloc(20); + + CHECK(device->create_resource_instance(M2MDevice::AvailablePowerSources,-1,0) == NULL); + CHECK(device->create_resource_instance(M2MDevice::AvailablePowerSources,8,0) == NULL); + CHECK(device->create_resource_instance(M2MDevice::AvailablePowerSources,7,0) != NULL); + CHECK(M2MBase::GET_ALLOWED == m2mbase_stub::operation); + + CHECK(device->create_resource_instance(M2MDevice::PowerSourceVoltage,10,0) != NULL); + CHECK(M2MBase::GET_ALLOWED == m2mbase_stub::operation); + + CHECK(device->create_resource_instance(M2MDevice::PowerSourceCurrent,10,0) != NULL); + CHECK(M2MBase::GET_ALLOWED == m2mbase_stub::operation); + + free(m2mbase_stub::void_value); + delete m2mobjectinstance_stub::create_resource_instance; + m2mobjectinstance_stub::create_resource_instance = NULL; + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; +} + +void Test_M2MDevice::test_create_resource_string() +{ + m2mresourceinstance_stub::value = NULL; + CHECK(device->create_resource(M2MDevice::Reboot,"test") == NULL); + CHECK(device->create_resource(M2MDevice::ErrorCode,"test") == NULL); + CHECK(device->create_resource(M2MDevice::SupportedBindingMode,"test") == NULL); + // Length 65, should fail + String max_lenght = "65656565656565656565656565656565656565656565656565656565656565656"; + + m2mobjectinstance_stub::create_resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + + CHECK(device->create_resource(M2MDevice::Manufacturer,"test") != NULL); + CHECK(M2MBase::GET_ALLOWED == m2mbase_stub::operation); + + CHECK(device->create_resource(M2MDevice::Manufacturer,max_lenght) == NULL); + CHECK(M2MBase::GET_ALLOWED == m2mbase_stub::operation); + + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + m2mresource_stub::bool_value = false; + //Duplicate resource + CHECK(device->create_resource(M2MDevice::Manufacturer,"test") == NULL); + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; + + CHECK(device->create_resource(M2MDevice::DeviceType,"test") != NULL); + CHECK(M2MBase::GET_ALLOWED == m2mbase_stub::operation); + CHECK(device->create_resource(M2MDevice::DeviceType,"") != NULL); + CHECK(device->create_resource(M2MDevice::DeviceType,max_lenght) == NULL); + + CHECK(device->create_resource(M2MDevice::ModelNumber,"test") != NULL); + CHECK(M2MBase::GET_ALLOWED == m2mbase_stub::operation); + CHECK(device->create_resource(M2MDevice::ModelNumber,max_lenght) == NULL); + + + CHECK(device->create_resource(M2MDevice::SerialNumber,"test") != NULL); + CHECK(M2MBase::GET_ALLOWED == m2mbase_stub::operation); + CHECK(device->create_resource(M2MDevice::SerialNumber,max_lenght) == NULL); + + + CHECK(device->create_resource(M2MDevice::HardwareVersion,"test") != NULL); + CHECK(M2MBase::GET_ALLOWED == m2mbase_stub::operation); + CHECK(device->create_resource(M2MDevice::HardwareVersion,max_lenght) == NULL); + + + CHECK(device->create_resource(M2MDevice::FirmwareVersion,"test") != NULL); + CHECK(M2MBase::GET_ALLOWED == m2mbase_stub::operation); + CHECK(device->create_resource(M2MDevice::FirmwareVersion,max_lenght) == NULL); + + + CHECK(device->create_resource(M2MDevice::SoftwareVersion,"test") != NULL); + CHECK(M2MBase::GET_ALLOWED == m2mbase_stub::operation); + CHECK(device->create_resource(M2MDevice::SoftwareVersion,max_lenght) == NULL); + + + CHECK(device->create_resource(M2MDevice::UTCOffset,"test") != NULL); + CHECK(M2MBase::GET_PUT_ALLOWED == m2mbase_stub::operation); + CHECK(device->create_resource(M2MDevice::UTCOffset,max_lenght) == NULL); + + + CHECK(device->create_resource(M2MDevice::Timezone,"test") != NULL); + CHECK(M2MBase::GET_PUT_ALLOWED == m2mbase_stub::operation); + CHECK(device->create_resource(M2MDevice::Timezone,max_lenght) == NULL); + + CHECK(device->create_resource(M2MDevice::BatteryLevel,"test") == NULL); + CHECK(device->create_resource(M2MDevice::BatteryStatus,"test") == NULL); + CHECK(device->create_resource(M2MDevice::MemoryFree,"test") == NULL); + CHECK(device->create_resource(M2MDevice::MemoryTotal,"test") == NULL); + CHECK(device->create_resource(M2MDevice::ResetErrorCode,"test") == NULL); + CHECK(device->create_resource(M2MDevice::CurrentTime,"test") == NULL); + CHECK(device->create_resource(M2MDevice::AvailablePowerSources,"test") == NULL); + CHECK(device->create_resource(M2MDevice::PowerSourceVoltage,"test") == NULL); + CHECK(device->create_resource(M2MDevice::PowerSourceCurrent,"test") == NULL); + CHECK(device->create_resource(M2MDevice::FactoryReset,"test") == NULL); + + delete m2mobjectinstance_stub::create_resource; + m2mobjectinstance_stub::create_resource = NULL; +} + +void Test_M2MDevice::test_create_resource_int() +{ + m2mobjectinstance_stub::create_resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::INTEGER,M2MBase::Dynamic); + + CHECK(device->create_resource(M2MDevice::Reboot,10) == NULL); + CHECK(device->create_resource(M2MDevice::SupportedBindingMode,10) == NULL); + + CHECK(device->create_resource(M2MDevice::Manufacturer,10) == NULL); + CHECK(device->create_resource(M2MDevice::DeviceType,10) == NULL); + CHECK(device->create_resource(M2MDevice::ModelNumber,10) == NULL); + CHECK(device->create_resource(M2MDevice::SerialNumber,10) == NULL); + CHECK(device->create_resource(M2MDevice::HardwareVersion,10) == NULL); + CHECK(device->create_resource(M2MDevice::FirmwareVersion,10) == NULL); + CHECK(device->create_resource(M2MDevice::SoftwareVersion,10) == NULL); + CHECK(device->create_resource(M2MDevice::UTCOffset,10) == NULL); + CHECK(device->create_resource(M2MDevice::Timezone,10) == NULL); + CHECK(device->create_resource(M2MDevice::FactoryReset,10) == NULL); + + m2mbase_stub::void_value = malloc(20); + + CHECK(device->create_resource(M2MDevice::BatteryLevel,10) != NULL); + CHECK(M2MBase::GET_ALLOWED == m2mbase_stub::operation); + + // Range is above 100 + CHECK(device->create_resource(M2MDevice::BatteryLevel,101) == NULL); + + CHECK(device->create_resource(M2MDevice::BatteryStatus,4) != NULL); + CHECK(M2MBase::GET_ALLOWED == m2mbase_stub::operation); + + // Range is above 6 + CHECK(device->create_resource(M2MDevice::BatteryStatus,10) == NULL); + + CHECK(device->create_resource(M2MDevice::MemoryFree,10) != NULL); + CHECK(M2MBase::GET_ALLOWED == m2mbase_stub::operation); + + CHECK(device->create_resource(M2MDevice::MemoryTotal,10) != NULL); + CHECK(M2MBase::GET_ALLOWED == m2mbase_stub::operation); + + CHECK(device->create_resource(M2MDevice::CurrentTime,10) != NULL); + CHECK(M2MBase::GET_PUT_ALLOWED == m2mbase_stub::operation); + + free(m2mbase_stub::void_value); + delete m2mobjectinstance_stub::create_resource; + m2mobjectinstance_stub::create_resource = NULL; +} + +void Test_M2MDevice::test_create_resource_no_param() +{ + m2mobjectinstance_stub::create_resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + + + CHECK(device->create_resource(M2MDevice::Reboot) == NULL); + CHECK(device->create_resource(M2MDevice::ErrorCode) == NULL); + CHECK(device->create_resource(M2MDevice::SupportedBindingMode) == NULL); + + CHECK(device->create_resource(M2MDevice::Manufacturer) == NULL); + CHECK(device->create_resource(M2MDevice::DeviceType) == NULL); + CHECK(device->create_resource(M2MDevice::ModelNumber) == NULL); + CHECK(device->create_resource(M2MDevice::SerialNumber) == NULL); + CHECK(device->create_resource(M2MDevice::HardwareVersion) == NULL); + CHECK(device->create_resource(M2MDevice::FirmwareVersion) == NULL); + CHECK(device->create_resource(M2MDevice::SoftwareVersion) == NULL); + CHECK(device->create_resource(M2MDevice::UTCOffset) == NULL); + CHECK(device->create_resource(M2MDevice::Timezone) == NULL); + + CHECK(device->create_resource(M2MDevice::BatteryLevel) == NULL); + CHECK(device->create_resource(M2MDevice::BatteryStatus) == NULL); + CHECK(device->create_resource(M2MDevice::MemoryFree) == NULL); + CHECK(device->create_resource(M2MDevice::MemoryTotal) == NULL); + CHECK(device->create_resource(M2MDevice::CurrentTime) == NULL); + CHECK(device->create_resource(M2MDevice::AvailablePowerSources) == NULL); + CHECK(device->create_resource(M2MDevice::PowerSourceVoltage) == NULL); + CHECK(device->create_resource(M2MDevice::PowerSourceCurrent) == NULL); + + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + + CHECK(device->create_resource(M2MDevice::ResetErrorCode) != NULL); + + CHECK(device->create_resource(M2MDevice::FactoryReset) != NULL); + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; + + CHECK(M2MBase::POST_ALLOWED == m2mbase_stub::operation); + + delete m2mobjectinstance_stub::create_resource; + m2mobjectinstance_stub::create_resource = NULL; + + +} + +void Test_M2MDevice::test_delete_resource() +{ + m2mobjectinstance_stub::bool_value = true; + + CHECK(device->delete_resource(M2MDevice::Reboot) == false); + CHECK(device->delete_resource(M2MDevice::ErrorCode) == false); + CHECK(device->delete_resource(M2MDevice::SupportedBindingMode) == false); + + CHECK(device->delete_resource(M2MDevice::Manufacturer) == true); + CHECK(device->delete_resource(M2MDevice::BatteryLevel) == true); + CHECK(device->delete_resource(M2MDevice::FactoryReset) == true); +} + +void Test_M2MDevice::test_delete_resource_instance() +{ + m2mobjectinstance_stub::bool_value = true; + + CHECK(device->delete_resource_instance(M2MDevice::Reboot,0) == false); + CHECK(device->delete_resource_instance(M2MDevice::ErrorCode,0) == false); + CHECK(device->delete_resource_instance(M2MDevice::SupportedBindingMode,0) == false); + + CHECK(device->delete_resource_instance(M2MDevice::AvailablePowerSources,0) == true); + CHECK(device->delete_resource_instance(M2MDevice::PowerSourceVoltage,0) == true); + CHECK(device->delete_resource_instance(M2MDevice::PowerSourceCurrent,0) == true); +} + +void Test_M2MDevice::test_set_resource_value_string() +{ + // Length 65, should fail + m2mresourceinstance_stub::value = NULL; + String max_lenght = "65656565656565656565656565656565656565656565656565656565656565656"; + m2mbase_stub::bool_value = true; + m2mresourceinstance_stub::bool_value = true; + + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + m2mresource_stub::bool_value = false; + + m2mbase_stub::void_value = malloc(20); + + CHECK(device->set_resource_value(M2MDevice::Reboot,"test") == false); + CHECK(device->set_resource_value(M2MDevice::ErrorCode,"test") == false); + CHECK(device->set_resource_value(M2MDevice::SupportedBindingMode,"test") == false); + + CHECK(device->set_resource_value(M2MDevice::Manufacturer,"test") == true); + CHECK(device->set_resource_value(M2MDevice::Manufacturer,"") == true); + CHECK(device->set_resource_value(M2MDevice::Manufacturer,max_lenght) == false); + CHECK(device->set_resource_value(M2MDevice::DeviceType,"test") == true); + CHECK(device->set_resource_value(M2MDevice::DeviceType,max_lenght) == false); + CHECK(device->set_resource_value(M2MDevice::ModelNumber,"test") == true); + CHECK(device->set_resource_value(M2MDevice::ModelNumber,max_lenght) == false); + CHECK(device->set_resource_value(M2MDevice::SerialNumber,"test") == true); + CHECK(device->set_resource_value(M2MDevice::SerialNumber,max_lenght) == false); + CHECK(device->set_resource_value(M2MDevice::HardwareVersion,"test") == true); + CHECK(device->set_resource_value(M2MDevice::HardwareVersion,max_lenght) == false); + CHECK(device->set_resource_value(M2MDevice::FirmwareVersion,"test") == true); + CHECK(device->set_resource_value(M2MDevice::FirmwareVersion,max_lenght) == false); + CHECK(device->set_resource_value(M2MDevice::SoftwareVersion,"test") == true); + CHECK(device->set_resource_value(M2MDevice::SoftwareVersion,max_lenght) == false); + CHECK(device->set_resource_value(M2MDevice::UTCOffset,"test") == true); + CHECK(device->set_resource_value(M2MDevice::UTCOffset,max_lenght) == false); + CHECK(device->set_resource_value(M2MDevice::Timezone,"test") == true); + CHECK(device->set_resource_value(M2MDevice::Timezone,max_lenght) == false); + CHECK(device->set_resource_value(M2MDevice::Timezone,"") == true); + + CHECK(device->set_resource_value(M2MDevice::BatteryLevel,"test") == false); + CHECK(device->set_resource_value(M2MDevice::BatteryStatus,"test") == false); + CHECK(device->set_resource_value(M2MDevice::MemoryFree,"test") == false); + CHECK(device->set_resource_value(M2MDevice::MemoryTotal,"test") == false); + CHECK(device->set_resource_value(M2MDevice::ResetErrorCode,"test") == false); + CHECK(device->set_resource_value(M2MDevice::CurrentTime,"test") == false); + CHECK(device->set_resource_value(M2MDevice::AvailablePowerSources,"test") == false); + CHECK(device->set_resource_value(M2MDevice::PowerSourceVoltage,"test") == false); + CHECK(device->set_resource_value(M2MDevice::PowerSourceCurrent,"test") == false); + CHECK(device->set_resource_value(M2MDevice::FactoryReset,"test") == false); + + free(m2mbase_stub::void_value); + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; +} + +void Test_M2MDevice::test_set_resource_value_int() +{ + m2mresourceinstance_stub::bool_value = true; + + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::INTEGER,M2MBase::Dynamic); + m2mresource_stub::bool_value = false; + + m2mbase_stub::void_value = malloc(20); + + CHECK(device->set_resource_value(M2MDevice::Reboot,10) == false); + CHECK(device->set_resource_value(M2MDevice::SupportedBindingMode,10) == false); + + CHECK(device->set_resource_value(M2MDevice::Manufacturer,10) == false); + CHECK(device->set_resource_value(M2MDevice::DeviceType,10) == false); + CHECK(device->set_resource_value(M2MDevice::ModelNumber,10) == false); + CHECK(device->set_resource_value(M2MDevice::SerialNumber,10) == false); + CHECK(device->set_resource_value(M2MDevice::HardwareVersion,10) == false); + CHECK(device->set_resource_value(M2MDevice::FirmwareVersion,10) == false); + CHECK(device->set_resource_value(M2MDevice::SoftwareVersion,10) == false); + CHECK(device->set_resource_value(M2MDevice::UTCOffset,10) == false); + CHECK(device->set_resource_value(M2MDevice::Timezone,10) == false); + + CHECK(device->set_resource_value(M2MDevice::BatteryLevel,-1) == false); + CHECK(device->set_resource_value(M2MDevice::BatteryLevel,10) == true); + CHECK(device->set_resource_value(M2MDevice::BatteryLevel,101) == false); + CHECK(device->set_resource_value(M2MDevice::BatteryStatus,6) == true); + CHECK(device->set_resource_value(M2MDevice::BatteryStatus,-1) == false); + CHECK(device->set_resource_value(M2MDevice::BatteryStatus,7) == false); + CHECK(device->set_resource_value(M2MDevice::MemoryFree,10) == true); + CHECK(device->set_resource_value(M2MDevice::MemoryTotal,10) == true); + CHECK(device->set_resource_value(M2MDevice::CurrentTime,10) == true); + CHECK(device->set_resource_value(M2MDevice::FactoryReset,10) == false); + + free(m2mbase_stub::void_value); + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; +} + +void Test_M2MDevice::test_resource_value_int() +{ + uint8_t value[] = {"10"}; + uint8_t* ptr = (uint8_t*)malloc((uint32_t)sizeof(value)); + m2mresourceinstance_stub::value = ptr; + memset(m2mresourceinstance_stub::value,0,(uint32_t)sizeof(value)); + memcpy(m2mresourceinstance_stub::value,value,sizeof(value)); + m2mresourceinstance_stub::int_value = (uint32_t)sizeof(value); + + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::INTEGER,M2MBase::Dynamic); + + m2mresourceinstance_stub::bool_value = true; + m2mresource_stub::bool_value = false; + m2mbase_stub::void_value = malloc(20); + + CHECK(device->resource_value_int(M2MDevice::BatteryLevel) == 10); + CHECK(device->resource_value_int(M2MDevice::BatteryStatus) == 10); + CHECK(device->resource_value_int(M2MDevice::MemoryFree) == 10); + CHECK(device->resource_value_int(M2MDevice::MemoryTotal) == 10); + CHECK(device->resource_value_int(M2MDevice::ErrorCode) == 10); + CHECK(device->resource_value_int(M2MDevice::CurrentTime) == 10); + CHECK(device->resource_value_int(M2MDevice::AvailablePowerSources) == 10); + CHECK(device->resource_value_int(M2MDevice::PowerSourceVoltage) == 10); + CHECK(device->resource_value_int(M2MDevice::PowerSourceCurrent) == 10); + CHECK(device->resource_value_int(M2MDevice::Manufacturer) == -1); + + m2mresource_stub::instance = new M2MResourceInstance("name","type",M2MResourceInstance::INTEGER,*m2mobject_stub::inst); + m2mresource_stub::bool_value = true; + CHECK(device->resource_value_int(M2MDevice::AvailablePowerSources,1) == 10); + + free(m2mbase_stub::void_value); + + delete m2mresource_stub::instance; + m2mresource_stub::instance = NULL; + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; + + free(ptr); +} + +void Test_M2MDevice::test_resource_value_string() +{ + String test = "string"; + uint8_t value[] = {"string"}; + m2mresourceinstance_stub::value = (uint8_t*)malloc((uint32_t)sizeof(value)); + memset(m2mresourceinstance_stub::value,0,(uint32_t)sizeof(value)); + memcpy(m2mresourceinstance_stub::value,value,sizeof(value)); + m2mresourceinstance_stub::int_value = (uint32_t)sizeof(value); + + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + + m2mresourceinstance_stub::bool_value = true; + m2mresource_stub::bool_value = false; + m2mbase_stub::void_value = malloc(20); + + CHECK(device->resource_value_string(M2MDevice::Manufacturer) == test); + CHECK(device->resource_value_string(M2MDevice::DeviceType) == test); + CHECK(device->resource_value_string(M2MDevice::ModelNumber) == test); + CHECK(device->resource_value_string(M2MDevice::SerialNumber) == test); + CHECK(device->resource_value_string(M2MDevice::HardwareVersion) == test); + CHECK(device->resource_value_string(M2MDevice::FirmwareVersion) == test); + CHECK(device->resource_value_string(M2MDevice::SoftwareVersion) == test); + CHECK(device->resource_value_string(M2MDevice::UTCOffset) == test); + CHECK(device->resource_value_string(M2MDevice::Timezone) == test); + CHECK(device->resource_value_string(M2MDevice::BatteryLevel) == ""); + + free(m2mbase_stub::void_value); + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; + + free(m2mresourceinstance_stub::value); + m2mresourceinstance_stub::value = NULL; +} + +void Test_M2MDevice::test_is_resource_present() +{ + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + m2mresource_stub::bool_value = false; + CHECK(device->is_resource_present(M2MDevice::Reboot) == true); + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; + + CHECK(device->is_resource_present(M2MDevice::Manufacturer) == false); + CHECK(device->is_resource_present(M2MDevice::DeviceType) == false); +} + +void Test_M2MDevice::test_per_resource_count() +{ + m2mobjectinstance_stub::int_value = 1; + CHECK(device->per_resource_count(M2MDevice::Reboot) == 1); + + m2mobjectinstance_stub::int_value = 0; + + CHECK(device->per_resource_count(M2MDevice::Manufacturer) == 0); +} + +void Test_M2MDevice::test_total_resource_count() +{ + M2MResource res(*m2mobject_stub::inst,"test","test",M2MResourceInstance::STRING,M2MBase::Dynamic); + + m2mobjectinstance_stub::resource_list.push_back(&res); + M2MResource res2(*m2mobject_stub::inst,"test","test",M2MResourceInstance::STRING,M2MBase::Dynamic); + + m2mobjectinstance_stub::resource_list.push_back(&res2); + + CHECK(device->total_resource_count() == 2); + + m2mobjectinstance_stub::resource_list.clear(); +} + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mdevice/test_m2mdevice.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mdevice/test_m2mdevice.h new file mode 100755 index 0000000000..62ac7b2101 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mdevice/test_m2mdevice.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TEST_M2M_DEVICE_H +#define TEST_M2M_DEVICE_H + + +#include + +class Callback; + +class Test_M2MDevice +{ +public: + Test_M2MDevice(); + virtual ~Test_M2MDevice(); + + void test_create_resource_instance(); + + void test_create_resource_string(); + + void test_create_resource_int(); + + void test_create_resource_no_param(); + + void test_delete_resource(); + + void test_delete_resource_instance(); + + void test_set_resource_value_int(); + + void test_set_resource_value_string(); + + void test_resource_value_int(); + + void test_resource_value_string(); + + void test_is_resource_present(); + + void test_per_resource_count(); + + void test_total_resource_count(); + + M2MDevice* device; + Callback *callback; +}; + +#endif // TEST_M2M_DEVICE_H diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mfirmware/CMakeLists.txt b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mfirmware/CMakeLists.txt new file mode 100644 index 0000000000..62c7d6a750 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mfirmware/CMakeLists.txt @@ -0,0 +1,25 @@ +if(TARGET_LIKE_LINUX) +include("../includes.txt") +add_executable(m2mfirmware + "main.cpp" + "m2mfirmwaretest.cpp" + "test_m2mfirmware.cpp" + "../stub/m2mobject_stub.cpp" + "../stub/m2mobjectinstance_stub.cpp" + "../stub/m2mresource_stub.cpp" + "../stub/m2mresourceinstance_stub.cpp" + "../stub/m2mbase_stub.cpp" + "../stub/m2mstring_stub.cpp" + "../../../../source/m2mfirmware.cpp" +) +target_link_libraries(m2mfirmware + CppUTest + CppUTestExt +) +set_target_properties(m2mfirmware +PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" + LINK_FLAGS "${UTEST_LINK_FLAGS}") +set(binary "m2mfirmware") +add_test(m2mfirmware ${binary}) + +endif() diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mfirmware/m2mfirmwaretest.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mfirmware/m2mfirmwaretest.cpp new file mode 100644 index 0000000000..19897ae89a --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mfirmware/m2mfirmwaretest.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//CppUTest includes should be after your and system includes +#include "CppUTest/TestHarness.h" +#include "test_m2mfirmware.h" + +TEST_GROUP(M2MFirmware) +{ + Test_M2MFirmware* m2m_firmware; + + void setup() + { + m2m_firmware = new Test_M2MFirmware(); + } + void teardown() + { + delete m2m_firmware; + } +}; + +TEST(M2MFirmware, Create) +{ + CHECK(m2m_firmware != NULL); +} + +TEST(M2MFirmware, create_resource_string) +{ + m2m_firmware->test_create_resource_string(); +} + +TEST(M2MFirmware, create_resource_int) +{ + m2m_firmware->test_create_resource_int(); +} + +TEST(M2MFirmware, delete_resource) +{ + m2m_firmware->test_delete_resource(); +} + +TEST(M2MFirmware, set_resource_value_int) +{ + m2m_firmware->test_set_resource_value_int(); +} + +TEST(M2MFirmware, set_resource_value_string) +{ + m2m_firmware->test_set_resource_value_string(); +} + +TEST(M2MFirmware, resource_value_int) +{ + m2m_firmware->test_resource_value_int(); +} + +TEST(M2MFirmware, resource_value_string) +{ + m2m_firmware->test_resource_value_string(); +} + +TEST(M2MFirmware, is_resource_present) +{ + m2m_firmware->test_is_resource_present(); +} + +TEST(M2MFirmware, per_resource_count) +{ + m2m_firmware->test_per_resource_count(); +} + +TEST(M2MFirmware, total_resource_count) +{ + m2m_firmware->test_total_resource_count(); +} + +TEST(M2MFirmware, set_resource_value_buffer) +{ + m2m_firmware->test_set_resource_value_buffer(); +} + +TEST(M2MFirmware, resource_value_buffer) +{ + m2m_firmware->test_resource_value_buffer(); +} + +TEST(M2MFirmware, resource_name) +{ + m2m_firmware->test_resource_name(); +} + + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mfirmware/main.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mfirmware/main.cpp new file mode 100644 index 0000000000..f050e38eb5 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mfirmware/main.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP( M2MFirmware ); diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mfirmware/test_m2mfirmware.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mfirmware/test_m2mfirmware.cpp new file mode 100755 index 0000000000..d3c4b23584 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mfirmware/test_m2mfirmware.cpp @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include "test_m2mfirmware.h" +#include "m2mobject_stub.h" +#include "m2mobjectinstance_stub.h" +#include "m2mresource_stub.h" +#include "m2mresourceinstance_stub.h" +#include "m2mbase_stub.h" + +class Callback : public M2MObjectCallback { + +public: + + Callback(){} + ~Callback(){} + void notification_update(uint16_t obj_instance_id) { + visited = true; + } + + void clear() {visited = false;} + bool visited; +}; + + +Test_M2MFirmware::Test_M2MFirmware() +{ + callback = new Callback(); + m2mobject_stub::inst = new M2MObjectInstance("name",*callback); + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + m2mobjectinstance_stub::create_resource_instance= new M2MResourceInstance("name","type",M2MResourceInstance::STRING,*m2mobject_stub::inst); + m2mresource_stub::bool_value = true; + m2mobjectinstance_stub::create_resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + firmware = M2MFirmware::get_instance(); + + delete m2mobjectinstance_stub::create_resource; + m2mobjectinstance_stub::create_resource = NULL; + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; + + delete m2mobjectinstance_stub::create_resource_instance; + m2mobjectinstance_stub::create_resource_instance = NULL; +} + +Test_M2MFirmware::~Test_M2MFirmware() +{ + delete m2mobject_stub::inst; + m2mobject_stub::inst = NULL; + + M2MFirmware::delete_instance(); + firmware = NULL; + delete callback; +} + +void Test_M2MFirmware::test_create_resource_string() +{ + CHECK(firmware->create_resource(M2MFirmware::Package, "test") == NULL); + CHECK(firmware->create_resource(M2MFirmware::Update, "test") == NULL); + CHECK(firmware->create_resource(M2MFirmware::State, "test") == NULL); + + m2mobjectinstance_stub::create_resource = new M2MResource(*m2mobject_stub::inst, + "name", + "type", + M2MResourceInstance::STRING, + M2MBase::Dynamic); + + CHECK(firmware->create_resource(M2MFirmware::PackageName,"test") != NULL); + CHECK(M2MBase::GET_ALLOWED == m2mbase_stub::operation); + CHECK(firmware->create_resource(M2MFirmware::PackageName,"") != NULL); + + // Check size limit + String test = ""; + for (int i = 0; i <= 255; i++) { + test.append("a", 1); + } + // 255 + null-termination + CHECK(firmware->create_resource(M2MFirmware::PackageVersion,test) == NULL); + + test = ""; + for (int i = 0; i <= 254; i++) { + test.append("a", 1); + } + // 254 + null-termination + CHECK(firmware->create_resource(M2MFirmware::PackageVersion,test) != NULL); + CHECK(M2MBase::GET_ALLOWED == m2mbase_stub::operation); + + + CHECK(firmware->create_resource(M2MFirmware::Package,"test") == NULL); + CHECK(firmware->create_resource(M2MFirmware::Update,"test") == NULL); + CHECK(firmware->create_resource(M2MFirmware::State,"test") == NULL); + CHECK(firmware->create_resource(M2MFirmware::UpdateSupportedObjects,"test") == NULL); + CHECK(firmware->create_resource(M2MFirmware::UpdateResult,"test") == NULL); + + delete m2mobjectinstance_stub::create_resource; + m2mobjectinstance_stub::create_resource = NULL; +} + +void Test_M2MFirmware::test_create_resource_int() +{ + m2mobjectinstance_stub::create_resource = new M2MResource(*m2mobject_stub::inst, + "name", + "type", + M2MResourceInstance::INTEGER, + M2MBase::Dynamic); + + CHECK(firmware->create_resource(M2MFirmware::PackageVersion,10) == NULL); + CHECK(firmware->create_resource(M2MFirmware::PackageName,10) == NULL); + CHECK(firmware->create_resource(M2MFirmware::Package,10) == NULL); + CHECK(firmware->create_resource(M2MFirmware::Update,10) == NULL); + + m2mbase_stub::void_value = malloc(20); + + CHECK(firmware->create_resource(M2MFirmware::UpdateSupportedObjects,false) != NULL); + CHECK(firmware->create_resource(M2MFirmware::UpdateSupportedObjects,true) != NULL); + CHECK(firmware->create_resource(M2MFirmware::UpdateSupportedObjects,5) == NULL); + CHECK(M2MBase::GET_PUT_ALLOWED == m2mbase_stub::operation); + + CHECK(firmware->create_resource(M2MFirmware::Update,10) == NULL); + + free(m2mbase_stub::void_value); + delete m2mobjectinstance_stub::create_resource; + m2mobjectinstance_stub::create_resource = NULL; +} + + +void Test_M2MFirmware::test_delete_resource() +{ + m2mobjectinstance_stub::bool_value = true; + + CHECK(firmware->delete_resource(M2MFirmware::PackageName) == true); + CHECK(firmware->delete_resource(M2MFirmware::PackageVersion) == true); + CHECK(firmware->delete_resource(M2MFirmware::UpdateSupportedObjects) == true); + + CHECK(firmware->delete_resource(M2MFirmware::Package) == false); + CHECK(firmware->delete_resource(M2MFirmware::PackageUri) == false); + CHECK(firmware->delete_resource(M2MFirmware::State) == false); + CHECK(firmware->delete_resource(M2MFirmware::UpdateResult) == false); + CHECK(firmware->delete_resource(M2MFirmware::Update) == false); +} + +void Test_M2MFirmware::test_set_resource_value_string() +{ + m2mresourceinstance_stub::value = NULL; + m2mbase_stub::bool_value = true; + m2mresourceinstance_stub::bool_value = true; + + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst, + "name", + "type", + M2MResourceInstance::STRING,M2MBase::Dynamic); + m2mresource_stub::bool_value = false; + + m2mbase_stub::void_value = malloc(20); + + CHECK(firmware->set_resource_value(M2MFirmware::PackageName,"test") == true); + CHECK(firmware->set_resource_value(M2MFirmware::PackageVersion,"test") == true); + CHECK(firmware->set_resource_value(M2MFirmware::PackageUri,"test") == true); + CHECK(firmware->set_resource_value(M2MFirmware::PackageUri,"") == true); + + // Check size limit + String test = ""; + for (int i = 0; i <= 255; i++) { + test.append("a", 1); + } + CHECK(firmware->set_resource_value(M2MFirmware::PackageUri,test) == false); + + CHECK(firmware->set_resource_value(M2MFirmware::Package,"test") == false); + CHECK(firmware->set_resource_value(M2MFirmware::State,"test") == false); + CHECK(firmware->set_resource_value(M2MFirmware::UpdateResult,"test") == false); + CHECK(firmware->set_resource_value(M2MFirmware::UpdateSupportedObjects,"test") == false); + CHECK(firmware->set_resource_value(M2MFirmware::Update,"test") == false); + + free(m2mbase_stub::void_value); + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; +} + +void Test_M2MFirmware::test_set_resource_value_int() +{ + m2mresourceinstance_stub::bool_value = true; + + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst, + "name", + "type", + M2MResourceInstance::INTEGER, + M2MBase::Dynamic); + m2mresource_stub::bool_value = false; + + m2mbase_stub::void_value = malloc(20); + + CHECK(firmware->set_resource_value(M2MFirmware::PackageName,10) == false); + CHECK(firmware->set_resource_value(M2MFirmware::PackageVersion,10) == false); + CHECK(firmware->set_resource_value(M2MFirmware::PackageUri,10) == false); + + CHECK(firmware->set_resource_value(M2MFirmware::Package,10) == false); + CHECK(firmware->set_resource_value(M2MFirmware::State,2) == true); + CHECK(firmware->set_resource_value(M2MFirmware::State,1) == true); + CHECK(firmware->set_resource_value(M2MFirmware::State,3) == true); + CHECK(firmware->set_resource_value(M2MFirmware::State,4) == false); + CHECK(firmware->set_resource_value(M2MFirmware::State,0) == true); + CHECK(firmware->set_resource_value(M2MFirmware::UpdateResult,2) == true); + CHECK(firmware->set_resource_value(M2MFirmware::UpdateResult,20) == false); + CHECK(firmware->set_resource_value(M2MFirmware::UpdateSupportedObjects,true) == true); + CHECK(firmware->set_resource_value(M2MFirmware::Update,10) == false); + CHECK(firmware->check_value_range(M2MFirmware::Update,10) == false); + + free(m2mbase_stub::void_value); + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; +} + + +void Test_M2MFirmware::test_resource_value_int() +{ + uint8_t value[] = {"10"}; + uint8_t* ptr = (uint8_t*)malloc((uint32_t)sizeof(value)); + m2mresourceinstance_stub::value = ptr; + memset(m2mresourceinstance_stub::value,0,(uint32_t)sizeof(value)); + memcpy(m2mresourceinstance_stub::value, value,sizeof(value)); + m2mresourceinstance_stub::int_value = (uint32_t)sizeof(value); + + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst, + "name", + "type", + M2MResourceInstance::INTEGER, + M2MBase::Dynamic); + + m2mresourceinstance_stub::bool_value = true; + m2mresource_stub::bool_value = false; + m2mbase_stub::void_value = malloc(20); + + CHECK(firmware->resource_value_int(M2MFirmware::State) == 10); + CHECK(firmware->resource_value_int(M2MFirmware::UpdateResult) == 10); + CHECK(firmware->resource_value_int(M2MFirmware::UpdateSupportedObjects) == 10); + CHECK(firmware->resource_value_int(M2MFirmware::PackageName) == -1); + CHECK(firmware->resource_value_int(M2MFirmware::Package) == -1); + CHECK(firmware->resource_value_int(M2MFirmware::PackageUri) == -1); + CHECK(firmware->resource_value_int(M2MFirmware::PackageVersion) == -1); + CHECK(firmware->resource_value_int(M2MFirmware::Update) == -1); + + free(m2mbase_stub::void_value); + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; + + free(ptr); +} + +void Test_M2MFirmware::test_resource_value_string() +{ + String test = "string"; + uint8_t value[] = {"string"}; + m2mresourceinstance_stub::value = (uint8_t*)malloc((uint32_t)sizeof(value)); + memset(m2mresourceinstance_stub::value,0,(uint32_t)sizeof(value)); + memcpy(m2mresourceinstance_stub::value,value,sizeof(value)); + m2mresourceinstance_stub::int_value = (uint32_t)sizeof(value); + + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst, + "name", + "type", + M2MResourceInstance::STRING, + M2MBase::Dynamic); + + m2mresourceinstance_stub::bool_value = true; + m2mresource_stub::bool_value = false; + m2mbase_stub::void_value = malloc(20); + + CHECK(firmware->resource_value_string(M2MFirmware::PackageUri) == test); + CHECK(firmware->resource_value_string(M2MFirmware::PackageName) == test); + CHECK(firmware->resource_value_string(M2MFirmware::PackageVersion) == test); + CHECK(firmware->resource_value_string(M2MFirmware::Package) == ""); + CHECK(firmware->resource_value_string(M2MFirmware::Update) == ""); + CHECK(firmware->resource_value_string(M2MFirmware::UpdateResult) == ""); + CHECK(firmware->resource_value_string(M2MFirmware::UpdateSupportedObjects) == ""); + CHECK(firmware->resource_value_string(M2MFirmware::State) == ""); + + free(m2mbase_stub::void_value); + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; + + free(m2mresourceinstance_stub::value); + m2mresourceinstance_stub::value = NULL; +} + +void Test_M2MFirmware::test_is_resource_present() +{ + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst, + "name", + "type", + M2MResourceInstance::STRING, + M2MBase::Dynamic); + m2mresource_stub::bool_value = false; + CHECK(firmware->is_resource_present(M2MFirmware::PackageUri) == true); + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; + + CHECK(firmware->is_resource_present(M2MFirmware::PackageName) == false); + CHECK(firmware->is_resource_present(M2MFirmware::PackageVersion) == false); +} + +void Test_M2MFirmware::test_per_resource_count() +{ + m2mobjectinstance_stub::int_value = 1; + CHECK(firmware->per_resource_count(M2MFirmware::Package) == 1); + + m2mobjectinstance_stub::int_value = 0; + + CHECK(firmware->per_resource_count(M2MFirmware::PackageVersion) == 0); +} + + + +void Test_M2MFirmware::test_total_resource_count() +{ + M2MResource res(*m2mobject_stub::inst, + "test", + "test", + M2MResourceInstance::STRING, + M2MBase::Dynamic); + + m2mobjectinstance_stub::resource_list.push_back(&res); + M2MResource res2(*m2mobject_stub::inst, + "test", + "test", + M2MResourceInstance::STRING, + M2MBase::Dynamic); + + m2mobjectinstance_stub::resource_list.push_back(&res2); + + CHECK(firmware->total_resource_count() == 2); + + m2mobjectinstance_stub::resource_list.clear(); +} + +void Test_M2MFirmware::test_resource_value_buffer() +{ + m2mresourceinstance_stub::bool_value = true; + + uint8_t value[] = {"buffer"}; + uint8_t *out_value = NULL; + + m2mresourceinstance_stub::value = (uint8_t*)malloc((uint32_t)sizeof(value)); + memset(m2mresourceinstance_stub::value,0,(uint32_t)sizeof(value)); + memcpy(m2mresourceinstance_stub::value,value,sizeof(value)); + m2mresourceinstance_stub::int_value = (uint16_t)sizeof(value); + + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst, + "name", + "type", + M2MResourceInstance::STRING, + M2MBase::Dynamic); + + CHECK(firmware->resource_value_buffer(M2MFirmware::Package,out_value) != 0); + + CHECK(firmware->resource_value_buffer(M2MFirmware::PackageName,out_value) == 0); + CHECK(firmware->resource_value_buffer(M2MFirmware::PackageUri,out_value) == 0); + CHECK(firmware->resource_value_buffer(M2MFirmware::PackageVersion,out_value) == 0); + CHECK(firmware->resource_value_buffer(M2MFirmware::Update,out_value) == 0); + CHECK(firmware->resource_value_buffer(M2MFirmware::State,out_value) == 0); + CHECK(firmware->resource_value_buffer(M2MFirmware::UpdateResult,out_value) == 0); + CHECK(firmware->resource_value_buffer(M2MFirmware::UpdateSupportedObjects,out_value) == 0); + + + free(out_value); + out_value = NULL; + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; + + free(m2mresourceinstance_stub::value); + m2mresourceinstance_stub::value = NULL; +} + +void Test_M2MFirmware::test_set_resource_value_buffer() +{ + m2mresourceinstance_stub::bool_value = true; + + uint8_t value[] = {"value"}; + uint16_t length = (uint16_t)sizeof(value); + + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst, + "name", + "type", + M2MResourceInstance::STRING, + M2MBase::Dynamic); + + CHECK(firmware->set_resource_value(M2MFirmware::Package,value,length) == true); + CHECK(firmware->set_resource_value(M2MFirmware::PackageName,value,length) == false); + CHECK(firmware->set_resource_value(M2MFirmware::PackageUri,value,length) == false); + CHECK(firmware->set_resource_value(M2MFirmware::PackageVersion,value,length) == false); + CHECK(firmware->set_resource_value(M2MFirmware::State,value,length) == false); + CHECK(firmware->set_resource_value(M2MFirmware::Update,value,length) == false); + CHECK(firmware->set_resource_value(M2MFirmware::UpdateResult,value,length) == false); + CHECK(firmware->set_resource_value(M2MFirmware::UpdateSupportedObjects,value,length) == false); + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; +} + +void Test_M2MFirmware::test_resource_name() +{ + CHECK(firmware->resource_name(M2MFirmware::Package) == "0"); + CHECK(firmware->resource_name(M2MFirmware::PackageUri) == "1"); + CHECK(firmware->resource_name(M2MFirmware::Update) == "2"); + CHECK(firmware->resource_name(M2MFirmware::State) == "3"); + CHECK(firmware->resource_name(M2MFirmware::UpdateSupportedObjects) == "4"); + CHECK(firmware->resource_name(M2MFirmware::UpdateResult) == "5"); + CHECK(firmware->resource_name(M2MFirmware::PackageName) == "6"); + CHECK(firmware->resource_name(M2MFirmware::PackageVersion) == "7"); +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mfirmware/test_m2mfirmware.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mfirmware/test_m2mfirmware.h new file mode 100755 index 0000000000..5b14fcc206 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mfirmware/test_m2mfirmware.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TEST_M2M_FIRMWARE_H +#define TEST_M2M_FIRMWARE_H + + +#include + +class Callback; + +class Test_M2MFirmware +{ +public: + Test_M2MFirmware(); + virtual ~Test_M2MFirmware(); + + void test_create_resource_string(); + + void test_create_resource_int(); + + void test_delete_resource(); + + void test_set_resource_value_int(); + + void test_set_resource_value_string(); + + void test_resource_value_int(); + + void test_resource_value_string(); + + void test_is_resource_present(); + + void test_per_resource_count(); + + void test_total_resource_count(); + + void test_resource_value_buffer(); + + void test_set_resource_value_buffer(); + + void test_resource_name(); + + M2MFirmware* firmware; + Callback *callback; +}; + +#endif // TEST_M2M_FIRMWARE_H diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfacefactory/CMakeLists.txt b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfacefactory/CMakeLists.txt new file mode 100644 index 0000000000..5821cc543f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfacefactory/CMakeLists.txt @@ -0,0 +1,30 @@ +if(TARGET_LIKE_LINUX) +include("../includes.txt") +add_executable(m2minterfacefactorytest + "main.cpp" + "m2minterfacefactorytest.cpp" + "test_m2minterfacefactory.cpp" + "../stub/m2mobject_stub.cpp" + "../stub/m2mbase_stub.cpp" + "../stub/m2mresource_stub.cpp" + "../stub/m2mresourceinstance_stub.cpp" + "../stub/m2mstring_stub.cpp" + "../stub/m2mobjectinstance_stub.cpp" + "../stub/m2mdevice_stub.cpp" + "../stub/m2mfirmware_stub.cpp" + "../stub/m2msecurity_stub.cpp" + "../stub/m2mserver_stub.cpp" + "../stub/m2minterfaceimpl_stub.cpp" + "../../../../source/m2minterfacefactory.cpp" +) +target_link_libraries(m2minterfacefactorytest + CppUTest + CppUTestExt +) +set_target_properties(m2minterfacefactorytest +PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" + LINK_FLAGS "${UTEST_LINK_FLAGS}") +set(binary "m2minterfacefactorytest") +add_test(m2minterfacefactorytest ${binary}) + +endif() diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfacefactory/m2minterfacefactorytest.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfacefactory/m2minterfacefactorytest.cpp new file mode 100644 index 0000000000..e7b25a52fa --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfacefactory/m2minterfacefactorytest.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//CppUTest includes should be after your and system includes +#include "CppUTest/TestHarness.h" +#include "test_m2minterfacefactory.h" + +TEST_GROUP(M2MInterfaceFactory) +{ + Test_M2MInterfaceFactory* m2m_factory; + + void setup() + { + m2m_factory = new Test_M2MInterfaceFactory(); + } + void teardown() + { + delete m2m_factory; + } +}; + + +TEST(M2MInterfaceFactory, create_interface) +{ + m2m_factory->test_create_interface(); +} + +TEST(M2MInterfaceFactory, create_device) +{ + m2m_factory->test_create_device(); +} + +TEST(M2MInterfaceFactory, create_security) +{ + m2m_factory->test_create_security(); +} + +TEST(M2MInterfaceFactory, create_server) +{ + m2m_factory->test_create_server(); +} + +TEST(M2MInterfaceFactory, create_object) +{ + m2m_factory->test_create_object(); +} + +TEST(M2MInterfaceFactory, create_firmware) +{ + m2m_factory->test_create_firmware(); +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfacefactory/main.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfacefactory/main.cpp new file mode 100644 index 0000000000..67d97da1e2 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfacefactory/main.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP( M2MInterfaceFactory); diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfacefactory/test_m2minterfacefactory.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfacefactory/test_m2minterfacefactory.cpp new file mode 100755 index 0000000000..a3d6594082 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfacefactory/test_m2minterfacefactory.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include "test_m2minterfacefactory.h" +#include "m2minterfaceobserver.h" +#include "m2mserver.h" +#include "m2mdevice.h" +#include "m2mfirmware.h" + +class TestObserver : public M2MInterfaceObserver { + +public: + TestObserver(){} + void bootstrap_done(M2MSecurity */*server_object*/){} + void object_registered(M2MSecurity */*security_object*/, + const M2MServer &/*server_object*/) {} + + void object_unregistered(M2MSecurity */*server_object*/){} + + void registration_updated(M2MSecurity */*security_object*/, + const M2MServer &/*server_object*/){} + + void error(M2MInterface::Error /*error*/){} + + void value_updated(M2MBase */*base*/, M2MBase::BaseType /*type*/){} +}; + +Test_M2MInterfaceFactory::Test_M2MInterfaceFactory() +{ +} + +Test_M2MInterfaceFactory::~Test_M2MInterfaceFactory() +{ + +} + +void Test_M2MInterfaceFactory::test_create_interface() +{ + TestObserver test_obs; + M2MInterface *test = M2MInterfaceFactory::create_interface(test_obs, + "endpoint_name", + "endpoint_type", + 120, + 8000, + "domain"); + CHECK(test != NULL); + delete test; + test = NULL; + + // Endpoint name and type of length more than 64 characters + test = M2MInterfaceFactory::create_interface(test_obs, + "endpoint_name-very-long-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1", + "endpoint_type-very-long-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1", + 120, + 8000, + "domain"); + CHECK(test == NULL); + delete test; + + // Domain length more than 64 characters + test = M2MInterfaceFactory::create_interface(test_obs, + "endpoint_name", + "endpoint_type", + 120, + 8000, + "domaidomaindomaindomaindomaindomaindomaindomaindomaindomaindomaindomaindomaindomain"); + CHECK(test == NULL); + delete test; + +} + +void Test_M2MInterfaceFactory::test_create_security() +{ + M2MSecurity *test = M2MInterfaceFactory::create_security(M2MSecurity::Bootstrap); + CHECK(test != NULL); + delete test; + test = NULL; +} + +void Test_M2MInterfaceFactory::test_create_device() +{ + M2MDevice *test = M2MInterfaceFactory::create_device(); + CHECK(test != NULL); + delete test; + test = NULL; +} + +void Test_M2MInterfaceFactory::test_create_firmware() +{ + M2MFirmware *test = M2MInterfaceFactory::create_firmware(); + CHECK(test != NULL); + delete test; + test = NULL; +} + +void Test_M2MInterfaceFactory::test_create_server() +{ + M2MServer *test = M2MInterfaceFactory::create_server(); + CHECK(test != NULL); + delete test; + test = NULL; +} + +void Test_M2MInterfaceFactory::test_create_object() +{ + M2MObject *test = M2MInterfaceFactory::create_object("name"); + CHECK(test != NULL); + delete test; + test = NULL; + + // Length 65, should fail + String max_lenght = "65656565656565656565656565656565656565656565656565656565656565656"; + CHECK(M2MInterfaceFactory::create_object("") == NULL); + CHECK(M2MInterfaceFactory::create_object(max_lenght) == NULL); +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfacefactory/test_m2minterfacefactory.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfacefactory/test_m2minterfacefactory.h new file mode 100755 index 0000000000..0bec638507 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfacefactory/test_m2minterfacefactory.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TEST_M2M_INTERFACE_FACTORY_H +#define TEST_M2M_INTERFACE_FACTORY_H + +#include "m2minterfacefactory.h" + +class Test_M2MInterfaceFactory +{ + +public: + Test_M2MInterfaceFactory(); + virtual ~Test_M2MInterfaceFactory(); + + void test_create_interface(); + + void test_create_security(); + + void test_create_device(); + + void test_create_firmware(); + + void test_create_server(); + + void test_create_object(); +}; + +#endif // TEST_M2M_INTERFACE_FACTORY_H diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfaceimpl/CMakeLists.txt b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfaceimpl/CMakeLists.txt new file mode 100644 index 0000000000..6e88df2d96 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfaceimpl/CMakeLists.txt @@ -0,0 +1,32 @@ +if(TARGET_LIKE_LINUX) +include("../includes.txt") +add_executable(m2minterfaceimpl + "main.cpp" + "m2minterfaceimpltest.cpp" + "test_m2minterfaceimpl.cpp" + "../stub/m2mobject_stub.cpp" + "../stub/m2mbase_stub.cpp" + "../stub/m2mobject_stub.cpp" + "../stub/m2mstring_stub.cpp" + "../stub/m2mresource_stub.cpp" + "../stub/m2mresourceinstance_stub.cpp" + "../stub/m2mobjectinstance_stub.cpp" + "../stub/m2msecurity_stub.cpp" + "../stub/m2mtimer_stub.cpp" + "../stub/m2mnsdlinterface_stub.cpp" + "../stub/m2mconnectionhandler_stub.cpp" + "../stub/m2mconnectionsecurity_stub.cpp" + "../stub/nsdlaccesshelper_stub.cpp" + "../../../../source/m2minterfaceimpl.cpp" +) +target_link_libraries(m2minterfaceimpl + CppUTest + CppUTestExt +) +set_target_properties(m2minterfaceimpl +PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" + LINK_FLAGS "${UTEST_LINK_FLAGS}") +set(binary "m2minterfaceimpl") +add_test(m2minterfaceimpl ${binary}) + +endif() diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfaceimpl/m2minterfaceimpltest.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfaceimpl/m2minterfaceimpltest.cpp new file mode 100644 index 0000000000..3c4cda4394 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfaceimpl/m2minterfaceimpltest.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//CppUTest includes should be after your and system includes +#include "CppUTest/TestHarness.h" +#include "test_m2minterfaceimpl.h" + +TEST_GROUP(M2MInterfaceImpl) +{ + Test_M2MInterfaceImpl* m2m_interface_impl; + + void setup() + { + m2m_interface_impl = new Test_M2MInterfaceImpl(); + } + void teardown() + { + delete m2m_interface_impl; + } +}; + +TEST(M2MInterfaceImpl, create) +{ + CHECK(m2m_interface_impl->impl != NULL); +} + +TEST(M2MInterfaceImpl, test_constructor) +{ + m2m_interface_impl->test_constructor(); +} + +TEST(M2MInterfaceImpl, bootstrap) +{ + m2m_interface_impl->test_bootstrap(); +} + +TEST(M2MInterfaceImpl, cancel_bootstrap) +{ + m2m_interface_impl->test_cancel_bootstrap(); +} + +TEST(M2MInterfaceImpl, register_object) +{ + m2m_interface_impl->test_register_object(); +} + +TEST(M2MInterfaceImpl, update_registration) +{ + m2m_interface_impl->test_update_registration(); +} + +TEST(M2MInterfaceImpl, unregister_object) +{ + m2m_interface_impl->test_unregister_object(); +} + +TEST(M2MInterfaceImpl, set_queue_sleep_handler) +{ + m2m_interface_impl->test_set_queue_sleep_handler(); +} + +TEST(M2MInterfaceImpl, test_set_random_number_callback) +{ + m2m_interface_impl->test_set_random_number_callback(); +} + +TEST(M2MInterfaceImpl, test_set_entropy_callback) +{ + m2m_interface_impl->test_set_entropy_callback(); +} + +TEST(M2MInterfaceImpl, test_set_platform_network_handler) +{ + m2m_interface_impl->test_set_platform_network_handler(); +} + +TEST(M2MInterfaceImpl, coap_message_ready) +{ + m2m_interface_impl->test_coap_message_ready(); +} + +TEST(M2MInterfaceImpl, client_registered) +{ + m2m_interface_impl->test_client_registered(); +} + +TEST(M2MInterfaceImpl, test_registration_updated) +{ + m2m_interface_impl->test_registration_updated(); +} + +TEST(M2MInterfaceImpl, registration_error) +{ + m2m_interface_impl->test_registration_error(); +} + +TEST(M2MInterfaceImpl, client_unregistered) +{ + m2m_interface_impl->test_client_unregistered(); +} + +TEST(M2MInterfaceImpl, bootstrap_done) +{ + m2m_interface_impl->test_bootstrap_done(); +} + +TEST(M2MInterfaceImpl, bootstrap_error) +{ + m2m_interface_impl->test_bootstrap_error(); +} + +TEST(M2MInterfaceImpl, coap_data_processed) +{ + m2m_interface_impl->test_coap_data_processed(); +} + +TEST(M2MInterfaceImpl, test_value_updated) +{ + m2m_interface_impl->test_value_updated(); +} + +TEST(M2MInterfaceImpl, data_available) +{ + m2m_interface_impl->test_data_available(); +} + +TEST(M2MInterfaceImpl, socket_error) +{ + m2m_interface_impl->test_socket_error(); +} + +TEST(M2MInterfaceImpl, address_ready) +{ + m2m_interface_impl->test_address_ready(); +} + +TEST(M2MInterfaceImpl, data_sent) +{ + m2m_interface_impl->test_data_sent(); +} + +TEST(M2MInterfaceImpl, timer_expired) +{ + m2m_interface_impl->test_timer_expired(); +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfaceimpl/main.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfaceimpl/main.cpp new file mode 100644 index 0000000000..c06d1bee2d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfaceimpl/main.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP( M2MInterfaceImpl); diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfaceimpl/test_m2minterfaceimpl.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfaceimpl/test_m2minterfaceimpl.cpp new file mode 100755 index 0000000000..64f9db9571 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfaceimpl/test_m2minterfaceimpl.cpp @@ -0,0 +1,756 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include "test_m2minterfaceimpl.h" +#include "m2minterfaceobserver.h" +#include "m2mconnectionhandler_stub.h" +#include "m2msecurity_stub.h" +#include "m2mnsdlinterface_stub.h" +#include "m2mobject_stub.h" +#include "m2mobjectinstance_stub.h" +#include "m2mbase.h" + +entropy_cb ent_cb; + +class TestObserver : public M2MInterfaceObserver { + +public: + TestObserver() : val_updated(false), error_occured(false), + registered(false), unregistered(false), bootstrapped(false) + { + } + + virtual ~TestObserver(){} + void bootstrap_done(M2MSecurity */*server_object*/){ + bootstrapped = true; + } + void object_registered(M2MSecurity */*security_object*/, + const M2MServer &/*server_object*/) { + registered = true; + } + + void object_unregistered(M2MSecurity */*server_object*/){ + unregistered = true; + } + + void registration_updated(M2MSecurity */*security_object*/, + const M2MServer &/*server_object*/){ + registered = true; + } + + void error(M2MInterface::Error /*error*/){ + error_occured = true; + } + + void value_updated(M2MBase *, M2MBase::BaseType ){ + val_updated = true; + } + + bool val_updated; + bool error_occured; + bool registered; + bool unregistered; + bool bootstrapped; +}; + +class M2MBaseTest : public M2MBase +{ +public: + M2MBaseTest() : M2MBase("a", M2MBase::Static){} +}; + +Test_M2MInterfaceImpl::Test_M2MInterfaceImpl() +{ + observer = new TestObserver(); + impl = new M2MInterfaceImpl(*observer, + "endpoint_name", + "endpoint_type", + 120, + 8000, + "domain"); +} + +Test_M2MInterfaceImpl:: ~Test_M2MInterfaceImpl() +{ + delete observer; + delete impl; +} + +void Test_M2MInterfaceImpl::test_constructor() +{ + TestObserver obs; + + M2MInterfaceImpl* obj = new M2MInterfaceImpl(obs, + "endpoint_name", + "endpoint_type", + 120, + 8000, + "domain", + M2MInterface::TCP); + CHECK(obj->_current_state == 0); + //TODO: Check rest of variables + delete obj; + + obj = new M2MInterfaceImpl(obs, + "endpoint_name", + "endpoint_type", + 120, + 8000, + "domain", + M2MInterface::TCP_QUEUE); + + delete obj; +} + +void Test_M2MInterfaceImpl::test_bootstrap() +{ + M2MSecurity *sec = new M2MSecurity(M2MSecurity::Bootstrap); + m2msecurity_stub::int_value = 2; + String *val = new String("coaps://[2001:12:12:23::23:FF]:5685"); + + m2msecurity_stub::string_value = val; + m2mnsdlinterface_stub::bool_value = true; + m2mconnectionhandler_stub::bool_value = true; + + impl->bootstrap(sec); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_BOOTSTRAP); + + delete val; + + val = new String("coaps://[10.45.3.83:5685"); + + impl->_register_ongoing = false; + impl->_current_state = M2MInterfaceImpl::STATE_IDLE; + + m2msecurity_stub::string_value = val; + m2mnsdlinterface_stub::bool_value = true; + m2mconnectionhandler_stub::bool_value = true; + + impl->bootstrap(sec); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + + delete val; + + val = new String("coaps://10.45.3.83]:5685"); + + impl->_register_ongoing = false; + impl->_current_state = M2MInterfaceImpl::STATE_IDLE; + + m2msecurity_stub::string_value = val; + m2mnsdlinterface_stub::bool_value = true; + m2mconnectionhandler_stub::bool_value = true; + + impl->bootstrap(sec); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + + delete val; + + val = new String("coaps://10.45.3.83:5685"); + + impl->_register_ongoing = false; + impl->_current_state = M2MInterfaceImpl::STATE_IDLE; + + m2msecurity_stub::string_value = val; + m2mnsdlinterface_stub::bool_value = true; + m2mconnectionhandler_stub::bool_value = true; + + impl->bootstrap(sec); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_BOOTSTRAP); + + delete val; + + val = new String("coap://10.45.3.83:5685"); + m2msecurity_stub::string_value = val; + m2mconnectionhandler_stub::bool_value = true; + + impl->bootstrap(sec); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_BOOTSTRAP); + + impl->_current_state = M2MInterfaceImpl::STATE_IDLE; + m2mconnectionhandler_stub::bool_value = false; + + impl->bootstrap(sec); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + CHECK(observer->error_occured == true); + + // Ignore the event. + impl->_current_state = M2MInterfaceImpl::STATE_WAITING; + impl->bootstrap(sec); + + m2mconnectionhandler_stub::bool_value = true; + + impl->bootstrap(sec); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_WAITING); + CHECK(observer->error_occured == true); + + delete val; + val = NULL; + + delete sec; +} + +void Test_M2MInterfaceImpl::test_cancel_bootstrap() +{ + // Check for coverage, currently no implementation + impl->cancel_bootstrap(); +} + +void Test_M2MInterfaceImpl::test_register_object() +{ + M2MSecurity *sec = new M2MSecurity(M2MSecurity::M2MServer); + m2msecurity_stub::int_value = 2; + + M2MObject *object = new M2MObject("test"); + M2MObjectInstance *ins = object->create_object_instance(); + ins->create_dynamic_resource("test","type",M2MResourceInstance::STRING,false,false); + + M2MObjectList list; + list.push_back(object); + + String *val = new String("coaps://[2001:12:12:23::23:FF]:5685"); + m2msecurity_stub::string_value = val; + m2mnsdlinterface_stub::bool_value = true; + m2mconnectionhandler_stub::bool_value = true; + impl->register_object(sec,list); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_REGISTER); + + impl->_register_ongoing = false; + impl->_current_state = M2MInterfaceImpl::STATE_IDLE; + impl->register_object(sec,list); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_REGISTER); + + delete val; + val = new String("coaps://[10.45.3.83:5685"); + impl->_register_ongoing = false; + impl->_current_state = M2MInterfaceImpl::STATE_IDLE; + m2msecurity_stub::string_value = val; + m2mnsdlinterface_stub::bool_value = true; + m2mconnectionhandler_stub::bool_value = true; + + delete impl->_security; + impl->_security = NULL; + sec = new M2MSecurity(M2MSecurity::M2MServer); + impl->register_object(sec,list); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + CHECK(observer->error_occured == true); + observer->error_occured = false; + delete val; + val = new String("coaps://10.45.3.83]:5685"); + + impl->_register_ongoing = false; + impl->_current_state = M2MInterfaceImpl::STATE_IDLE; + + m2msecurity_stub::string_value = val; + m2mnsdlinterface_stub::bool_value = true; + m2mconnectionhandler_stub::bool_value = true; + + delete impl->_security; + impl->_security = NULL; + sec = new M2MSecurity(M2MSecurity::M2MServer); + impl->register_object(sec,list); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + CHECK(observer->error_occured == true); + + observer->error_occured = false; + delete val; + val = new String("coaps://10.45.3.83:5685"); + delete impl->_security; + impl->_security = NULL; + sec = new M2MSecurity(M2MSecurity::M2MServer); + + impl->_register_ongoing = false; + impl->_current_state = M2MInterfaceImpl::STATE_IDLE; + + m2msecurity_stub::string_value = val; + m2mnsdlinterface_stub::bool_value = true; + m2mconnectionhandler_stub::bool_value = true; + + impl->register_object(sec,list); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_REGISTER); + + observer->error_occured = false; + delete val; + val = new String("coap://10.45.3.83:5685"); + delete impl->_security; + impl->_security = NULL; + sec = new M2MSecurity(M2MSecurity::M2MServer); + + impl->_register_ongoing = false; + impl->_current_state = M2MInterfaceImpl::STATE_IDLE; + + m2msecurity_stub::string_value = val; + m2mnsdlinterface_stub::bool_value = true; + m2mconnectionhandler_stub::bool_value = true; + + impl->register_object(sec,list); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_REGISTER); + + delete val; + val = new String("coap://10.45.3.83:5685"); + impl->register_object(sec,list); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_REGISTER); + + + impl->_current_state = M2MInterfaceImpl::STATE_IDLE; + m2mconnectionhandler_stub::bool_value = true; + m2mnsdlinterface_stub::bool_value = false; + + delete impl->_security; + impl->_security = NULL; + sec = new M2MSecurity(M2MSecurity::M2MServer); + impl->register_object(sec,list); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + CHECK(observer->error_occured == true); + + + impl->_current_state = M2MInterfaceImpl::STATE_IDLE; + m2mconnectionhandler_stub::bool_value = false; + m2mnsdlinterface_stub::bool_value = true; + + impl->register_object(sec,list); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + CHECK(observer->error_occured == true); + + + impl->_register_ongoing = false; + impl->_current_state = M2MInterfaceImpl::STATE_BOOTSTRAP; + m2mconnectionhandler_stub::bool_value = true; + m2mnsdlinterface_stub::bool_value = true; + + impl->register_object(sec,list); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_BOOTSTRAP); + CHECK(observer->error_occured == true); + + impl->_current_state = M2MInterfaceImpl::STATE_IDLE; + m2mconnectionhandler_stub::bool_value = true; + m2mnsdlinterface_stub::bool_value = true; + + impl->register_object(sec,list); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + CHECK(observer->error_occured == true); + + impl->_current_state = M2MInterfaceImpl::STATE_BOOTSTRAP; + m2mconnectionhandler_stub::bool_value = true; + m2mnsdlinterface_stub::bool_value = true; + + impl->register_object(sec,list); + + CHECK(observer->error_occured == true); + + + delete val; + val = NULL; + + list.clear(); + delete object; + delete sec; +} + +void Test_M2MInterfaceImpl::test_update_registration() +{ + impl->_current_state = M2MInterfaceImpl::STATE_REGISTERED; + m2mnsdlinterface_stub::bool_value = true; + impl->update_registration(NULL,120); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_UPDATE_REGISTRATION); + + impl->_update_register_ongoing = false; + impl->_current_state = M2MInterfaceImpl::STATE_REGISTERED; + m2mnsdlinterface_stub::bool_value = false; + impl->update_registration(NULL,120); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_UPDATE_REGISTRATION); + + impl->_current_state = M2MInterfaceImpl::STATE_REGISTERED; + m2mnsdlinterface_stub::bool_value = false; + impl->update_registration(NULL,120); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_REGISTERED); + + impl->_current_state = M2MInterfaceImpl::STATE_IDLE; + impl->update_registration(NULL,120); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + CHECK(observer->error_occured == true); + + impl->_update_register_ongoing = false; + impl->_current_state = M2MInterfaceImpl::STATE_BOOTSTRAP; + impl->update_registration(NULL,120); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_BOOTSTRAP); + CHECK(observer->error_occured == true); + + impl->update_registration(NULL,30); + CHECK(observer->error_occured == true); + + impl->_update_register_ongoing = true; + impl->update_registration(NULL,120); + CHECK(observer->error_occured == true); + +} + +void Test_M2MInterfaceImpl::test_unregister_object() +{ + impl->_current_state = M2MInterfaceImpl::STATE_REGISTERED; + m2mnsdlinterface_stub::bool_value = true; + + impl->unregister_object(NULL); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_WAITING); + + impl->_current_state = M2MInterfaceImpl::STATE_REGISTERED; + m2mnsdlinterface_stub::bool_value = false; + + impl->unregister_object(NULL); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + CHECK(observer->error_occured == true); + + impl->_current_state = M2MInterfaceImpl::STATE_IDLE; + + impl->unregister_object(NULL); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + CHECK(observer->error_occured == true); +} + +void Test_M2MInterfaceImpl::test_set_queue_sleep_handler() +{ + callback_handler cb(this,&Test_M2MInterfaceImpl::test_callback_handler); + impl->set_queue_sleep_handler(cb); + CHECK(impl->_callback_handler != NULL); + + callback_handler cb1(NULL); + impl->set_queue_sleep_handler(cb1); + CHECK(impl->_callback_handler == NULL); +} + + +void Test_M2MInterfaceImpl::test_set_random_number_callback() +{ + random_number_cb cb(&test_random_callback); + impl->set_random_number_callback(cb); +} + +void Test_M2MInterfaceImpl::test_set_entropy_callback() +{ + impl->set_entropy_callback(ent_cb); +} + +void Test_M2MInterfaceImpl::test_set_platform_network_handler() +{ + void *test = NULL; + impl->set_platform_network_handler(test); +} + +void Test_M2MInterfaceImpl::test_coap_message_ready() +{ + m2mconnectionhandler_stub::bool_value = true; + uint8_t *data_ptr = (uint8_t *)malloc(sizeof(uint8_t)); + uint16_t data_len = sizeof(uint8_t); + sn_nsdl_addr_s *address_ptr = (sn_nsdl_addr_s*)malloc(sizeof(sn_nsdl_addr_s)); + + impl->coap_message_ready(data_ptr,data_len,address_ptr); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_WAITING); + + m2mconnectionhandler_stub::bool_value = false; + impl->coap_message_ready(data_ptr,data_len,address_ptr); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + CHECK(observer->error_occured == true); + + free(address_ptr); + free(data_ptr); +} + +void Test_M2MInterfaceImpl::test_client_registered() +{ + impl->client_registered(NULL); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_REGISTERED); + CHECK(observer->registered == true); +} + +void Test_M2MInterfaceImpl::test_registration_updated() +{ + M2MServer *server = NULL; + impl->registration_updated(*server); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_REGISTERED); + CHECK(observer->registered == true); +} + +void Test_M2MInterfaceImpl::test_registration_error() +{ + impl->registration_error(1); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + CHECK(observer->error_occured == true); + + observer->error_occured = false; + impl->registration_error(1, true); + CHECK(observer->error_occured == false); +} + +void Test_M2MInterfaceImpl::test_client_unregistered() +{ + impl->client_unregistered(); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + CHECK(observer->unregistered == true); +} + +void Test_M2MInterfaceImpl::test_bootstrap_done() +{ + M2MSecurity *sec = new M2MSecurity(M2MSecurity::M2MServer); + impl->bootstrap_done(sec); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_BOOTSTRAPPED); + CHECK(observer->bootstrapped == true); + + delete sec; +} + +void Test_M2MInterfaceImpl::test_bootstrap_error() +{ + impl->bootstrap_error(); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + CHECK(observer->error_occured == true); +} + +void Test_M2MInterfaceImpl::test_coap_data_processed() +{ + impl->coap_data_processed(); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_WAITING); +} + +void Test_M2MInterfaceImpl::test_value_updated() +{ + impl->value_updated(NULL); + CHECK(observer->val_updated == false); + + M2MBaseTest b; + impl->value_updated(&b); + CHECK(observer->val_updated == true); +} + +void Test_M2MInterfaceImpl::test_data_available() +{ + uint8_t* data = (uint8_t*)malloc(sizeof(uint8_t)); + uint16_t data_size = sizeof(uint8_t); + M2MConnectionObserver::SocketAddress *address = (M2MConnectionObserver::SocketAddress*) + malloc(sizeof(M2MConnectionObserver::SocketAddress)); + + address->_stack = M2MInterface::LwIP_IPv4; + m2mnsdlinterface_stub::bool_value = true; + + impl->data_available(data,data_size,*address); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_WAITING); + + address->_stack = M2MInterface::LwIP_IPv6; + m2mnsdlinterface_stub::bool_value = true; + + impl->data_available(data,data_size,*address); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_WAITING); + + address->_stack = M2MInterface::LwIP_IPv4; + m2mnsdlinterface_stub::bool_value = false; + + impl->data_available(data,data_size,*address); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_WAITING); + CHECK(observer->error_occured == true); + + free(data); + free(address); +} + +void Test_M2MInterfaceImpl::test_socket_error() +{ + for (int i = 0; i <= MBED_CLIENT_RECONNECTION_COUNT; i++) { + impl->socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR); + impl->_retry_timer_expired = true; + } + CHECK(observer->error_occured == true); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + + observer->error_occured = false; + impl->socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, false); + CHECK(observer->error_occured == true); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + + observer->error_occured = false; + impl->socket_error(M2MConnectionHandler::DNS_RESOLVING_ERROR, false); + CHECK(observer->error_occured == true); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + + observer->error_occured = false; + impl->socket_error(M2MConnectionHandler::SOCKET_SEND_ERROR, false); + CHECK(observer->error_occured == true); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + + observer->error_occured = false; + impl->socket_error(M2MConnectionHandler::SSL_HANDSHAKE_ERROR, false); + CHECK(observer->error_occured == true); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + + observer->error_occured = false; + impl->socket_error(M2MConnectionHandler::SOCKET_ABORT, false); + CHECK(observer->error_occured == true); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + + observer->error_occured = false; + impl->socket_error(M2MConnectionHandler::ERROR_NONE, false); + CHECK(observer->error_occured == false); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); +} + +void Test_M2MInterfaceImpl::test_address_ready() +{ + M2MConnectionObserver::SocketAddress *address = + (M2MConnectionObserver::SocketAddress*) malloc(sizeof(M2MConnectionObserver::SocketAddress)); + M2MConnectionObserver::ServerType server_type = M2MConnectionObserver::Bootstrap; + uint16_t server_port = 5685; + + address->_stack = M2MInterface::LwIP_IPv6; + m2mnsdlinterface_stub::bool_value = true; + + impl->address_ready(*address,server_type,server_port); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_BOOTSTRAP_RESOURCE_CREATED); + + address->_stack = M2MInterface::LwIP_IPv4; + m2mnsdlinterface_stub::bool_value = true; + + impl->address_ready(*address,server_type,server_port); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_BOOTSTRAP_RESOURCE_CREATED); + + + address->_stack = M2MInterface::LwIP_IPv6; + m2mnsdlinterface_stub::bool_value = false; + + impl->address_ready(*address,server_type,server_port); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + CHECK(observer->error_occured == true); + + // Test for Address resolving for LWM2M server + server_type = M2MConnectionObserver::LWM2MServer; + + address->_stack = M2MInterface::LwIP_IPv6; + m2mnsdlinterface_stub::bool_value = true; + + impl->address_ready(*address,server_type,server_port); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_REGISTER_RESOURCE_CREATED); + + address->_stack = M2MInterface::LwIP_IPv4; + m2mnsdlinterface_stub::bool_value = true; + + impl->address_ready(*address,server_type,server_port); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_REGISTER_RESOURCE_CREATED); + + + address->_stack = M2MInterface::LwIP_IPv6; + m2mnsdlinterface_stub::bool_value = false; + + impl->address_ready(*address,server_type,server_port); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_IDLE); + CHECK(observer->error_occured == true); + + free(address); +} + +void Test_M2MInterfaceImpl::test_data_sent() +{ + m2mconnectionhandler_stub::bool_value = true; + + impl->data_sent(); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_WAITING); + + m2mconnectionhandler_stub::bool_value = false; + + impl->data_sent(); + + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_WAITING); + CHECK(observer->error_occured == false); + + impl->_callback_handler = callback_handler(this, &Test_M2MInterfaceImpl::test_callback_handler); + + m2mconnectionhandler_stub::bool_value = true; + + impl->_binding_mode = M2MInterface::UDP_QUEUE; + impl->data_sent(); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_WAITING); + + impl->_binding_mode = M2MInterface::TCP_QUEUE; + impl->data_sent(); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_WAITING); + + impl->_binding_mode = M2MInterface::SMS_QUEUE; + impl->data_sent(); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_WAITING); + + impl->_binding_mode = M2MInterface::UDP_SMS_QUEUE; + impl->data_sent(); + CHECK(impl->_current_state == M2MInterfaceImpl::STATE_WAITING); +} + +void Test_M2MInterfaceImpl::test_timer_expired() +{ + visited = false; + impl->_callback_handler = NULL; + impl->timer_expired(M2MTimerObserver::QueueSleep); + CHECK(visited == false); + + impl->_callback_handler = callback_handler(this, &Test_M2MInterfaceImpl::test_callback_handler); + + visited = false; + impl->timer_expired(M2MTimerObserver::QueueSleep); + CHECK(visited == true); + + int port = impl->_listen_port; + impl->timer_expired(M2MTimerObserver::RetryTimer); + CHECK(impl->_listen_port != port); + + observer->error_occured = false; + impl->timer_expired(M2MTimerObserver::BootstrapTimer); + CHECK(observer->error_occured == true); +} + +void Test_M2MInterfaceImpl::test_callback_handler() +{ + visited = true; +} + +uint32_t test_random_callback(void) +{ + return 1; +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfaceimpl/test_m2minterfaceimpl.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfaceimpl/test_m2minterfaceimpl.h new file mode 100755 index 0000000000..1efca5cdee --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2minterfaceimpl/test_m2minterfaceimpl.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TEST_M2M_INTERFACE_IMPL_H +#define TEST_M2M_INTERFACE_IMPL_H + +#include "m2minterfaceimpl.h" + +class TestObserver; + +uint32_t test_random_callback(void); + +class Test_M2MInterfaceImpl +{ +public: + Test_M2MInterfaceImpl(); + + virtual ~Test_M2MInterfaceImpl(); + + void test_constructor(); + + void test_bootstrap(); + + void test_cancel_bootstrap(); + + void test_register_object(); + + void test_update_registration(); + + void test_unregister_object(); + + void test_set_queue_sleep_handler(); + + void test_set_random_number_callback(); + + void test_set_entropy_callback(); + + void test_set_platform_network_handler(); + + void test_coap_message_ready(); + + void test_client_registered(); + + void test_registration_updated(); + + void test_registration_error(); + + void test_client_unregistered(); + + void test_bootstrap_done(); + + void test_bootstrap_error(); + + void test_coap_data_processed(); + + void test_value_updated(); + + void test_data_available(); + + void test_socket_error(); + + void test_address_ready(); + + void test_data_sent(); + + void test_timer_expired(); + + void test_callback_handler(); + + M2MInterfaceImpl* impl; + TestObserver *observer; + bool visited; +}; + +#endif // TEST_M2M_INTERFACE_IMPL_H diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mnsdlinterface/CMakeLists.txt b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mnsdlinterface/CMakeLists.txt new file mode 100644 index 0000000000..b0269a679b --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mnsdlinterface/CMakeLists.txt @@ -0,0 +1,34 @@ +if(TARGET_LIKE_LINUX) +include("../includes.txt") +add_executable(m2mnsdlinterface + "main.cpp" + "m2mnsdlinterfacetest.cpp" + "test_m2mnsdlinterface.cpp" + "../stub/m2mbase_stub.cpp" + "../stub/m2mobject_stub.cpp" + "../stub/m2mserver_stub.cpp" + "../stub/m2mresource_stub.cpp" + "../stub/m2mresourceinstance_stub.cpp" + "../stub/m2mobjectinstance_stub.cpp" + "../stub/m2mstring_stub.cpp" + "../stub/m2msecurity_stub.cpp" + "../stub/m2mconnectionsecurity_stub.cpp" + "../stub/m2mconnectionhandler_stub.cpp" + "../stub/m2mtimer_stub.cpp" + "../stub/common_stub.cpp" + "../stub/nsdlaccesshelper_stub.cpp" + "../stub/m2mtlvserializer_stub.cpp" + "../stub/m2mtlvdeserializer_stub.cpp" + "../../../../source/m2mnsdlinterface.cpp" +) +target_link_libraries(m2mnsdlinterface + CppUTest + CppUTestExt +) +set_target_properties(m2mnsdlinterface +PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" + LINK_FLAGS "${UTEST_LINK_FLAGS}") +set(binary "m2mnsdlinterface") +add_test(m2mnsdlinterface ${binary}) + +endif() diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mnsdlinterface/m2mnsdlinterfacetest.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mnsdlinterface/m2mnsdlinterfacetest.cpp new file mode 100644 index 0000000000..04cd415713 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mnsdlinterface/m2mnsdlinterfacetest.cpp @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//CppUTest includes should be after your and system includes +#include "CppUTest/TestHarness.h" +#include "test_m2mnsdlinterface.h" + +TEST_GROUP(M2MNsdlInterface) +{ + Test_M2MNsdlInterface* m2m_nsdl_interface; + + void setup() + { + m2m_nsdl_interface = new Test_M2MNsdlInterface(); + } + void teardown() + { + delete m2m_nsdl_interface; + m2m_nsdl_interface = NULL; + } +}; + + +TEST(M2MNsdlInterface, create) +{ + CHECK(m2m_nsdl_interface->nsdl != NULL); +} + +TEST(M2MNsdlInterface, memory_free) +{ + m2m_nsdl_interface->test_memory_free(); +} + +TEST(M2MNsdlInterface, memory_alloc) +{ + m2m_nsdl_interface->test_memory_alloc(); +} + +TEST(M2MNsdlInterface, send_unregister_message) +{ + m2m_nsdl_interface->test_send_unregister_message(); +} + +TEST(M2MNsdlInterface, send_update_registration) +{ + m2m_nsdl_interface->test_send_update_registration(); +} + +TEST(M2MNsdlInterface, send_register_message) +{ + m2m_nsdl_interface->test_send_register_message(); +} + +TEST(M2MNsdlInterface, create_bootstrap_resource) +{ + m2m_nsdl_interface->test_create_bootstrap_resource(); +} + +TEST(M2MNsdlInterface, delete_nsdl_resource) +{ + m2m_nsdl_interface->test_delete_nsdl_resource(); +} + +TEST(M2MNsdlInterface, delete_endpoint) +{ + m2m_nsdl_interface->test_delete_endpoint(); +} + +TEST(M2MNsdlInterface, create_endpoint) +{ + m2m_nsdl_interface->test_create_endpoint(); +} + +TEST(M2MNsdlInterface, send_to_server_callback) +{ + m2m_nsdl_interface->test_send_to_server_callback(); +} + +TEST(M2MNsdlInterface, received_from_server_callback) +{ + m2m_nsdl_interface->test_received_from_server_callback(); +} + +TEST(M2MNsdlInterface, create_nsdl_list_structure) +{ + m2m_nsdl_interface->test_create_nsdl_list_structure(); +} + +TEST(M2MNsdlInterface, resource_callback) +{ + m2m_nsdl_interface->test_resource_callback(); +} + +TEST(M2MNsdlInterface, resource_callback_get) +{ + m2m_nsdl_interface->test_resource_callback_get(); +} + + +TEST(M2MNsdlInterface, resource_callback_post) +{ + m2m_nsdl_interface->test_resource_callback_post(); +} + +TEST(M2MNsdlInterface, resource_callback_delete) +{ + m2m_nsdl_interface->test_resource_callback_delete(); +} + +TEST(M2MNsdlInterface, resource_callback_reset) +{ + m2m_nsdl_interface->test_resource_callback_reset(); +} + +TEST(M2MNsdlInterface, timer_expired) +{ + m2m_nsdl_interface->test_timer_expired(); +} + +TEST(M2MNsdlInterface, process_received_data) +{ + m2m_nsdl_interface->test_process_received_data(); +} + +TEST(M2MNsdlInterface, stop_timers) +{ + m2m_nsdl_interface->test_stop_timers(); +} + +TEST(M2MNsdlInterface, observation_to_be_sent) +{ + m2m_nsdl_interface->test_observation_to_be_sent(); +} + +TEST(M2MNsdlInterface, resource_to_be_deleted) +{ + m2m_nsdl_interface->test_resource_to_be_deleted(); +} + +TEST(M2MNsdlInterface, value_updated) +{ + m2m_nsdl_interface->test_value_updated(); +} + +TEST(M2MNsdlInterface, find_resource) +{ + m2m_nsdl_interface->test_find_resource(); +} + +TEST(M2MNsdlInterface, remove_object) +{ + m2m_nsdl_interface->test_remove_object(); +} + +TEST(M2MNsdlInterface, add_object_to_list) +{ + m2m_nsdl_interface->test_add_object_to_list(); +} + +TEST(M2MNsdlInterface, test_send_delayed_response) +{ + m2m_nsdl_interface->test_send_delayed_response(); +} + +TEST(M2MNsdlInterface, resource_callback_put) +{ + m2m_nsdl_interface->test_resource_callback_put(); +} + +TEST(M2MNsdlInterface, get_nsdl_handle) +{ + m2m_nsdl_interface->test_get_nsdl_handle(); +} + +TEST(M2MNsdlInterface, endpoint_name) +{ + m2m_nsdl_interface->test_endpoint_name(); +} + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mnsdlinterface/main.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mnsdlinterface/main.cpp new file mode 100644 index 0000000000..4e5c44fad0 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mnsdlinterface/main.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP( M2MNsdlInterface); diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mnsdlinterface/test_m2mnsdlinterface.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mnsdlinterface/test_m2mnsdlinterface.cpp new file mode 100755 index 0000000000..be4b48418f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mnsdlinterface/test_m2mnsdlinterface.cpp @@ -0,0 +1,1705 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include "test_m2mnsdlinterface.h" +#include "common_stub.h" +#include "m2msecurity_stub.h" +#include "m2mnsdlobserver.h" +#include "m2mobject_stub.h" +#include "m2mobjectinstance_stub.h" +#include "m2mresource_stub.h" +#include "m2mresourceinstance_stub.h" +#include "m2mresource.h" +#include "m2mbase_stub.h" +#include "m2mserver.h" +#include "m2msecurity.h" +#include "m2mtlvdeserializer_stub.h" +class TestObserver : public M2MNsdlObserver { + +public: + TestObserver(){} + virtual ~TestObserver(){} + void coap_message_ready(uint8_t *, + uint16_t, + sn_nsdl_addr_s *){ + message_ready = true; + } + + void client_registered(M2MServer *){ + registered = true; + } + + void registration_updated(const M2MServer &){ + register_updated = true; + } + + void registration_error(uint8_t, bool retry = false){ + register_error = true; + } + + void client_unregistered(){ + unregistered = true; + } + + void bootstrap_done(M2MSecurity *sec){ + if(sec) { + boot_done = true; + delete sec; + sec = NULL; + } + } + + void bootstrap_error(){ + boot_error = true; + } + + void coap_data_processed(){ + data_processed = true; + } + + void value_updated(M2MBase *){ + value_update = true; + } + + bool register_error; + bool boot_error; + bool boot_done; + bool registered; + bool register_updated; + bool data_processed; + bool unregistered; + bool message_ready; + bool value_update; +}; + +struct nsdl_s { + struct grs_s *grs; + + uint8_t *oma_bs_address_ptr; /* Bootstrap address pointer. If null, no bootstrap in use */ + uint8_t oma_bs_address_len; /* Bootstrap address length */ + uint16_t oma_bs_port; /* Bootstrap port */ + void (*sn_nsdl_oma_bs_done_cb)(sn_nsdl_oma_server_info_t *server_info_ptr); /* Callback to inform application when bootstrap is done */ + sn_nsdl_ep_parameters_s *ep_information_ptr; // Endpoint parameters, Name, Domain etc.. + sn_nsdl_oma_server_info_t *nsp_address_ptr; // NSP server address information + uint8_t sn_nsdl_endpoint_registered; + + uint16_t register_msg_id; + uint16_t unregister_msg_id; + + void *(*sn_nsdl_alloc)(uint16_t); + void (*sn_nsdl_free)(void *); + uint8_t (*sn_nsdl_tx_callback)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *); + uint8_t (*sn_nsdl_rx_callback)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *); + void (*sn_nsdl_oma_bs_done_cb_handle)(sn_nsdl_oma_server_info_t *server_info_ptr, + struct nsdl_s *handle); /* Callback to inform application when bootstrap is done with nsdl handle */ + uint16_t update_register_msg_id; + uint16_t register_msg_len; + uint16_t update_register_msg_len; + uint16_t bootstrap_msg_id; + bool handle_bootstrap_msg; +}; + +Test_M2MNsdlInterface::Test_M2MNsdlInterface() +{ + observer = new TestObserver(); + nsdl = new M2MNsdlInterface(*observer); + //nsdl->_server = new M2MServer(); +} + +Test_M2MNsdlInterface:: ~Test_M2MNsdlInterface() +{ + delete nsdl; + nsdl = NULL; + delete observer; + observer = NULL; +} + +void Test_M2MNsdlInterface::test_create_endpoint() +{ + u_int8_t value[] = {"120"}; + if( nsdl->_endpoint == NULL){ + nsdl->_endpoint = (sn_nsdl_ep_parameters_s*)nsdl->memory_alloc(sizeof(sn_nsdl_ep_parameters_s)); + } + + nsdl->create_endpoint("name", "type",120,"domain",100,"context"); + CHECK(nsdl->_endpoint->lifetime_len == 3); + CHECK(*nsdl->_endpoint->lifetime_ptr == *value); +} + +void Test_M2MNsdlInterface::test_delete_endpoint() +{ + if( nsdl->_endpoint == NULL){ + nsdl->_endpoint = (sn_nsdl_ep_parameters_s*)nsdl->memory_alloc(sizeof(sn_nsdl_ep_parameters_s)); + } + nsdl->_endpoint->lifetime_ptr = (uint8_t*)malloc(sizeof(uint8_t)); + + nsdl->delete_endpoint(); + CHECK(nsdl->_endpoint == NULL); +} + +void Test_M2MNsdlInterface::test_create_nsdl_list_structure() +{ + String *name = new String("name"); + common_stub::int_value = 0; + m2mbase_stub::int_value = 0; + M2MObject *object = new M2MObject(*name); + M2MObjectInstance* instance = new M2MObjectInstance(*name,*object); + + M2MResource* create_resource = new M2MResource(*instance, + *name, + *name, + M2MResourceInstance::INTEGER, + M2MResource::Dynamic, + false); + + M2MResourceInstance* res_instance = new M2MResourceInstance(*name, + *name, + M2MResourceInstance::INTEGER, + *instance); + + m2mobject_stub::instance_list.clear(); + m2mobject_stub::instance_list.push_back(instance); + + m2mobjectinstance_stub::resource_list.clear(); + m2mobjectinstance_stub::resource_list.push_back(create_resource); + + M2MObjectList list; + list.push_back(object); + + m2mbase_stub::string_value = name; + m2mbase_stub::mode_value = M2MBase::Static; + + CHECK(nsdl->create_nsdl_list_structure(list)== true); + + m2mresource_stub::bool_value = true; + m2mbase_stub::mode_value = M2MBase::Dynamic; + + m2mresource_stub::list.push_back(res_instance); + + CHECK(nsdl->create_nsdl_list_structure(list)== true); + + nsdl->_resource->path = ((uint8_t*)nsdl->memory_alloc(3)); + m2mbase_stub::mode_value = M2MBase::Directory; + CHECK(nsdl->create_nsdl_list_structure(list)== true); + + list.clear(); + delete object; + delete name; + name = NULL; + m2mobject_stub::instance_list.clear(); + delete instance; + instance = NULL; + m2mobjectinstance_stub::resource_list.clear(); + delete create_resource; + create_resource = NULL; + + m2mresource_stub::list.clear(); + delete res_instance; + res_instance = NULL; +} + +void Test_M2MNsdlInterface::test_delete_nsdl_resource() +{ + common_stub::int_value = -1; + + CHECK(nsdl->delete_nsdl_resource("name") == false); + + common_stub::int_value = 0; + + CHECK(nsdl->delete_nsdl_resource("name") == true); +} + +void Test_M2MNsdlInterface::test_create_bootstrap_resource() +{ + common_stub::uint_value = 11; + CHECK(nsdl->create_bootstrap_resource(NULL, "") == true); + + common_stub::uint_value = 0; + CHECK(nsdl->create_bootstrap_resource(NULL, "") == false); +} + +void Test_M2MNsdlInterface::test_send_register_message() +{ + common_stub::uint_value = 12; + CHECK(nsdl->send_register_message(NULL,100,SN_NSDL_ADDRESS_TYPE_IPV6) == true); + + common_stub::uint_value = 0; + CHECK(nsdl->send_register_message(NULL,100,SN_NSDL_ADDRESS_TYPE_IPV6) == false); +} + +void Test_M2MNsdlInterface::test_send_update_registration() +{ + common_stub::uint_value = 23; + nsdl->_nsdl_handle = (nsdl_s*)malloc(sizeof(1)); + CHECK(nsdl->send_update_registration(120) == true); + + /* Update already in progress */ + common_stub::uint_value = 0; + CHECK(nsdl->send_update_registration(120) == true); + + /* Update lifetime value */ + nsdl->_update_register_ongoing = false; + common_stub::uint_value = 1; + CHECK(nsdl->send_update_registration(100) == true); + + /* Lifetime value is 0, don't change the existing lifetime value */ + nsdl->_update_register_ongoing = false; + common_stub::uint_value = 1; + CHECK(nsdl->send_update_registration(0) == true); + + free(nsdl->_nsdl_handle); +} + +void Test_M2MNsdlInterface::test_send_unregister_message() +{ + common_stub::uint_value = 22; + CHECK(nsdl->send_unregister_message() == true); + + /* Unreg already in progress */ + common_stub::uint_value = 0; + CHECK(nsdl->send_unregister_message() == true); +} + +void Test_M2MNsdlInterface::test_memory_alloc() +{ + CHECK(nsdl->memory_alloc(0) == 0); + uint8_t *ptr = 0; + ptr = (uint8_t*)nsdl->memory_alloc(sizeof(uint8_t)); + CHECK(ptr != NULL); + nsdl->memory_free(ptr); +} + +void Test_M2MNsdlInterface::test_memory_free() +{ + uint8_t *ptr = (uint8_t*)nsdl->memory_alloc(sizeof(uint8_t)); + nsdl->memory_free((void*)ptr); + //memory leak test will fail, if there is a leak, so no need for CHECK +} + +void Test_M2MNsdlInterface::test_send_to_server_callback() +{ + uint8_t *data_ptr = (uint8_t*)malloc(sizeof(uint8_t)); + uint16_t data_len = sizeof(uint8_t); + sn_nsdl_addr_s *address = (sn_nsdl_addr_s *)malloc(sizeof(sn_nsdl_addr_s)); + + nsdl->send_to_server_callback(NULL, SN_NSDL_PROTOCOL_COAP, data_ptr,data_len,address); + CHECK(observer->message_ready == true); + + free(data_ptr); + free(address); +} + +void Test_M2MNsdlInterface::test_received_from_server_callback() +{ + nsdl_s* handle = (nsdl_s*)malloc(sizeof(nsdl_s)); + memset(handle,0,sizeof(nsdl_s)); + + sn_coap_hdr_s *coap_header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(coap_header, 0, sizeof(sn_coap_hdr_s)); + coap_header->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + + + coap_header->options_list_ptr = (sn_coap_options_list_s *)malloc(sizeof(sn_coap_options_list_s)); + memset(coap_header->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + + coap_header->options_list_ptr->max_age_len = 2; + coap_header->options_list_ptr->max_age_ptr = (uint8_t *)malloc(sizeof(coap_header->options_list_ptr->max_age_len)); + memset(coap_header->options_list_ptr->max_age_ptr, 0, sizeof(coap_header->options_list_ptr->max_age_len)); + + coap_header->options_list_ptr->location_path_len = 2; + coap_header->options_list_ptr->location_path_ptr = (uint8_t *)malloc(sizeof(coap_header->options_list_ptr->location_path_len)); + memset(coap_header->options_list_ptr->location_path_ptr, 0, sizeof(coap_header->options_list_ptr->location_path_len)); + + observer->data_processed = false; + observer->registered = false; + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->data_processed == true); + CHECK(observer->registered == true); + + free(nsdl->_endpoint->lifetime_ptr); + nsdl->_endpoint->lifetime_ptr = NULL; + + free(nsdl->_endpoint->location_ptr); + nsdl->_endpoint->location_ptr = NULL; + + uint8_t life1[] = {"120"}; + nsdl->_endpoint->lifetime_ptr = (uint8_t*)malloc(sizeof(life1)); + memcpy(nsdl->_endpoint->lifetime_ptr,life1,sizeof(life1)); + nsdl->_endpoint->lifetime_len = (uint8_t)sizeof(life1); + + observer->data_processed = false; + observer->registered = false; + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->data_processed == true); + CHECK(observer->registered == true); + + free(coap_header->options_list_ptr->max_age_ptr); + coap_header->options_list_ptr->max_age_ptr = NULL; + + free(coap_header->options_list_ptr->location_path_ptr); + coap_header->options_list_ptr->location_path_ptr = NULL; + + free(coap_header->options_list_ptr); + coap_header->options_list_ptr = NULL; + + free(nsdl->_endpoint->lifetime_ptr); + nsdl->_endpoint->lifetime_ptr = NULL; + + uint8_t life[] = {"120"}; + nsdl->_endpoint->lifetime_ptr = (uint8_t*)malloc(sizeof(life)); + memcpy(nsdl->_endpoint->lifetime_ptr,life,sizeof(life)); + nsdl->_endpoint->lifetime_len = (uint8_t)sizeof(life); + + observer->data_processed = false; + observer->registered = false; + + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->data_processed == true); + CHECK(observer->registered == true); + free(nsdl->_endpoint->lifetime_ptr); + nsdl->_endpoint->lifetime_ptr = NULL; + + uint8_t big_life[] = {"4000"}; + nsdl->_endpoint->lifetime_ptr = (uint8_t*)malloc(sizeof(big_life)); + memcpy(nsdl->_endpoint->lifetime_ptr,big_life,sizeof(big_life)); + nsdl->_endpoint->lifetime_len = (uint8_t)sizeof(big_life); + observer->data_processed = false; + observer->registered = false; + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->data_processed == true); + CHECK(observer->registered == true); + + free(nsdl->_endpoint->lifetime_ptr); + nsdl->_endpoint->lifetime_ptr = NULL; + + observer->data_processed = false; + observer->registered = false; + + uint8_t less_life[] = {"30"}; + nsdl->_endpoint->lifetime_ptr = (uint8_t*)malloc(sizeof(less_life)); + memcpy(nsdl->_endpoint->lifetime_ptr,less_life,sizeof(less_life)); + nsdl->_endpoint->lifetime_len = (uint8_t)sizeof(less_life); + + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->data_processed == true); + CHECK(observer->registered == true); + + observer->data_processed = false; + observer->registered = false; + observer->unregistered = false; + observer->register_error = false; + + coap_header->msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->data_processed == true); + CHECK(observer->register_error == true); + + coap_header->msg_code = COAP_MSG_CODE_RESPONSE_BAD_OPTION; + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->data_processed == true); + CHECK(observer->register_error == true); + + coap_header->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE; + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->data_processed == true); + CHECK(observer->register_error == true); + + coap_header->msg_code = COAP_MSG_CODE_RESPONSE_PRECONDITION_FAILED; + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->data_processed == true); + CHECK(observer->register_error == true); + + coap_header->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE; + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->data_processed == true); + CHECK(observer->register_error == true); + + coap_header->msg_code = COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->data_processed == true); + CHECK(observer->register_error == true); + + coap_header->msg_code = COAP_MSG_CODE_RESPONSE_UNAUTHORIZED; + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->data_processed == true); + CHECK(observer->register_error == true); + + coap_header->msg_code = COAP_MSG_CODE_RESPONSE_FORBIDDEN; + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->data_processed == true); + CHECK(observer->register_error == true); + + coap_header->msg_code = COAP_MSG_CODE_RESPONSE_NOT_FOUND; + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->data_processed == true); + CHECK(observer->register_error == true); + + coap_header->msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->data_processed == true); + CHECK(observer->register_error == true); + + coap_header->msg_code = COAP_MSG_CODE_RESPONSE_BAD_GATEWAY; + coap_header->coap_status = COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED; + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->data_processed == true); + CHECK(observer->register_error == true); + + + coap_header->msg_id = 8; + handle->unregister_msg_id = 8; + + coap_header->msg_code = COAP_MSG_CODE_RESPONSE_DELETED; + observer->register_error = false; + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->unregistered == true); + + observer->register_error = false; + handle->unregister_msg_id = 8; + coap_header->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->register_error == true); + + observer->register_error = false; + handle->unregister_msg_id = 8; + coap_header->coap_status = COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED; + coap_header->msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->register_error == true); + + observer->register_error = false; + handle->unregister_msg_id = 8; + coap_header->coap_status = COAP_STATUS_PARSER_ERROR_IN_HEADER; + coap_header->msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->register_error == true); + + observer->register_error = false; + handle->unregister_msg_id = 8; + coap_header->coap_status = COAP_STATUS_PARSER_ERROR_IN_HEADER; + coap_header->msg_code = COAP_MSG_CODE_RESPONSE_GATEWAY_TIMEOUT; + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->register_error == true); + + handle->unregister_msg_id = 0; + observer->boot_error = false; + nsdl->_bootstrap_id = 8; + handle->bootstrap_msg_id = 8; + coap_header->coap_status = COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED; + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(observer->boot_error == true); + + //_update_id == msg_id + handle->update_register_msg_id = 10; + coap_header->msg_id = 10; + coap_header->msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(nsdl->_update_register_ongoing == false); + CHECK(observer->register_updated == true); + + coap_header->msg_id = 10; + coap_header->msg_code = COAP_MSG_CODE_RESPONSE_FORBIDDEN; + coap_header->coap_status = COAP_STATUS_OK; + nsdl->received_from_server_callback(handle,coap_header,NULL); + CHECK(nsdl->_register_ongoing == true); + CHECK(observer->register_error == true); + + coap_header->msg_id = 11; + CHECK( 0== nsdl->received_from_server_callback(handle,coap_header,NULL) ); + + handle->update_register_msg_id = 0; + handle->register_msg_id = 0; + handle->unregister_msg_id = 0; + coap_header->msg_id = 10; + coap_header->msg_code = COAP_MSG_CODE_REQUEST_POST; + + uint8_t object[] = {"name"}; + + coap_header->uri_path_ptr = object; + coap_header->uri_path_len = sizeof(object); + + CHECK(0== nsdl->received_from_server_callback(handle,coap_header,NULL)); + + uint8_t object_instance[] = {"name/0"}; + + coap_header->uri_path_ptr = object_instance; + coap_header->uri_path_len = sizeof(object_instance); + + coap_header->payload_ptr = (uint8_t*)malloc(1); + m2mobjectinstance_stub::bool_value = true; + CHECK(0== nsdl->received_from_server_callback(handle,coap_header,NULL)); + + M2MObject *obj = new M2MObject("name"); + + m2mbase_stub::string_value = new String("name"); + + nsdl->_object_list.push_back(obj); + + m2mobject_stub::inst = new M2MObjectInstance("name",*obj); + + m2mobject_stub::header = (sn_coap_hdr_s*) malloc(sizeof(sn_coap_hdr_s)); + memset(m2mobject_stub::header,0,sizeof(sn_coap_hdr_s)); + + m2mobjectinstance_stub::header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(m2mobjectinstance_stub::header, 0, sizeof(sn_coap_hdr_s)); + m2mobjectinstance_stub::header->msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; + common_stub::coap_header = NULL; + + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,NULL)); + m2mobjectinstance_stub::header = NULL; + + m2mobjectinstance_stub::header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(m2mobjectinstance_stub::header, 0, sizeof(sn_coap_hdr_s)); + + m2mobjectinstance_stub::header->msg_code = COAP_MSG_CODE_RESPONSE_CREATED; + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,NULL)); + + m2mobjectinstance_stub::header = NULL; + + free(coap_header->payload_ptr); + coap_header->payload_ptr = NULL; + + CHECK(0== nsdl->received_from_server_callback(handle,coap_header,NULL)); + + delete m2mobject_stub::inst; + delete m2mbase_stub::string_value; + m2mbase_stub::string_value = NULL; + nsdl->_object_list.clear(); + delete obj; + + free(coap_header->payload_ptr); + free(m2mobject_stub::header); + m2mobject_stub::header = NULL; + + uint8_t object_instance1[] = {"name/65536"}; + + coap_header->uri_path_ptr = object_instance1; + coap_header->uri_path_len = sizeof(object_instance1); + + obj = new M2MObject("name"); + + m2mbase_stub::string_value = new String("name"); + + nsdl->_object_list.push_back(obj); + + m2mobject_stub::inst = new M2MObjectInstance("name",*obj); + + m2mobject_stub::header = (sn_coap_hdr_s*) malloc(sizeof(sn_coap_hdr_s)); + memset(m2mobject_stub::header,0,sizeof(sn_coap_hdr_s)); + + CHECK(0== nsdl->received_from_server_callback(handle,coap_header,NULL)); + + delete m2mobject_stub::inst; + delete m2mbase_stub::string_value; + m2mbase_stub::string_value = NULL; + nsdl->_object_list.clear(); + delete obj; + + free(m2mobject_stub::header); + + uint8_t resource[] = {"name/0/resource"}; + + coap_header->uri_path_ptr = resource; + coap_header->uri_path_len = sizeof(resource); + + CHECK(0== nsdl->received_from_server_callback(handle,coap_header,NULL)); + + common_stub::coap_header = (sn_coap_hdr_s *) malloc(sizeof(sn_coap_hdr_s)); + sn_nsdl_addr_s *address = (sn_nsdl_addr_s *)malloc(sizeof(sn_nsdl_addr_s)); + memset(address, 0, sizeof(sn_nsdl_addr_s)); + address->addr_len = 1; + address->addr_ptr = (uint8_t *)malloc(1); + address->addr_ptr[0] = 1; + address->port = 5683; + handle->oma_bs_address_len = 1; + handle->oma_bs_port = 5683; + handle->oma_bs_address_ptr = (uint8_t *)malloc(1); + handle->oma_bs_address_ptr[0] = 1; + coap_header->msg_code = COAP_MSG_CODE_REQUEST_PUT; + + observer->boot_error = false; + CHECK(0== nsdl->received_from_server_callback(handle,coap_header,address)); + CHECK(observer->boot_error == true); + + obj = new M2MObject("0"); + m2mbase_stub::string_value = new String("0"); + nsdl->_object_list.push_back(obj); + m2mobject_stub::inst = new M2MObjectInstance("name",*obj); + uint8_t security[] = {"0"}; + coap_header->uri_path_ptr = security; + coap_header->uri_path_len = sizeof(security); + + + M2MResource res(*m2mobject_stub::inst,"test","test",M2MResourceInstance::STRING,M2MBase::Dynamic); + + m2mobjectinstance_stub::resource_list.push_back(&res); + observer->boot_error = false; + m2msecurity_stub::resource = new M2MResource(*m2mobject_stub::inst,"1","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,address)); + CHECK(observer->boot_error == true); + + coap_header->token_ptr = String::convert_integer_to_array(1,coap_header->token_len); + observer->boot_error = false; + m2mtlvdeserializer_stub::is_object_bool_value = true; + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,address)); + CHECK(observer->boot_error == true); + + coap_header->content_type_ptr = String::convert_integer_to_array(99,coap_header->content_type_len); + observer->boot_error = false; + observer->boot_done = false; + m2mtlvdeserializer_stub::is_object_bool_value = true; + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,address)); + CHECK(observer->boot_error == false); + + observer->boot_error = false; + observer->boot_done = false; + m2mtlvdeserializer_stub::is_object_bool_value = false; + m2mtlvdeserializer_stub::bool_value = true; + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,address)); + CHECK(observer->boot_error == false); + + observer->boot_error = false; + observer->boot_done = false; + m2mtlvdeserializer_stub::is_object_bool_value = false; + m2mtlvdeserializer_stub::bool_value = true; + m2mtlvdeserializer_stub::error = M2MTLVDeserializer::NotAllowed; + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,address)); + CHECK(observer->boot_error == true); + + + delete m2mobject_stub::inst; + delete m2mbase_stub::string_value; + m2mbase_stub::string_value = NULL; + nsdl->_object_list.clear(); + delete obj; + + obj = new M2MObject("1"); + m2mbase_stub::string_value = new String("1"); + nsdl->_object_list.push_back(obj); + m2mobject_stub::inst = new M2MObjectInstance("name",*obj); + uint8_t server[] = {"1"}; + coap_header->uri_path_ptr = server; + coap_header->uri_path_len = 1; + + observer->boot_error = false; + observer->boot_done = false; + m2mtlvdeserializer_stub::is_object_bool_value = false; + m2mtlvdeserializer_stub::bool_value = true; + m2mtlvdeserializer_stub::error = M2MTLVDeserializer::None; + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,address)); + CHECK(observer->boot_error == false); + + observer->boot_error = false; + observer->boot_done = false; + m2mtlvdeserializer_stub::is_object_bool_value = true; + m2mtlvdeserializer_stub::bool_value = false; + m2mtlvdeserializer_stub::error = M2MTLVDeserializer::None; + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,address)); + CHECK(observer->boot_error == false); + + observer->boot_error = false; + observer->boot_done = false; + m2mtlvdeserializer_stub::is_object_bool_value = false; + m2mtlvdeserializer_stub::bool_value = false; + m2mtlvdeserializer_stub::error = M2MTLVDeserializer::None; + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,address)); + CHECK(observer->boot_error == true); + CHECK(nsdl->_security == NULL); + + nsdl->_security = new M2MSecurity(M2MSecurity::M2MServer); + observer->boot_error = false; + observer->boot_done = false; + coap_header->msg_code = COAP_MSG_CODE_REQUEST_DELETE; + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,address)); + CHECK(observer->boot_error == false); + + free(common_stub::coap_header); + common_stub::coap_header = NULL; + observer->boot_error = false; + observer->boot_done = false; + coap_header->msg_code = COAP_MSG_CODE_REQUEST_DELETE; + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,address)); + CHECK(observer->boot_error == true); + CHECK(nsdl->_security == NULL); + + free(common_stub::coap_header); + common_stub::coap_header = NULL; + uint8_t object_name[] = {"0/0"}; + coap_header->uri_path_ptr = object_name; + coap_header->uri_path_len = 3; + observer->boot_error = false; + observer->boot_done = false; + coap_header->msg_code = COAP_MSG_CODE_REQUEST_DELETE; + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,address)); + CHECK(observer->boot_error == true); + CHECK(nsdl->_security == NULL); + + free(common_stub::coap_header); + common_stub::coap_header = NULL; + uint8_t invalid[] = {"0/0/1"}; + coap_header->uri_path_ptr = invalid; + coap_header->uri_path_len = 5; + observer->boot_error = false; + observer->boot_done = false; + coap_header->msg_code = COAP_MSG_CODE_REQUEST_DELETE; + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,address)); + CHECK(observer->boot_error == true); + CHECK(nsdl->_security == NULL); + + coap_header->uri_path_ptr = server; + coap_header->uri_path_len = 1; + nsdl->_security = new M2MSecurity(M2MSecurity::M2MServer); + observer->boot_error = false; + observer->boot_done = false; + coap_header->msg_code = COAP_MSG_CODE_REQUEST_POST; + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,address)); + CHECK(observer->boot_error == true); + CHECK(nsdl->_security == NULL); + + nsdl->_security = new M2MSecurity(M2MSecurity::M2MServer); + common_stub::coap_header = (sn_coap_hdr_s *) malloc(sizeof(sn_coap_hdr_s)); + m2msecurity_stub::string_value = new String("coaps://"); + observer->boot_error = false; + observer->boot_done = false; + coap_header->msg_code = COAP_MSG_CODE_REQUEST_POST; + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,address)); + CHECK(observer->boot_error == true); + CHECK(nsdl->_security == NULL); + + + nsdl->_security = new M2MSecurity(M2MSecurity::M2MServer); + m2msecurity_stub::sec_mode = M2MSecurity::NoSecurity; + m2msecurity_stub::int_value = true; + m2msecurity_stub::bool_value = false; + observer->boot_error = false; + observer->boot_done = false; + coap_header->uri_path_ptr = (uint8_t*)malloc(2); + coap_header->uri_path_len = 2; + coap_header->uri_path_ptr[0] = 'b'; + coap_header->uri_path_ptr[1] = 's'; + coap_header->msg_code = COAP_MSG_CODE_REQUEST_POST; + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,address)); + CHECK(observer->boot_error == false); + CHECK(observer->boot_done == true); + + nsdl->_security = new M2MSecurity(M2MSecurity::M2MServer); + m2msecurity_stub::sec_mode = M2MSecurity::Certificate; + m2mresourceinstance_stub::int_value = 10; + m2msecurity_stub::int_value = true; + m2msecurity_stub::bool_value = false; + observer->boot_error = false; + observer->boot_done = false; + coap_header->msg_code = COAP_MSG_CODE_REQUEST_POST; + + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,address)); + CHECK(observer->boot_error == false); + CHECK(observer->boot_done == true); + + nsdl->_security = new M2MSecurity(M2MSecurity::M2MServer); + m2msecurity_stub::sec_mode = M2MSecurity::Psk; + m2msecurity_stub::int_value = true; + m2msecurity_stub::bool_value = false; + observer->boot_error = false; + observer->boot_done = false; + coap_header->msg_code = COAP_MSG_CODE_REQUEST_POST; + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,address)); + CHECK(observer->boot_error == true); + CHECK(observer->boot_done == false); + + nsdl->_security = new M2MSecurity(M2MSecurity::M2MServer); + m2msecurity_stub::sec_mode = M2MSecurity::Certificate; + m2msecurity_stub::int_value = true; + m2msecurity_stub::bool_value = true; + observer->boot_error = false; + observer->boot_done = false; + coap_header->msg_code = COAP_MSG_CODE_REQUEST_POST; + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,address)); + CHECK(observer->boot_error == true); + CHECK(observer->boot_done == false); + + nsdl->_security = new M2MSecurity(M2MSecurity::M2MServer); + m2msecurity_stub::sec_mode = M2MSecurity::Certificate; + m2msecurity_stub::int_value = false; + m2msecurity_stub::bool_value = false; + m2mresourceinstance_stub::int_value = 0; + observer->boot_error = false; + observer->boot_done = false; + coap_header->msg_code = COAP_MSG_CODE_REQUEST_POST; + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,address)); + CHECK(observer->boot_error == true); + CHECK(observer->boot_done == false); + + nsdl->_security = new M2MSecurity(M2MSecurity::M2MServer); + free(coap_header->uri_path_ptr); + coap_header->uri_path_ptr = (uint8_t*)malloc(4); + coap_header->uri_path_len = 4; + coap_header->uri_path_ptr[0] = 'b'; + coap_header->uri_path_ptr[1] = 's'; + coap_header->uri_path_ptr[2] = 's'; + coap_header->uri_path_ptr[3] = 's'; + m2msecurity_stub::sec_mode = M2MSecurity::Certificate; + m2msecurity_stub::int_value = true; + m2msecurity_stub::bool_value = false; + observer->boot_error = false; + observer->boot_done = false; + coap_header->msg_code = COAP_MSG_CODE_REQUEST_POST; + CHECK(0 == nsdl->received_from_server_callback(handle,coap_header,address)); + CHECK(observer->boot_error == true); + CHECK(observer->boot_done == false); + + delete m2mobject_stub::inst; + delete m2mbase_stub::string_value; + m2mbase_stub::string_value = NULL; + nsdl->_object_list.clear(); + m2mobjectinstance_stub::resource_list.clear(); + delete obj; + delete m2msecurity_stub::string_value; + delete m2msecurity_stub::resource; + free(common_stub::coap_header); + free(address->addr_ptr); + free(address); + free(coap_header->content_type_ptr); + free(coap_header->token_ptr); + free(coap_header->uri_path_ptr); + free(coap_header); + free(handle->oma_bs_address_ptr); + free(handle); +} + +void Test_M2MNsdlInterface::test_resource_callback() +{ + uint8_t value[] = {"name"}; + sn_coap_hdr_s *coap_header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(coap_header,0,sizeof(sn_coap_hdr_s)); + sn_nsdl_addr_s *address = (sn_nsdl_addr_s *)malloc(sizeof(sn_nsdl_addr_s)); + memset(address,0,sizeof(sn_nsdl_addr_s)); + + common_stub::coap_header = (sn_coap_hdr_ *)malloc(sizeof(sn_coap_hdr_)); + memset(common_stub::coap_header,0,sizeof(sn_coap_hdr_)); + + common_stub::coap_header->payload_ptr =(uint8_t*)malloc(1); + common_stub::coap_header->payload_len = 1; + + coap_header->uri_path_ptr = value; + coap_header->uri_path_len = sizeof(value); + + common_stub::int_value = 0; + + coap_header->msg_code = COAP_MSG_CODE_REQUEST_GET; + + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_HTTP) ==0); + + common_stub::int_value = 0; + m2mbase_stub::string_value = new String("name"); + M2MObject *object = new M2MObject("name"); + m2mbase_stub::int_value = 0; + m2mobject_stub::int_value = 1; + + nsdl->_object_list.push_back(object); + + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_COAP) ==0); + + coap_header->msg_code = COAP_MSG_CODE_REQUEST_PUT; + m2mobject_stub::bool_value = true; + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_COAP) ==0); + + coap_header->msg_code = COAP_MSG_CODE_REQUEST_POST; + + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_COAP) ==0); + + + delete object; + delete m2mbase_stub::string_value; + m2mbase_stub::string_value = NULL; + + free(common_stub::coap_header); + free(address); + free(coap_header); +} + +void Test_M2MNsdlInterface::test_resource_callback_get() +{ +} + +void Test_M2MNsdlInterface::test_resource_callback_put() +{ + uint8_t value[] = {"name/0/resource"}; + sn_coap_hdr_s *coap_header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(coap_header,0,sizeof(sn_coap_hdr_s)); + sn_nsdl_addr_s *address = (sn_nsdl_addr_s *)malloc(sizeof(sn_nsdl_addr_s)); + memset(address,0,sizeof(sn_nsdl_addr_s)); + + coap_header->uri_path_ptr = value; + coap_header->uri_path_len = sizeof(value); + + coap_header->msg_code = COAP_MSG_CODE_REQUEST_PUT; + + String *name = new String("name"); + String *res_name = new String("res"); + common_stub::int_value = 0; + m2mbase_stub::string_value = name; + + M2MObject *object = new M2MObject(*name); + M2MObjectInstance* instance = new M2MObjectInstance(*name,*object); + M2MResource* create_resource = new M2MResource(*instance, + *res_name, + *res_name, + M2MResourceInstance::INTEGER, + false); + m2mobject_stub::int_value = 2; + m2mobject_stub::instance_list.push_back(instance); + + m2mobjectinstance_stub::resource_list.push_back(create_resource); + m2mobjectinstance_stub::int_value = 1; + + nsdl->_object_list.push_back(object); + + m2mbase_stub::operation = M2MBase::PUT_ALLOWED; + + coap_header->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + + uint8_t query[] = {"pmax=200&pmin=120"}; + coap_header->options_list_ptr->uri_query_ptr = (uint8_t*)malloc(sizeof(query)); + coap_header->options_list_ptr->uri_query_len = sizeof(query); + + m2mbase_stub::bool_value = true; + + common_stub::coap_header = (sn_coap_hdr_ *)malloc(sizeof(sn_coap_hdr_)); + memset(common_stub::coap_header,0,sizeof(sn_coap_hdr_)); + + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_HTTP) ==0); + + m2mobject_stub::base_type = M2MBase::Resource; + m2mbase_stub::base_type = M2MBase::Resource; + m2mobject_stub::bool_value = true; + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_HTTP) ==0); + + m2mobject_stub::base_type = M2MBase::ObjectInstance; + m2mbase_stub::base_type = M2MBase::ObjectInstance; + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_HTTP) ==0); + + m2mbase_stub::base_type = M2MBase::Object; + m2mbase_stub::bool_value = false; + + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_HTTP) ==0); + + delete object; + m2mobject_stub::instance_list.clear(); + delete instance; +// m2mobjectinstance_stub::resource_list.clear(); + delete create_resource; + + free(coap_header->options_list_ptr->uri_query_ptr); + free(coap_header->options_list_ptr); + if(common_stub::coap_header){ + if( common_stub::coap_header->content_type_ptr ){ + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if( common_stub::coap_header->options_list_ptr){ + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + free(common_stub::coap_header); + common_stub::coap_header = NULL; + } + free(coap_header); + free(address); + + delete name; + delete res_name; + name = NULL; + + m2mbase_stub::clear(); + common_stub::clear(); + m2mobject_stub::clear(); + m2mobjectinstance_stub::clear(); +} + +void Test_M2MNsdlInterface::test_resource_callback_post() +{ + uint8_t value[] = {"name/0/name"}; + sn_coap_hdr_s *coap_header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(coap_header,0,sizeof(sn_coap_hdr_s)); + sn_nsdl_addr_s *address = (sn_nsdl_addr_s *)malloc(sizeof(sn_nsdl_addr_s)); + memset(address,0,sizeof(sn_nsdl_addr_s)); + + coap_header->uri_path_ptr = value; + coap_header->uri_path_len = sizeof(value); + + coap_header->msg_code = COAP_MSG_CODE_REQUEST_POST; + + String *name = new String("name"); + common_stub::int_value = 0; + m2mbase_stub::string_value = name; + m2mbase_stub::bool_value = false; + M2MObject *object = new M2MObject(*name); + M2MObjectInstance* instance = new M2MObjectInstance(*name,*object); + M2MResource* create_resource = new M2MResource(*instance, + *name, + *name, + M2MResourceInstance::INTEGER, + M2MResource::Dynamic,false); + m2mobject_stub::int_value = 2; + m2mobject_stub::instance_list.push_back(instance); + + m2mobjectinstance_stub::resource_list.push_back(create_resource); + m2mobjectinstance_stub::int_value = 1; + + nsdl->_object_list.push_back(object); + + m2mbase_stub::operation = M2MBase::POST_ALLOWED; + + coap_header->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + + uint8_t query[] = {"pmax=200&pmin=120"}; + coap_header->options_list_ptr->uri_query_ptr = (uint8_t*)malloc(sizeof(query)); + coap_header->options_list_ptr->uri_query_len = sizeof(query); + + m2mbase_stub::bool_value = true; + + common_stub::coap_header = (sn_coap_hdr_ *)malloc(sizeof(sn_coap_hdr_)); + memset(common_stub::coap_header,0,sizeof(sn_coap_hdr_)); + + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_HTTP) ==0); + + m2mobject_stub::base_type = M2MBase::Resource; + m2mbase_stub::base_type = M2MBase::Resource; + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_HTTP) ==0); + + m2mobject_stub::base_type = M2MBase::ResourceInstance; + m2mbase_stub::base_type = M2MBase::ResourceInstance; + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_HTTP) ==0); + + m2mobject_stub::base_type = M2MBase::ObjectInstance; + m2mbase_stub::base_type = M2MBase::ObjectInstance; + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_HTTP) ==0); + + m2mbase_stub::base_type = M2MBase::Object; + m2mbase_stub::bool_value = false; + + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_HTTP) ==0); + + delete object; + m2mobject_stub::instance_list.clear(); + delete instance; + m2mobjectinstance_stub::resource_list.clear(); + delete create_resource; + + free(coap_header->options_list_ptr->uri_query_ptr); + free(coap_header->options_list_ptr); + if(common_stub::coap_header){ + if( common_stub::coap_header->content_type_ptr ){ + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if( common_stub::coap_header->options_list_ptr){ + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + free(common_stub::coap_header); + common_stub::coap_header = NULL; + } + free(coap_header); + free(address); + + delete name; + name = NULL; + + m2mbase_stub::clear(); + common_stub::clear(); + m2mobject_stub::clear(); + m2mobjectinstance_stub::clear(); +} + +void Test_M2MNsdlInterface::test_resource_callback_delete() +{ + uint8_t value[] = {"name/0"}; + sn_coap_hdr_s *coap_header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(coap_header,0,sizeof(sn_coap_hdr_s)); + sn_nsdl_addr_s *address = (sn_nsdl_addr_s *)malloc(sizeof(sn_nsdl_addr_s)); + memset(address,0,sizeof(sn_nsdl_addr_s)); + + common_stub::coap_header = (sn_coap_hdr_ *)malloc(sizeof(sn_coap_hdr_)); + memset(common_stub::coap_header,0,sizeof(sn_coap_hdr_)); + + coap_header->uri_path_ptr = value; + coap_header->uri_path_len = sizeof(value); + + coap_header->msg_code = COAP_MSG_CODE_REQUEST_DELETE; + + common_stub::int_value = 0; + + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_HTTP) ==0); + + String *name = new String("name"); + common_stub::int_value = 0; + m2mbase_stub::string_value = new String("name"); + M2MObject *object = new M2MObject(*name); + M2MObjectInstance* instance = new M2MObjectInstance(*name,*object); + m2mbase_stub::int_value = 0; + m2mobject_stub::int_value = 1; + m2mobject_stub::bool_value = true; + m2mobject_stub::instance_list.push_back(instance); + + nsdl->_object_list.push_back(object); + + m2mbase_stub::operation = M2MBase::DELETE_ALLOWED; + m2mobjectinstance_stub::base_type = M2MBase::ObjectInstance; + + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_HTTP) ==0); + + m2mobjectinstance_stub::base_type = M2MBase::Object; + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_HTTP) ==0); + + delete instance; + delete object; + delete name; + delete m2mbase_stub::string_value; + m2mbase_stub::string_value = NULL; + + free(common_stub::coap_header); + free(address); + free(coap_header); + m2mobject_stub::instance_list.clear(); +} + +void Test_M2MNsdlInterface::test_resource_callback_reset() +{ + uint8_t value[] = {"name"}; + sn_coap_hdr_s *coap_header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(coap_header,0,sizeof(sn_coap_hdr_s)); + sn_nsdl_addr_s *address = (sn_nsdl_addr_s *)malloc(sizeof(sn_nsdl_addr_s)); + memset(address,0,sizeof(sn_nsdl_addr_s)); + + coap_header->uri_path_ptr = value; + coap_header->uri_path_len = sizeof(value); + + coap_header->msg_type = COAP_MSG_TYPE_RESET; + m2mobjectinstance_stub::base_type = M2MBase::Object; + String *name = new String("name"); + common_stub::int_value = 0; + m2mbase_stub::string_value = name; + M2MObject *object = new M2MObject(*name); + M2MObjectInstance* instance = new M2MObjectInstance(*name,*object); + M2MResource* create_resource = new M2MResource(*instance, + *name, + *name, + M2MResourceInstance::INTEGER, + M2MResource::Dynamic,false); + m2mobject_stub::int_value = 2; + m2mobject_stub::instance_list.push_back(instance); + + m2mobjectinstance_stub::resource_list.push_back(create_resource); + m2mobjectinstance_stub::int_value = 1; + + nsdl->_object_list.push_back(object); + // No response for RESET message + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_HTTP) == 1); + + + m2mobject_stub::base_type = M2MBase::ObjectInstance; + // No response for RESET message + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_HTTP) == 1); + + m2mobject_stub::base_type = M2MBase::Resource; + // No response for RESET message + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_HTTP) == 1); + + delete instance; + delete object; + delete name; + delete create_resource; + free(address); + free(coap_header); + m2mobject_stub::instance_list.clear(); + m2mobjectinstance_stub::resource_list.clear(); + //nsdl->_object_list.clear(); + /*uint8_t value[] = {"name"}; + sn_coap_hdr_s *coap_header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(coap_header,0,sizeof(sn_coap_hdr_s)); + sn_nsdl_addr_s *address = (sn_nsdl_addr_s *)malloc(sizeof(sn_nsdl_addr_s)); + memset(address,0,sizeof(sn_nsdl_addr_s)); + common_stub::coap_header = (sn_coap_hdr_ *)malloc(sizeof(sn_coap_hdr_)); + memset(common_stub::coap_header,0,sizeof(sn_coap_hdr_)); + coap_header->uri_path_ptr = value; + coap_header->uri_path_len = sizeof(value); + coap_header->msg_type = COAP_MSG_TYPE_RESET; + + String *name = new String("name"); + common_stub::int_value = 0; + m2mbase_stub::string_value = new String("name"); + M2MObject *object = new M2MObject(*name); + nsdl->_object_list.push_back(object); + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_HTTP) == 0); + + uint8_t value2[] = {"name/0"}; + coap_header->uri_path_ptr = value2; + coap_header->uri_path_len = sizeof(value2); + M2MObjectInstance* instance = new M2MObjectInstance(*name,*object); + m2mbase_stub::int_value = 0; + m2mobject_stub::int_value = 1; + m2mobject_stub::bool_value = true; + m2mobject_stub::instance_list.push_back(instance); + m2mobjectinstance_stub::base_type = M2MBase::ObjectInstance; + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_HTTP) == 0); + + uint8_t value3[] = {"name/0/1"}; + coap_header->uri_path_ptr = value3; + coap_header->uri_path_len = sizeof(value3); + M2MResource *res = new M2MResource(*instance, + "1","1", + M2MResourceInstance::INTEGER, + false); + nsdl->_object_list.clear(); + nsdl->_object_list.push_back(object); + m2mbase_stub::int_value = 0; + m2mobject_stub::int_value = 1; + m2mobject_stub::bool_value = true; + m2mobjectinstance_stub::resource_list.push_back(res); + m2mobjectinstance_stub::int_value = 0; + CHECK(nsdl->resource_callback(NULL,coap_header,address,SN_NSDL_PROTOCOL_HTTP) == 0); + + delete instance; + delete object; + delete name; + delete res; + delete m2mbase_stub::string_value; + m2mbase_stub::string_value = NULL; + + free(common_stub::coap_header); + free(address); + free(coap_header);*/ +} + + + +void Test_M2MNsdlInterface::test_process_received_data() +{ + uint8_t *data = (uint8_t*)malloc(sizeof(uint8_t)); + uint16_t data_size = sizeof(uint16_t); + sn_nsdl_addr_s *address = (sn_nsdl_addr_s *)malloc(sizeof(sn_nsdl_addr_s)); + + common_stub::int_value = 0; + + CHECK(nsdl->process_received_data(data,data_size,address) == true); + + common_stub::int_value = -1; + + CHECK(nsdl->process_received_data(data,data_size,address) == false); + + free(address); + free(data); + common_stub::clear(); +} + +void Test_M2MNsdlInterface::test_stop_timers() +{ + // Check if there is no memory leak or crash + nsdl->stop_timers(); +} + +void Test_M2MNsdlInterface::test_timer_expired() +{ + nsdl->timer_expired(M2MTimerObserver::NsdlExecution); + CHECK(nsdl->_counter_for_nsdl == 1); + + if( nsdl->_endpoint == NULL){ + nsdl->_endpoint = (sn_nsdl_ep_parameters_s*)nsdl->memory_alloc(sizeof(sn_nsdl_ep_parameters_s)); + } + nsdl->_endpoint->lifetime_ptr = (uint8_t*)malloc(sizeof(uint8_t)); + + // For checking the registration update + nsdl->timer_expired(M2MTimerObserver::Registration); + + nsdl->delete_endpoint(); + CHECK(nsdl->_endpoint == NULL); +} + +void Test_M2MNsdlInterface::test_observation_to_be_sent() +{ + Vector instance_list_ids; + M2MObject *object = new M2MObject("name"); + M2MObjectInstance* instance = new M2MObjectInstance("name",*object); + M2MResource *res = new M2MResource(*instance, + "name","name", + M2MResourceInstance::INTEGER, + false,true); + + M2MResource *res2 = new M2MResource(*instance, + "res2","res2", + M2MResourceInstance::INTEGER, + false,true); + + M2MResourceInstance* res_instance = new M2MResourceInstance("res2","res2", + M2MResourceInstance::INTEGER, + *instance); + M2MResourceInstance* res_instance_1 = new M2MResourceInstance("res2","res2", + M2MResourceInstance::INTEGER, + *instance); + m2mresource_stub::list.clear(); + m2mresource_stub::list.push_back(res_instance); + m2mresource_stub::list.push_back(res_instance_1); + m2mresource_stub::int_value = 2; + instance_list_ids.push_back(0); + + uint8_t value[] = {"value"}; + m2mresourceinstance_stub::value = (uint8_t *)malloc(sizeof(value)); + memset( m2mresourceinstance_stub::value, 0, sizeof(value)); + memcpy(m2mresourceinstance_stub::value,value,sizeof(value)); + m2mresourceinstance_stub::int_value = sizeof(value); + + m2mbase_stub::uint16_value = 321; + String *owned = new String("token"); + m2mbase_stub::string_value = owned; + + m2mresourceinstance_stub::base_type = M2MBase::Resource; + + nsdl->_nsdl_handle = (nsdl_s*)malloc(sizeof(nsdl_s)); + memset(nsdl->_nsdl_handle,0,sizeof(nsdl_s)); + sn_nsdl_oma_server_info_t * nsp_address = (sn_nsdl_oma_server_info_t *)malloc(sizeof(sn_nsdl_oma_server_info_t)); + memset(nsp_address,0,sizeof(sn_nsdl_oma_server_info_t)); + sn_nsdl_addr_s* address = (sn_nsdl_addr_s*)malloc(sizeof(sn_nsdl_addr_s)); + memset(address,0,sizeof(sn_nsdl_addr_s)); + + nsdl->_nsdl_handle->nsp_address_ptr = nsp_address; + memset(nsdl->_nsdl_handle->nsp_address_ptr,0,sizeof(sn_nsdl_oma_server_info_t)); + nsdl->_nsdl_handle->nsp_address_ptr->omalw_address_ptr = address; + + //CHECK if nothing crashes + nsdl->observation_to_be_sent(res2, 1, instance_list_ids); + + m2mresourceinstance_stub::resource_type = M2MResource::OPAQUE; + + //CHECK if nothing crashes + nsdl->observation_to_be_sent(res2, 1, instance_list_ids); + + m2mresource_stub::list.clear(); + m2mresource_stub::int_value = 0; + + //CHECK if nothing crashes + nsdl->observation_to_be_sent(res, 500, instance_list_ids); + + M2MObjectInstance *object_instance = new M2MObjectInstance("name",*object); + m2mobject_stub::int_value = 1; + m2mobject_stub::base_type = M2MBase::Object; + m2mobject_stub::inst = object_instance; + m2mobjectinstance_stub::resource_list.push_back(res); + nsdl->_object_list.push_back(object); + instance_list_ids.push_back(1); + //CHECK if nothing crashes + nsdl->observation_to_be_sent(object, 1, instance_list_ids); + nsdl->observation_to_be_sent(object, 500, instance_list_ids, true); + + //CHECK if nothing crashes + nsdl->observation_to_be_sent(object_instance, 1, instance_list_ids); + nsdl->observation_to_be_sent(object_instance, 500, instance_list_ids); + + delete owned; + owned = NULL; + + free(m2mresourceinstance_stub::value); + m2mresourceinstance_stub::value = NULL; + + m2mbase_stub::clear(); + m2mresourceinstance_stub::clear(); + m2mobjectinstance_stub::clear(); + m2mobject_stub::clear(); + m2mresource_stub::list.clear(); + delete res; + res = NULL; + + delete res2; + res2 = NULL; + + delete res_instance; + res_instance = NULL; + + delete res_instance_1; + res_instance_1 = NULL; + + + delete object_instance; + object_instance = NULL; + + delete object; + object = NULL; + + delete instance; + instance = NULL; + + free(nsp_address); + free(address); + free(nsdl->_nsdl_handle); +} + +void Test_M2MNsdlInterface::test_resource_to_be_deleted() +{ + //Checking coverage for the code + nsdl->resource_to_be_deleted("name"); +} + +void Test_M2MNsdlInterface::test_value_updated() +{ + M2MObject *object = new M2MObject("name"); + M2MObjectInstance *object_instance = new M2MObjectInstance("name",*object); + M2MResource *resource = new M2MResource(*object_instance, + "resource_name", + "resource_type", + M2MResourceInstance::INTEGER, + false); + + M2MResourceInstance *resource_instance = new M2MResourceInstance("resource_name", + "resource_type", + M2MResourceInstance::INTEGER, + *object_instance); + + + m2mobject_stub::base_type = M2MBase::Object; + m2mbase_stub::string_value = new String("name"); + m2mbase_stub::operation = M2MBase::GET_ALLOWED; + nsdl->value_updated(object,"name"); + CHECK(observer->value_update == true); + observer->value_update = false; + + m2mobjectinstance_stub::base_type = M2MBase::ObjectInstance; + + nsdl->value_updated(object_instance,"name/0"); + CHECK(observer->value_update == true); + observer->value_update = false; + + common_stub::resource = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(common_stub::resource,0, sizeof(sn_nsdl_resource_info_s)); + common_stub::resource->resource = (uint8_t*)malloc(2); + memset(common_stub::resource->resource,0, 2); + + common_stub::resource->mode = SN_GRS_STATIC; + m2mbase_stub::mode_value = M2MBase::Static; + + common_stub::resource->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s)); + memset(common_stub::resource->resource_parameters_ptr,0, sizeof(sn_nsdl_resource_parameters_s)); + + common_stub::resource->resource_parameters_ptr->observable = false; + m2mbase_stub::bool_value = true; + + m2mresourceinstance_stub::int_value = 2; + uint8_t value[] = "1"; + m2mresourceinstance_stub::value = value; + + m2mresourceinstance_stub::base_type = M2MBase::Resource; + + nsdl->value_updated(resource,"name/0/name"); + CHECK(observer->value_update == true); + observer->value_update = false; + + m2mresourceinstance_stub::clear(); + free(common_stub::resource->resource_parameters_ptr); + free(common_stub::resource->resource); + free(common_stub::resource); + common_stub::resource = NULL; + common_stub::clear(); + + m2mresourceinstance_stub::base_type = M2MBase::ResourceInstance; + + common_stub::resource = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s)); + memset(common_stub::resource,0, sizeof(sn_nsdl_resource_info_s)); + common_stub::resource->resource = (uint8_t*)malloc(2); + memset(common_stub::resource->resource,0, 2); + + common_stub::resource->mode = SN_GRS_STATIC; + m2mbase_stub::mode_value = M2MBase::Static; + + m2mresourceinstance_stub::int_value = 2; + m2mresourceinstance_stub::value = value; + + nsdl->value_updated(resource_instance,"name/0/name/0"); + CHECK(observer->value_update == true); + observer->value_update = false; + + m2mbase_stub::is_value_updated_function_set = true; + nsdl->value_updated(resource_instance,"name/0/name/0"); + CHECK(observer->value_update == false); + observer->value_update = false; + + delete m2mbase_stub::string_value; + m2mbase_stub::string_value = NULL; + + m2mobject_stub::clear(); + m2mobjectinstance_stub::clear(); + + m2mresourceinstance_stub::clear(); + + free(common_stub::resource->resource); + free(common_stub::resource); + + common_stub::resource = NULL; + common_stub::clear(); + + delete resource_instance; + delete resource; + delete object_instance; + delete object; +} + +void Test_M2MNsdlInterface::test_find_resource() +{ + m2mbase_stub::string_value = new String("name"); + M2MObject *object = new M2MObject("name"); + M2MObjectInstance *object_instance = new M2MObjectInstance("name",*object); + M2MResource *resource = new M2MResource(*object_instance, + "resource_name", + "resource_type", + M2MResourceInstance::INTEGER, + false); + + M2MResourceInstance *resource_instance = new M2MResourceInstance("name", + "resource_type", + M2MResourceInstance::INTEGER, + *object_instance); + + + m2mobject_stub::instance_list.push_back(object_instance); + m2mobjectinstance_stub::resource_list.push_back(resource); + m2mresource_stub::list.push_back(resource_instance); + + m2mobject_stub::base_type = M2MBase::Object; + + nsdl->_object_list.push_back(object); + + CHECK(nsdl->find_resource("name") != NULL); + + m2mbase_stub::int_value = 0; + + CHECK(nsdl->find_resource("name/0") != NULL); + + CHECK(nsdl->find_resource("name/0/name") != NULL); + + m2mresource_stub::bool_value = true; + + CHECK(nsdl->find_resource("name/0/name/0") != NULL); + + CHECK(nsdl->find_resource("name1") == NULL); + CHECK(nsdl->find_resource("name/1") == NULL); + CHECK(nsdl->find_resource("name/0/name1") == NULL); + CHECK(nsdl->find_resource("name/0/name/1") == NULL); + + delete m2mbase_stub::string_value; + m2mbase_stub::string_value = NULL; + + m2mobject_stub::clear(); + m2mobjectinstance_stub::clear(); + + m2mresourceinstance_stub::clear(); + m2mresource_stub::clear(); + m2mobjectinstance_stub::clear(); + m2mobject_stub::clear(); + + delete resource_instance; + delete resource; + delete object_instance; + delete object; +} + +void Test_M2MNsdlInterface::test_remove_object() +{ + String name = "name"; + M2MObject *obj = new M2MObject(name); + nsdl->_object_list.push_back(obj); + + nsdl->remove_object((M2MBase*)obj); + + CHECK(nsdl->_object_list.empty() == true); + + nsdl->_object_list.clear(); + delete obj; +} + +void Test_M2MNsdlInterface::test_add_object_to_list() +{ + M2MObject *obj = new M2MObject("name"); + nsdl->_object_list.push_back(obj); + + nsdl->add_object_to_list(obj); + CHECK(nsdl->_object_list.size() == 1); + + nsdl->_object_list.clear(); + delete obj; +} + +void Test_M2MNsdlInterface::test_send_delayed_response() +{ + String *name = new String("name"); + common_stub::int_value = 0; + m2mbase_stub::int_value = 0; + + M2MObject *object = new M2MObject(*name); + M2MObjectInstance* instance = new M2MObjectInstance(*name,*object); + nsdl->_nsdl_handle = (nsdl_s*)malloc(sizeof(nsdl_s)); + memset(nsdl->_nsdl_handle,0,sizeof(nsdl_s)); + + sn_nsdl_oma_server_info_t * nsp_address = (sn_nsdl_oma_server_info_t *)malloc(sizeof(sn_nsdl_oma_server_info_t)); + memset(nsp_address,0,sizeof(sn_nsdl_oma_server_info_t)); + sn_nsdl_addr_s* address = (sn_nsdl_addr_s*)malloc(sizeof(sn_nsdl_addr_s)); + memset(address,0,sizeof(sn_nsdl_addr_s)); + + M2MResource* resource = new M2MResource(*instance, + *name, + *name, + M2MResourceInstance::INTEGER, + M2MResource::Dynamic, + false); + + uint8_t val[] = {"name"}; + m2mresource_stub::delayed_token = (uint8_t*)malloc(sizeof(val)); + memcpy(m2mresource_stub::delayed_token,val,sizeof(val)); + m2mresource_stub::delayed_token_len = sizeof(val); + + m2mresourceinstance_stub::base_type = M2MBase::Resource; + + nsdl->_nsdl_handle->nsp_address_ptr = nsp_address; + memset(nsdl->_nsdl_handle->nsp_address_ptr,0,sizeof(sn_nsdl_oma_server_info_t)); + nsdl->_nsdl_handle->nsp_address_ptr->omalw_address_ptr = address; + + nsdl->send_delayed_response(resource); + + free(nsp_address); + free(address); + free(nsdl->_nsdl_handle); + + delete object; + delete name; + name = NULL; + delete instance; + instance = NULL; + delete resource; + resource = NULL; + free(m2mresource_stub::delayed_token); + m2mresource_stub::delayed_token = NULL; + m2mresource_stub::delayed_token_len = 0; +} + +void Test_M2MNsdlInterface::test_get_nsdl_handle() +{ + CHECK(nsdl->get_nsdl_handle() == nsdl->_nsdl_handle); +} + +void Test_M2MNsdlInterface::test_endpoint_name() +{ + String endpoint = "test"; + nsdl->_endpoint_name = endpoint; + CHECK(nsdl->endpoint_name() == endpoint); +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mnsdlinterface/test_m2mnsdlinterface.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mnsdlinterface/test_m2mnsdlinterface.h new file mode 100755 index 0000000000..dcbb77ef41 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mnsdlinterface/test_m2mnsdlinterface.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TEST_M2M_NSDL_INTERFACE_H +#define TEST_M2M_NSDL_INTERFACE_H + +#include "m2mnsdlinterface.h" +#include "common_stub.h" + +class TestObserver; + +class Test_M2MNsdlInterface +{ +public: + Test_M2MNsdlInterface(); + + virtual ~Test_M2MNsdlInterface(); + + void test_create_endpoint(); + + void test_delete_endpoint(); + + void test_create_nsdl_list_structure(); + + void test_delete_nsdl_resource(); + + void test_create_bootstrap_resource(); + + void test_send_register_message(); + + void test_send_update_registration(); + + void test_send_unregister_message(); + + void test_memory_alloc(); + + void test_memory_free(); + + void test_send_to_server_callback(); + + void test_received_from_server_callback(); + + void test_resource_callback(); + + void test_resource_callback_get(); + + void test_resource_callback_put(); + + void test_resource_callback_post(); + + void test_resource_callback_delete(); + + void test_resource_callback_reset(); + + void test_bootstrap_done_callback(); + + void test_process_received_data(); + + void test_stop_timers(); + + void test_timer_expired(); + + void test_observation_to_be_sent(); + + void test_resource_to_be_deleted(); + + void test_value_updated(); + + void test_find_resource(); + + void test_remove_object(); + + void test_add_object_to_list(); //Special: Would be too difficult to test in normal ways + + void test_send_delayed_response(); + + void test_get_nsdl_handle(); + + void test_endpoint_name(); + + M2MNsdlInterface* nsdl; + + TestObserver *observer; +}; + +#endif // TEST_M2M_NSDL_INTERFACE_H diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobject/CMakeLists.txt b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobject/CMakeLists.txt new file mode 100644 index 0000000000..92df2281b0 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobject/CMakeLists.txt @@ -0,0 +1,30 @@ +if(TARGET_LIKE_LINUX) +include("../includes.txt") +add_executable(m2mobject + "main.cpp" + "m2mobjecttest.cpp" + "test_m2mobject.cpp" + "../stub/m2mbase_stub.cpp" + "../stub/m2mresource_stub.cpp" + "../stub/m2mresourceinstance_stub.cpp" + "../stub/m2mobjectinstance_stub.cpp" + "../stub/m2mtlvserializer_stub.cpp" + "../stub/m2mtlvdeserializer_stub.cpp" + "../stub/m2mreporthandler_stub.cpp" + "../stub/common_stub.cpp" + "../stub/m2mstring_stub.cpp" + "../stub/m2mtlvserializer_stub.cpp" + "../../../../source/m2mobject.cpp" +) +target_link_libraries(m2mobject + CppUTest + CppUTestExt +) +set_target_properties(m2mobject +PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" + LINK_FLAGS "${UTEST_LINK_FLAGS}") + +set(binary "m2mobject") +add_test(m2mobject ${binary}) + +endif() diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobject/m2mobjecttest.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobject/m2mobjecttest.cpp new file mode 100644 index 0000000000..228494e8b9 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobject/m2mobjecttest.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//CppUTest includes should be after your and system includes +#include "CppUTest/TestHarness.h" +#include "test_m2mobject.h" + +TEST_GROUP(M2MObject) +{ + Test_M2MObject* m2m_object; + + void setup() + { + m2m_object = new Test_M2MObject(); + } + void teardown() + { + delete m2m_object; + } +}; + +TEST(M2MObject, Create) +{ + CHECK(m2m_object != NULL); +} + +TEST(M2MObject, base_type) +{ + m2m_object->test_base_type(); +} + +TEST(M2MObject, copy_constructor) +{ + m2m_object->test_copy_constructor(); +} + +TEST(M2MObject, create_object_instance) +{ + m2m_object->test_create_object_instance(); +} + +TEST(M2MObject, remove_object_instance) +{ + m2m_object->test_remove_object_instance(); +} + +TEST(M2MObject, object_instance) +{ + m2m_object->test_object_instance(); +} + +TEST(M2MObject, instance_count) +{ + m2m_object->test_instance_count(); +} + +TEST(M2MObject, instances) +{ + m2m_object->test_instances(); +} + +TEST(M2MObject, handle_get_request) +{ + m2m_object->test_handle_get_request(); +} + +TEST(M2MObject, handle_put_request) +{ + m2m_object->test_handle_put_request(); +} + +TEST(M2MObject, handle_post_request) +{ + m2m_object->test_handle_post_request(); +} + +TEST(M2MObject, notification_update) +{ + m2m_object->test_notification_update(); +} + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobject/main.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobject/main.cpp new file mode 100644 index 0000000000..13513a3fc9 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobject/main.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP( M2MObject); diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobject/test_m2mobject.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobject/test_m2mobject.cpp new file mode 100755 index 0000000000..e9b5e8feae --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobject/test_m2mobject.cpp @@ -0,0 +1,874 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include "test_m2mobject.h" +#include "m2mobjectinstance_stub.h" +#include "m2mresource_stub.h" +#include "m2mbase_stub.h" +#include "common_stub.h" +#include "m2mtlvdeserializer_stub.h" +#include "m2mtlvserializer_stub.h" +#include "m2mreporthandler_stub.h" + +class TestReportObserver : public M2MReportObserver{ +public : + TestReportObserver() {} + ~TestReportObserver() {} + void observation_to_be_sent(m2m::Vector,bool){ } +}; + +class Handler : public M2MObservationHandler { + +public: + + Handler(){} + ~Handler(){} + void observation_to_be_sent(M2MBase *, uint16_t, m2m::Vector,bool){ + visited = true; + } + void send_delayed_response(M2MBase *){} + void resource_to_be_deleted(const String &){visited=true;} + void remove_object(M2MBase *){visited = true;} + void value_updated(M2MBase *,const String&){visited = true;} + + void clear() {visited = false;} + bool visited; +}; + +Test_M2MObject::Test_M2MObject() +{ + handler = new Handler(); + object = new M2MObject("name"); +} + +Test_M2MObject::~Test_M2MObject() +{ + m2mobjectinstance_stub::clear(); + m2mresource_stub::clear(); + m2mbase_stub::clear(); + m2mbase_stub::string_value = new String("name"); + m2mtlvdeserializer_stub::clear(); + m2mtlvserializer_stub::clear(); + delete object; + delete handler; + delete m2mbase_stub::string_value; + m2mbase_stub::string_value = NULL; +} + +void Test_M2MObject::test_copy_constructor() +{ + String *name = new String("name"); + m2mbase_stub::string_value = name; + + M2MObject* copy = new M2MObject(*name); + M2MObjectInstance *ins = new M2MObjectInstance("name",*object); + copy->set_instance_id(0); + copy->_instance_list.push_back(ins); + + M2MObject* copy1 = new M2MObject(*copy); + + CHECK(1 == copy1->_instance_list.size()); + + delete copy; + delete copy1; + delete name; + name = NULL; +} + +void Test_M2MObject::test_create_object_instance() +{ + m2mbase_stub::name_id_value = 1; + CHECK(object->create_object_instance() != NULL); +} + +void Test_M2MObject::test_remove_object_instance() +{ + m2mbase_stub::string_value = new String("name"); + + M2MObjectInstance *ins = new M2MObjectInstance("name",*object); + object->set_instance_id(0); + object->_instance_list.push_back(ins); + + CHECK(true == object->remove_object_instance(0)); + + CHECK(false == object->remove_object_instance(0)); + + delete m2mbase_stub::string_value; +} + +void Test_M2MObject::test_object_instance() +{ + String *test = new String("name"); + M2MObjectInstance *ins = new M2MObjectInstance(*test,*object); + object->set_instance_id(0); + object->_instance_list.push_back(ins); + + m2mbase_stub::string_value = test; + + M2MObjectInstance *obj = object->object_instance(0); + + CHECK(obj != NULL); + CHECK(0 == obj->name().compare(0,test->size(),*test)); + + delete test; + test = NULL; +} + +void Test_M2MObject::test_instances() +{ + String *test = new String("name"); + M2MObjectInstance *ins = new M2MObjectInstance(*test,*object); + ins->set_instance_id(0); + object->_instance_list.push_back(ins); + + M2MObjectInstance *ins1 = new M2MObjectInstance(*test,*object); + ins1->set_instance_id(1); + object->_instance_list.push_back(ins1); + + m2mbase_stub::string_value = test; + + M2MObjectInstanceList list = object->instances(); + + M2MObjectInstance *obj = list[0]; + CHECK(2 == list.size()); + CHECK(0 == obj->name().compare(0,test->size(),*test)); + + delete test; + test = NULL; +} + +void Test_M2MObject::test_instance_count() +{ + String test = "name"; + M2MObjectInstance *ins = new M2MObjectInstance(test,*object); + object->set_instance_id(0); + object->_instance_list.push_back(ins); + + M2MObjectInstance *ins1 = new M2MObjectInstance(test,*object); + object->set_instance_id(1); + object->_instance_list.push_back(ins1); + + CHECK(2 == object->instance_count()); + + object->_instance_list.clear(); + delete ins; + delete ins1; +} + +void Test_M2MObject::test_base_type() +{ + CHECK(M2MBase::Object == object->base_type()); +} + +void Test_M2MObject::test_handle_get_request() +{ + M2MObjectInstance *ins = new M2MObjectInstance("name",*object); + object->set_instance_id(0); + object->_instance_list.push_back(ins); + + uint8_t value[] = {"name"}; + sn_coap_hdr_s *coap_header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(coap_header, 0, sizeof(sn_coap_hdr_s)); + + coap_header->uri_path_ptr = value; + coap_header->uri_path_len = sizeof(value); + + coap_header->msg_code = COAP_MSG_CODE_REQUEST_GET; + + String *name = new String("name"); + common_stub::int_value = 0; + m2mbase_stub::string_value = name; + + m2mbase_stub::operation = M2MBase::GET_ALLOWED; + m2mbase_stub::uint8_value = 200; + + common_stub::coap_header = (sn_coap_hdr_ *)malloc(sizeof(sn_coap_hdr_)); + memset(common_stub::coap_header,0,sizeof(sn_coap_hdr_)); + + m2mtlvserializer_stub::uint8_value = (uint8_t*)malloc(1); + + coap_header->token_ptr = (uint8_t*)malloc(sizeof(value)); + memcpy(coap_header->token_ptr, value, sizeof(value)); + + coap_header->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + coap_header->options_list_ptr->observe = 0; + + + coap_header->content_type_ptr = (uint8_t*)malloc(1); + coap_header->content_type_len = 1; + *coap_header->content_type_ptr = 110; + + CHECK(object->handle_get_request(NULL,coap_header,handler) != NULL); + + if(coap_header->content_type_ptr) { + free(coap_header->content_type_ptr); + coap_header->content_type_ptr = NULL; + } + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + // Not OMA TLV or JSON + m2mbase_stub::uint8_value = 110; + CHECK(object->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + // OMA TLV + m2mbase_stub::uint8_value = 99; + CHECK(object->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + // OMA JSON + m2mbase_stub::uint8_value = 100; + CHECK(object->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + coap_header->options_list_ptr->observe = 1; + + uint8_t obs = 0; + coap_header->options_list_ptr->observe_ptr = (uint8_t*)malloc(sizeof(obs)); + memcpy(coap_header->options_list_ptr->observe_ptr,&obs,sizeof(obs)); + coap_header->options_list_ptr->observe_len = 0; + m2mbase_stub::uint16_value = 0x1c1c; + m2mbase_stub::uint8_value = 99; + m2mbase_stub::bool_value = true; + + CHECK(object->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + + if(common_stub::coap_header->options_list_ptr->observe_ptr) { + free(common_stub::coap_header->options_list_ptr->observe_ptr); + common_stub::coap_header->options_list_ptr->observe_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + + m2mbase_stub::uint16_value = 10; + CHECK(object->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + + if(common_stub::coap_header->options_list_ptr->observe_ptr) { + free(common_stub::coap_header->options_list_ptr->observe_ptr); + common_stub::coap_header->options_list_ptr->observe_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + // Not observable + m2mbase_stub::bool_value = false; + CHECK(object->handle_get_request(NULL,coap_header,handler) != NULL); + + m2mbase_stub::bool_value = true; + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + + if(common_stub::coap_header->options_list_ptr->observe_ptr) { + free(common_stub::coap_header->options_list_ptr->observe_ptr); + common_stub::coap_header->options_list_ptr->observe_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + coap_header->options_list_ptr->observe_len = 1; + + CHECK(object->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + + if(common_stub::coap_header->options_list_ptr->observe_ptr) { + free(common_stub::coap_header->options_list_ptr->observe_ptr); + common_stub::coap_header->options_list_ptr->observe_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + + obs = 1; + memcpy(coap_header->options_list_ptr->observe_ptr,&obs,sizeof(obs)); + CHECK(object->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + + if(common_stub::coap_header->options_list_ptr->observe_ptr) { + free(common_stub::coap_header->options_list_ptr->observe_ptr); + common_stub::coap_header->options_list_ptr->observe_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + m2mbase_stub::operation = M2MBase::NOT_ALLOWED; + CHECK(object->handle_get_request(NULL,coap_header,handler) != NULL); + + CHECK(object->handle_get_request(NULL,NULL,handler) != NULL); + + if(coap_header->token_ptr) { + free(coap_header->token_ptr); + coap_header->token_ptr = NULL; + } + if(coap_header->content_type_ptr) { + free(coap_header->content_type_ptr); + coap_header->content_type_ptr = NULL; + } + if(coap_header->options_list_ptr->observe_ptr) { + free(coap_header->options_list_ptr->observe_ptr); + coap_header->options_list_ptr->observe_ptr = NULL; + } + if(coap_header->options_list_ptr) { + free(coap_header->options_list_ptr); + coap_header->options_list_ptr = NULL; + } + + if(common_stub::coap_header){ + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + free(common_stub::coap_header); + common_stub::coap_header = NULL; + } + free(coap_header); + coap_header = NULL; + + delete name; + name = NULL; + + if(m2mtlvserializer_stub::uint8_value) { + free(m2mtlvserializer_stub::uint8_value); + } + m2mtlvserializer_stub::clear(); + + m2mbase_stub::clear(); + common_stub::clear(); + + object->_instance_list.clear(); + delete ins; +} + +void Test_M2MObject::test_handle_put_request() +{ + uint8_t value[] = {"name"}; + bool execute_value_updated = false; + sn_coap_hdr_s *coap_header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(coap_header, 0, sizeof(sn_coap_hdr_s)); + sn_coap_hdr_s * coap_response = NULL; + + coap_header->uri_path_ptr = value; + coap_header->uri_path_len = sizeof(value); + + coap_header->msg_code = COAP_MSG_CODE_REQUEST_PUT; + + String *name = new String("name"); + common_stub::int_value = 0; + m2mbase_stub::string_value = name; + + m2mbase_stub::operation = M2MBase::PUT_ALLOWED; + m2mbase_stub::uint8_value = 200; + + common_stub::coap_header = (sn_coap_hdr_ *)malloc(sizeof(sn_coap_hdr_)); + memset(common_stub::coap_header,0,sizeof(sn_coap_hdr_)); + + coap_header->payload_ptr = (uint8_t*)malloc(1); + + CHECK(object->handle_put_request(NULL,coap_header,handler,execute_value_updated) != NULL); + free(coap_header->payload_ptr); + coap_header->payload_ptr = NULL; + + CHECK(object->handle_put_request(NULL,coap_header,handler,execute_value_updated) != NULL); + + coap_header->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + coap_header->options_list_ptr->uri_query_ptr = value; + coap_header->options_list_ptr->uri_query_len = sizeof(value); + + coap_header->content_type_ptr = (uint8_t*)malloc(1); + coap_header->content_type_len = 1; + *coap_header->content_type_ptr = 99; + m2mtlvdeserializer_stub::bool_value = true; + + m2mbase_stub::bool_value = false; + + CHECK(object->handle_put_request(NULL,coap_header,handler,execute_value_updated) != NULL); + + m2mtlvdeserializer_stub::bool_value = false; + + CHECK(object->handle_put_request(NULL,coap_header,handler, execute_value_updated) != NULL); + + *coap_header->content_type_ptr = 100; + + CHECK(object->handle_put_request(NULL,coap_header,handler, execute_value_updated) != NULL); + + m2mbase_stub::bool_value = true; + + CHECK(object->handle_put_request(NULL,coap_header,handler, execute_value_updated) != NULL); + + m2mbase_stub::operation = M2MBase::NOT_ALLOWED; + + CHECK(object->handle_put_request(NULL,coap_header,handler, execute_value_updated) != NULL); + + CHECK(object->handle_put_request(NULL,NULL,handler, execute_value_updated) != NULL); + + m2mbase_stub::operation = M2MBase::PUT_ALLOWED; + + + + + free(coap_header->payload_ptr); + coap_header->payload_ptr = NULL; + coap_response = object->handle_put_request(NULL,coap_header,handler,execute_value_updated); + CHECK(coap_response != NULL); + CHECK(coap_response->msg_code == COAP_MSG_CODE_RESPONSE_CHANGED); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + m2mbase_stub::bool_value = false; + coap_response = object->handle_put_request(NULL,coap_header,handler,execute_value_updated); + CHECK(coap_response != NULL); + CHECK(coap_response->msg_code == COAP_MSG_CODE_RESPONSE_BAD_REQUEST); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + free(coap_header->options_list_ptr); + coap_header->options_list_ptr = NULL; + coap_response = object->handle_put_request(NULL,coap_header,handler,execute_value_updated); + CHECK(coap_response != NULL); + CHECK(coap_response->msg_code == COAP_MSG_CODE_RESPONSE_BAD_REQUEST); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + free(coap_header->content_type_ptr); + free(coap_header->options_list_ptr); + free(common_stub::coap_header); + delete name; + free(coap_header); + + m2mtlvdeserializer_stub::clear(); + common_stub::clear(); + m2mbase_stub::clear(); +} + +void Test_M2MObject::test_handle_post_request() +{ + uint8_t value[] = {"name"}; + bool execute_value_updated = false; + sn_coap_hdr_s *coap_header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(coap_header, 0, sizeof(sn_coap_hdr_s)); + + coap_header->uri_path_ptr = value; + coap_header->uri_path_len = sizeof(value); + + coap_header->msg_code = COAP_MSG_CODE_REQUEST_POST; + + String *name = new String("name"); + common_stub::int_value = 0; + m2mbase_stub::string_value = name; + + m2mbase_stub::operation = M2MBase::POST_ALLOWED; + m2mbase_stub::uint8_value = 200; + + common_stub::coap_header = (sn_coap_hdr_ *)malloc(sizeof(sn_coap_hdr_)); + memset(common_stub::coap_header,0,sizeof(sn_coap_hdr_)); + + m2mbase_stub::bool_value = false; + + sn_coap_hdr_s * coap_response = NULL; + m2mbase_stub::uint8_value = 99; + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + + + m2mbase_stub::uint8_value = 100; + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + + coap_header->payload_ptr = (uint8_t*)malloc(1); + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + + m2mbase_stub::uint8_value = 99; + + object->_max_instance_count = 0; + + String *test = new String("name"); + M2MObjectInstance *ins = new M2MObjectInstance(*test,*object); + ins->set_instance_id(0); + object->_instance_list.push_back(ins); + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + + object->remove_object_instance(0); + delete test; + + object->_max_instance_count = 65535; + + m2mbase_stub::uint8_value = 0; + + coap_header->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + coap_header->options_list_ptr->uri_query_ptr = value; + coap_header->options_list_ptr->uri_query_len = sizeof(value); + + coap_header->content_type_ptr = (uint8_t*)malloc(1); + coap_header->content_type_len = 1; + *coap_header->content_type_ptr = 99; + m2mtlvdeserializer_stub::is_object_bool_value = true; + m2mtlvdeserializer_stub::bool_value = false; + m2mbase_stub::bool_value = false; + + m2mtlvdeserializer_stub::error = M2MTLVDeserializer::None; + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + if (coap_response->options_list_ptr) { + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + + m2mbase_stub::operation = M2MBase::POST_ALLOWED; + m2mtlvdeserializer_stub::is_object_bool_value = true; + m2mtlvdeserializer_stub::bool_value = false; + m2mtlvdeserializer_stub::int_value = 10; + m2mbase_stub::bool_value = false; + + m2mtlvdeserializer_stub::error = M2MTLVDeserializer::NotAllowed; + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + + m2mbase_stub::operation = M2MBase::POST_ALLOWED; + m2mtlvdeserializer_stub::is_object_bool_value = false; + m2mtlvdeserializer_stub::bool_value = true; + m2mbase_stub::bool_value = false; + m2mtlvdeserializer_stub::error = M2MTLVDeserializer::None; + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + + m2mbase_stub::operation = M2MBase::POST_ALLOWED; + m2mtlvdeserializer_stub::is_object_bool_value = false; + m2mtlvdeserializer_stub::bool_value = true; + m2mbase_stub::bool_value = false; + m2mtlvdeserializer_stub::error = M2MTLVDeserializer::NotFound; + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + + m2mbase_stub::operation = M2MBase::POST_ALLOWED; + m2mtlvdeserializer_stub::bool_value = false; + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + + + *coap_header->content_type_ptr = 100; + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + + + m2mbase_stub::bool_value = true; + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + + + m2mbase_stub::operation = M2MBase::NOT_ALLOWED; + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + coap_response = object->handle_post_request(NULL,NULL,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + + m2mbase_stub::operation = M2MBase::POST_ALLOWED; + m2mtlvdeserializer_stub::int_value = 0; + m2mtlvdeserializer_stub::is_object_bool_value = true; + *coap_header->content_type_ptr = 99; + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + + free(coap_header->content_type_ptr); + free(coap_header->options_list_ptr); + free(coap_header->payload_ptr); + free(common_stub::coap_header); + delete name; + free(coap_header); + + m2mtlvdeserializer_stub::clear(); + common_stub::clear(); + m2mbase_stub::clear(); +} + +void Test_M2MObject::test_notification_update() +{ + TestReportObserver obs; + m2mbase_stub::report = new M2MReportHandler(obs); + m2mbase_stub::bool_value = true; + + object->notification_update(0); + + delete m2mbase_stub::report; + m2mbase_stub::report = NULL; +} + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobject/test_m2mobject.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobject/test_m2mobject.h new file mode 100755 index 0000000000..90a95ab645 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobject/test_m2mobject.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TEST_M2M_OBJECT_H +#define TEST_M2M_OBJECT_H + +#include "m2mobject.h" + +class Handler; + +class Test_M2MObject +{ +public: + Test_M2MObject(); + virtual ~Test_M2MObject(); + + void test_copy_constructor(); + + void test_create_object_instance(); + + void test_remove_object_instance(); + + void test_object_instance(); + + void test_instances(); + + void test_instance_count(); + + void test_base_type(); + + void test_handle_get_request(); + + void test_handle_put_request(); + + void test_handle_post_request(); + + void test_notification_update(); + + M2MObject* object; + + Handler* handler; +}; + +#endif // TEST_M2M_OBJECT_H diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobjectinstance/CMakeLists.txt b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobjectinstance/CMakeLists.txt new file mode 100644 index 0000000000..175b5e377a --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobjectinstance/CMakeLists.txt @@ -0,0 +1,28 @@ +if(TARGET_LIKE_LINUX) +include("../includes.txt") +add_executable(m2mobjectinstance + "main.cpp" + "m2mobjectinstancetest.cpp" + "test_m2mobjectinstance.cpp" + "../stub/m2mbase_stub.cpp" + "../stub/m2mbase_stub.cpp" + "../stub/m2mresource_stub.cpp" + "../stub/m2mresourceinstance_stub.cpp" + "../stub/common_stub.cpp" + "../stub/m2mtlvserializer_stub.cpp" + "../stub/m2mtlvdeserializer_stub.cpp" + "../stub/m2mreporthandler_stub.cpp" + "../stub/m2mstring_stub.cpp" + "../../../../source/m2mobjectinstance.cpp" +) +target_link_libraries(m2mobjectinstance + CppUTest + CppUTestExt +) +set_target_properties(m2mobjectinstance +PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" + LINK_FLAGS "${UTEST_LINK_FLAGS}") +set(binary "m2mobjectinstance") +add_test(m2mobjectinstance ${binary}) + +endif() diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobjectinstance/m2mobjectinstancetest.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobjectinstance/m2mobjectinstancetest.cpp new file mode 100644 index 0000000000..e75551bfbc --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobjectinstance/m2mobjectinstancetest.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//CppUTest includes should be after your and system includes +#include "CppUTest/TestHarness.h" +#include "test_m2mobjectinstance.h" + +TEST_GROUP(M2MObjectInstance) +{ + Test_M2MObjectInstance* m2m_object_instance; + + void setup() + { + m2m_object_instance = new Test_M2MObjectInstance(); + } + void teardown() + { + delete m2m_object_instance; + } +}; + +TEST(M2MObjectInstance, Create) +{ + CHECK(m2m_object_instance != NULL); +} + +TEST(M2MObjectInstance, copy_constructor) +{ + m2m_object_instance->test_copy_constructor(); +} + +TEST(M2MObjectInstance, create_static_resource) +{ + m2m_object_instance->test_create_static_resource(); +} + +TEST(M2MObjectInstance, create_static_resource_instance) +{ + m2m_object_instance->test_create_static_resource_instance(); +} + +TEST(M2MObjectInstance, create_dynamic_resource) +{ + m2m_object_instance->test_create_dynamic_resource(); +} + +TEST(M2MObjectInstance, create_dynamic_resource_instance) +{ + m2m_object_instance->test_create_dynamic_resource_instance(); +} + +TEST(M2MObjectInstance, remove_resource) +{ + m2m_object_instance->test_remove_resource(); +} + +TEST(M2MObjectInstance, remove_resource_instance) +{ + m2m_object_instance->test_remove_resource_instance(); +} + +TEST(M2MObjectInstance, resource) +{ + m2m_object_instance->test_resource(); +} + +TEST(M2MObjectInstance, resources) +{ + m2m_object_instance->test_resources(); +} + +TEST(M2MObjectInstance, resource_count) +{ + m2m_object_instance->test_resource_count(); +} + +TEST(M2MObjectInstance, total_resource_count) +{ + m2m_object_instance->test_total_resource_count(); +} + +TEST(M2MObjectInstance, base_type) +{ + m2m_object_instance->test_base_type(); +} + +TEST(M2MObjectInstance, handle_get_request) +{ + m2m_object_instance->test_handle_get_request(); +} + +TEST(M2MObjectInstance, handle_put_request) +{ + m2m_object_instance->test_handle_put_request(); +} + +TEST(M2MObjectInstance, handle_post_request) +{ + m2m_object_instance->test_handle_post_request(); +} + +TEST(M2MObjectInstance, notification_update) +{ + m2m_object_instance->test_notification_update(); +} + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobjectinstance/main.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobjectinstance/main.cpp new file mode 100644 index 0000000000..8815a25a91 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobjectinstance/main.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP( M2MObjectInstance); diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobjectinstance/test_m2mobjectinstance.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobjectinstance/test_m2mobjectinstance.cpp new file mode 100755 index 0000000000..a7b8477258 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobjectinstance/test_m2mobjectinstance.cpp @@ -0,0 +1,1162 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include "test_m2mobjectinstance.h" +#include "m2mresource_stub.h" +#include "common_stub.h" +#include "m2mresourceinstance_stub.h" +#include "m2mbase_stub.h" +#include "m2mtlvdeserializer_stub.h" +#include "m2mtlvserializer_stub.h" +#include "m2mreporthandler_stub.h" + +// Length is 65 +String max_length = "65656565656565656565656565656565656565656565656565656565656565656"; + +class Handler : public M2MObservationHandler { + +public: + + Handler(){} + ~Handler(){} + void observation_to_be_sent(M2MBase *, uint16_t, m2m::Vector,bool){ + visited = true; + } + void send_delayed_response(M2MBase *){} + void resource_to_be_deleted(const String &){visited=true;} + void remove_object(M2MBase *){visited = true;} + void value_updated(M2MBase *,const String&){visited = true;} + + void clear() {visited = false;} + bool visited; +}; + +class TestReportObserver : public M2MReportObserver{ +public : + TestReportObserver() {} + ~TestReportObserver() {} + void observation_to_be_sent(m2m::Vector,bool){ } +}; + +class Callback : public M2MObjectCallback { + +public: + + Callback() : visited(false){} + ~Callback(){} + void notification_update(uint16_t obj_instance_id) { + visited = true; + } + + void clear() {visited = false;} + bool visited; +}; + +Test_M2MObjectInstance::Test_M2MObjectInstance() +{ + handler = new Handler(); + callback = new Callback(); + object = new M2MObjectInstance("name",*callback); +} + +void Test_M2MObjectInstance::test_copy_constructor() +{ + M2MResource *res = new M2MResource(*object,"name","type",M2MResourceInstance::STRING,M2MBase::Static); + m2mbase_stub::string_value = new String("name"); + object->_resource_list.push_back(res); + + M2MObjectInstance* copy = new M2MObjectInstance(*object); + + CHECK(1 == copy->_resource_list.size()); + delete copy; +} + + +Test_M2MObjectInstance::~Test_M2MObjectInstance() +{ + delete object; + delete callback; + delete handler; + delete m2mbase_stub::string_value; + m2mresource_stub::clear(); + m2mbase_stub::clear(); + m2mtlvdeserializer_stub::clear(); + m2mtlvserializer_stub::clear(); + +} + +void Test_M2MObjectInstance::test_create_static_resource() +{ + m2mbase_stub::string_value = new String("name"); + u_int8_t value[] = {"value"}; + + m2mbase_stub::bool_value = true; + + m2mbase_stub::uint8_value = 99; + M2MResource * res = object->create_static_resource("name","type",M2MResourceInstance::STRING,value,(u_int32_t)sizeof(value),false); + + CHECK(res != NULL); + res = object->create_static_resource("name2","type",M2MResourceInstance::STRING,value,(u_int32_t)sizeof(value),true); + + CHECK(res != NULL); + CHECK(2 == object->_resource_list.size()); + + res = object->create_static_resource("","type",M2MResourceInstance::STRING,value,(u_int32_t)sizeof(value)); + CHECK(res == NULL); + + res = object->create_static_resource(max_length,"type",M2MResourceInstance::STRING,value,(u_int32_t)sizeof(value)); + CHECK(res == NULL); +} + +void Test_M2MObjectInstance::test_create_static_resource_instance() +{ + m2mbase_stub::string_value = new String("name"); + u_int8_t value[] = {"value"}; + + m2mbase_stub::bool_value = true; + m2mresource_stub::bool_value = true; + m2mbase_stub::uint8_value = 99; + M2MResourceInstance *ins = object->create_static_resource_instance("name","type", + M2MResourceInstance::STRING, + value,(u_int32_t)sizeof(value), + 0); + + CHECK(ins != NULL); + CHECK(1 == object->_resource_list.size()); + + delete ins; + + ins = object->create_static_resource_instance("name","type", + M2MResourceInstance::STRING, + value,(u_int32_t)sizeof(value), + 1); + + CHECK(ins != NULL); + CHECK(1 == object->_resource_list.size()); + + delete ins; + + ins = object->create_static_resource_instance("","type", + M2MResourceInstance::STRING,value, + (u_int32_t)sizeof(value),0); + CHECK(ins == NULL); + + delete ins; + + ins = object->create_static_resource_instance(max_length,"type", + M2MResourceInstance::STRING,value, + (u_int32_t)sizeof(value),0); + CHECK(ins == NULL); +} + +void Test_M2MObjectInstance::test_create_dynamic_resource_instance() +{ + m2mbase_stub::string_value = new String("name"); + + m2mresource_stub::bool_value = true; + m2mbase_stub::uint8_value = 99; + + M2MResourceInstance * ins = object->create_dynamic_resource_instance("name","type", + M2MResourceInstance::STRING, + false,0); + CHECK(ins != NULL); + CHECK(1 == object->_resource_list.size()); + + delete ins; + + ins = object->create_dynamic_resource_instance("name","type", + M2MResourceInstance::STRING, + false,1); + CHECK(ins != NULL); + CHECK(1 == object->_resource_list.size()); + + delete ins; + + ins = object->create_dynamic_resource_instance("","type", + M2MResourceInstance::STRING, + false,1); + + CHECK(ins == NULL); + + ins = object->create_dynamic_resource_instance(max_length,"type", + M2MResourceInstance::STRING, + false,1); + CHECK(ins == NULL); +} + +void Test_M2MObjectInstance::test_create_dynamic_resource() +{ + m2mbase_stub::string_value = new String("name"); + m2mbase_stub::uint8_value = 99; + + M2MResource * res = object->create_dynamic_resource("name","type",M2MResourceInstance::STRING,false,false); + CHECK(res != NULL); + CHECK(1 == object->_resource_list.size()); + + res = object->create_dynamic_resource("multiple","type",M2MResourceInstance::STRING,false,true); + CHECK(res != NULL); + CHECK(2 == object->_resource_list.size()); + + M2MResource * res1 = object->create_dynamic_resource("name1","type",M2MResourceInstance::STRING,false,false); + CHECK(res1 != NULL); + CHECK(3 == object->_resource_list.size()); + + M2MResource * res2 = object->create_dynamic_resource("","type",M2MResourceInstance::STRING,false,false); + CHECK(res2 == NULL); + + M2MResource * res3 = object->create_dynamic_resource(max_length,"type",M2MResourceInstance::STRING,false,false); + CHECK(res3 == NULL); +} + +void Test_M2MObjectInstance::test_remove_resource() +{ + CHECK(false == object->remove_resource("name")); + + M2MResource *res = new M2MResource(*object,"name","type",M2MResourceInstance::STRING,M2MBase::Static,true); + object->_resource_list.push_back(res); + + m2mbase_stub::string_value = new String("name"); + m2mbase_stub::int_value = 0; + m2mbase_stub::void_value = malloc(20); + + m2mresource_stub::bool_value = true; + CHECK(true == object->remove_resource("name")); + CHECK(0 == object->_resource_list.size()); + + free(m2mbase_stub::void_value); +} + +void Test_M2MObjectInstance::test_remove_resource_instance() +{ + CHECK(false == object->remove_resource_instance("name",0)); + + M2MResource *res = new M2MResource(*object,"name","type",M2MResourceInstance::STRING,M2MBase::Static,true); + object->_resource_list.push_back(res); + + m2mbase_stub::string_value = new String("name"); + m2mbase_stub::int_value = 0; + m2mbase_stub::void_value = malloc(20); + + m2mresource_stub::bool_value = true; + + M2MResourceInstance *ins = new M2MResourceInstance("name","type",M2MResourceInstance::STRING,*object); + + m2mresource_stub::list.push_back(ins); + + CHECK(true == object->remove_resource_instance("name",0)); + CHECK(0 == object->_resource_list.size()); + + free(m2mbase_stub::void_value); + + delete ins; + ins = NULL; +} + + +void Test_M2MObjectInstance::test_resource() +{ + M2MResource *res = new M2MResource(*object,"name","type",M2MResourceInstance::STRING,M2MBase::Static,true); + object->_resource_list.push_back(res); + + m2mbase_stub::string_value = new String("name"); + m2mbase_stub::int_value = 0; + + M2MResource *result = object->resource("name"); + CHECK(result != NULL); + + res = new M2MResource(*object,"name","type",M2MResourceInstance::STRING,M2MBase::Static,true); + object->_resource_list.push_back(res); + + m2mbase_stub::int_value = 1; + + result = object->resource("name"); + CHECK(result != NULL); +} + +void Test_M2MObjectInstance::test_resources() +{ + M2MResource *res = new M2MResource(*object,"name","type",M2MResourceInstance::STRING,M2MBase::Static,true); + m2mbase_stub::string_value = new String("name"); + object->_resource_list.push_back(res); + + res = new M2MResource(*object,"name","type",M2MResourceInstance::STRING,M2MBase::Static,true); + object->_resource_list.push_back(res); + + M2MResourceList resources =object->resources(); + + CHECK(2 == resources.size()); +} + +void Test_M2MObjectInstance::test_resource_count() +{ + M2MResource *res = new M2MResource(*object,"name","type",M2MResourceInstance::STRING,M2MBase::Static,true); + m2mbase_stub::string_value = new String("name"); + object->_resource_list.push_back(res); + + res = new M2MResource(*object,"name","type",M2MResourceInstance::STRING,M2MBase::Static,true); + object->_resource_list.push_back(res); + + + m2mbase_stub::int_value = 0; + m2mresource_stub::bool_value = true; + m2mresource_stub::int_value = 1; + + CHECK(2 == object->resource_count("name")); + + m2mresource_stub::bool_value = false; + + CHECK(2 == object->resource_count("name")); +} + +void Test_M2MObjectInstance::test_total_resource_count() +{ + M2MResource *res = new M2MResource(*object,"name","type",M2MResourceInstance::STRING,M2MBase::Static,true); + m2mbase_stub::string_value = new String("name"); + object->_resource_list.push_back(res); + + res = new M2MResource(*object,"name1","type1",M2MResourceInstance::STRING,M2MBase::Static,true); + object->_resource_list.push_back(res); + + m2mresource_stub::bool_value = true; + m2mresource_stub::int_value = 1; + + CHECK(2 == object->resource_count()); + + m2mresource_stub::bool_value = false; + + CHECK(2 == object->resource_count()); +} + +void Test_M2MObjectInstance::test_base_type() +{ + m2mbase_stub::base_type = M2MBase::ObjectInstance; + CHECK(M2MBase::ObjectInstance == object->base_type()); +} + +void Test_M2MObjectInstance::test_handle_get_request() +{ + M2MResource *res = new M2MResource(*object,"name1","type1",M2MResourceInstance::STRING,M2MBase::Static,true); + object->_resource_list.push_back(res); + m2mbase_stub::string_value = new String("name1"); + uint8_t value[] = {"name"}; + sn_coap_hdr_s *coap_header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(coap_header, 0, sizeof(sn_coap_hdr_s)); + + coap_header->uri_path_ptr = value; + coap_header->uri_path_len = sizeof(value); + + coap_header->msg_code = COAP_MSG_CODE_REQUEST_GET; + + common_stub::int_value = 0; + + m2mbase_stub::operation = M2MBase::GET_ALLOWED; + m2mbase_stub::uint8_value = 200; + + common_stub::coap_header = (sn_coap_hdr_ *)malloc(sizeof(sn_coap_hdr_)); + memset(common_stub::coap_header,0,sizeof(sn_coap_hdr_)); + + m2mtlvserializer_stub::uint8_value = (uint8_t*)malloc(1); + + coap_header->token_ptr = (uint8_t*)malloc(sizeof(value)); + memcpy(coap_header->token_ptr, value, sizeof(value)); + + coap_header->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + coap_header->options_list_ptr->observe = 0; + + coap_header->content_type_ptr = (uint8_t*)malloc(1); + coap_header->content_type_len = 1; + *coap_header->content_type_ptr = 110; + + CHECK(object->handle_get_request(NULL,coap_header,handler) != NULL); + + if(coap_header->content_type_ptr) { + free(coap_header->content_type_ptr); + coap_header->content_type_ptr = NULL; + } + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + // Not OMA TLV or JSON + m2mbase_stub::uint8_value = 110; + CHECK(object->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + // OMA TLV + m2mbase_stub::uint8_value = 99; + CHECK(object->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + // OMA JSON + m2mbase_stub::uint8_value = 100; + CHECK(object->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + coap_header->options_list_ptr->observe = 1; + + uint8_t obs = 0; + coap_header->options_list_ptr->observe_ptr = (uint8_t*)malloc(sizeof(obs)); + memcpy(coap_header->options_list_ptr->observe_ptr,&obs,sizeof(obs)); + coap_header->options_list_ptr->observe_len = 0; + m2mbase_stub::uint16_value = 0x1c1c; + m2mbase_stub::uint8_value = 99; + m2mbase_stub::bool_value = true; + + CHECK(object->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + + if(common_stub::coap_header->options_list_ptr->observe_ptr) { + free(common_stub::coap_header->options_list_ptr->observe_ptr); + common_stub::coap_header->options_list_ptr->observe_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + m2mbase_stub::uint16_value = 10; + + CHECK(object->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + + if(common_stub::coap_header->options_list_ptr->observe_ptr) { + free(common_stub::coap_header->options_list_ptr->observe_ptr); + common_stub::coap_header->options_list_ptr->observe_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + // Not observable + m2mbase_stub::bool_value = false; + CHECK(object->handle_get_request(NULL,coap_header,handler) != NULL); + + m2mbase_stub::bool_value = true; + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + + if(common_stub::coap_header->options_list_ptr->observe_ptr) { + free(common_stub::coap_header->options_list_ptr->observe_ptr); + common_stub::coap_header->options_list_ptr->observe_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + coap_header->options_list_ptr->observe_len = 1; + + CHECK(object->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + + if(common_stub::coap_header->options_list_ptr->observe_ptr) { + free(common_stub::coap_header->options_list_ptr->observe_ptr); + common_stub::coap_header->options_list_ptr->observe_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + + obs = 1; + memcpy(coap_header->options_list_ptr->observe_ptr,&obs,sizeof(obs)); + m2mbase_stub::uint8_value = 99; + CHECK(object->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + + if(common_stub::coap_header->options_list_ptr->observe_ptr) { + free(common_stub::coap_header->options_list_ptr->observe_ptr); + common_stub::coap_header->options_list_ptr->observe_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + m2mbase_stub::operation = M2MBase::NOT_ALLOWED; + CHECK(object->handle_get_request(NULL,coap_header,handler) != NULL); + + CHECK(object->handle_get_request(NULL,NULL,handler) != NULL); + + if(coap_header->token_ptr) { + free(coap_header->token_ptr); + coap_header->token_ptr = NULL; + } + if(coap_header->content_type_ptr) { + free(coap_header->content_type_ptr); + coap_header->content_type_ptr = NULL; + } + if(coap_header->options_list_ptr->observe_ptr) { + free(coap_header->options_list_ptr->observe_ptr); + coap_header->options_list_ptr->observe_ptr = NULL; + } + if(coap_header->options_list_ptr) { + free(coap_header->options_list_ptr); + coap_header->options_list_ptr = NULL; + } + + if(common_stub::coap_header){ + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + free(common_stub::coap_header); + common_stub::coap_header = NULL; + } + free(coap_header); + coap_header = NULL; + + if(m2mtlvserializer_stub::uint8_value) { + free(m2mtlvserializer_stub::uint8_value); + } + m2mtlvserializer_stub::clear(); + common_stub::clear(); +} + +void Test_M2MObjectInstance::test_handle_put_request() +{ + uint8_t value[] = {"name"}; + bool execute_value_updated = false; + sn_coap_hdr_s *coap_header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(coap_header, 0, sizeof(sn_coap_hdr_s)); + + coap_header->uri_path_ptr = value; + coap_header->uri_path_len = sizeof(value); + + coap_header->msg_code = COAP_MSG_CODE_REQUEST_PUT; + + common_stub::int_value = 0; + m2mbase_stub::string_value = new String("name"); + + m2mbase_stub::operation = M2MBase::PUT_ALLOWED; + m2mbase_stub::uint8_value = 200; + + common_stub::coap_header = (sn_coap_hdr_ *)malloc(sizeof(sn_coap_hdr_)); + memset(common_stub::coap_header,0,sizeof(sn_coap_hdr_)); + + coap_header->payload_ptr = (uint8_t*)malloc(1); + + sn_coap_hdr_s *coap_response = NULL; + m2mbase_stub::uint8_value = 99; + coap_response = object->handle_put_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + + m2mbase_stub::uint8_value = 0; + + coap_header->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + coap_header->options_list_ptr->uri_query_ptr = value; + coap_header->options_list_ptr->uri_query_len = sizeof(value); + + coap_header->content_type_ptr = (uint8_t*)malloc(1); + coap_header->content_type_len = 1; + *coap_header->content_type_ptr = 99; + m2mtlvdeserializer_stub::bool_value = true; + m2mtlvdeserializer_stub::error = M2MTLVDeserializer::None; + + m2mbase_stub::bool_value = false; + + + coap_response = object->handle_put_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + m2mbase_stub::bool_value = true; + + coap_response = object->handle_put_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + free(coap_header->options_list_ptr); + coap_header->options_list_ptr = NULL; + + m2mbase_stub::bool_value = false; + + coap_response = object->handle_put_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + m2mtlvdeserializer_stub::error = M2MTLVDeserializer::NotFound; + + m2mbase_stub::bool_value = false; + + + coap_response = object->handle_put_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + m2mtlvdeserializer_stub::error = M2MTLVDeserializer::NotValid; + + m2mbase_stub::bool_value = false; + + + coap_response = object->handle_put_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + m2mtlvdeserializer_stub::error = M2MTLVDeserializer::NotAllowed; + + m2mbase_stub::bool_value = false; + + + coap_response = object->handle_put_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + m2mtlvdeserializer_stub::bool_value = false; + + coap_response = object->handle_put_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + *coap_header->content_type_ptr = 100; + + coap_response = object->handle_put_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + free(coap_header->payload_ptr); + coap_header->payload_ptr = NULL; + + m2mbase_stub::bool_value = true; + + coap_response = object->handle_put_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + m2mbase_stub::bool_value = false; + + coap_response = object->handle_put_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + m2mbase_stub::operation = M2MBase::NOT_ALLOWED; + + coap_response = object->handle_put_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + coap_response = object->handle_put_request(NULL,NULL,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + + free(coap_header->content_type_ptr); + //free(coap_header->options_list_ptr); + free(common_stub::coap_header); + delete m2mbase_stub::string_value; + free(coap_header); + + m2mtlvdeserializer_stub::clear(); + common_stub::clear(); + m2mbase_stub::clear(); +} + +void Test_M2MObjectInstance::test_handle_post_request() +{ + uint8_t value[] = {"name"}; + bool execute_value_updated = false; + sn_coap_hdr_s *coap_header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(coap_header, 0, sizeof(sn_coap_hdr_s)); + + coap_header->uri_path_ptr = value; + coap_header->uri_path_len = sizeof(value); + + coap_header->msg_code = COAP_MSG_CODE_REQUEST_POST; + + common_stub::int_value = 0; + m2mbase_stub::string_value = new String("name"); + + m2mbase_stub::operation = M2MBase::POST_ALLOWED; + m2mbase_stub::uint8_value = 200; + + common_stub::coap_header = (sn_coap_hdr_ *)malloc(sizeof(sn_coap_hdr_)); + memset(common_stub::coap_header,0,sizeof(sn_coap_hdr_)); + + m2mbase_stub::bool_value = false; + + sn_coap_hdr_s * coap_response = NULL; + m2mbase_stub::uint8_value = 99; + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + + m2mbase_stub::uint8_value = 100; + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + coap_header->payload_ptr = (uint8_t*)malloc(1); + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + m2mbase_stub::uint8_value = 99; + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + + m2mbase_stub::uint8_value = 0; + + coap_header->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + coap_header->options_list_ptr->uri_query_ptr = value; + coap_header->options_list_ptr->uri_query_len = sizeof(value); + + coap_header->content_type_ptr = (uint8_t*)malloc(1); + coap_header->content_type_len = 1; + *coap_header->content_type_ptr = 99; + m2mtlvdeserializer_stub::is_object_bool_value = true; + m2mtlvdeserializer_stub::bool_value = false; + m2mbase_stub::bool_value = false; + + m2mtlvdeserializer_stub::error = M2MTLVDeserializer::None; + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + + m2mbase_stub::operation = M2MBase::POST_ALLOWED; + m2mtlvdeserializer_stub::is_object_bool_value = true; + m2mtlvdeserializer_stub::bool_value = false; + m2mbase_stub::bool_value = false; + + m2mtlvdeserializer_stub::error = M2MTLVDeserializer::NotAllowed; + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + + m2mtlvdeserializer_stub::error = M2MTLVDeserializer::NotValid; + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + + + m2mbase_stub::operation = M2MBase::POST_ALLOWED; + m2mtlvdeserializer_stub::is_object_bool_value = false; + m2mtlvdeserializer_stub::bool_value = true; + m2mbase_stub::bool_value = false; + m2mtlvdeserializer_stub::error = M2MTLVDeserializer::None; + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + + m2mbase_stub::operation = M2MBase::POST_ALLOWED; + m2mtlvdeserializer_stub::is_object_bool_value = false; + m2mtlvdeserializer_stub::bool_value = true; + m2mbase_stub::bool_value = false; + m2mtlvdeserializer_stub::error = M2MTLVDeserializer::NotFound; + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + + m2mbase_stub::operation = M2MBase::POST_ALLOWED; + m2mtlvdeserializer_stub::bool_value = false; + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + + + *coap_header->content_type_ptr = 100; + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + + + m2mbase_stub::bool_value = true; + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + + + m2mbase_stub::operation = M2MBase::NOT_ALLOWED; + + coap_response = object->handle_post_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + + coap_response = object->handle_post_request(NULL,NULL,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + if (coap_response->options_list_ptr) { + if (coap_response->options_list_ptr->location_path_ptr) { + free(coap_response->options_list_ptr->location_path_ptr); + coap_response->options_list_ptr->location_path_ptr = NULL; + } + free(coap_response->options_list_ptr); + coap_response->options_list_ptr = NULL; + } + } + + free(coap_header->content_type_ptr); + free(coap_header->options_list_ptr); + free(coap_header->payload_ptr); + free(common_stub::coap_header); + free(coap_header); + delete m2mbase_stub::string_value; + m2mtlvdeserializer_stub::clear(); + common_stub::clear(); + m2mbase_stub::clear(); + +} + +void Test_M2MObjectInstance::test_notification_update() +{ + M2MBase::Observation obs_level = M2MBase::O_Attribute; + + object->notification_update(obs_level); + CHECK(callback->visited == true); + + obs_level = M2MBase::OI_Attribute; + + TestReportObserver obs; + m2mbase_stub::report = new M2MReportHandler(obs); + m2mbase_stub::bool_value = true; + + object->notification_update(obs_level); + + delete m2mbase_stub::report; + m2mbase_stub::report = NULL; +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobjectinstance/test_m2mobjectinstance.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobjectinstance/test_m2mobjectinstance.h new file mode 100755 index 0000000000..5ea7e76fc4 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mobjectinstance/test_m2mobjectinstance.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TEST_M2M_OBJECT_INSTANCE_H +#define TEST_M2M_OBJECT_INSTANCE_H + +#include "m2mobjectinstance.h" + +class Handler; +class Callback; + +class Test_M2MObjectInstance +{ +public: + Test_M2MObjectInstance(); + + void test_copy_constructor(); + + virtual ~Test_M2MObjectInstance(); + + void test_create_static_resource(); + + void test_create_static_resource_instance(); + + void test_create_dynamic_resource(); + + void test_create_dynamic_resource_instance(); + + void test_remove_resource(); + + void test_remove_resource_instance(); + + void test_resource(); + + void test_resources(); + + void test_resource_count(); + + void test_total_resource_count(); + + void test_base_type(); + + void test_handle_get_request(); + + void test_handle_put_request(); + + void test_handle_post_request(); + + void test_notification_update(); + + M2MObjectInstance* object; + + Handler* handler; + + Callback* callback; +}; + +#endif // TEST_M2M_OBJECT_INSTANCE_H diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mreporthandler/CMakeLists.txt b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mreporthandler/CMakeLists.txt new file mode 100644 index 0000000000..64e1a7f2c2 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mreporthandler/CMakeLists.txt @@ -0,0 +1,25 @@ +if(TARGET_LIKE_LINUX) +include("../includes.txt") + + +add_executable(m2mreporthandler + "main.cpp" + "m2mreporthandlertest.cpp" + "test_m2mreporthandler.cpp" + "../stub/m2mtimer_stub.cpp" + "../stub/m2mstring_stub.cpp" + "../../../../source/m2mreporthandler.cpp" + +) +target_link_libraries(m2mreporthandler + CppUTest + CppUTestExt +) + +set_target_properties(m2mreporthandler +PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" + LINK_FLAGS "${UTEST_LINK_FLAGS}") +set(binary "m2mreporthandler") +add_test(m2mreporthandler ${binary}) + +endif() diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mreporthandler/m2mreporthandlertest.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mreporthandler/m2mreporthandlertest.cpp new file mode 100644 index 0000000000..47de306409 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mreporthandler/m2mreporthandlertest.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//CppUTest includes should be after your and system includes +#include "CppUTest/TestHarness.h" +#include "test_m2mreporthandler.h" + + +TEST_GROUP(M2MReportHandler) +{ + Test_M2MReportHandler* m2m_reporthandler; + + void setup() + { + m2m_reporthandler = new Test_M2MReportHandler(); + } + void teardown() + { + delete m2m_reporthandler; + } +}; + +TEST(M2MReportHandler, Create) +{ + CHECK(m2m_reporthandler != NULL); +} + +TEST(M2MReportHandler, test_set_under_observation) +{ + m2m_reporthandler->test_set_under_observation(); +} + +TEST(M2MReportHandler, test_parse_notification_attribute) +{ + m2m_reporthandler->test_parse_notification_attribute(); +} + +TEST(M2MReportHandler, test_timer_expired) +{ + m2m_reporthandler->test_timer_expired(); +} + +TEST(M2MReportHandler, test_set_value) +{ + m2m_reporthandler->test_set_value(); +} + +TEST(M2MReportHandler, test_trigger_object_notification) +{ + m2m_reporthandler->test_trigger_object_notification(); +} + +TEST(M2MReportHandler, test_set_string_notification_trigger) +{ + m2m_reporthandler->test_set_string_notification_trigger(); +} + +TEST(M2MReportHandler, test_timers) +{ + m2m_reporthandler->test_timers(); +} + +TEST(M2MReportHandler, test_attribute_flags) +{ + m2m_reporthandler->test_attribute_flags(); +} + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mreporthandler/main.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mreporthandler/main.cpp new file mode 100644 index 0000000000..c8fe476a3b --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mreporthandler/main.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP( M2MReportHandler); diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mreporthandler/test_m2mreporthandler.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mreporthandler/test_m2mreporthandler.cpp new file mode 100755 index 0000000000..85a885b12d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mreporthandler/test_m2mreporthandler.cpp @@ -0,0 +1,422 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include "test_m2mreporthandler.h" +#include "m2mobservationhandler.h" +#include "m2mtimer.h" +#include "m2mtimerobserver.h" +#include "m2mbase.h" + +class Observer : public M2MReportObserver{ + +public: + + Observer() : visited(false) {} + virtual ~Observer(){} + void observation_to_be_sent(m2m::Vector,bool){ + visited = true; + } + bool visited; +}; + +class TimerObserver : public M2MTimerObserver +{ +public: + TimerObserver() : visited(false) {} + virtual ~TimerObserver(){} + + virtual void timer_expired(M2MTimerObserver::Type ){ + visited = true; + } + + bool visited; +}; + +Test_M2MReportHandler::Test_M2MReportHandler() +{ + _observer = new Observer(); + M2MReportHandler handler(*_observer); + _handler = new M2MReportHandler(*_observer); +} + +Test_M2MReportHandler::~Test_M2MReportHandler() +{ + delete _handler; + delete _observer; +} + +void Test_M2MReportHandler::test_set_under_observation() +{ + _observer->visited = false; + + _handler->set_under_observation(true); + CHECK(false == _observer->visited); + CHECK(_handler->_pmin_timer == NULL); + + _observer->visited = false; + _handler->set_under_observation(false); + CHECK(false == _observer->visited); +} + +void Test_M2MReportHandler::test_parse_notification_attribute() +{ + char* val = {"value"}; + CHECK(false == _handler->parse_notification_attribute(val, M2MBase::ObjectInstance )); + + char* val2 = {"value&eval"}; + CHECK(false == _handler->parse_notification_attribute(val2, M2MBase::ObjectInstance )); + + char* val3 = {"toolongvaluevaluevaluevaluevalue&toolongvaluevaluevaluevaluevalue"}; + CHECK(false == _handler->parse_notification_attribute(val3, M2MBase::ObjectInstance )); + + char* val_real = {"st=6&pmax=3<=1>=100"}; + CHECK(true == _handler->parse_notification_attribute(val_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + char* val_real1 = {"a=1&pmin=2&pmax=3>=4<=5&st=6"}; + CHECK(false == _handler->parse_notification_attribute(val_real1, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + char* val2_real = {"st=6<=50>=1"}; + CHECK(false == _handler->parse_notification_attribute(val2_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + char* val3_real = {"gt=40<=5&st=6"}; + CHECK(true == _handler->parse_notification_attribute(val3_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + _handler->set_default_values(); + + char* val5_real = {"pmin=10"}; + CHECK(true == _handler->parse_notification_attribute(val5_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + char* val6_real = {"pmin=100&pmax=5"}; + CHECK(false == _handler->parse_notification_attribute(val6_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + char* val7_real = {"st=6&pmax=30<=1>=100&pmin=0"}; + CHECK(true == _handler->parse_notification_attribute(val7_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + char* val8_real = {"pmax=30<=10>=5&pmin=1"}; + CHECK(false == _handler->parse_notification_attribute(val8_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + // low = lt + 2 * st = 18 + char* val9_real = {"pmax=30<=10>=17&pmin=1&st=4"}; + CHECK(false == _handler->parse_notification_attribute(val9_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + // low = lt + 2 * st = 18 + char* val10_real = {"pmax=30<=10>=19&pmin=1&st=4"}; + CHECK(true == _handler->parse_notification_attribute(val10_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + char* val11_real = {"pmax=30&pmin=30"}; + CHECK(true == _handler->parse_notification_attribute(val11_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + _handler->set_default_values(); + + char* inst_real = {"st=6&pmax=3<=1>=100"}; + CHECK(true == _handler->parse_notification_attribute(inst_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + char* inst1_real1 = {"a=1&pmin=2&pmax=3>=4<=5&st=6"}; + CHECK(false == _handler->parse_notification_attribute(inst1_real1, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + char* inst2_real = {"st=6<=50>=1"}; + CHECK(false == _handler->parse_notification_attribute(inst2_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + char* inst3_real = {"gt=40<=5&st=6"}; + CHECK(true == _handler->parse_notification_attribute(inst3_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + _handler->set_default_values(); + char* inst5_real = {"pmin=10"}; + CHECK(true == _handler->parse_notification_attribute(inst5_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + char* inst6_real = {"pmin=100&pmax=5"}; + CHECK(false == _handler->parse_notification_attribute(inst6_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + char* inst7_real = {"st=6&pmax=30<=1>=100&pmin=0"}; + CHECK(true == _handler->parse_notification_attribute(inst7_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + char* inst8_real = {"pmax=30<=10>=5&pmin=1"}; + CHECK(false == _handler->parse_notification_attribute(inst8_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + // low = lt + 2 * st = 18 + char* inst9_real = {"pmax=30<=10>=17&pmin=1&st=4"}; + CHECK(false == _handler->parse_notification_attribute(inst9_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + // low = lt + 2 * st = 18 + char* inst10_real = {"pmax=30<=10>=19&pmin=1&st=4"}; + CHECK(true == _handler->parse_notification_attribute(inst10_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + char* inst11_real = {"pmax=30&pmin=30"}; + CHECK(true == _handler->parse_notification_attribute(inst11_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + char* inst12_real = {"pmax=&pmin=30"}; + CHECK(false == _handler->parse_notification_attribute(inst12_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + char* inst13_real = {"st="}; + CHECK(false == _handler->parse_notification_attribute(inst13_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + _handler->set_default_values(); + + char* inst14_real = {"stp=10"}; + CHECK(true == _handler->parse_notification_attribute(inst14_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + char* inst15_real = {"stp=10&st=15"}; + CHECK(true == _handler->parse_notification_attribute(inst15_real, M2MBase::Resource, + M2MResourceInstance::INTEGER )); + + _handler->set_default_values(); + + DOUBLES_EQUAL(0,_handler->_lt,0); + DOUBLES_EQUAL(0,_handler->_gt,0); + DOUBLES_EQUAL(-1,_handler->_pmax,0); + DOUBLES_EQUAL(1,_handler->_pmin,0); + DOUBLES_EQUAL(0,_handler->_st,0); + DOUBLES_EQUAL(0,_handler->_high_step,0); + DOUBLES_EQUAL(0,_handler->_low_step,0); + DOUBLES_EQUAL(-1,_handler->_last_value,0); + DOUBLES_EQUAL(0,_handler->_attribute_state,0); + CHECK_FALSE(_handler->_pmin_exceeded); + CHECK_FALSE(_handler->_pmax_exceeded); +} + +void Test_M2MReportHandler::test_timer_expired() +{ + _handler->timer_expired(M2MTimerObserver::Notdefined); + CHECK(_observer->visited == false); + + _handler->_notify = true; + _handler->_pmin_exceeded = true; + _handler->timer_expired(M2MTimerObserver::PMaxTimer); + CHECK(_observer->visited == true); + + _handler->_pmin_exceeded = false; + _handler->_notify = false; + _handler->_attribute_state = M2MReportHandler::Pmax; + _handler->_current_value = 100; + _handler->timer_expired(M2MTimerObserver::PMinTimer); + CHECK(_handler->_pmin_exceeded == true); + + _observer->visited = false; + _handler->_notify = true; + _handler->timer_expired(M2MTimerObserver::PMinTimer); + CHECK(_observer->visited == true); + + _handler->_notify = true; + _handler->_pmin_exceeded = true; + _handler->timer_expired(M2MTimerObserver::PMinTimer); + CHECK(_handler->_pmin_exceeded == true); + + _handler->_notify = true; + _handler->_pmin_exceeded = false; + _handler->_attribute_state = M2MReportHandler::Pmax; + _handler->timer_expired(M2MTimerObserver::PMaxTimer); + CHECK(_handler->_pmax_exceeded == true); +} + +void Test_M2MReportHandler::test_set_value() +{ + _handler->_notify = true; + _handler->_pmin_exceeded = false; + _observer->visited = false; + + _handler->set_value(1); + _handler->set_value(10); + CHECK(_observer->visited == true); + + char* query = {"st=6"}; + _handler->_attribute_state = 0; + CHECK(true == _handler->parse_notification_attribute(query, + M2MBase::Resource, + M2MResourceInstance::INTEGER)); + _observer->visited = false; + _handler->set_value(15); + CHECK(_observer->visited == false); + + _observer->visited = false; + _handler->set_value(21); + CHECK(_observer->visited == true); + + _handler->set_value(10); + char* query2 = {"st=3<=10>=100"}; + _handler->_attribute_state = 0; + CHECK(true == _handler->parse_notification_attribute(query2, + M2MBase::Resource, + M2MResourceInstance::INTEGER)); + + _observer->visited = false; + _handler->set_value(12); + CHECK(_observer->visited == false); + + _observer->visited = false; + _handler->set_value(15); + CHECK(_observer->visited == true); + + _observer->visited = false; + _handler->set_value(5); + CHECK(_observer->visited == true); + + _observer->visited = false; + _handler->set_value(4); + CHECK(_observer->visited == true); + + _observer->visited = false; + _handler->set_value(101); + CHECK(_observer->visited == true); + + _observer->visited = false; + _handler->set_value(102); + CHECK(_observer->visited == true); + + char* query3 = {"lt=10"}; + _handler->set_default_values(); + CHECK(true == _handler->parse_notification_attribute(query3, M2MBase::Resource, M2MResourceInstance::INTEGER)); + _observer->visited = false; + _handler->set_value(9); + CHECK(_observer->visited == true); + + _observer->visited = false; + _handler->set_value(15); + CHECK(_observer->visited == false); + + char* query4 = {"gt=10"}; + _handler->set_default_values(); + CHECK(true == _handler->parse_notification_attribute(query4, M2MBase::Resource, M2MResourceInstance::INTEGER)); + + // Instantiate timers + _handler->_attribute_state |= M2MReportHandler::Pmin; + _handler->handle_timers(); + _observer->visited = false; + _handler->set_value(9); + CHECK(_observer->visited == false); + // Stop timers and reset flag to previous state + _handler->stop_timers(); + _handler->_attribute_state = M2MReportHandler::Gt; + + _observer->visited = false; + _handler->set_value(15); + CHECK(_observer->visited == true); + + _observer->visited = false; + _handler->set_value(16); + CHECK(_observer->visited == true); + + _observer->visited = false; + char* query5 = {"gt=10"}; + _handler->set_default_values(); + CHECK(false == _handler->parse_notification_attribute(query5, M2MBase::Resource, M2MResourceInstance::STRING)); + + _observer->visited = false; + char* query6 = {"pmin=10"}; + _handler->set_default_values(); + CHECK(true == _handler->parse_notification_attribute(query6, M2MBase::Resource, M2MResourceInstance::STRING)); + + _observer->visited = false; + char* query7 = {"pmin=10&pmax=20"}; + _handler->set_default_values(); + CHECK(true == _handler->parse_notification_attribute(query7, M2MBase::Resource, M2MResourceInstance::OPAQUE)); + + _observer->visited = false; + _handler->handle_timers(); + _handler->set_value(26); + _handler->_pmin_exceeded = true; + _handler->timer_expired(M2MTimerObserver::PMaxTimer); + CHECK(_observer->visited == true); +} + +void Test_M2MReportHandler::test_trigger_object_notification() +{ + _handler->_notify = true; + _handler->_pmin_exceeded = true; + _handler->set_notification_trigger(); + CHECK(_handler->_pmin_exceeded == false); + CHECK(_observer->visited == true); + + _handler->_changed_instance_ids.push_back(0); + _handler->_changed_instance_ids.push_back(1); + _handler->_changed_instance_ids.push_back(2); + + _handler->set_notification_trigger(); + CHECK(_handler->_pmin_exceeded == false); + CHECK(_observer->visited == true); + +} + +void Test_M2MReportHandler::test_set_string_notification_trigger() +{ + _handler->_notify = true; + _handler->_pmin_exceeded = true; + _handler->set_notification_trigger(); + CHECK(_handler->_pmin_exceeded == false); +} + +void Test_M2MReportHandler::test_timers() +{ + _handler->handle_timers(); + CHECK(_handler->_pmin_timer == NULL); + + _handler->_attribute_state |= M2MReportHandler::Pmin; + _handler->handle_timers(); + CHECK(_handler->_pmin_timer != NULL); + + _handler->stop_timers(); + CHECK(_handler->_pmin_timer == NULL); + + _handler->_attribute_state |= M2MReportHandler::Pmax; + _handler->handle_timers(); + CHECK(_handler->_pmin_timer != NULL); + CHECK(_handler->_pmax_timer == NULL); + + _handler->stop_timers(); + CHECK(_handler->_pmin_timer == NULL); + CHECK(_handler->_pmax_timer == NULL); + + _handler->_pmax = 2; + _handler->_pmin = 2; + _handler->handle_timers(); + CHECK(_handler->_pmin_timer == NULL); + CHECK(_handler->_pmax_timer != NULL); + CHECK(_handler->_pmin_exceeded == true); + + _handler->stop_timers(); + CHECK(_handler->_pmin_timer == NULL); + CHECK(_handler->_pmax_timer == NULL); +} + +void Test_M2MReportHandler::test_attribute_flags() +{ + CHECK(_handler->attribute_flags() == 0); + _handler->_attribute_state = M2MReportHandler::Pmax | M2MReportHandler::Pmin | + M2MReportHandler::St | M2MReportHandler::Gt | M2MReportHandler::Lt | M2MReportHandler::Cancel; + CHECK(_handler->attribute_flags() == (1 << 6) - 1); +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mreporthandler/test_m2mreporthandler.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mreporthandler/test_m2mreporthandler.h new file mode 100755 index 0000000000..35935a50ca --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mreporthandler/test_m2mreporthandler.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TEST_M2M_REPORT_HANDLER_H +#define TEST_M2M_REPORT_HANDLER_H + +#include "m2mreporthandler.h" + +class Observer; + +class Test_M2MReportHandler +{ +public: + Test_M2MReportHandler(); + + virtual ~Test_M2MReportHandler(); + + void test_set_under_observation(); + + void test_parse_notification_attribute(); + + void test_timer_expired(); + + void test_set_value(); + + void test_trigger_object_notification(); + + void test_set_string_notification_trigger(); + + void test_timers(); + + void test_attribute_flags(); + + M2MReportHandler *_handler; + Observer * _observer; +}; + + +#endif // TEST_M2M_BASE_H diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresource/CMakeLists.txt b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresource/CMakeLists.txt new file mode 100644 index 0000000000..0ef48472ff --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresource/CMakeLists.txt @@ -0,0 +1,27 @@ +if(TARGET_LIKE_LINUX) +include("../includes.txt") +add_executable(m2mresource + "../../../../source/m2mresource.cpp" + "main.cpp" + "../stub/m2mbase_stub.cpp" + "../stub/m2mstring_stub.cpp" + "../stub/m2mtimer_stub.cpp" + "../stub/m2mreporthandler_stub.cpp" + "../stub/m2mresourceinstance_stub.cpp" + "../stub/m2mtlvdeserializer_stub.cpp" + "../stub/m2mtlvserializer_stub.cpp" + "../stub/common_stub.cpp" + "m2mresourcetest.cpp" + "test_m2mresource.cpp" +) +target_link_libraries(m2mresource + CppUTest + CppUTestExt +) +set_target_properties(m2mresource +PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" + LINK_FLAGS "${UTEST_LINK_FLAGS}") +set(binary "m2mresource") +add_test(m2mresource ${binary}) + +endif() diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresource/m2mresourcetest.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresource/m2mresourcetest.cpp new file mode 100644 index 0000000000..dd837b9128 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresource/m2mresourcetest.cpp @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//CppUTest includes should be after your and system includes +#include "CppUTest/TestHarness.h" +#include "test_m2mresource.h" + +TEST_GROUP(M2MResource) +{ + Test_M2MResource* m2m_resource; + + void setup() + { + m2m_resource = new Test_M2MResource(); + } + void teardown() + { + delete m2m_resource; + } +}; + +TEST(M2MResource, Create) +{ + CHECK(m2m_resource != NULL); +} + +TEST(M2MResource, copy_constructor) +{ + m2m_resource->test_copy_constructor(); +} + +TEST(M2MResource, static_resource) +{ + m2m_resource->test_static_resource(); +} + +TEST(M2MResource, base_type) +{ + m2m_resource->test_base_type(); +} + +TEST(M2MResource, muliptle_instances) +{ + m2m_resource->test_muliptle_instances(); +} + +TEST(M2MResource, test_handle_observation_attribute) +{ + m2m_resource->test_handle_observation_attribute(); +} + +TEST(M2MResource, test_add_resource_instance) +{ + m2m_resource->test_add_resource_instance(); +} + +TEST(M2MResource, test_remove_resource_instance) +{ + m2m_resource->test_remove_resource_instance(); +} + +TEST(M2MResource, test_resource_instance_count) +{ + m2m_resource->test_resource_instance_count(); +} + +TEST(M2MResource, test_resource_instances) +{ + m2m_resource->test_resource_instances(); +} + +TEST(M2MResource, test_resource_instance) +{ + m2m_resource->test_resource_instance(); +} + +TEST(M2MResource, test_add_observation_level) +{ + m2m_resource->test_add_observation_level(); +} + +TEST(M2MResource, test_remove_observation_level) +{ + m2m_resource->test_remove_observation_level(); +} + +TEST(M2MResource, test_handle_get_request) +{ + m2m_resource->test_handle_get_request(); +} + +TEST(M2MResource, test_handle_put_request) +{ + m2m_resource->test_handle_put_request(); +} + +TEST(M2MResource, test_handle_post_request) +{ + m2m_resource->test_handle_post_request(); +} + +TEST(M2MResource, test_notification_update) +{ + m2m_resource->test_notification_update(); +} + +TEST(M2MResource, test_set_delayed_response) +{ + m2m_resource->test_set_delayed_response(); +} + +TEST(M2MResource, test_send_delayed_post_response) +{ + m2m_resource->test_send_delayed_post_response(); +} + +TEST(M2MResource, test_get_delayed_token) +{ + m2m_resource->test_get_delayed_token(); +} + +TEST(M2MResource, test_delayed_response) +{ + m2m_resource->test_delayed_response(); +} + +TEST(M2MResource, test_execute_params) +{ + m2m_resource->test_execute_params(); +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresource/main.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresource/main.cpp new file mode 100644 index 0000000000..4e48b066fd --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresource/main.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP( M2MResource); diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresource/test_m2mresource.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresource/test_m2mresource.cpp new file mode 100755 index 0000000000..553e808aff --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresource/test_m2mresource.cpp @@ -0,0 +1,839 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include "test_m2mresource.h" +#include "CppUTest/MemoryLeakDetectorMallocMacros.h" +#include "m2mbase_stub.h" +#include "m2mresourceinstance_stub.h" +#include "m2mobjectinstance_stub.h" +#include "m2mtlvdeserializer_stub.h" +#include "m2mreporthandler_stub.h" +#include "common_stub.h" +#include "m2mreporthandler.h" + +class TestReportObserver : public M2MReportObserver{ +public : + TestReportObserver() {} + ~TestReportObserver() {} + void observation_to_be_sent(m2m::Vector,bool){ } +}; + + + + +class Callback : public M2MObjectInstanceCallback { + +public: + + Callback(){} + ~Callback(){} + void notification_update(M2MBase::Observation) { + visited = true; + } + + void clear() {visited = false;} + bool visited; +}; + +class Handler : public M2MObservationHandler { + +public: + + Handler(){} + ~Handler(){} + void observation_to_be_sent(M2MBase *, uint16_t,m2m::Vector,bool){ + visited = true; + } + void send_delayed_response(M2MBase *){} + void resource_to_be_deleted(const String &){visited=true;} + void remove_object(M2MBase *){visited = true;} + void value_updated(M2MBase *,const String&){visited = true;} + + void clear() {visited = false;} + bool visited; +}; + +Test_M2MResource::Test_M2MResource() +{ + callback = new Callback(); + handler = new Handler(); + resource = new M2MResource(*callback, + "name", + "resource_type", + M2MResourceInstance::INTEGER, + false,false); +} + +void Test_M2MResource::test_copy_constructor() +{ + u_int8_t value[] = {"value"}; + resource->set_value(value,(u_int32_t)sizeof(value)); + resource->_delayed_token = (u_int8_t*)malloc(sizeof(value)); + resource->_delayed_token_len = sizeof(value); + + M2MResourceInstance *res = new M2MResourceInstance("name","type",M2MResourceInstance::STRING,*callback); + resource->add_resource_instance(res); + + M2MResource* copy = new M2MResource(*resource); + u_int8_t* out_value = (u_int8_t*)malloc(sizeof(u_int8_t)); + u_int32_t out_size; + + uint8_t* ptr = (uint8_t*)malloc((uint32_t)sizeof(value)); + m2mresourceinstance_stub::value = ptr; + memset(m2mresourceinstance_stub::value,0,(uint32_t)sizeof(value)); + memcpy(m2mresourceinstance_stub::value,value,sizeof(value)); + m2mresourceinstance_stub::int_value = (uint32_t)sizeof(value); + + copy->get_value(out_value,out_size); + + CHECK(out_size == sizeof(value)); + + free(out_value); + free(ptr); + + delete copy; +} + +Test_M2MResource::~Test_M2MResource() +{ + delete resource; + delete handler; + delete callback; + m2mtlvdeserializer_stub::clear(); +} + +void Test_M2MResource::test_static_resource() +{ + u_int8_t value[] = {"value"}; + M2MResource *res = new M2MResource(*callback, + "name", + "resource_type", + M2MResourceInstance::INTEGER, + value,(uint32_t)sizeof(value), + true); + + CHECK(res != NULL); + delete res; + +} + +void Test_M2MResource::test_base_type() +{ + m2mresourceinstance_stub::base_type = M2MBase::Resource; + CHECK(M2MBase::Resource == resource->base_type()); +} + +void Test_M2MResource::test_muliptle_instances() +{ + CHECK(false == resource->supports_multiple_instances()); +} + +void Test_M2MResource::test_handle_observation_attribute() +{ + char *d = "s"; + + m2mresourceinstance_stub::resource_type = M2MResourceInstance::INTEGER; + CHECK(false == resource->handle_observation_attribute(d)); + + m2mresourceinstance_stub::resource_type = M2MResourceInstance::FLOAT; + CHECK(false == resource->handle_observation_attribute(d)); + + M2MResourceInstance *res = new M2MResourceInstance("name","type",M2MResourceInstance::INTEGER,*callback); + resource->add_resource_instance(res); + + TestReportObserver obs; + m2mbase_stub::report = new M2MReportHandler(obs); + + m2mbase_stub::bool_value = true; + CHECK(false == resource->handle_observation_attribute(d)); + + resource->_resource_type = M2MResourceInstance::INTEGER; + m2mreporthandler_stub::bool_return = true; + CHECK(true == resource->handle_observation_attribute(d)); + + m2mbase_stub::bool_value = false; + CHECK(true == resource->handle_observation_attribute(d)); + + delete m2mbase_stub::report; + m2mbase_stub::report = NULL; +} + +void Test_M2MResource::test_add_resource_instance() +{ + M2MResourceInstance *res = new M2MResourceInstance("name","type",M2MResourceInstance::STRING,*callback); + resource->add_resource_instance(res); + CHECK(resource->_resource_instance_list.size() == 1); +} + +void Test_M2MResource::test_remove_resource_instance() +{ + M2MResourceInstance *res = new M2MResourceInstance("name","type",M2MResourceInstance::STRING,*callback); + resource->_resource_instance_list.push_back(res); + CHECK(resource->remove_resource_instance(0) == true); +} + +void Test_M2MResource::test_resource_instance() +{ + M2MResourceInstance *res = new M2MResourceInstance("name","type",M2MResourceInstance::STRING,*callback); + resource->_resource_instance_list.push_back(res); + CHECK(resource->resource_instance(0) != NULL); +} + +void Test_M2MResource::test_resource_instances() +{ + M2MResourceInstance *res = new M2MResourceInstance("name","type",M2MResourceInstance::STRING,*callback); + resource->_resource_instance_list.push_back(res); + M2MResourceInstanceList list = resource->resource_instances(); + CHECK(list.size() ==1); +} + +void Test_M2MResource::test_resource_instance_count() +{ + M2MResourceInstance *res = new M2MResourceInstance("name","type",M2MResourceInstance::STRING,*callback); + resource->_resource_instance_list.push_back(res); + CHECK(resource->resource_instance_count() ==1); +} + +void Test_M2MResource::test_add_observation_level() +{ + M2MResourceInstance *res = new M2MResourceInstance("name","type",M2MResourceInstance::STRING,*callback); + resource->_resource_instance_list.push_back(res); + + M2MBase::Observation obs_level = M2MBase::R_Attribute; + + resource->add_observation_level(obs_level); +} + +void Test_M2MResource::test_remove_observation_level() +{ + M2MResourceInstance *res = new M2MResourceInstance("name","type",M2MResourceInstance::STRING,*callback); + resource->_resource_instance_list.push_back(res); + + M2MBase::Observation obs_level = M2MBase::R_Attribute; + + resource->remove_observation_level(obs_level); +} + +void Test_M2MResource::test_handle_get_request() +{ + uint8_t value[] = {"name"}; + sn_coap_hdr_s *coap_header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(coap_header, 0, sizeof(sn_coap_hdr_s)); + + coap_header->uri_path_ptr = value; + coap_header->uri_path_len = sizeof(value); + + coap_header->msg_code = COAP_MSG_CODE_REQUEST_GET; + + String *name = new String("name"); + common_stub::int_value = 0; + m2mbase_stub::string_value = name; + + m2mbase_stub::operation = M2MBase::GET_ALLOWED; + m2mbase_stub::uint8_value = 200; + + common_stub::coap_header = (sn_coap_hdr_ *)malloc(sizeof(sn_coap_hdr_)); + memset(common_stub::coap_header,0,sizeof(sn_coap_hdr_)); + + coap_header->token_ptr = (uint8_t*)malloc(sizeof(value)); + memcpy(coap_header->token_ptr, value, sizeof(value)); + + coap_header->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + coap_header->options_list_ptr->observe = 0; + + coap_header->content_type_ptr = (uint8_t*)malloc(1); + coap_header->content_type_len = 1; + *coap_header->content_type_ptr = 110; + + m2mresourceinstance_stub::header = NULL; + + M2MResourceInstance* res_instance = new M2MResourceInstance("name","res2", + M2MResourceInstance::INTEGER, + *callback); + M2MResourceInstance* res_instance_1 = new M2MResourceInstance("name","res2", + M2MResourceInstance::INTEGER, + *callback); + + CHECK(resource->handle_get_request(NULL,coap_header,handler) == NULL); + + resource->_has_multiple_instances = true; + resource->add_resource_instance(res_instance); + resource->add_resource_instance(res_instance_1); + + CHECK(resource->handle_get_request(NULL,coap_header,handler) != NULL); + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + CHECK(resource->handle_get_request(NULL,coap_header,handler) != NULL); + + if(coap_header->content_type_ptr) { + free(coap_header->content_type_ptr); + coap_header->content_type_ptr = NULL; + } + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + // Not OMA TLV or JSON + m2mbase_stub::uint8_value = 110; + CHECK(resource->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + // OMA TLV + m2mbase_stub::uint8_value = 99; + CHECK(resource->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + // OMA JSON + m2mbase_stub::uint8_value = 100; + CHECK(resource->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + coap_header->options_list_ptr->observe = 1; + + uint8_t obs = 0; + coap_header->options_list_ptr->observe_ptr = (uint8_t*)malloc(sizeof(obs)); + memcpy(coap_header->options_list_ptr->observe_ptr,&obs,sizeof(obs)); + coap_header->options_list_ptr->observe_len = 0; + m2mbase_stub::uint16_value = 0x1c1c; + m2mbase_stub::bool_value = true; + + CHECK(resource->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->observe_ptr) { + free(common_stub::coap_header->options_list_ptr->observe_ptr); + common_stub::coap_header->options_list_ptr->observe_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + m2mbase_stub::uint16_value = 10; + CHECK(resource->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->observe_ptr) { + free(common_stub::coap_header->options_list_ptr->observe_ptr); + common_stub::coap_header->options_list_ptr->observe_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + coap_header->options_list_ptr->observe_len = 1; + + CHECK(resource->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + + if(common_stub::coap_header->options_list_ptr->observe_ptr) { + free(common_stub::coap_header->options_list_ptr->observe_ptr); + common_stub::coap_header->options_list_ptr->observe_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + + obs = 1; + memcpy(coap_header->options_list_ptr->observe_ptr,&obs,sizeof(obs)); + CHECK(resource->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + + if(common_stub::coap_header->options_list_ptr->observe_ptr) { + free(common_stub::coap_header->options_list_ptr->observe_ptr); + common_stub::coap_header->options_list_ptr->observe_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + // Not observable + m2mbase_stub::bool_value = false; + CHECK(resource->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->observe_ptr) { + free(common_stub::coap_header->options_list_ptr->observe_ptr); + common_stub::coap_header->options_list_ptr->observe_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + m2mbase_stub::operation = M2MBase::NOT_ALLOWED; + CHECK(resource->handle_get_request(NULL,coap_header,handler) != NULL); + + CHECK(resource->handle_get_request(NULL,NULL,handler) != NULL); + + if(coap_header->token_ptr) { + free(coap_header->token_ptr); + coap_header->token_ptr = NULL; + } + if(coap_header->content_type_ptr) { + free(coap_header->content_type_ptr); + coap_header->content_type_ptr = NULL; + } + if(coap_header->options_list_ptr->observe_ptr) { + free(coap_header->options_list_ptr->observe_ptr); + coap_header->options_list_ptr->observe_ptr = NULL; + } + if(coap_header->options_list_ptr) { + free(coap_header->options_list_ptr); + coap_header->options_list_ptr = NULL; + } + + if(common_stub::coap_header){ + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + free(common_stub::coap_header); + common_stub::coap_header = NULL; + } + free(coap_header); + coap_header = NULL; + + delete name; + name = NULL; + + m2mbase_stub::clear(); + common_stub::clear(); +} + +void Test_M2MResource::test_handle_put_request() +{ + uint8_t value[] = {"name"}; + bool execute_value_updated = false; + sn_coap_hdr_s *coap_header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + TestReportObserver obs; + m2mbase_stub::report = new M2MReportHandler(obs); + + memset(coap_header, 0, sizeof(sn_coap_hdr_s)); + + coap_header->uri_path_ptr = value; + coap_header->uri_path_len = sizeof(value); + + coap_header->msg_code = COAP_MSG_CODE_REQUEST_PUT; + + String *name = new String("name"); + common_stub::int_value = 0; + m2mbase_stub::string_value = name; + + m2mbase_stub::operation = M2MBase::PUT_ALLOWED; + m2mbase_stub::uint8_value = 200; + + common_stub::coap_header = (sn_coap_hdr_ *)malloc(sizeof(sn_coap_hdr_)); + memset(common_stub::coap_header,0,sizeof(sn_coap_hdr_)); + + coap_header->payload_ptr = (uint8_t*)malloc(1); + + sn_coap_hdr_s *coap_response = NULL; + + m2mresourceinstance_stub::header = NULL; + + CHECK(resource->handle_put_request(NULL,coap_header,handler,execute_value_updated) == NULL); + + resource->_has_multiple_instances = true; + m2mbase_stub::uint8_value = 99; + + coap_response = resource->handle_put_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + + m2mbase_stub::uint8_value = 0; + + coap_header->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + coap_header->options_list_ptr->uri_query_ptr = value; + coap_header->options_list_ptr->uri_query_len = sizeof(value); + + coap_header->content_type_ptr = (uint8_t*)malloc(1); + coap_header->content_type_len = 1; + *coap_header->content_type_ptr = 99; + m2mtlvdeserializer_stub::bool_value = true; + + m2mbase_stub::bool_value = false; + + + coap_response = resource->handle_put_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + free(coap_header->options_list_ptr); + coap_header->options_list_ptr = NULL; + + coap_response = resource->handle_put_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + + m2mtlvdeserializer_stub::bool_value = false; + + coap_response = resource->handle_put_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + m2mtlvdeserializer_stub::error = M2MTLVDeserializer::NotFound; + coap_response = resource->handle_put_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + m2mtlvdeserializer_stub::error = M2MTLVDeserializer::NotValid; + coap_response = resource->handle_put_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + m2mtlvdeserializer_stub::error = M2MTLVDeserializer::NotAllowed; + coap_response = resource->handle_put_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + *coap_header->content_type_ptr = 100; + + coap_response = resource->handle_put_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + m2mbase_stub::bool_value = true; + + coap_response = resource->handle_put_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + m2mbase_stub::operation = M2MBase::NOT_ALLOWED; + + coap_response = resource->handle_put_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + coap_response = resource->handle_put_request(NULL,NULL,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + free(coap_header->content_type_ptr); + //free(coap_header->options_list_ptr); + free(coap_header->payload_ptr); + free(common_stub::coap_header); + delete name; + free(coap_header); + delete m2mbase_stub::report; + m2mbase_stub::report = NULL; + m2mtlvdeserializer_stub::clear(); + common_stub::clear(); + m2mbase_stub::clear(); +} + +void Test_M2MResource::test_handle_post_request() +{ + uint8_t value[] = {"name"}; + bool execute_value_updated = false; + sn_coap_hdr_s *coap_header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(coap_header, 0, sizeof(sn_coap_hdr_s)); + + coap_header->uri_path_ptr = value; + coap_header->uri_path_len = sizeof(value); + + coap_header->msg_code = COAP_MSG_CODE_REQUEST_POST; + + String *name = new String("name"); + common_stub::int_value = 0; + m2mbase_stub::string_value = name; + + m2mbase_stub::operation = M2MBase::POST_ALLOWED; + m2mbase_stub::uint8_value = 200; + + common_stub::coap_header = (sn_coap_hdr_ *)malloc(sizeof(sn_coap_hdr_)); + memset(common_stub::coap_header,0,sizeof(sn_coap_hdr_)); + + coap_header->payload_ptr = (uint8_t*)malloc(1); + + coap_header->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + coap_header->options_list_ptr->uri_query_ptr = value; + coap_header->options_list_ptr->uri_query_len = sizeof(value); + + coap_header->content_type_ptr = (uint8_t*)malloc(1); + coap_header->content_type_len = 1; + *coap_header->content_type_ptr = 99; + + + resource->_delayed_response = true; + resource->_delayed_token = (uint8_t*)malloc(1); + *resource->_delayed_token = 2; + coap_header->token_ptr = (uint8_t*)malloc(1); + *coap_header->token_ptr = 1; + coap_header->token_len = 1; + + m2mbase_stub::bool_value = false; + m2mresourceinstance_stub::string_value = name; + + CHECK(resource->handle_post_request(NULL,coap_header,handler,execute_value_updated) != NULL); + + *coap_header->content_type_ptr = 0; + + CHECK(resource->handle_post_request(NULL,coap_header,handler,execute_value_updated) != NULL); + + m2mresourceinstance_stub::int_value = sizeof(value); + m2mresourceinstance_stub::value = value; + + resource->_delayed_response = false; + sn_coap_hdr_s *coap_response = resource->handle_post_request(NULL,coap_header,handler,execute_value_updated); + + CHECK(coap_response != NULL); + free(coap_response->payload_ptr); + + m2mbase_stub::operation = M2MBase::NOT_ALLOWED; + CHECK(resource->handle_post_request(NULL,coap_header,handler,execute_value_updated) != NULL); + + CHECK(resource->handle_post_request(NULL,NULL,handler,execute_value_updated) != NULL); + + free(coap_header->token_ptr); + free(coap_header->content_type_ptr); + free(coap_header->options_list_ptr); + free(coap_header->payload_ptr); + + delete name; + free(coap_header); + free(common_stub::coap_header); + + m2mbase_stub::clear(); + common_stub::clear(); +} + +void Test_M2MResource::test_notification_update() +{ + TestReportObserver obs; + m2mbase_stub::report = new M2MReportHandler(obs); + m2mbase_stub::bool_value = true; + + resource->notification_update(); + + delete m2mbase_stub::report; + m2mbase_stub::report = NULL; +} + +void Test_M2MResource::test_set_delayed_response() +{ + resource->set_delayed_response(true); + CHECK(resource->_delayed_response == true); +} + +void Test_M2MResource::test_send_delayed_post_response() +{ + resource->_delayed_response = true; + m2mbase_stub::observe = handler; + CHECK(resource->send_delayed_post_response() == true); +} + +void Test_M2MResource::test_get_delayed_token() +{ + uint8_t value[] = {"1"}; + uint8_t *token = NULL; + uint8_t token_len = 0; + resource->_delayed_token_len = 1; + resource->_delayed_token = (uint8_t*)malloc(sizeof(1)); + memcpy(resource->_delayed_token,value,1); + resource->get_delayed_token(token,token_len); + CHECK(token != NULL); +} + +void Test_M2MResource::test_delayed_response() +{ + resource->_delayed_response = false; + CHECK(resource->delayed_response() == false); +} + +void Test_M2MResource::test_execute_params() +{ + M2MResource::M2MExecuteParameter *params = new M2MResource::M2MExecuteParameter(); + CHECK(params->get_argument_value() == NULL); + CHECK(params->get_argument_value_length() == 0); + CHECK(params->get_argument_object_name() == ""); + CHECK(params->get_argument_resource_name() == ""); + CHECK(params->get_argument_object_instance_id() == 0); + + uint8_t value[] = {"test"}; + int length = sizeof(value); + params->_value = (uint8_t*)malloc(length); + memcpy(params->_value,value,length); + params->_value_length = length; + params->_object_name = "object"; + params->_resource_name = "resource"; + params->_object_instance_id = 0; + CHECK(params->_value == params->get_argument_value()); + CHECK(params->_value_length == params->get_argument_value_length()); + CHECK(params->_resource_name == params->get_argument_resource_name()); + CHECK(params->_object_name == params->get_argument_object_name()); + CHECK(params->_object_instance_id == params->get_argument_object_instance_id()); + + delete params; +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresource/test_m2mresource.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresource/test_m2mresource.h new file mode 100755 index 0000000000..f6ac757b4c --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresource/test_m2mresource.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TEST_M2M_RESOURCE_H +#define TEST_M2M_RESOURCE_H + +#include "m2mresource.h" + +class Callback; +class Handler; + +class Test_M2MResource +{ +public: + + Test_M2MResource(); + + void test_copy_constructor(); + + virtual ~Test_M2MResource(); + + void test_static_resource(); + + void test_base_type(); + + void test_muliptle_instances(); + + void test_handle_observation_attribute(); + + void test_add_resource_instance(); + + void test_remove_resource_instance(); + + void test_resource_instance(); + + void test_resource_instances(); + + void test_resource_instance_count(); + + void test_add_observation_level(); + + void test_remove_observation_level(); + + void test_handle_get_request(); + + void test_handle_put_request(); + + void test_handle_post_request(); + + void test_notification_update(); + + void test_set_delayed_response(); + + void test_send_delayed_post_response(); + + void test_get_delayed_token(); + + void test_delayed_response(); + + void test_execute_params(); + + M2MResource* resource; + Callback *callback; + + Handler* handler; +}; + +#endif // TEST_M2M_RESOURCE_H diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresourceinstance/CMakeLists.txt b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresourceinstance/CMakeLists.txt new file mode 100644 index 0000000000..f63ef1257d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresourceinstance/CMakeLists.txt @@ -0,0 +1,26 @@ +if(TARGET_LIKE_LINUX) +include("../includes.txt") +add_executable(m2mresourceinstance + "../../../../source/m2mresourceinstance.cpp" + "main.cpp" + "../stub/m2mbase_stub.cpp" + "../stub/m2mstring_stub.cpp" + "../stub/m2mtimer_stub.cpp" + "../stub/m2mreporthandler_stub.cpp" + "../stub/common_stub.cpp" + "../stub/m2mtlvdeserializer_stub.cpp" + "m2mresourceinstancetest.cpp" + "test_m2mresourceinstance.cpp" +) +target_link_libraries(m2mresourceinstance + CppUTest + CppUTestExt +) +set_target_properties(m2mresourceinstance +PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" + LINK_FLAGS "${UTEST_LINK_FLAGS}") +set(binary "m2mresourceinstance") +add_test(m2mresourceinstance ${binary}) + + +endif() diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresourceinstance/m2mresourceinstancetest.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresourceinstance/m2mresourceinstancetest.cpp new file mode 100644 index 0000000000..a9fc70f971 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresourceinstance/m2mresourceinstancetest.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//CppUTest includes should be after your and system includes +#include "CppUTest/TestHarness.h" +#include "test_m2mresourceinstance.h" + +TEST_GROUP(M2MResourceInstance) +{ + Test_M2MResourceInstance* m2m_resourceinstance; + + void setup() + { + m2m_resourceinstance = new Test_M2MResourceInstance(); + } + void teardown() + { + delete m2m_resourceinstance; + } +}; + +TEST(M2MResourceInstance, Create) +{ + CHECK(m2m_resourceinstance != NULL); +} + +TEST(M2MResourceInstance, test_static_resource_instance) +{ + m2m_resourceinstance->test_static_resource_instance(); +} + +TEST(M2MResourceInstance, copy_constructor) +{ + m2m_resourceinstance->test_copy_constructor(); +} + +TEST(M2MResourceInstance, assignment_constructor) +{ + m2m_resourceinstance->test_assignment_constructor(); +} + +TEST(M2MResourceInstance, base_type) +{ + m2m_resourceinstance->test_base_type(); +} + +TEST(M2MResourceInstance, test_handle_observation_attribute) +{ + m2m_resourceinstance->test_handle_observation_attribute(); +} + +TEST(M2MResourceInstance, test_set_execute_function) +{ + m2m_resourceinstance->test_set_execute_function(); +} + +TEST(M2MResourceInstance, test_execute) +{ + m2m_resourceinstance->test_execute(); +} + +TEST(M2MResourceInstance, test_resource_instance_type) +{ + m2m_resourceinstance->test_resource_instance_type(); +} + +TEST(M2MResourceInstance, test_set_value) +{ + m2m_resourceinstance->test_set_value(); +} + +TEST(M2MResourceInstance, test_clear_value) +{ + m2m_resourceinstance->test_clear_value(); +} + +TEST(M2MResourceInstance, test_get_value) +{ + m2m_resourceinstance->test_get_value(); +} + +TEST(M2MResourceInstance, test_value) +{ + m2m_resourceinstance->test_value(); +} + +TEST(M2MResourceInstance, test_value_length) +{ + m2m_resourceinstance->test_value_length(); +} + +TEST(M2MResourceInstance, test_handle_get_request) +{ + m2m_resourceinstance->test_handle_get_request(); +} + +TEST(M2MResourceInstance, test_handle_put_request) +{ + m2m_resourceinstance->test_handle_put_request(); +} + +TEST(M2MResourceInstance, test_set_resource_observer) +{ + m2m_resourceinstance->test_set_resource_observer(); +} + +TEST(M2MResourceInstance, test_get_object_instance_id) +{ + m2m_resourceinstance->test_get_object_instance_id(); +} + +TEST(M2MResourceInstance, test_get_object_name) +{ + m2m_resourceinstance->test_get_object_name(); +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresourceinstance/main.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresourceinstance/main.cpp new file mode 100644 index 0000000000..8841f0ecf1 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresourceinstance/main.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP( M2MResourceInstance); diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresourceinstance/test_m2mresourceinstance.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresourceinstance/test_m2mresourceinstance.cpp new file mode 100755 index 0000000000..5af453d8b7 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresourceinstance/test_m2mresourceinstance.cpp @@ -0,0 +1,782 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include "test_m2mresourceinstance.h" +#include "CppUTest/MemoryLeakDetectorMallocMacros.h" +#include "m2mbase_stub.h" +#include "m2mobservationhandler.h" +#include "m2mreporthandler.h" +#include "m2mreporthandler_stub.h" +#include "common_stub.h" +#include "m2mtlvdeserializer_stub.h" +static bool cb_visited = false; +static void callback_function(void *args) +{ + cb_visited = true; +} + +class MyTest{ +public: + void execute_function(void */*argument*/) { + visited = true; + } + + bool visited; +}; + +class TestReportObserver : public M2MReportObserver{ +public : + TestReportObserver() {} + ~TestReportObserver() {} + void observation_to_be_sent(m2m::Vector,bool){ } +}; + +class ResourceCallback : public M2MResourceCallback { + +public: + + ResourceCallback() : visited(false) {} + ~ResourceCallback(){} + void notification_update() { + visited = true; + } + + void clear() {visited = false;} + bool visited; +}; + +class Handler : public M2MObservationHandler { + +public: + + Handler(){} + ~Handler(){} + void observation_to_be_sent(M2MBase *, uint16_t, m2m::Vector, bool){ + visited = true; + } + void send_delayed_response(M2MBase *){} + void resource_to_be_deleted(const String &){visited=true;} + void remove_object(M2MBase *){visited = true;} + void value_updated(M2MBase *,const String&){visited = true;} + + void clear() {visited = false;} + bool visited; +}; + +class Callback : public M2MObjectInstanceCallback { + +public: + + Callback(){} + ~Callback(){} + void notification_update(M2MBase::Observation) { + visited = true; + } + + void clear() {visited = false;} + bool visited; +}; + + +Test_M2MResourceInstance::Test_M2MResourceInstance() +{ + callback = new Callback(); + handler = new Handler(); + resource_instance = new M2MResourceInstance("name", + "resource_type", + M2MResourceInstance::STRING, + *callback); + //resource_instance->_resource_callback = new ResourceCallback(); +} + +Test_M2MResourceInstance::~Test_M2MResourceInstance() +{ + delete resource_instance; + delete handler; + delete callback; +} + +void Test_M2MResourceInstance::test_copy_constructor() +{ + u_int8_t value[] = {"value"}; + resource_instance->set_value(value,(u_int32_t)sizeof(value)); + + M2MResourceInstance* copy = new M2MResourceInstance(*resource_instance); + u_int8_t* out_value = (u_int8_t*)malloc(sizeof(u_int8_t)); + u_int32_t out_size; + + copy->get_value(out_value,out_size); + CHECK(out_size == sizeof(value)); + free(out_value); + + delete copy; +} + +void Test_M2MResourceInstance::test_assignment_constructor() +{ + u_int8_t value[] = {"value"}; + resource_instance->set_value(value,(u_int32_t)sizeof(value)); + + M2MResourceInstance* res = new M2MResourceInstance("name", + "resource_type", + M2MResourceInstance::STRING, + *callback); + + u_int8_t value1[] = {"value1"}; + res->set_value(value1,(u_int32_t)sizeof(value1)); + + *res = *resource_instance; + + u_int8_t* out_value = (u_int8_t*)malloc(sizeof(u_int8_t)); + u_int32_t out_size; + + res->get_value(out_value,out_size); + + CHECK(out_size == sizeof(value)); + free(out_value); + + delete res; +} + + +void Test_M2MResourceInstance::test_resource_instance_type() +{ + CHECK(resource_instance->resource_instance_type() == M2MResourceInstance::STRING); +} + +void Test_M2MResourceInstance::test_static_resource_instance() +{ + u_int8_t value[] = {"value"}; + M2MResourceInstance *res = new M2MResourceInstance("name1", "type1", + M2MResourceInstance::INTEGER, + value, (uint32_t)sizeof(value), + *callback); + + CHECK(res != NULL); + delete res; +} + +void Test_M2MResourceInstance::test_base_type() +{ + m2mbase_stub::base_type = M2MBase::Resource; + CHECK(M2MBase::Resource == resource_instance->base_type()); +} + +void Test_M2MResourceInstance::test_handle_observation_attribute() +{ + char *d = "s"; + TestReportObserver obs; + m2mbase_stub::report = new M2MReportHandler(obs); + + CHECK(false == resource_instance->handle_observation_attribute(d)); + + resource_instance->_resource_type = M2MResourceInstance::INTEGER; + CHECK(false == resource_instance->handle_observation_attribute(d)); + + resource_instance->_resource_type = M2MResourceInstance::FLOAT; + CHECK(false == resource_instance->handle_observation_attribute(d)); + + m2mreporthandler_stub::bool_return = true; + CHECK(true == resource_instance->handle_observation_attribute(d)); + + m2mbase_stub::bool_value = false; + CHECK(true == resource_instance->handle_observation_attribute(d)); + + delete m2mbase_stub::report; + m2mbase_stub::report = NULL; +} + +void Test_M2MResourceInstance::test_set_execute_function() +{ + MyTest test; + resource_instance->set_execute_function(execute_callback(&test,&MyTest::execute_function)); + resource_instance->set_execute_function(callback_function); +} + +void Test_M2MResourceInstance::test_execute() +{ + MyTest test; + void *args = NULL; + + resource_instance->set_execute_function(execute_callback(&test,&MyTest::execute_function)); + resource_instance->execute(args); + + cb_visited = false; + resource_instance->set_execute_function(callback_function); + resource_instance->execute(args); + CHECK(true == cb_visited); + + // Check delete + cb_visited = false; + resource_instance->set_execute_function(callback_function); + resource_instance->execute(args); + CHECK(true == cb_visited); +} + +void Test_M2MResourceInstance::test_set_value() +{ + u_int8_t value[] = {"value2"}; + resource_instance->_value = (u_int8_t*)malloc(sizeof(u_int8_t)); + m2mbase_stub::bool_value = true; + + CHECK(resource_instance->set_value(value,(u_int32_t)sizeof(value)) == true); + CHECK( resource_instance->_value_length == sizeof(value)); + CHECK( *resource_instance->_value == *value); + + m2mbase_stub::observe = (M2MObservationHandler*)handler; + + u_int8_t value2[] = {"12"}; + CHECK(resource_instance->set_value(value2,(u_int32_t)sizeof(value2)) == true); + + u_int8_t value3[] = {"13"}; + CHECK(resource_instance->set_value(value3,(u_int32_t)sizeof(value3)) == true); + + CHECK(resource_instance->set_value(123456789) == true); + CHECK(memcmp(resource_instance->_value, "123456789", 9) == 0); + + // verify int value helper + CHECK(resource_instance->get_value_int() == 123456789); + + // verify string value helper + CHECK(resource_instance->get_value_string() == "123456789"); + + free(resource_instance->_value); + resource_instance->_value_length = 0; + + CHECK(resource_instance->set_value(NULL,0) == false); + + CHECK(resource_instance->set_value(NULL,0) == false); + + m2mbase_stub::observation_level_value = M2MBase::R_Attribute; + resource_instance->_value = (u_int8_t*)malloc(sizeof(value)+1); + memset(resource_instance->_value,0,sizeof(value)+1); + memcpy(resource_instance->_value,value,sizeof(value)); + resource_instance->_value_length = sizeof(value); + TestReportObserver obs; + m2mbase_stub::report = new M2MReportHandler(obs); + + u_int8_t value4[] = {"value4"}; + CHECK(resource_instance->set_value(value4,(u_int32_t)sizeof(value4)) == true); + + + m2mbase_stub::base_type = M2MBase::ResourceInstance; + m2mbase_stub::observation_level_value = M2MBase::O_Attribute; + resource_instance->_resource_type = M2MResourceInstance::INTEGER; + m2mbase_stub::mode_value = M2MBase::Dynamic; + ResourceCallback *resource_cb = new ResourceCallback(); + resource_instance->set_resource_observer(resource_cb); + CHECK(resource_instance->set_value(value2,(u_int32_t)sizeof(value2)) == true); + + // XXX: the callback will not be called on current code with combination of + // M2MBase::Dynamic and M2MBase::R_Attribute. + CHECK(resource_cb->visited == false); + + resource_cb->visited = false; + m2mbase_stub::observation_level_value = M2MBase::R_Attribute; + CHECK(resource_instance->set_value(value3,(u_int32_t)sizeof(value3)) == true); + CHECK(resource_cb->visited == true); + + resource_instance->set_resource_observer(NULL); + resource_cb->visited = false; + m2mbase_stub::observation_level_value = M2MBase::R_Attribute; + CHECK(resource_instance->set_value(value2,(u_int32_t)sizeof(value2)) == true); + CHECK(resource_cb->visited == false); + + + CHECK(resource_instance->set_value(value3,(u_int32_t)sizeof(value3)) == true); + + m2mbase_stub::observation_level_value = M2MBase::OI_Attribute; + + resource_instance->_resource_type = M2MResourceInstance::INTEGER; + + m2mbase_stub::mode_value = M2MBase::Dynamic; + + CHECK(resource_instance->set_value(value2,(u_int32_t)sizeof(value2)) == true); + + m2mbase_stub::observation_level_value = M2MBase::OOI_Attribute; + + resource_instance->_resource_type = M2MResourceInstance::INTEGER; + + m2mbase_stub::mode_value = M2MBase::Dynamic; + + CHECK(resource_instance->set_value(value2,(u_int32_t)sizeof(value2)) == true); + + delete m2mbase_stub::report; + m2mbase_stub::report = NULL; + delete resource_cb; +} + +void Test_M2MResourceInstance::test_clear_value() +{ + u_int8_t value[] = {"value"}; + resource_instance->_value = (u_int8_t*)malloc(sizeof(u_int8_t)); + + m2mbase_stub::observe = handler; + TestReportObserver obs; + m2mbase_stub::report = new M2MReportHandler(obs); + + CHECK(resource_instance->set_value(value,(u_int32_t)sizeof(value)) == true); + CHECK( resource_instance->_value_length == sizeof(value)); + CHECK( *resource_instance->_value == *value); + resource_instance->clear_value(); + + CHECK( resource_instance->_value_length == 0); + CHECK( resource_instance->_value == NULL); + + m2mbase_stub::bool_value = true; + m2mbase_stub::mode_value = M2MBase::Dynamic; + m2mbase_stub::observation_level_value = M2MBase::R_Attribute; + resource_instance->_resource_type = M2MResourceInstance::INTEGER; + resource_instance->clear_value(); + + CHECK( resource_instance->_value_length == 0); + CHECK( resource_instance->_value == NULL); + + delete m2mbase_stub::report; + m2mbase_stub::report = NULL; +} + +void Test_M2MResourceInstance::test_get_value() +{ + u_int8_t test_value[] = {"value3"}; + u_int32_t value_length((u_int32_t)sizeof(test_value)); + + resource_instance->_value = (u_int8_t *)malloc(value_length); + resource_instance->_value_length = value_length; + memcpy((u_int8_t *)resource_instance->_value, (u_int8_t *)test_value, value_length); + + resource_instance->clear_value(); + + CHECK(resource_instance->_value == NULL); + +} + +void Test_M2MResourceInstance::test_value() +{ + CHECK(resource_instance->value() == NULL); +} + +void Test_M2MResourceInstance::test_value_length() +{ + CHECK(resource_instance->value_length() == 0); +} + +void Test_M2MResourceInstance::test_handle_get_request() +{ + uint8_t value[] = {"name"}; + sn_coap_hdr_s *coap_header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(coap_header, 0, sizeof(sn_coap_hdr_s)); + + coap_header->uri_path_ptr = value; + coap_header->uri_path_len = sizeof(value); + + coap_header->msg_code = COAP_MSG_CODE_REQUEST_GET; + + String *name = new String("name"); + common_stub::int_value = 0; + m2mbase_stub::string_value = name; + + m2mbase_stub::operation = M2MBase::GET_ALLOWED; + m2mbase_stub::uint8_value = 200; + common_stub::coap_header = (sn_coap_hdr_ *)malloc(sizeof(sn_coap_hdr_)); + memset(common_stub::coap_header,0,sizeof(sn_coap_hdr_)); + + coap_header->token_ptr = (uint8_t*)malloc(sizeof(value)); + memcpy(coap_header->token_ptr, value, sizeof(value)); + + coap_header->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + coap_header->options_list_ptr->observe = 0; + + coap_header->content_type_ptr = (uint8_t*)malloc(1); + coap_header->content_type_len = 1; + *coap_header->content_type_ptr = 110; + + CHECK(resource_instance->handle_get_request(NULL,coap_header,handler) != NULL); + + if(coap_header->content_type_ptr) { + free(coap_header->content_type_ptr); + coap_header->content_type_ptr = NULL; + } + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + // OMA OPAQUE + resource_instance->_resource_type = M2MResourceInstance::OPAQUE; + + CHECK(resource_instance->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + // Not OMA TLV or JSON + m2mbase_stub::uint8_value = 110; + CHECK(resource_instance->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + // OMA TLV + m2mbase_stub::uint8_value = 99; + CHECK(resource_instance->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + // OMA JSON + m2mbase_stub::uint8_value = 100; + CHECK(resource_instance->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + coap_header->options_list_ptr->observe = 1; + + uint8_t obs = 0; + coap_header->options_list_ptr->observe_ptr = (uint8_t*)malloc(sizeof(obs)); + memcpy(coap_header->options_list_ptr->observe_ptr,&obs,sizeof(obs)); + coap_header->options_list_ptr->observe_len = 0; + m2mbase_stub::uint16_value = 0x1c1c; + m2mbase_stub::bool_value = true; + + CHECK(resource_instance->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->observe_ptr) { + free(common_stub::coap_header->options_list_ptr->observe_ptr); + common_stub::coap_header->options_list_ptr->observe_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + // Not observable + m2mbase_stub::bool_value = false; + CHECK(resource_instance->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->observe_ptr) { + free(common_stub::coap_header->options_list_ptr->observe_ptr); + common_stub::coap_header->options_list_ptr->observe_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + m2mbase_stub::bool_value = true; + + coap_header->options_list_ptr->observe_len = 1; + + CHECK(resource_instance->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + + if(common_stub::coap_header->options_list_ptr->observe_ptr) { + free(common_stub::coap_header->options_list_ptr->observe_ptr); + common_stub::coap_header->options_list_ptr->observe_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + + obs = 1; + memcpy(coap_header->options_list_ptr->observe_ptr,&obs,sizeof(obs)); + CHECK(resource_instance->handle_get_request(NULL,coap_header,handler) != NULL); + + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + + if(common_stub::coap_header->options_list_ptr->observe_ptr) { + free(common_stub::coap_header->options_list_ptr->observe_ptr); + common_stub::coap_header->options_list_ptr->observe_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr->max_age_ptr) { + free(common_stub::coap_header->options_list_ptr->max_age_ptr); + common_stub::coap_header->options_list_ptr->max_age_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + + m2mbase_stub::operation = M2MBase::NOT_ALLOWED; + CHECK(resource_instance->handle_get_request(NULL,coap_header,handler) != NULL); + + CHECK(resource_instance->handle_get_request(NULL,NULL,handler) != NULL); + + if(coap_header->token_ptr) { + free(coap_header->token_ptr); + coap_header->token_ptr = NULL; + } + if(coap_header->content_type_ptr) { + free(coap_header->content_type_ptr); + coap_header->content_type_ptr = NULL; + } + if(coap_header->options_list_ptr->observe_ptr) { + free(coap_header->options_list_ptr->observe_ptr); + coap_header->options_list_ptr->observe_ptr = NULL; + } + if(coap_header->options_list_ptr) { + free(coap_header->options_list_ptr); + coap_header->options_list_ptr = NULL; + } + + if(common_stub::coap_header){ + if(common_stub::coap_header->content_type_ptr) { + free(common_stub::coap_header->content_type_ptr); + common_stub::coap_header->content_type_ptr = NULL; + } + if(common_stub::coap_header->options_list_ptr) { + free(common_stub::coap_header->options_list_ptr); + common_stub::coap_header->options_list_ptr = NULL; + } + free(common_stub::coap_header); + common_stub::coap_header = NULL; + } + free(coap_header); + coap_header = NULL; + + delete name; + name = NULL; + + m2mbase_stub::clear(); + common_stub::clear(); +} + +void Test_M2MResourceInstance::test_handle_put_request() +{ + uint8_t value[] = {"name"}; + bool execute_value_updated = false; + sn_coap_hdr_s *coap_header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s)); + memset(coap_header, 0, sizeof(sn_coap_hdr_s)); + + coap_header->uri_path_ptr = value; + coap_header->uri_path_len = sizeof(value); + + coap_header->msg_code = COAP_MSG_CODE_REQUEST_PUT; + + String *name = new String("name"); + common_stub::int_value = 0; + m2mbase_stub::string_value = name; + + m2mbase_stub::operation = M2MBase::PUT_ALLOWED; + m2mbase_stub::uint8_value = 200; + + common_stub::coap_header = (sn_coap_hdr_ *)malloc(sizeof(sn_coap_hdr_)); + memset(common_stub::coap_header,0,sizeof(sn_coap_hdr_)); + + coap_header->payload_ptr = (uint8_t*)malloc(1); + + coap_header->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + coap_header->options_list_ptr->uri_query_ptr = value; + coap_header->options_list_ptr->uri_query_len = sizeof(value); + + coap_header->content_type_ptr = (uint8_t*)malloc(1); + coap_header->content_type_len = 1; + *coap_header->content_type_ptr = 99; + m2mtlvdeserializer_stub::bool_value = true; + + m2mbase_stub::bool_value = false; + + sn_coap_hdr_s *coap_response = NULL; + coap_response = resource_instance->handle_put_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + free(coap_header->options_list_ptr); + coap_header->options_list_ptr = NULL; + + coap_response = resource_instance->handle_put_request(NULL,coap_header,handler,execute_value_updated); + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + m2mtlvdeserializer_stub::bool_value = false; + + coap_response = resource_instance->handle_put_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + *coap_header->content_type_ptr = 100; + + coap_response = resource_instance->handle_put_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + m2mbase_stub::bool_value = true; + + coap_response = resource_instance->handle_put_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + m2mbase_stub::operation = M2MBase::NOT_ALLOWED; + + coap_response = resource_instance->handle_put_request(NULL,coap_header,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + coap_response = resource_instance->handle_put_request(NULL,NULL,handler,execute_value_updated); + + CHECK( coap_response != NULL); + if(coap_response) { + if(coap_response->content_type_ptr) { + free(coap_response->content_type_ptr); + coap_response->content_type_ptr = NULL; + } + } + + free(coap_header->content_type_ptr); + free(coap_header->options_list_ptr); + free(coap_header->payload_ptr); + free(common_stub::coap_header); + delete name; + free(coap_header); + + m2mtlvdeserializer_stub::clear(); + common_stub::clear(); + m2mbase_stub::clear(); +} + +void Test_M2MResourceInstance::test_set_resource_observer() +{ + ResourceCallback *resource_cb = new ResourceCallback(); + resource_instance->set_resource_observer(resource_cb); + CHECK(resource_instance->_resource_callback == resource_cb) + delete resource_cb; +} + + +void Test_M2MResourceInstance::test_get_object_name() +{ + resource_instance->_object_name = "object"; + CHECK(resource_instance->object_name() == "object"); +} + +void Test_M2MResourceInstance::test_get_object_instance_id() +{ + resource_instance->_object_instance_id = 100; + CHECK(resource_instance->object_instance_id() == 100); +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresourceinstance/test_m2mresourceinstance.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresourceinstance/test_m2mresourceinstance.h new file mode 100755 index 0000000000..7d512556e3 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mresourceinstance/test_m2mresourceinstance.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TEST_M2M_RESOURCE_INSTANCE_H +#define TEST_M2M_RESOURCE_INSTANCE_H + +#include "m2mresourceinstance.h" + +class Handler; +class Callback; +class ResourceCallback; + +class Test_M2MResourceInstance +{ +public: + Test_M2MResourceInstance(); + + ~Test_M2MResourceInstance(); + + void test_copy_constructor(); + + void test_assignment_constructor(); + + void test_static_resource_instance(); + + void test_base_type(); + + void test_resource_instance_type(); + + void test_handle_observation_attribute(); + + void test_set_execute_function(); + + void test_execute(); + + void test_set_value(); + + void test_clear_value(); + + void test_get_value(); + + void test_value(); + + void test_value_length(); + + void test_handle_get_request(); + + void test_handle_put_request(); + + void test_set_resource_observer(); + + void test_get_object_name(); + + void test_get_object_instance_id(); + + M2MResourceInstance* resource_instance; + + Callback *callback; + + Handler* handler; +}; + +#endif // TEST_M2M_RESOURCE_INSTANCE_H diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2msecurity/CMakeLists.txt b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2msecurity/CMakeLists.txt new file mode 100644 index 0000000000..541d4c6593 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2msecurity/CMakeLists.txt @@ -0,0 +1,26 @@ +if(TARGET_LIKE_LINUX) +include("../includes.txt") +add_executable(m2msecurity + "main.cpp" + "m2msecuritytest.cpp" + "test_m2msecurity.cpp" + "../stub/m2mobject_stub.cpp" + "../stub/m2mstring_stub.cpp" + "../stub/m2mobjectinstance_stub.cpp" + "../stub/m2mresource_stub.cpp" + "../stub/m2mresourceinstance_stub.cpp" + "../stub/m2mbase_stub.cpp" + "../../../../source/m2msecurity.cpp" +) +target_link_libraries(m2msecurity + CppUTest + CppUTestExt +) +set_target_properties(m2msecurity +PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" + LINK_FLAGS "${UTEST_LINK_FLAGS}") + +set(binary "m2msecurity") +add_test(m2msecurity ${binary}) + +endif() diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2msecurity/m2msecuritytest.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2msecurity/m2msecuritytest.cpp new file mode 100644 index 0000000000..e960f3efdf --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2msecurity/m2msecuritytest.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//CppUTest includes should be after your and system includes +#include "CppUTest/TestHarness.h" +#include "test_m2msecurity.h" + +TEST_GROUP(M2MSecurity) +{ + Test_M2MSecurity* m2m_security; + + void setup() + { + m2m_security = new Test_M2MSecurity(); + } + void teardown() + { + delete m2m_security; + } +}; + +TEST(M2MSecurity, Create) +{ + CHECK(m2m_security != NULL); +} + +TEST(M2MSecurity, create_resource_int) +{ + m2m_security->test_create_resource_int(); +} + +TEST(M2MSecurity, delete_resource) +{ + m2m_security->test_delete_resource(); +} + +TEST(M2MSecurity, set_resource_value_int) +{ + m2m_security->test_set_resource_value_int(); +} + +TEST(M2MSecurity, set_resource_value_string) +{ + m2m_security->test_set_resource_value_string(); +} + +TEST(M2MSecurity, set_resource_value_buffer) +{ + m2m_security->test_set_resource_value_buffer(); +} + +TEST(M2MSecurity, resource_value_int) +{ + m2m_security->test_resource_value_int(); +} + +TEST(M2MSecurity, resource_value_string) +{ + m2m_security->test_resource_value_string(); +} + +TEST(M2MSecurity, resource_value_buffer) +{ + m2m_security->test_resource_value_buffer(); +} + +TEST(M2MSecurity, is_resource_present) +{ + m2m_security->test_is_resource_present(); +} + +TEST(M2MSecurity, total_resource_count) +{ + m2m_security->test_total_resource_count(); +} + +TEST(M2MSecurity, m2m_server_constructor) +{ + m2m_security->test_m2m_server_constructor(); +} + +TEST(M2MSecurity, server_type) +{ + m2m_security->test_server_type(); +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2msecurity/main.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2msecurity/main.cpp new file mode 100644 index 0000000000..aace7dd10b --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2msecurity/main.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP( M2MSecurity); diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2msecurity/test_m2msecurity.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2msecurity/test_m2msecurity.cpp new file mode 100755 index 0000000000..6a55392d4b --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2msecurity/test_m2msecurity.cpp @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include "test_m2msecurity.h" +#include "m2mobject_stub.h" +#include "m2mobjectinstance_stub.h" +#include "m2mresource_stub.h" +#include "m2mresourceinstance_stub.h" +#include "m2mbase_stub.h" + +class Callback : public M2MObjectCallback { + +public: + + Callback(){} + ~Callback(){} + void notification_update(uint16_t obj_instance_id) { + visited = true; + } + + void clear() {visited = false;} + bool visited; +}; + +Test_M2MSecurity::Test_M2MSecurity() +{ + callback = new Callback(); + m2mobject_stub::inst = new M2MObjectInstance("name",*callback); + m2mresource_stub::bool_value = true; + m2mobjectinstance_stub::create_resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + security = new M2MSecurity(M2MSecurity::Bootstrap); + + delete m2mobjectinstance_stub::create_resource; + m2mobjectinstance_stub::create_resource = NULL; +} + +Test_M2MSecurity::~Test_M2MSecurity() +{ + delete m2mobject_stub::inst; + m2mobject_stub::inst = NULL; + m2mobject_stub::clear(); + m2mobjectinstance_stub::clear(); + m2mresource_stub::clear(); + m2mbase_stub::clear(); + delete security; + delete callback; +} + +void Test_M2MSecurity::test_create_resource_int() +{ + m2mobjectinstance_stub::create_resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + + CHECK(security->create_resource(M2MSecurity::M2MServerUri,10) == NULL); + CHECK(security->create_resource(M2MSecurity::BootstrapServer,10) == NULL); + CHECK(security->create_resource(M2MSecurity::SecurityMode,10) == NULL); + CHECK(security->create_resource(M2MSecurity::PublicKey,10) == NULL); + CHECK(security->create_resource(M2MSecurity::ServerPublicKey,10) == NULL); + CHECK(security->create_resource(M2MSecurity::Secretkey,10) == NULL); + CHECK(security->create_resource(M2MSecurity::SMSBindingKey,10) == NULL); + CHECK(security->create_resource(M2MSecurity::SMSBindingSecretKey,10) == NULL); + + CHECK(security->create_resource(M2MSecurity::M2MServerSMSNumber,10) != NULL); + CHECK(security->create_resource(M2MSecurity::ShortServerID,10) != NULL); + CHECK(security->create_resource(M2MSecurity::ClientHoldOffTime,10) != NULL); + CHECK(security->create_resource(M2MSecurity::SMSSecurityMode,10) != NULL); + + delete m2mobjectinstance_stub::create_resource; + m2mobjectinstance_stub::create_resource = NULL; +} + +void Test_M2MSecurity::test_delete_resource() +{ + m2mresourceinstance_stub::bool_value = true; + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + + CHECK(security->delete_resource(M2MSecurity::SMSBindingSecretKey) == false); + CHECK(security->delete_resource(M2MSecurity::SMSBindingKey) == false); + CHECK(security->delete_resource(M2MSecurity::M2MServerUri) == false); + CHECK(security->delete_resource(M2MSecurity::Secretkey) == false); + CHECK(security->delete_resource(M2MSecurity::ServerPublicKey) == false); + CHECK(security->delete_resource(M2MSecurity::BootstrapServer) == false); + CHECK(security->delete_resource(M2MSecurity::PublicKey) == false); + CHECK(security->delete_resource(M2MSecurity::SecurityMode) == false); + + m2mobjectinstance_stub::bool_value = true; + + CHECK(security->delete_resource(M2MSecurity::M2MServerSMSNumber) == true); + CHECK(security->delete_resource(M2MSecurity::ShortServerID) == true); + CHECK(security->delete_resource(M2MSecurity::ClientHoldOffTime) == true); + CHECK(security->delete_resource(M2MSecurity::SMSSecurityMode) == true); + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; +} + +void Test_M2MSecurity::test_set_resource_value_string() +{ + m2mresourceinstance_stub::bool_value = true; + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + + CHECK(security->set_resource_value(M2MSecurity::M2MServerUri,"test") == true); + + CHECK(security->set_resource_value(M2MSecurity::M2MServerSMSNumber,"test") == false); + CHECK(security->set_resource_value(M2MSecurity::ShortServerID,"test") == false); + CHECK(security->set_resource_value(M2MSecurity::SMSBindingKey,"test") == false); + CHECK(security->set_resource_value(M2MSecurity::SMSBindingSecretKey,"test") == false); + CHECK(security->set_resource_value(M2MSecurity::ClientHoldOffTime,"test") == false); + CHECK(security->set_resource_value(M2MSecurity::SMSSecurityMode,"test") == false); + CHECK(security->set_resource_value(M2MSecurity::Secretkey,"test") == false); + CHECK(security->set_resource_value(M2MSecurity::ServerPublicKey,"test") == false); + CHECK(security->set_resource_value(M2MSecurity::PublicKey,"test") == false); + CHECK(security->set_resource_value(M2MSecurity::BootstrapServer,"test") == false); + CHECK(security->set_resource_value(M2MSecurity::SecurityMode,"test") == false); + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; +} + +void Test_M2MSecurity::test_set_resource_value_int() +{ + m2mresourceinstance_stub::bool_value = true; + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name", "name", M2MResourceInstance::STRING,M2MBase::Dynamic); + + CHECK(security->set_resource_value(M2MSecurity::M2MServerUri,10) == false); + CHECK(security->set_resource_value(M2MSecurity::SMSBindingKey,10) == false); + CHECK(security->set_resource_value(M2MSecurity::SMSBindingSecretKey,10) == false); + CHECK(security->set_resource_value(M2MSecurity::Secretkey,10) == false); + CHECK(security->set_resource_value(M2MSecurity::ServerPublicKey,10) == false); + CHECK(security->set_resource_value(M2MSecurity::PublicKey,10) == false); + CHECK(security->set_resource_value(M2MSecurity::BootstrapServer,10) == false); + + CHECK(security->set_resource_value(M2MSecurity::SecurityMode,10) == true); + CHECK(security->set_resource_value(M2MSecurity::SMSSecurityMode,10) == true); + CHECK(security->set_resource_value(M2MSecurity::M2MServerSMSNumber,10) == true); + CHECK(security->set_resource_value(M2MSecurity::ShortServerID,10) == true); + CHECK(security->set_resource_value(M2MSecurity::ClientHoldOffTime,10) == true); + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; +} + +void Test_M2MSecurity::test_set_resource_value_buffer() +{ + m2mresourceinstance_stub::bool_value = true; + + uint8_t value[] = {"value"}; + uint16_t length = (uint16_t)sizeof(value); + + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + + CHECK(security->set_resource_value(M2MSecurity::Secretkey,value,length) == true); + CHECK(security->set_resource_value(M2MSecurity::ServerPublicKey,value,length) == true); + CHECK(security->set_resource_value(M2MSecurity::PublicKey,value,length) == true); + + CHECK(security->set_resource_value(M2MSecurity::M2MServerUri,value,length) == false); + CHECK(security->set_resource_value(M2MSecurity::SMSBindingKey,value,length) == false); + CHECK(security->set_resource_value(M2MSecurity::SMSBindingSecretKey,value,length) == false); + CHECK(security->set_resource_value(M2MSecurity::BootstrapServer,value,length) == false); + + CHECK(security->set_resource_value(M2MSecurity::SecurityMode,value,length) == false); + CHECK(security->set_resource_value(M2MSecurity::SMSSecurityMode,value,length) == false); + CHECK(security->set_resource_value(M2MSecurity::M2MServerSMSNumber,value,length) == false); + CHECK(security->set_resource_value(M2MSecurity::ShortServerID,value,length) == false); + CHECK(security->set_resource_value(M2MSecurity::ClientHoldOffTime,value,length) == false); + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; +} + +void Test_M2MSecurity::test_resource_value_int() +{ + m2mresourceinstance_stub::bool_value = true; + + uint8_t value[] = {"10"}; + //m2mresourceinstance_stub::value = (uint8_t*)malloc((uint32_t)sizeof(value)); + uint8_t size = 0; + m2mresourceinstance_stub::value = String::convert_integer_to_array(10,size); + /*memset(m2mresourceinstance_stub::value,0,(uint32_t)size); + memcpy(m2mresourceinstance_stub::value, 10, size);*/ + m2mresourceinstance_stub::int_value = (uint16_t)size; + + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst, + "name", + "type", + M2MResourceInstance::INTEGER, + M2MBase::Dynamic); + + CHECK(security->resource_value_int(M2MSecurity::SecurityMode) == 10); + CHECK(security->resource_value_int(M2MSecurity::SMSSecurityMode) == 10); + CHECK(security->resource_value_int(M2MSecurity::M2MServerSMSNumber) == 10); + CHECK(security->resource_value_int(M2MSecurity::ShortServerID) == 10); + CHECK(security->resource_value_int(M2MSecurity::ClientHoldOffTime) == 10); + CHECK(security->resource_value_int(M2MSecurity::BootstrapServer) == 0); + CHECK(security->resource_value_int(M2MSecurity::PublicKey) == 0); + CHECK(security->resource_value_int(M2MSecurity::ServerPublicKey) == 0); + CHECK(security->resource_value_int(M2MSecurity::Secretkey) == 0); + CHECK(security->resource_value_int(M2MSecurity::SMSBindingSecretKey) == 0); + CHECK(security->resource_value_int(M2MSecurity::SMSBindingKey) == 0); + CHECK(security->resource_value_int(M2MSecurity::M2MServerUri) == 0); + + security->clear_resources(); + CHECK(security->resource_value_int(M2MSecurity::SecurityMode) == 0); + CHECK(security->resource_value_int(M2MSecurity::SMSSecurityMode) == 0); + CHECK(security->resource_value_int(M2MSecurity::M2MServerSMSNumber) == 0); + CHECK(security->resource_value_int(M2MSecurity::ShortServerID) == 0); + CHECK(security->resource_value_int(M2MSecurity::ClientHoldOffTime) == 0); + CHECK(security->resource_value_int(M2MSecurity::BootstrapServer) == 0); + CHECK(security->resource_value_int(M2MSecurity::PublicKey) == 0); + CHECK(security->resource_value_int(M2MSecurity::ServerPublicKey) == 0); + CHECK(security->resource_value_int(M2MSecurity::Secretkey) == 0); + CHECK(security->resource_value_int(M2MSecurity::SMSBindingSecretKey) == 0); + CHECK(security->resource_value_int(M2MSecurity::SMSBindingKey) == 0); + CHECK(security->resource_value_int(M2MSecurity::M2MServerUri) == 0); + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; + + free(m2mresourceinstance_stub::value); + m2mresourceinstance_stub::value = NULL; +} + +void Test_M2MSecurity::test_resource_value_string() +{ + m2mresourceinstance_stub::bool_value = true; + String test = "string"; + uint8_t value[] = {"string"}; + m2mresourceinstance_stub::value = (uint8_t*)malloc((uint32_t)sizeof(value)); + memset(m2mresourceinstance_stub::value,0,(uint32_t)sizeof(value)); + memcpy(m2mresourceinstance_stub::value,value,sizeof(value)); + m2mresourceinstance_stub::int_value = (uint16_t)sizeof(value); + + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + + CHECK(security->resource_value_string(M2MSecurity::M2MServerUri) == test); + + CHECK(security->resource_value_string(M2MSecurity::SMSBindingKey) == ""); + CHECK(security->resource_value_string(M2MSecurity::SMSBindingSecretKey) == ""); + CHECK(security->resource_value_string(M2MSecurity::Secretkey) == ""); + CHECK(security->resource_value_string(M2MSecurity::ServerPublicKey) == ""); + CHECK(security->resource_value_string(M2MSecurity::PublicKey) == ""); + CHECK(security->resource_value_string(M2MSecurity::BootstrapServer) == ""); + CHECK(security->resource_value_string(M2MSecurity::ClientHoldOffTime) == ""); + CHECK(security->resource_value_string(M2MSecurity::ShortServerID) == ""); + CHECK(security->resource_value_string(M2MSecurity::M2MServerSMSNumber) == ""); + CHECK(security->resource_value_string(M2MSecurity::SMSSecurityMode) == ""); + CHECK(security->resource_value_string(M2MSecurity::SecurityMode) == ""); + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; + + free(m2mresourceinstance_stub::value); + m2mresourceinstance_stub::value = NULL; +} + +void Test_M2MSecurity::test_resource_value_buffer() +{ + m2mresourceinstance_stub::bool_value = true; + + uint8_t value[] = {"buffer"}; + uint8_t *out_value = NULL; + + m2mresourceinstance_stub::value = (uint8_t*)malloc((uint32_t)sizeof(value)); + memset(m2mresourceinstance_stub::value,0,(uint32_t)sizeof(value)); + memcpy(m2mresourceinstance_stub::value,value,sizeof(value)); + m2mresourceinstance_stub::int_value = (uint16_t)sizeof(value); + + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + + CHECK(security->resource_value_buffer(M2MSecurity::Secretkey,out_value) != 0); + CHECK(security->resource_value_buffer(M2MSecurity::ServerPublicKey,out_value) != 0); + CHECK(security->resource_value_buffer(M2MSecurity::PublicKey,out_value) != 0); + + CHECK(security->resource_value_buffer(M2MSecurity::M2MServerUri,out_value) == 0); + + CHECK(security->resource_value_buffer(M2MSecurity::SMSBindingKey,out_value) == 0); + CHECK(security->resource_value_buffer(M2MSecurity::SMSBindingSecretKey,out_value) == 0); + CHECK(security->resource_value_buffer(M2MSecurity::BootstrapServer,out_value) == 0); + CHECK(security->resource_value_buffer(M2MSecurity::ClientHoldOffTime,out_value) == 0); + CHECK(security->resource_value_buffer(M2MSecurity::ShortServerID,out_value) == 0); + CHECK(security->resource_value_buffer(M2MSecurity::M2MServerSMSNumber,out_value) == 0); + CHECK(security->resource_value_buffer(M2MSecurity::SMSSecurityMode,out_value) == 0); + CHECK(security->resource_value_buffer(M2MSecurity::SecurityMode,out_value) == 0); + + const uint8_t *outvalue = NULL; + CHECK(security->resource_value_buffer(M2MSecurity::Secretkey,outvalue) != 0); + CHECK(security->resource_value_buffer(M2MSecurity::ServerPublicKey,outvalue) != 0); + CHECK(security->resource_value_buffer(M2MSecurity::PublicKey,outvalue) != 0); + + free(out_value); + out_value = NULL; + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; + + free(m2mresourceinstance_stub::value); + m2mresourceinstance_stub::value = NULL; +} + +void Test_M2MSecurity::test_is_resource_present() +{ + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + + CHECK(security->is_resource_present(M2MSecurity::M2MServerUri) == true); + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; + + CHECK(security->is_resource_present(M2MSecurity::ClientHoldOffTime) == false); +} + +void Test_M2MSecurity::test_total_resource_count() +{ + M2MResource *res = new M2MResource(*m2mobject_stub::inst,"test","test",M2MResourceInstance::STRING,M2MBase::Dynamic); + + m2mobjectinstance_stub::resource_list.push_back(res); + M2MResource *res2 = new M2MResource(*m2mobject_stub::inst,"test","test",M2MResourceInstance::STRING,M2MBase::Dynamic); + + m2mobjectinstance_stub::resource_list.push_back(res2); + + CHECK(security->total_resource_count() == 2); + + m2mobjectinstance_stub::resource_list.clear(); + + delete res2; + delete res; +} + +void Test_M2MSecurity::test_m2m_server_constructor() +{ + m2mobjectinstance_stub::create_resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + + M2MSecurity* sec = new M2MSecurity(M2MSecurity::M2MServer); + CHECK(M2MSecurity::M2MServer == sec->server_type()); + + delete sec; + delete m2mobjectinstance_stub::create_resource; + m2mobjectinstance_stub::create_resource = NULL; +} + +void Test_M2MSecurity::test_server_type() +{ + CHECK(M2MSecurity::Bootstrap ==security->server_type()); +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2msecurity/test_m2msecurity.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2msecurity/test_m2msecurity.h new file mode 100755 index 0000000000..dff2fde8ba --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2msecurity/test_m2msecurity.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TEST_M2M_SECURITY_H +#define TEST_M2M_SECURITY_H + +#include "m2msecurity.h" + +class Callback; + +class Test_M2MSecurity +{ +public: + Test_M2MSecurity(); + virtual ~Test_M2MSecurity(); + + void test_create_resource_int(); + + void test_create_resource_string(); + + void test_delete_resource(); + + void test_set_resource_value_int(); + + void test_set_resource_value_string(); + + void test_set_resource_value_buffer(); + + void test_resource_value_int(); + + void test_resource_value_string(); + + void test_resource_value_buffer(); + + void test_is_resource_present(); + + void test_total_resource_count(); + + void test_m2m_server_constructor(); + + void test_server_type(); + + M2MSecurity* security; + Callback* callback; +}; + +#endif // TEST_M2M_SECURITY_H diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mserver/CMakeLists.txt b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mserver/CMakeLists.txt new file mode 100644 index 0000000000..14e8db32e2 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mserver/CMakeLists.txt @@ -0,0 +1,26 @@ +if(TARGET_LIKE_LINUX) +include("../includes.txt") +add_executable(m2mserver + "main.cpp" + "m2mservertest.cpp" + "test_m2mserver.cpp" + "../stub/m2mobject_stub.cpp" + "../stub/m2mstring_stub.cpp" + "../stub/m2mobjectinstance_stub.cpp" + "../stub/m2mresource_stub.cpp" + "../stub/m2mresourceinstance_stub.cpp" + "../stub/m2mbase_stub.cpp" + "../../../../source/m2mserver.cpp" +) + +target_link_libraries(m2mserver + CppUTest + CppUTestExt +) +set_target_properties(m2mserver +PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" + LINK_FLAGS "${UTEST_LINK_FLAGS}") +set(binary "m2mserver") +add_test(m2mserver ${binary}) + +endif() diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mserver/m2mservertest.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mserver/m2mservertest.cpp new file mode 100644 index 0000000000..cc54cd9dda --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mserver/m2mservertest.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//CppUTest includes should be after your and system includes +#include "CppUTest/TestHarness.h" +#include "test_m2mserver.h" + +TEST_GROUP(M2MServer) +{ + Test_M2MServer* m2m_server; + + void setup() + { + m2m_server = new Test_M2MServer(); + } + void teardown() + { + delete m2m_server; + } +}; + +TEST(M2MServer, Create) +{ + CHECK(m2m_server->server != NULL); +} + +TEST(M2MServer, create_resource_int) +{ + m2m_server->test_create_resource_int(); +} + +TEST(M2MServer, create_resource) +{ + m2m_server->test_create_resource(); +} + +TEST(M2MServer, delete_resource) +{ + m2m_server->test_delete_resource(); +} + +TEST(M2MServer, set_resource_value_int) +{ + m2m_server->test_set_resource_value_int(); +} + +TEST(M2MServer, set_resource_value_string) +{ + m2m_server->test_set_resource_value_string(); +} + +TEST(M2MServer, resource_value_int) +{ + m2m_server->test_resource_value_int(); +} + +TEST(M2MServer, resource_value_string) +{ + m2m_server->test_resource_value_string(); +} + +TEST(M2MServer, is_resource_present) +{ + m2m_server->test_is_resource_present(); +} + +TEST(M2MServer, total_resource_count) +{ + m2m_server->test_total_resource_count(); +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mserver/main.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mserver/main.cpp new file mode 100644 index 0000000000..796460cee7 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mserver/main.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP( M2MServer); diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mserver/test_m2mserver.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mserver/test_m2mserver.cpp new file mode 100755 index 0000000000..3862275c20 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mserver/test_m2mserver.cpp @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include "test_m2mserver.h" +#include "m2mobject_stub.h" +#include "m2mobjectinstance_stub.h" +#include "m2mresource_stub.h" +#include "m2mresourceinstance_stub.h" +#include "m2mbase_stub.h" + +class Callback : public M2MObjectCallback { + +public: + + Callback(){} + ~Callback(){} + void notification_update(uint16_t obj_instance_id) { + visited = true; + } + + void clear() {visited = false;} + bool visited; +}; + +Test_M2MServer::Test_M2MServer() +{ + callback = new Callback(); + m2mobject_stub::inst = new M2MObjectInstance("name",*callback); + m2mresource_stub::bool_value = true; + m2mobjectinstance_stub::create_resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + server = new M2MServer(); + + delete m2mobjectinstance_stub::create_resource; + m2mobjectinstance_stub::create_resource = NULL; +} + +Test_M2MServer::~Test_M2MServer() +{ + delete m2mobject_stub::inst; + m2mobject_stub::inst = NULL; + + m2mobject_stub::clear(); + m2mobjectinstance_stub::clear(); + m2mresource_stub::clear(); + m2mbase_stub::clear(); + delete server; + delete callback; +} + +void Test_M2MServer::test_create_resource_int() +{ + m2mobjectinstance_stub::create_resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + + CHECK(server->create_resource(M2MServer::DefaultMinPeriod,10) != NULL); + CHECK(server->create_resource(M2MServer::DefaultMaxPeriod,10) != NULL); + CHECK(server->create_resource(M2MServer::DisableTimeout,10) != NULL); + + CHECK(server->create_resource(M2MServer::ShortServerID,10) == NULL); + CHECK(server->create_resource(M2MServer::Lifetime,10) == NULL); + CHECK(server->create_resource(M2MServer::Disable,10) == NULL); + CHECK(server->create_resource(M2MServer::Binding,10) == NULL); + CHECK(server->create_resource(M2MServer::NotificationStorage,10) == NULL); + CHECK(server->create_resource(M2MServer::Binding,10) == NULL); + CHECK(server->create_resource(M2MServer::RegistrationUpdate,10) == NULL); + + delete m2mobjectinstance_stub::create_resource; + m2mobjectinstance_stub::create_resource = NULL; +} + +void Test_M2MServer::test_create_resource() +{ + m2mobjectinstance_stub::create_resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + + CHECK(server->create_resource(M2MServer::Disable) != NULL); + + CHECK(server->create_resource(M2MServer::DefaultMinPeriod) == NULL); + CHECK(server->create_resource(M2MServer::DefaultMaxPeriod) == NULL); + CHECK(server->create_resource(M2MServer::DefaultMaxPeriod) == NULL); + CHECK(server->create_resource(M2MServer::ShortServerID) == NULL); + CHECK(server->create_resource(M2MServer::Lifetime) == NULL); + CHECK(server->create_resource(M2MServer::DisableTimeout) == NULL); + CHECK(server->create_resource(M2MServer::Binding) == NULL); + CHECK(server->create_resource(M2MServer::NotificationStorage) == NULL); + CHECK(server->create_resource(M2MServer::RegistrationUpdate) == NULL); + + delete m2mobjectinstance_stub::create_resource; + m2mobjectinstance_stub::create_resource = NULL; +} + +void Test_M2MServer::test_delete_resource() +{ + m2mobjectinstance_stub::bool_value = true; + + CHECK(server->delete_resource(M2MServer::ShortServerID) == false); + CHECK(server->delete_resource(M2MServer::Binding) == false); + CHECK(server->delete_resource(M2MServer::NotificationStorage) == false); + CHECK(server->delete_resource(M2MServer::Lifetime) == false); + CHECK(server->delete_resource(M2MServer::RegistrationUpdate) == false); + + CHECK(server->delete_resource(M2MServer::DefaultMinPeriod) == true); + CHECK(server->delete_resource(M2MServer::DefaultMaxPeriod) == true); + CHECK(server->delete_resource(M2MServer::DisableTimeout) == true); + CHECK(server->delete_resource(M2MServer::Disable) == true); +} + +void Test_M2MServer::test_set_resource_value_int() +{ + m2mbase_stub::bool_value = true; + + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name", "name",M2MResourceInstance::STRING,M2MBase::Dynamic); + + CHECK(server->set_resource_value(M2MServer::DefaultMinPeriod,10) == true); + CHECK(server->set_resource_value(M2MServer::DefaultMaxPeriod,10) == true); + CHECK(server->set_resource_value(M2MServer::DisableTimeout,10) == true); + CHECK(server->set_resource_value(M2MServer::ShortServerID,10) == true); + CHECK(server->set_resource_value(M2MServer::NotificationStorage,10) == true); + CHECK(server->set_resource_value(M2MServer::Lifetime,10) == true); + + CHECK(server->set_resource_value(M2MServer::Binding,10) == false); + CHECK(server->set_resource_value(M2MServer::RegistrationUpdate,10) == false); + CHECK(server->set_resource_value(M2MServer::Disable,10) == false); + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; +} + +void Test_M2MServer::test_set_resource_value_string() +{ + m2mresourceinstance_stub::bool_value = true; + + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name", "name", M2MResourceInstance::STRING, M2MBase::Dynamic); + + CHECK(server->set_resource_value(M2MServer::Binding,"test") == true); + + CHECK(server->set_resource_value(M2MServer::DefaultMinPeriod,"test") == false); + CHECK(server->set_resource_value(M2MServer::DefaultMaxPeriod,"test") == false); + CHECK(server->set_resource_value(M2MServer::DisableTimeout,"test") == false); + CHECK(server->set_resource_value(M2MServer::ShortServerID,"test") == false); + CHECK(server->set_resource_value(M2MServer::NotificationStorage,"test") == false); + CHECK(server->set_resource_value(M2MServer::Lifetime,"test") == false); + CHECK(server->set_resource_value(M2MServer::RegistrationUpdate,"test") == false); + CHECK(server->set_resource_value(M2MServer::Disable,"test") == false); + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; +} + +void Test_M2MServer::test_resource_value_int() +{ + uint8_t value[] = {"10"}; + m2mresourceinstance_stub::value = (uint8_t*)malloc((uint32_t)sizeof(value)); + memset(m2mresourceinstance_stub::value,0,(uint32_t)sizeof(value)); + memcpy(m2mresourceinstance_stub::value,value,sizeof(value)); + m2mresourceinstance_stub::int_value = (uint32_t)sizeof(value); + + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name", "name", M2MResourceInstance::STRING, M2MBase::Dynamic); + + CHECK(server->resource_value_int(M2MServer::ShortServerID) == 10); + CHECK(server->resource_value_int(M2MServer::DefaultMinPeriod) == 10); + CHECK(server->resource_value_int(M2MServer::DefaultMaxPeriod) == 10); + CHECK(server->resource_value_int(M2MServer::DisableTimeout) == 10); + CHECK(server->resource_value_int(M2MServer::NotificationStorage) == 10); + CHECK(server->resource_value_int(M2MServer::Lifetime) == 10); + CHECK(server->resource_value_int(M2MServer::Binding) == 0); + CHECK(server->resource_value_int(M2MServer::RegistrationUpdate) == 0); + CHECK(server->resource_value_int(M2MServer::Disable) == 0); + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; + + free(m2mresourceinstance_stub::value); + m2mresourceinstance_stub::value = NULL; +} + +void Test_M2MServer::test_resource_value_string() +{ + String test = "string"; + uint8_t value[] = {"string"}; + + m2mresourceinstance_stub::value = (uint8_t*)malloc((uint32_t)sizeof(value)); + memset(m2mresourceinstance_stub::value,0,(uint32_t)sizeof(value)); + memcpy(m2mresourceinstance_stub::value,value,sizeof(value)); + m2mresourceinstance_stub::int_value = (uint32_t)sizeof(value); + + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name", "name", M2MResourceInstance::STRING, M2MBase::Dynamic); + + CHECK(server->resource_value_string(M2MServer::Binding) == test); + + CHECK(server->resource_value_string(M2MServer::Disable) == ""); + CHECK(server->resource_value_string(M2MServer::RegistrationUpdate) == ""); + CHECK(server->resource_value_string(M2MServer::Lifetime) == ""); + CHECK(server->resource_value_string(M2MServer::NotificationStorage) == ""); + CHECK(server->resource_value_string(M2MServer::DisableTimeout) == ""); + CHECK(server->resource_value_string(M2MServer::DefaultMaxPeriod) == ""); + CHECK(server->resource_value_string(M2MServer::DefaultMinPeriod) == ""); + CHECK(server->resource_value_string(M2MServer::ShortServerID) == ""); + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; + + free(m2mresourceinstance_stub::value); + m2mresourceinstance_stub::value = NULL; +} + +void Test_M2MServer::test_is_resource_present() +{ + m2mobjectinstance_stub::resource = new M2MResource(*m2mobject_stub::inst,"name","type",M2MResourceInstance::STRING,M2MBase::Dynamic); + + CHECK(server->is_resource_present(M2MServer::ShortServerID) == true); + + delete m2mobjectinstance_stub::resource; + m2mobjectinstance_stub::resource = NULL; + + CHECK(server->is_resource_present(M2MServer::DefaultMinPeriod) == false); +} + +void Test_M2MServer::test_total_resource_count() +{ + M2MResource *res = new M2MResource(*m2mobject_stub::inst,"test","test",M2MResourceInstance::STRING,M2MBase::Dynamic); + + m2mobjectinstance_stub::resource_list.push_back(res); + M2MResource *res2 = new M2MResource(*m2mobject_stub::inst,"test","test",M2MResourceInstance::STRING,M2MBase::Dynamic); + + m2mobjectinstance_stub::resource_list.push_back(res2); + + CHECK(server->total_resource_count() == 2); + + m2mobjectinstance_stub::resource_list.clear(); + + delete res2; + delete res; +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mserver/test_m2mserver.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mserver/test_m2mserver.h new file mode 100755 index 0000000000..25c8abeb5e --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mserver/test_m2mserver.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TEST_M2M_SERVER_H +#define TEST_M2M_SERVER_H + +#include "m2mserver.h" + +class Callback; + +class Test_M2MServer +{ +public: + Test_M2MServer(); + virtual ~Test_M2MServer(); + + void test_create_resource(); + + void test_create_resource_int(); + + void test_delete_resource(); + + void test_set_resource_value_int(); + + void test_set_resource_value_string(); + + void test_resource_value_int(); + + void test_resource_value_string(); + + void test_is_resource_present(); + + void test_total_resource_count(); + + M2MServer* server; + Callback* callback; +}; + +#endif // TEST_M2M_SERVER_H + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mstring/CMakeLists.txt b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mstring/CMakeLists.txt new file mode 100644 index 0000000000..e066bea37f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mstring/CMakeLists.txt @@ -0,0 +1,21 @@ +if(TARGET_LIKE_LINUX) +include("../includes.txt") +add_executable(m2mstring + "main.cpp" + "test_m2mstring.cpp" + "m2mstringtest.cpp" + "../../../../source/m2mstring.cpp" +) + +target_link_libraries(m2mstring + CppUTest + CppUTestExt +) +set_target_properties(m2mstring +PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" + LINK_FLAGS "${UTEST_LINK_FLAGS}") + +set(binary "m2mstring") +add_test(m2mstring ${binary}) + +endif() diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mstring/m2mstringtest.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mstring/m2mstringtest.cpp new file mode 100644 index 0000000000..46edbfe8be --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mstring/m2mstringtest.cpp @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//CppUTest includes should be after your and system includes +#include "CppUTest/TestHarness.h" +#include "test_m2mstring.h" + +TEST_GROUP(M2MString) +{ + Test_M2MString* m2m_string; + + void setup() + { + m2m_string = new Test_M2MString(); + } + void teardown() + { + delete m2m_string; + } +}; + +TEST(M2MString, Create) +{ + CHECK(m2m_string != NULL); +} + +TEST(M2MString, copy_constructor) +{ + m2m_string->test_copy_constructor(); +} + +TEST(M2MString, test_operator_assign) +{ + m2m_string->test_operator_assign(); +} + +TEST(M2MString, test_operator_add) +{ + m2m_string->test_operator_add(); +} + +TEST(M2MString, test_push_back) +{ + m2m_string->test_push_back(); +} + +TEST(M2MString, test_operator_equals) +{ + m2m_string->test_operator_equals(); +} + +TEST(M2MString, test_clear) +{ + m2m_string->test_clear(); +} + +TEST(M2MString, test_size) +{ + m2m_string->test_size(); +} + +TEST(M2MString, test_length) +{ + m2m_string->test_length(); +} + +TEST(M2MString, test_capacity) +{ + m2m_string->test_capacity(); +} + +TEST(M2MString, test_empty) +{ + m2m_string->test_empty(); +} + +TEST(M2MString, test_c_str) +{ + m2m_string->test_c_str(); +} + +TEST(M2MString, test_reserve) +{ + m2m_string->test_reserve(); +} + +TEST(M2MString, test_resize) +{ + m2m_string->test_resize(); +} + +TEST(M2MString, test_swap) +{ + m2m_string->test_swap(); +} + +TEST(M2MString, test_substr) +{ + m2m_string->test_substr(); +} + +TEST(M2MString, test_operator_get) +{ + m2m_string->test_operator_get(); +} + +TEST(M2MString, test_at) +{ + m2m_string->test_at(); +} + +TEST(M2MString, test_erase) +{ + m2m_string->test_erase(); +} + +TEST(M2MString, test_append) +{ + m2m_string->test_append(); +} + +TEST(M2MString, test_append_raw) +{ + m2m_string->test_append_raw(); +} + +TEST(M2MString, test_append_int) +{ + m2m_string->test_append_int(); +} + +TEST(M2MString, test_compare) +{ + m2m_string->test_compare(); +} + +TEST(M2MString, test_find_last_of) +{ + m2m_string->test_find_last_of(); +} + +TEST(M2MString, test_operator_lt) +{ + m2m_string->test_operator_lt(); +} + +TEST(M2MString, test_reverse) +{ + m2m_string->test_reverse(); +} + +TEST(M2MString, test_itoa_c) +{ + m2m_string->test_itoa_c(); +} + +TEST(M2MString, test_convert_integer_to_array) +{ + m2m_string->test_convert_integer_to_array(); +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mstring/main.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mstring/main.cpp new file mode 100644 index 0000000000..7717a0bd13 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mstring/main.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" + +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP( M2MString); diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mstring/test_m2mstring.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mstring/test_m2mstring.cpp new file mode 100755 index 0000000000..84e3703666 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mstring/test_m2mstring.cpp @@ -0,0 +1,412 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include "test_m2mstring.h" +#include +#include + +Test_M2MString::Test_M2MString() +{ + str = new String("test"); +} + +Test_M2MString::~Test_M2MString() +{ + delete str; +} + +void Test_M2MString::test_copy_constructor() +{ + String s("name"); + String s1(s); + CHECK(s1.p[1] == 'a'); +} + +void Test_M2MString::test_operator_assign() +{ + String s("name"); + String s1 = s; + const String s2("yes"); + CHECK(s1.p[1] == 'a'); + + s1 = "yeb"; + CHECK(s1.p[1] == 'e'); + s = s2; + CHECK(s.p[1] == 'e'); +} + +void Test_M2MString::test_operator_add() +{ + String s("name"); + String s1("yeb"); + + s += 'r'; + CHECK(s.p[4] == 'r'); + + s += s1; + CHECK(s.p[5] == 'y'); + + s += "hoi"; + CHECK(s.p[9] == 'o'); + + s1 += "somethingverylongggggggg"; + +} + +void Test_M2MString::test_push_back() +{ + String s("name"); + + s.push_back('r'); + CHECK(s.p[4] == 'r'); +} + +void Test_M2MString::test_operator_equals() +{ + String s("name"); + String s1("yeb"); + + CHECK( (s == s1) == false); + CHECK( (s == "name") == true); + const char c = NULL; + CHECK( (s == c) == false); + free(s.p); + s.p = NULL; + CHECK( (s == c) == true); +} + +void Test_M2MString::test_clear() +{ + String s("name"); + + s.clear(); + CHECK(s.size_ == 0); +} + +void Test_M2MString::test_size() +{ + String s("name"); + String s1("yeb"); + + CHECK(s.size() == 4); +} + +void Test_M2MString::test_length() +{ + String s("name"); + String s1("yeb"); + + CHECK(s.length() == 4); +} + +void Test_M2MString::test_capacity() +{ + String s("name"); + String s1("yeb"); + + CHECK(s.capacity() == 4); +} + +void Test_M2MString::test_empty() +{ + String s("name"); + String s1("yeb"); + + CHECK(s.empty() == false); +} + +void Test_M2MString::test_c_str() +{ + String s("name"); + String s1("yeb"); + + CHECK( s.c_str() != NULL); +} + +void Test_M2MString::test_reserve() +{ + String s("name"); + String s1("yeb"); + + s.reserve(12); + CHECK(s.allocated_ == 13); +} + +void Test_M2MString::test_resize() +{ + String s("name"); + String s1("yeb"); + + s.resize(2); + CHECK( s.size() == 2); + + s.resize(12); + CHECK( s.size() == 12); +} + +void Test_M2MString::test_swap() +{ + String s("name"); + String s1("yeb"); + + s.swap(s1); + CHECK(s1.p[1] == 'a'); + + CHECK(s.p[1] == 'e'); +} + +void Test_M2MString::test_substr() +{ + String s("name"); + String s1("yeb"); + + CHECK(s.substr(1, 1) == "a"); + CHECK(s.substr(3, 4) == "e"); +} + +void Test_M2MString::test_operator_get() +{ + String s("name"); + const String s1("yeb"); + + CHECK(s[1] == 'a'); + CHECK(s1[1] == 'e'); +} + +void Test_M2MString::test_at() +{ + String s("name"); + const String s1("yeb"); + + CHECK(s.at(1) == 'a'); + CHECK(s.at(14) == '\0'); + CHECK(s1.at(1) == 'e'); + CHECK(s1.at(31) == '\0'); +} + +void Test_M2MString::test_erase() +{ + String s("name"); + String s1("yeb"); + + s.erase(1,1); + CHECK(s[1] == 'm'); +} + +void Test_M2MString::test_append() +{ + String s("name"); + String s1("yeb"); + + s.append( s1.c_str(), 1 ); + CHECK(s.size() == 5); + + s.append( s1.c_str(), 15 ); + CHECK(s.size() == 8); +} + +void Test_M2MString::test_append_raw() +{ + String s("name"); + const char test_source[] = "something"; + String expected("namesomething"); + + s.append_raw(test_source, 1); + CHECK(s.size() == 5); + + s.append_raw(test_source + 1, 8); + CHECK(s.size() == 13); + + CHECK(s == expected); +} + +void Test_M2MString::test_append_int() +{ + String s("source"); + String expected("source1234"); + String expected2("source12342147483647"); + + s.append_int(1234); + CHECK(s.size() == 10); + + CHECK(s == expected); + + s.append_int(INT32_MAX); + + CHECK(s == expected2); +} + +void Test_M2MString::test_compare() +{ + String s("name"); + String s1("yeb"); + String s2("name"); + String s3("nam"); + + CHECK(s.compare(1,5, s1) < 0); + CHECK(s1.compare(0,5, s2) > 0); + CHECK(s.compare(0,4, s2) == 0); + CHECK(s.compare(0,4, s3) > 0); + + CHECK(s.compare(1,5, "yeb") < 0); + CHECK(s1.compare(0,5, "name") > 0); + CHECK(s.compare(0,4, "name") == 0); + CHECK(s.compare(0,4, "nam") > 0); +} + +void Test_M2MString::test_find_last_of() +{ + String s("namenamename"); + String s1("yeb"); + + CHECK(s.find_last_of('n') == 8); +} + +void Test_M2MString::test_operator_lt() +{ + String s("name"); + String s1("yeb"); + String s2("yea"); + + CHECK( (s < s1 ) == true); + CHECK( (s1 < s2 ) == false); +} +void Test_M2MString::test_reverse() +{ + char string1[] = "123"; + char string2[] = "321"; + m2m::reverse(string1, strlen(string1)); + char string3[] = "9223372036854775807"; + char string4[] = "7085774586302733229"; + m2m::reverse(string3, strlen(string3)); + + CHECK(strcmp(string1, string2) == 0); + CHECK(strcmp(string3, string4) == 0); +} +void Test_M2MString::test_itoa_c() +{ + int64_t value1 = 0; + char* string1 = "0"; + int64_t value2 = -10; + char* string2 = "-10"; + int64_t value3 = 10000; + char* string3 = "10000"; + int64_t value4 = 9223372036854775807; + char* string4 = "9223372036854775807"; + int64_t value5 = -9223372036854775807; + char* string5 = "-9223372036854775807"; + + char *buffer = (char*)malloc(21); + + if(buffer) { + m2m::itoa_c(value1, buffer); + CHECK(strcmp(string1, buffer) == 0); + m2m::itoa_c(value2, buffer); + CHECK(strcmp(string2, buffer) == 0); + m2m::itoa_c(value3, buffer); + CHECK(strcmp(string3, buffer) == 0); + m2m::itoa_c(value4, buffer); + CHECK(strcmp(string4, buffer) == 0); + m2m::itoa_c(value5, buffer); + CHECK(strcmp(string5, buffer) == 0); + free(buffer); + } +} + +void Test_M2MString::test_convert_integer_to_array() +{ + uint8_t *max_age_ptr = NULL; + uint8_t max_age_len = 0; + uint8_t *temp = NULL; + uint8_t temp_len = 0; + + int64_t val = 0; + max_age_ptr = m2m::String::convert_integer_to_array(val,max_age_len); + CHECK(max_age_ptr != NULL); + CHECK(val == m2m::String::convert_array_to_integer(max_age_ptr, max_age_len)); + temp = m2m::String::convert_integer_to_array(0,temp_len, max_age_ptr, max_age_len); + CHECK(temp != NULL); + CHECK(val == m2m::String::convert_array_to_integer(temp, temp_len)); + free(temp); + free(max_age_ptr); + max_age_ptr = NULL; + + val = 0xff; + max_age_ptr = m2m::String::convert_integer_to_array(val,max_age_len); + CHECK(max_age_ptr != NULL); + CHECK(val == m2m::String::convert_array_to_integer(max_age_ptr, max_age_len)); + temp = m2m::String::convert_integer_to_array(0,temp_len, max_age_ptr, max_age_len); + CHECK(temp != NULL); + CHECK(val == m2m::String::convert_array_to_integer(temp, temp_len)); + free(temp); + free(max_age_ptr); + max_age_ptr = NULL; + + val = 0xffff; + max_age_ptr = m2m::String::convert_integer_to_array(val,max_age_len); + CHECK(max_age_ptr != NULL); + CHECK(val == m2m::String::convert_array_to_integer(max_age_ptr, max_age_len)); + free(max_age_ptr); + max_age_ptr = NULL; + + val = 0xffffff; + max_age_ptr = m2m::String::convert_integer_to_array(val,max_age_len); + CHECK(max_age_ptr != NULL); + CHECK(val == m2m::String::convert_array_to_integer(max_age_ptr, max_age_len)); + free(max_age_ptr); + max_age_ptr = NULL; + + val = 0xffffffff; + max_age_ptr = m2m::String::convert_integer_to_array(val,max_age_len); + CHECK(max_age_ptr != NULL); + CHECK(val == m2m::String::convert_array_to_integer(max_age_ptr, max_age_len)); + free(max_age_ptr); + max_age_ptr = NULL; + + val = 0xffffffffff; + max_age_ptr = m2m::String::convert_integer_to_array(val,max_age_len); + CHECK(max_age_ptr != NULL); + CHECK(val == m2m::String::convert_array_to_integer(max_age_ptr, max_age_len)); + free(max_age_ptr); + max_age_ptr = NULL; + + val = 0xffffffffffff; + max_age_ptr = m2m::String::convert_integer_to_array(val,max_age_len); + CHECK(max_age_ptr != NULL); + CHECK(val == m2m::String::convert_array_to_integer(max_age_ptr, max_age_len)); + free(max_age_ptr); + max_age_ptr = NULL; + + val = 0xffffffffffffff; + max_age_ptr = m2m::String::convert_integer_to_array(val,max_age_len); + CHECK(max_age_ptr != NULL); + CHECK(val == m2m::String::convert_array_to_integer(max_age_ptr, max_age_len)); + free(max_age_ptr); + max_age_ptr = NULL; + + val = 0xffff; + max_age_ptr = m2m::String::convert_integer_to_array(val,max_age_len); + CHECK(max_age_ptr != NULL); + CHECK(val == m2m::String::convert_array_to_integer(max_age_ptr, max_age_len)); + free(max_age_ptr); + max_age_ptr = NULL; + + + +} + + + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mstring/test_m2mstring.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mstring/test_m2mstring.h new file mode 100755 index 0000000000..54dd1ff4ff --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mstring/test_m2mstring.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TEST_M2M_STRING_H +#define TEST_M2M_STRING_H + +#include "m2mstring.h" + +using namespace m2m; + +class Test_M2MString +{ +public: + Test_M2MString(); + virtual ~Test_M2MString(); + + void test_copy_constructor(); + void test_operator_assign(); + void test_operator_add(); + void test_push_back(); + void test_operator_equals(); + void test_clear(); + void test_size(); + void test_length(); + void test_capacity(); + void test_empty(); + void test_c_str(); + void test_reserve(); + void test_resize(); + void test_swap(); + void test_substr(); + void test_operator_get(); + void test_at(); + void test_erase(); + void test_append(); + void test_append_raw(); + void test_append_int(); + void test_compare(); + void test_find_last_of(); + void test_operator_lt(); + void test_reverse(); + void test_itoa_c(); + void test_convert_integer_to_array(); + + String* str; +}; + +#endif // TEST_M2M_STRING_H diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/CMakeLists.txt b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/CMakeLists.txt new file mode 100644 index 0000000000..7dc7b39406 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/CMakeLists.txt @@ -0,0 +1,29 @@ +if(TARGET_LIKE_LINUX) +include("../includes.txt") +add_executable(m2mtlv + "../../../../source/m2mtlvdeserializer.cpp" + "../../../../source/m2mtlvserializer.cpp" + "main.cpp" + "m2mtlvdeserializertest.cpp" + "test_m2mtlvdeserializer.cpp" + "../stub/m2mstring_stub.cpp" + "../stub/m2mbase_stub.cpp" + "../stub/m2mresource_stub.cpp" + "../stub/m2mresourceinstance_stub.cpp" + "../stub/m2mobjectinstance_stub.cpp" + "../stub/m2mobject_stub.cpp" + "test_m2mtlvserializer.cpp" +) + +target_link_libraries(m2mtlv + CppUTest + CppUTestExt +) +set_target_properties(m2mtlv +PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" + LINK_FLAGS "${UTEST_LINK_FLAGS}") + +set(binary "m2mtlv") +add_test(m2mtlv ${binary}) + +endif() diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/m2mtlvdeserializertest.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/m2mtlvdeserializertest.cpp new file mode 100644 index 0000000000..04400f04a7 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/m2mtlvdeserializertest.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//CppUTest includes should be after your and system includes +#include "CppUTest/TestHarness.h" +#include "test_m2mtlvdeserializer.h" +#include "test_m2mtlvserializer.h" + +TEST_GROUP(M2MTLVDeserializer) +{ + Test_M2MTLVDeserializer* m2m_deserializer; + + void setup() + { + m2m_deserializer = new Test_M2MTLVDeserializer(); + } + void teardown() + { + delete m2m_deserializer; + } +}; + +TEST_GROUP(M2MTLVSerializer) +{ + Test_M2MTLVSerializer* m2m_serializer; + + void setup() + { + m2m_serializer = new Test_M2MTLVSerializer(); + } + void teardown() + { + delete m2m_serializer; + } +}; + +TEST(M2MTLVSerializer, Create) +{ + CHECK(m2m_serializer != NULL); +} + +TEST(M2MTLVSerializer, serialize_object) +{ + m2m_serializer->test_serialize_object(); +} + +TEST(M2MTLVSerializer, serialize_object_instance) +{ + m2m_serializer->test_serialize_object_instance(); +} + +TEST(M2MTLVSerializer, serialize_resource) +{ + m2m_serializer->test_serialize_resource(); +} + +TEST(M2MTLVSerializer, serialize_resource_instance) +{ + m2m_serializer->test_serialize_resource_instance(); +} + +TEST(M2MTLVDeserializer, Create) +{ + CHECK(m2m_deserializer != NULL); +} + +TEST(M2MTLVDeserializer, is_object_instance) +{ + m2m_deserializer->test_is_object_instance(); +} + +TEST(M2MTLVDeserializer, is_resource) +{ + m2m_deserializer->test_is_resource(); +} + +TEST(M2MTLVDeserializer, is_multiple_resource) +{ + m2m_deserializer->test_is_multiple_resource(); +} + +TEST(M2MTLVDeserializer, is_resource_instance) +{ + m2m_deserializer->test_is_resource_instance(); +} + +TEST(M2MTLVDeserializer, deserialise_object_instances) +{ + m2m_deserializer->test_deserialise_object_instances(); +} + +TEST(M2MTLVDeserializer, deserialize_resources) +{ + m2m_deserializer->test_deserialize_resources(); +} + +TEST(M2MTLVDeserializer, test_deserialize_resource_instance_1) +{ + m2m_deserializer->test_deserialize_resource_instance_1(); +} + +TEST(M2MTLVDeserializer, test_deserialize_resource_instance) +{ + m2m_deserializer->test_deserialize_resource_instance(); +} + +TEST(M2MTLVDeserializer, test_instance_id) +{ + m2m_deserializer->test_instance_id(); +} + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/main.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/main.cpp new file mode 100644 index 0000000000..633ac31a00 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/main.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP( M2MTLVDeserializer); +IMPORT_TEST_GROUP( M2MTLVSerializer); diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/test_m2mtlvdeserializer.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/test_m2mtlvdeserializer.cpp new file mode 100755 index 0000000000..109b4db01e --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/test_m2mtlvdeserializer.cpp @@ -0,0 +1,642 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include "test_m2mtlvdeserializer.h" +#include "m2mtlvserializer.h" +#include "m2mobject_stub.h" +#include "m2mobjectinstance_stub.h" +#include "m2mresource_stub.h" +#include "m2mresourceinstance_stub.h" +#include "m2mbase_stub.h" + + +Test_M2MTLVDeserializer::Test_M2MTLVDeserializer() +{ + deserializer = new M2MTLVDeserializer(); +} + +Test_M2MTLVDeserializer::~Test_M2MTLVDeserializer() +{ + delete deserializer; + m2mbase_stub::clear(); + m2mresourceinstance_stub::clear(); + m2mobjectinstance_stub::clear(); + m2mobject_stub::clear(); + m2mresource_stub::clear(); +} + +void Test_M2MTLVDeserializer::test_is_object_instance() +{ + uint8_t data_resource[] = {0xC3,0x0}; + uint8_t data_object[] = {0x08,0x0}; + + CHECK(deserializer->is_object_instance(data_resource) == false); + CHECK(deserializer->is_object_instance(data_object) == true); +} + +void Test_M2MTLVDeserializer::test_is_resource() +{ + uint8_t data_resource[] = {0xC3,0x0}; + uint8_t data_object[] = {0x08,0x0}; + + CHECK(deserializer->is_resource(data_resource) == true); + CHECK(deserializer->is_resource(data_object) == false); + +} + +void Test_M2MTLVDeserializer::test_is_multiple_resource() +{ + uint8_t data_resource[] = {0xC3,0x0}; + uint8_t data_object[] = {0x88,0x0}; + + CHECK(deserializer->is_multiple_resource(data_resource) == false); + CHECK(deserializer->is_multiple_resource(data_object) == true); +} + +void Test_M2MTLVDeserializer::test_is_resource_instance() +{ + uint8_t data_resource[] = {0xC3,0x0}; + uint8_t data_object[] = {0x44,0x0}; + + CHECK(deserializer->is_resource_instance(data_object) == true); + CHECK(deserializer->is_resource_instance(data_resource) == false); +} + +void Test_M2MTLVDeserializer::test_deserialise_object_instances() +{ + uint32_t size = 0; + uint8_t *data = 0; + + String *name = new String("1"); + M2MObject *object = new M2MObject(*name); + M2MObjectInstance* instance = new M2MObjectInstance(*name,*object); + + M2MObjectInstance* instance_1 = new M2MObjectInstance("2",*object); + + + m2mobject_stub::instance_list.push_back(instance); + + M2MResource* resource = new M2MResource(*instance, + *name, + *name, + M2MResourceInstance::INTEGER, + M2MResource::Dynamic, + false); + + M2MResource* resource_1 = new M2MResource(*instance, + "2", + *name, + M2MResourceInstance::INTEGER, + M2MResource::Dynamic, + false); + + + m2mobjectinstance_stub::resource_list.push_back(resource); + m2mobjectinstance_stub::resource_list.push_back(resource_1); + + m2mbase_stub::name_id_value = 0; + m2mbase_stub::operation = M2MBase::GET_PUT_POST_ALLOWED; + + M2MTLVSerializer *serializer = new M2MTLVSerializer(); + + data = serializer->serialize( m2mobject_stub::instance_list,size); + + CHECK(M2MTLVDeserializer::None == deserializer->deserialise_object_instances(data,size,*object,M2MTLVDeserializer::Post)); + + size = 0; + + if(data) { + free(data); + data = 0; + } + + m2mbase_stub::operation = M2MBase::GET_ALLOWED; + + data = serializer->serialize( m2mobject_stub::instance_list,size); + + CHECK(M2MTLVDeserializer::NotAllowed == deserializer->deserialise_object_instances(data,size,*object,M2MTLVDeserializer::Post)); + + size = 0; + + if(data) { + free(data); + data = 0; + } + + m2mbase_stub::operation = M2MBase::GET_PUT_POST_ALLOWED; + + u_int8_t value[] = {"value"}; + m2mresourceinstance_stub::value = value; + m2mresourceinstance_stub::int_value = sizeof(value); + + data = serializer->serialize( m2mobject_stub::instance_list,size); + + delete serializer; + + CHECK(M2MTLVDeserializer::None == deserializer->deserialise_object_instances(data,size,*object,M2MTLVDeserializer::Post)); + CHECK(M2MTLVDeserializer::None == deserializer->deserialise_object_instances(data,size,*object,M2MTLVDeserializer::Put)); + + size = 0; + + if(data) { + free(data); + data = 0; + } + + m2mobject_stub::instance_list.push_back(instance_1); + + m2mbase_stub::operation = M2MBase::NOT_ALLOWED; + serializer = new M2MTLVSerializer(); + + data = serializer->serialize( m2mobject_stub::instance_list,size); + + delete serializer; + + CHECK(M2MTLVDeserializer::None != deserializer->deserialise_object_instances(data,size,*object,M2MTLVDeserializer::Post)); + size = 0; + + if(data) { + free(data); + data = 0; + } + + CHECK(M2MTLVDeserializer::NotValid == deserializer->deserialise_object_instances(data,size,*object,M2MTLVDeserializer::Post)); + + M2MResourceInstance* res_instance = new M2MResourceInstance(*name, + *name, + M2MResourceInstance::INTEGER, + *instance); + + M2MResourceInstance* res_instance_1 = new M2MResourceInstance("2", + *name, + M2MResourceInstance::INTEGER, + *instance); + + + m2mresource_stub::bool_value = true; + m2mresource_stub::list.push_back(res_instance); + m2mresource_stub::list.push_back(res_instance_1); + + m2mobject_stub::instance_list.pop_back(); + + serializer = new M2MTLVSerializer(); + data = serializer->serialize( m2mobject_stub::instance_list,size); + delete serializer; + + m2mbase_stub::operation = M2MBase::GET_PUT_POST_ALLOWED; + + m2mbase_stub::string_value = new String("name"); + m2mobjectinstance_stub::create_resource_instance = new M2MResource(*instance, + *name, + *name, + M2MResourceInstance::INTEGER, + M2MResource::Dynamic, + false); + + deserializer->deserialise_object_instances(data,size,*object,M2MTLVDeserializer::Post); + + deserializer->deserialise_object_instances(data,size,*object,M2MTLVDeserializer::Put); + + size = 0; + if(data) { + free(data); + data = 0; + } + + m2mbase_stub::name_id_value = 300; + + m2mresourceinstance_stub::int_value = 6; + m2mresourceinstance_stub::value = (uint8_t*) malloc(m2mresourceinstance_stub::int_value); + serializer = new M2MTLVSerializer(); + data = serializer->serialize( m2mobject_stub::instance_list,size); + delete serializer; + + deserializer->deserialise_object_instances(data,size,*object, M2MTLVDeserializer::Post); + deserializer->deserialise_object_instances(data,size,*object, M2MTLVDeserializer::Put); + size = 0; + + if(data) { + free(data); + data = 0; + } + free(m2mresourceinstance_stub::value); + m2mresourceinstance_stub::value = NULL; + + m2mresourceinstance_stub::int_value = 256; + m2mresourceinstance_stub::value = (uint8_t*) malloc(m2mresourceinstance_stub::int_value); + serializer = new M2MTLVSerializer(); + data = serializer->serialize( m2mobject_stub::instance_list,size); + delete serializer; + + deserializer->deserialise_object_instances(data,size,*object,M2MTLVDeserializer::Post); + deserializer->deserialise_object_instances(data,size,*object,M2MTLVDeserializer::Put); + size = 0; + + if(data) { + free(data); + data = 0; + } + free(m2mresourceinstance_stub::value); + m2mresourceinstance_stub::value = NULL; + + m2mresourceinstance_stub::int_value = 65536; + m2mresourceinstance_stub::value = (uint8_t*) malloc(m2mresourceinstance_stub::int_value); + serializer = new M2MTLVSerializer(); + data = serializer->serialize( m2mobject_stub::instance_list,size); + delete serializer; + + deserializer->deserialise_object_instances(data,size,*object,M2MTLVDeserializer::Post); + deserializer->deserialise_object_instances(data,size,*object,M2MTLVDeserializer::Put); + size = 0; + + if(data) { + free(data); + data = 0; + } + + free(m2mresourceinstance_stub::value); + m2mresourceinstance_stub::value = NULL; + + delete m2mbase_stub::string_value; + m2mbase_stub::string_value = NULL; + + delete m2mobjectinstance_stub::create_resource_instance; + m2mobjectinstance_stub::create_resource_instance = NULL; + + delete res_instance; + delete res_instance_1; + delete name; + delete resource; + delete resource_1; + delete instance; + delete instance_1; + delete object; +} + +void Test_M2MTLVDeserializer::test_deserialize_resources() +{ + uint8_t data_resource[] = {0xC3,0x0,'A','R','M'}; + + String *name = new String("1"); + M2MObject *object = new M2MObject(*name); + M2MObjectInstance* instance = new M2MObjectInstance(*name,*object); + + m2mobject_stub::instance_list.push_back(instance); + + + + M2MResource* resource = new M2MResource(*instance, + *name, + *name, + M2MResourceInstance::INTEGER, + M2MResource::Dynamic, + false); + + + m2mobjectinstance_stub::resource_list.push_back(resource); + + CHECK(deserializer->is_resource(data_resource) == true); + + uint8_t invalid_data_resource[] = {0x65,0x0,'A','R','M'}; + + CHECK( M2MTLVDeserializer::NotValid == deserializer->deserialize_resources(invalid_data_resource, + sizeof(invalid_data_resource), + *instance,M2MTLVDeserializer::Post)); + + m2mbase_stub::operation = M2MBase::GET_PUT_POST_ALLOWED; + + m2mobjectinstance_stub::create_resource = new M2MResource(*instance, + *name, + *name, + M2MResourceInstance::INTEGER, + M2MResource::Dynamic, + false); + + CHECK( M2MTLVDeserializer::None == deserializer->deserialize_resources(data_resource,sizeof(data_resource),*instance,M2MTLVDeserializer::Post)); + + delete m2mobjectinstance_stub::create_resource; + m2mobjectinstance_stub::create_resource = NULL; + + CHECK( M2MTLVDeserializer::NotFound == deserializer->deserialize_resources(data_resource,sizeof(data_resource),*instance,M2MTLVDeserializer::Put)); + + m2mbase_stub::operation = M2MBase::NOT_ALLOWED; + + deserializer->deserialize_resources(data_resource,sizeof(data_resource),*instance,M2MTLVDeserializer::Post); + + + M2MResourceInstance* res_instance = new M2MResourceInstance(*name, + *name, + M2MResourceInstance::INTEGER, + *instance); + + + m2mresource_stub::bool_value = true; + m2mresource_stub::list.push_back(res_instance); + +// M2MResourceInstance* res_instance_1 = new M2MResourceInstance("2", +// *name, +// M2MResourceInstance::INTEGER, +// *instance); + +// m2mresource_stub::list.push_back(res_instance_1); + + uint8_t data_multiple_resource[] = {0x86,0x6, 0x81,0x0, 0x01, 0x41, 0x01, 0x05}; + CHECK(deserializer->is_multiple_resource(data_multiple_resource) == true); + deserializer->deserialize_resources(data_multiple_resource,sizeof(data_multiple_resource),*instance,M2MTLVDeserializer::Post); + + M2MTLVSerializer *serializer = new M2MTLVSerializer(); + + m2mbase_stub::name_id_value = 1; + uint32_t size = 0; + uint8_t* data = serializer->serialize(resource,size); + + delete serializer; + + m2mbase_stub::operation = M2MBase::GET_PUT_POST_ALLOWED; + + deserializer->deserialize_resources(data,size,*instance,M2MTLVDeserializer::Post); + + free(data); + + delete res_instance; +// delete res_instance_1; + delete resource; + delete instance; + delete object; + delete name; + + m2mresourceinstance_stub::clear(); + m2mresource_stub::clear(); + m2mobjectinstance_stub::clear(); + m2mobject_stub::clear(); +} + +void Test_M2MTLVDeserializer::test_deserialize_resource_instance_1() +{ + uint8_t data_resource[] = {0xC3,0x0,'A','R','M'}; + + m2mbase_stub::name_id_value = 1; + + String *name = new String("1"); + M2MObject *object = new M2MObject(*name); + M2MObjectInstance* instance = new M2MObjectInstance(*name,*object); + + m2mobject_stub::instance_list.push_back(instance); + + + + M2MResource* resource = new M2MResource(*instance, + *name, + *name, + M2MResourceInstance::INTEGER, + M2MResource::Dynamic, + false); + + + m2mobjectinstance_stub::resource_list.push_back(resource); + + CHECK(deserializer->is_resource(data_resource) == true); + + m2mbase_stub::operation = M2MBase::GET_PUT_POST_ALLOWED; + + deserializer->deserialize_resource_instances(data_resource,sizeof(data_resource), + *resource,M2MTLVDeserializer::Put); + + M2MResourceInstance* res_instance = new M2MResourceInstance(*name, + *name, + M2MResourceInstance::INTEGER, + *instance); + + + m2mresource_stub::bool_value = true; + m2mresource_stub::list.push_back(res_instance); + + M2MResourceInstance* res_instance_1 = new M2MResourceInstance("2", + *name, + M2MResourceInstance::INTEGER, + *instance); + + m2mresource_stub::list.push_back(res_instance_1); + + M2MTLVSerializer *serializer = new M2MTLVSerializer(); + + uint32_t size = 0; + uint8_t* data = serializer->serialize( resource,size); + + delete serializer; + + deserializer->deserialize_resource_instances(data,size, + *resource,M2MTLVDeserializer::Put); + + + free(data); + + delete res_instance; + delete res_instance_1; + delete resource; + delete instance; + delete object; + delete name; + + m2mresourceinstance_stub::clear(); + m2mresource_stub::clear(); + m2mobjectinstance_stub::clear(); + m2mobject_stub::clear(); +} + + +void Test_M2MTLVDeserializer::test_deserialize_resource_instance() +{ + uint32_t size = 0; + uint8_t *data = 0; + + String *name = new String("1"); + M2MObject *object = new M2MObject(*name); + M2MObjectInstance* instance = new M2MObjectInstance(*name,*object); + + M2MObjectInstance* instance_1 = new M2MObjectInstance("2",*object); + + + m2mobject_stub::instance_list.push_back(instance); + m2mobject_stub::instance_list.push_back(instance_1); + + + M2MResource* resource = new M2MResource(*instance, + *name, + *name, + M2MResourceInstance::INTEGER, + M2MResource::Dynamic, + false); + + M2MResource* resource_1 = new M2MResource(*instance, + "2", + *name, + M2MResourceInstance::INTEGER, + M2MResource::Dynamic, + false); + + m2mobjectinstance_stub::resource_list.push_back(resource); + m2mobjectinstance_stub::resource_list.push_back(resource_1); + + m2mbase_stub::name_id_value = 0; + + M2MTLVSerializer *serializer = new M2MTLVSerializer(); + + data = serializer->serialize( resource,size); + + delete serializer; + + m2mbase_stub::operation = M2MBase::GET_PUT_POST_ALLOWED; + + deserializer->deserialize_resource_instances(data,size,*resource,M2MTLVDeserializer::Post); + size = 0; + + if(data) { + free(data); + data = 0; + } + + m2mbase_stub::operation = M2MBase::NOT_ALLOWED; + + deserializer->deserialize_resource_instances(data,size,*resource,M2MTLVDeserializer::Post); + size = 0; + + if(data) { + free(data); + data = 0; + } + + M2MResourceInstance* res_instance = new M2MResourceInstance(*name, + *name, + M2MResourceInstance::INTEGER, + *instance); + + M2MResourceInstance* res_instance_1 = new M2MResourceInstance("2", + *name, + M2MResourceInstance::INTEGER, + *instance); + + + m2mbase_stub::operation = M2MBase::GET_ALLOWED; + + m2mresource_stub::bool_value = true; + m2mresource_stub::list.push_back(res_instance); + m2mresource_stub::list.push_back(res_instance_1); + serializer = new M2MTLVSerializer(); + data = serializer->serialize( resource,size); + delete serializer; + + deserializer->deserialize_resource_instances(data,size,*resource,M2MTLVDeserializer::Post); + + m2mbase_stub::operation = M2MBase::GET_PUT_POST_ALLOWED; + deserializer->deserialize_resource_instances(data,size,*resource,M2MTLVDeserializer::Post); + + m2mresource_stub::list.pop_back(); + m2mresource_stub::list.pop_back(); + + CHECK(M2MTLVDeserializer::NotAllowed ==deserializer->deserialize_resource_instances(data,size,*resource,M2MTLVDeserializer::Post)); + + CHECK(M2MTLVDeserializer::NotFound == deserializer->deserialize_resource_instances(data,size,*resource,M2MTLVDeserializer::Put)); + + size = 0; + if(data) { + free(data); + data = 0; + } + + serializer = new M2MTLVSerializer(); + data = serializer->serialize( resource,size); + delete serializer; + + deserializer->deserialize_resource_instances(data,size,*resource,M2MTLVDeserializer::Put); + size = 0; + if(data) { + free(data); + data = 0; + } + + m2mresource_stub::list.push_back(res_instance); + m2mresource_stub::list.push_back(res_instance_1); + + m2mbase_stub::name_id_value = 300; + + m2mresourceinstance_stub::int_value = 6; + m2mresourceinstance_stub::value = (uint8_t*) malloc(m2mresourceinstance_stub::int_value); + serializer = new M2MTLVSerializer(); + data = serializer->serialize( resource,size); + delete serializer; + + deserializer->deserialize_resource_instances(data,size,*resource, M2MTLVDeserializer::Post); + size = 0; + + if(data) { + free(data); + data = 0; + } + free(m2mresourceinstance_stub::value); + m2mresourceinstance_stub::value = NULL; + + m2mresourceinstance_stub::int_value = 256; + m2mresourceinstance_stub::value = (uint8_t*) malloc(m2mresourceinstance_stub::int_value); + serializer = new M2MTLVSerializer(); + data = serializer->serialize( resource,size); + delete serializer; + + deserializer->deserialize_resource_instances(data,size,*resource,M2MTLVDeserializer::Post); + size = 0; + + if(data) { + free(data); + data = 0; + } + free(m2mresourceinstance_stub::value); + m2mresourceinstance_stub::value = NULL; + + m2mresourceinstance_stub::int_value = 65536; + m2mresourceinstance_stub::value = (uint8_t*) malloc(m2mresourceinstance_stub::int_value); + serializer = new M2MTLVSerializer(); + data = serializer->serialize( resource,size); + delete serializer; + + deserializer->deserialize_resource_instances(data,size,*resource,M2MTLVDeserializer::Post); + size = 0; + + if(data) { + free(data); + data = 0; + } + + free(m2mresourceinstance_stub::value); + m2mresourceinstance_stub::value = NULL; + + delete res_instance; + delete res_instance_1; + delete name; + delete resource; + delete resource_1; + delete instance; + delete instance_1; + delete object; +} + +void Test_M2MTLVDeserializer::test_instance_id() +{ + uint8_t data_resource[] = {0xC3,0x1}; + uint8_t data_object[] = {0x08,0x2}; + + CHECK(deserializer->instance_id(data_resource) == 1); + CHECK(deserializer->instance_id(data_object) == 2); +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/test_m2mtlvdeserializer.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/test_m2mtlvdeserializer.h new file mode 100755 index 0000000000..ebcc60f9aa --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/test_m2mtlvdeserializer.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TEST_M2M_TLV_DESERIALIZER_H +#define TEST_M2M_TLV_DESERIALIZER_H + +#include "m2mtlvdeserializer.h" + +class Test_M2MTLVDeserializer +{ +public: + Test_M2MTLVDeserializer(); + + virtual ~Test_M2MTLVDeserializer(); + + void test_is_object_instance(); + + void test_is_resource(); + + void test_is_multiple_resource(); + + void test_is_resource_instance(); + + void test_deserialise_object_instances(); + + void test_deserialize_resources(); + + void test_deserialize_resource_instance_1(); + + void test_deserialize_resource_instance(); + + void test_instance_id(); + + M2MTLVDeserializer *deserializer; +}; + +#endif // TEST_M2M_TLV_DESERIALIZER_H diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/test_m2mtlvserializer.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/test_m2mtlvserializer.cpp new file mode 100755 index 0000000000..904f10fbdf --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/test_m2mtlvserializer.cpp @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include "test_m2mtlvserializer.h" +#include "m2mobject_stub.h" +#include "m2mobjectinstance_stub.h" +#include "m2mresource_stub.h" +#include "m2mresourceinstance_stub.h" +#include "m2mbase_stub.h" + + +Test_M2MTLVSerializer::Test_M2MTLVSerializer() +{ + serializer = new M2MTLVSerializer(); +} + +Test_M2MTLVSerializer::~Test_M2MTLVSerializer() +{ + delete serializer; +} + +void Test_M2MTLVSerializer::test_serialize_object() +{ + uint32_t size = 0; + uint8_t *data = 0; + + String *name = new String("1"); + M2MObject *object = new M2MObject(*name); + M2MObjectInstance* instance = new M2MObjectInstance(*name,*object); + + m2mobject_stub::instance_list.push_back(instance); + + + + M2MResource* resource = new M2MResource(*instance, + *name, + *name, + M2MResourceInstance::INTEGER, + M2MResource::Dynamic, + false); + + + m2mobjectinstance_stub::resource_list.push_back(resource); + + m2mbase_stub::name_id_value = 0; + data = serializer->serialize( m2mobject_stub::instance_list,size); + CHECK(data != NULL); + + if(data) { + free(data); + data = 0; + } + + M2MResourceInstance* res_instance = new M2MResourceInstance(*name, + *name, + M2MResourceInstance::INTEGER, + *instance); + + M2MResourceInstance* res_instance_1 = new M2MResourceInstance("2", + *name, + M2MResourceInstance::INTEGER, + *instance); + + + m2mresource_stub::bool_value = true; + m2mresource_stub::list.push_back(res_instance); + m2mresource_stub::list.push_back(res_instance_1); + data = serializer->serialize( m2mobject_stub::instance_list,size); + CHECK(data != NULL); + + if(data) { + free(data); + data = 0; + } + + m2mbase_stub::name_id_value = 256; + + m2mresourceinstance_stub::int_value = 6; + m2mresourceinstance_stub::value = (uint8_t*) malloc(m2mresourceinstance_stub::int_value); + data = serializer->serialize( m2mobject_stub::instance_list,size); + CHECK(data != NULL); + + if(data) { + free(data); + data = 0; + } + free(m2mresourceinstance_stub::value); + m2mresourceinstance_stub::value = NULL; + + m2mresourceinstance_stub::int_value = 256; + m2mresourceinstance_stub::value = (uint8_t*) malloc(m2mresourceinstance_stub::int_value); + data = serializer->serialize( m2mobject_stub::instance_list,size); + CHECK(data != NULL); + + if(data) { + free(data); + data = 0; + } + free(m2mresourceinstance_stub::value); + m2mresourceinstance_stub::value = NULL; + + m2mresourceinstance_stub::int_value = 65536; + m2mresourceinstance_stub::value = (uint8_t*) malloc(m2mresourceinstance_stub::int_value); + data = serializer->serialize( m2mobject_stub::instance_list,size); + CHECK(data != NULL); + + if(data) { + free(data); + data = 0; + } + + m2mbase_stub::name_id_value = -1; + data = serializer->serialize( m2mobject_stub::instance_list,size); + CHECK(data == NULL); + + delete name; + delete res_instance_1; + delete res_instance; + delete resource; + delete instance; + delete object; + + free(m2mresourceinstance_stub::value); + + m2mresourceinstance_stub::clear(); + m2mresource_stub::clear(); + m2mobjectinstance_stub::clear(); + m2mobject_stub::clear(); +} + +void Test_M2MTLVSerializer::test_serialize_object_instance() +{ + String *name = new String("1"); + M2MObject *object = new M2MObject(*name); + M2MObjectInstance* instance = new M2MObjectInstance(*name,*object); + + uint32_t size = 0; + uint8_t *data = 0; + m2mbase_stub::name_id_value = 0; + M2MResource* resource = new M2MResource(*instance, + *name, + *name, + M2MResourceInstance::INTEGER, + M2MResource::Dynamic, + false); + + M2MResourceInstance* res_instance = new M2MResourceInstance(*name, + *name, + M2MResourceInstance::INTEGER, + *instance); + + + m2mobjectinstance_stub::resource_list.clear(); + m2mobjectinstance_stub::resource_list.push_back(resource); + + m2mresource_stub::bool_value = true; + m2mresource_stub::list.push_back(res_instance); + + m2mbase_stub::operation = M2MBase::GET_ALLOWED; + + data = serializer->serialize( m2mobjectinstance_stub::resource_list,size); + CHECK(data != NULL); + + if(data) { + free(data); + data = NULL; + } + + + m2mbase_stub::name_id_value = -1; + data = serializer->serialize( m2mobject_stub::instance_list,size); + CHECK(data == NULL); + + delete name; + delete res_instance; + delete resource; + delete instance; + delete object; + + m2mresource_stub::clear(); + m2mobjectinstance_stub::clear(); + m2mobject_stub::clear(); +} + +void Test_M2MTLVSerializer::test_serialize_resource() +{ + String *name = new String("1"); + M2MObject *object = new M2MObject(*name); + M2MObjectInstance* instance = new M2MObjectInstance(*name,*object); + + uint32_t size = 0; + uint8_t *data = 0; + m2mbase_stub::name_id_value = 0; + M2MResource* resource = new M2MResource(*instance, + *name, + *name, + M2MResourceInstance::INTEGER, + M2MResource::Dynamic, + false); + + M2MResourceInstance* res_instance = new M2MResourceInstance(*name, + *name, + M2MResourceInstance::INTEGER, + *instance); + + + m2mobjectinstance_stub::resource_list.clear(); + m2mobjectinstance_stub::resource_list.push_back(resource); + + m2mresource_stub::bool_value = true; + m2mresource_stub::list.push_back(res_instance); + + m2mbase_stub::operation = M2MBase::GET_ALLOWED; + + data = serializer->serialize( resource,size); + CHECK(data != NULL); + + if(data) { + free(data); + data = NULL; + } + + + m2mbase_stub::name_id_value = -1; + data = serializer->serialize( m2mobject_stub::instance_list,size); + CHECK(data == NULL); + + delete name; + delete res_instance; + delete resource; + delete instance; + delete object; + + m2mresource_stub::clear(); + m2mobjectinstance_stub::clear(); + m2mobject_stub::clear(); + +} + +void Test_M2MTLVSerializer::test_serialize_resource_instance() +{ + String *name = new String("1"); + M2MObject *object = new M2MObject(*name); + M2MObjectInstance* instance = new M2MObjectInstance(*name,*object); + + uint32_t size = 0; + uint8_t *data = 0; + m2mbase_stub::name_id_value = 0; + M2MResource* resource = new M2MResource(*instance, + *name, + *name, + M2MResourceInstance::INTEGER, + M2MResource::Dynamic, + false); + + M2MResourceInstance* res_instance = new M2MResourceInstance(*name, + *name, + M2MResourceInstance::INTEGER, + *instance); + + + m2mobjectinstance_stub::resource_list.clear(); + m2mobjectinstance_stub::resource_list.push_back(resource); + + m2mresource_stub::bool_value = true; + m2mresource_stub::list.push_back(res_instance); + + m2mbase_stub::operation = M2MBase::GET_ALLOWED; + + data = serializer->serialize( m2mobjectinstance_stub::resource_list,size); + CHECK(data != NULL); + + if(data) { + free(data); + data = NULL; + } + + + m2mbase_stub::name_id_value = -1; + data = serializer->serialize( m2mobject_stub::instance_list,size); + CHECK(data == NULL); + + delete name; + delete res_instance; + delete resource; + delete instance; + delete object; + + m2mresource_stub::clear(); + m2mobjectinstance_stub::clear(); + m2mobject_stub::clear(); +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/test_m2mtlvserializer.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/test_m2mtlvserializer.h new file mode 100755 index 0000000000..ba0a317aef --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/m2mtlvdeserializer/test_m2mtlvserializer.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TEST_M2M_TLV_SERIALIZER_H +#define TEST_M2M_TLV_SERIALIZER_H + +#include "m2mtlvserializer.h" + +class Test_M2MTLVSerializer +{ +public: + Test_M2MTLVSerializer(); + + virtual ~Test_M2MTLVSerializer(); + + void test_serialize_object(); + + void test_serialize_object_instance(); + + void test_serialize_resource(); + + void test_serialize_resource_instance(); + + M2MTLVSerializer *serializer; +}; + +#endif // TEST_M2M_TLV_SERIALIZER_H diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/nsdlaccesshelper/CMakeLists.txt b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/nsdlaccesshelper/CMakeLists.txt new file mode 100644 index 0000000000..cc1c6e9bc4 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/nsdlaccesshelper/CMakeLists.txt @@ -0,0 +1,26 @@ +if(TARGET_LIKE_LINUX) +include("../includes.txt") +add_executable(nsdlaccesshelper + "../../../../source/nsdlaccesshelper.cpp" + "main.cpp" + "nsdlaccesshelpertest.cpp" + "test_nsdlaccesshelper.cpp" + "../stub/common_stub.cpp" + "../stub/m2mnsdlinterface_stub.cpp" + "../stub/m2mstring_stub.cpp" + "../stub/m2mconnectionhandler_stub.cpp" + "../stub/m2mconnectionsecurity_stub.cpp" +) + +target_link_libraries(nsdlaccesshelper + CppUTest + CppUTestExt +) +set_target_properties(nsdlaccesshelper +PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" + LINK_FLAGS "${UTEST_LINK_FLAGS}") + +set(binary "nsdlaccesshelper") +add_test(nsdlaccesshelper ${binary}) + +endif() diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/nsdlaccesshelper/main.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/nsdlaccesshelper/main.cpp new file mode 100644 index 0000000000..2632230d9d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/nsdlaccesshelper/main.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP( NsdlAccessHelper); diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/nsdlaccesshelper/nsdlaccesshelpertest.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/nsdlaccesshelper/nsdlaccesshelpertest.cpp new file mode 100644 index 0000000000..bdc7fc6357 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/nsdlaccesshelper/nsdlaccesshelpertest.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//CppUTest includes should be after your and system includes +#include "CppUTest/TestHarness.h" +#include "test_nsdlaccesshelper.h" + +TEST_GROUP(NsdlAccessHelper) +{ + Test_NsdlAccessHelper* nsdl; + + void setup() + { + nsdl = new Test_NsdlAccessHelper(); + } + void teardown() + { + delete nsdl; + } +}; + + +TEST(NsdlAccessHelper, create) +{ + CHECK(nsdl != NULL); +} + +TEST(NsdlAccessHelper, test_nsdl_c_callback) +{ + nsdl->test_nsdl_c_callback(); +} + +TEST(NsdlAccessHelper, test_nsdl_c_memory_alloc) +{ + nsdl->test_nsdl_c_memory_alloc(); +} + +TEST(NsdlAccessHelper, test_nsdl_c_memory_free) +{ + nsdl->test_nsdl_c_memory_free(); +} + +TEST(NsdlAccessHelper, test_nsdl_c_send_to_server) +{ + nsdl->test_nsdl_c_send_to_server(); +} + +TEST(NsdlAccessHelper, test_nsdl_c_received_from_server) +{ + nsdl->test_nsdl_c_received_from_server(); +} + + +TEST(NsdlAccessHelper, test_socket_malloc) +{ + nsdl->test_socket_malloc(); +} + +TEST(NsdlAccessHelper, test_socket_free) +{ + nsdl->test_socket_free(); +} + +TEST(NsdlAccessHelper, test_mutex_claim) +{ + nsdl->test_mutex_claim(); +} + +TEST(NsdlAccessHelper, test_mutex_release) +{ + nsdl->test_mutex_release(); +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/nsdlaccesshelper/test_nsdlaccesshelper.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/nsdlaccesshelper/test_nsdlaccesshelper.cpp new file mode 100755 index 0000000000..ac3c7af7e9 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/nsdlaccesshelper/test_nsdlaccesshelper.cpp @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "CppUTest/TestHarness.h" +#include "test_nsdlaccesshelper.h" +#include "common_stub.h" +#include "m2mnsdlinterface_stub.h" +#include "m2mnsdlobserver.h" +#include "m2mconnectionobserver.h" + +class TestObserver : public M2MNsdlObserver, + public M2MConnectionObserver +{ + +public: + TestObserver(){} + virtual ~TestObserver(){} + void coap_message_ready(uint8_t *, + uint16_t, + sn_nsdl_addr_s *){ + message_ready = true; + } + + void client_registered(M2MServer *){ + registered = true; + } + + void registration_updated(const M2MServer &){ + + } + + void registration_error(uint8_t, bool retry = false){ + register_error = true; + } + + void client_unregistered(){ + unregistered = true; + } + + void bootstrap_done(M2MSecurity *sec){ + if(sec) { + boot_done = true; + } + } + + void bootstrap_error(){ + boot_error = true; + } + + void coap_data_processed(){ + data_processed = true; + } + + void value_updated(M2MBase *){ + } + + void data_available(uint8_t*, + uint16_t, + const M2MConnectionObserver::SocketAddress &) { + + } + + void socket_error(uint8_t, bool) { + + } + + void address_ready(const M2MConnectionObserver::SocketAddress &, + M2MConnectionObserver::ServerType, + const uint16_t) { + + } + + void data_sent() { + + } + + bool register_error; + bool boot_error; + bool boot_done; + bool registered; + bool data_processed; + bool unregistered; + bool message_ready; + +}; + +Test_NsdlAccessHelper::Test_NsdlAccessHelper() +{ + observer = new TestObserver(); +} + +Test_NsdlAccessHelper::~Test_NsdlAccessHelper() +{ + delete observer; + observer = NULL; + + clear_list(); +} + +void Test_NsdlAccessHelper::test_nsdl_c_callback() +{ + CHECK(__nsdl_c_callback(NULL,NULL,NULL,SN_NSDL_PROTOCOL_HTTP) == 0 ); + + m2mnsdlinterface_stub::int_value = 1; + m2mnsdlinterface_stub::void_value = malloc(1); + __nsdl_interface_list.clear(); + __nsdl_interface_list.push_back(new M2MNsdlInterface(*observer)); + common_stub::coap_header = (sn_coap_hdr_s *) malloc(sizeof(sn_coap_hdr_s)); + memset(common_stub::coap_header, 0, sizeof(sn_coap_hdr_s)); + common_stub::coap_header->options_list_ptr = (sn_coap_options_list_s *) malloc(sizeof(sn_coap_options_list_s)); + common_stub::coap_header->options_list_ptr->block1_len = 2; + + CHECK(__nsdl_c_callback((nsdl_s*)m2mnsdlinterface_stub::void_value, + common_stub::coap_header,NULL,SN_NSDL_PROTOCOL_HTTP) == 1 ); + free(common_stub::coap_header->options_list_ptr); + free(common_stub::coap_header); + free(m2mnsdlinterface_stub::void_value); + clear_list(); +} + +void Test_NsdlAccessHelper::test_nsdl_c_memory_alloc() +{ + void *ptr = __nsdl_c_memory_alloc(6); + CHECK(ptr != NULL); + free(ptr); + ptr = NULL; + ptr = __nsdl_c_memory_alloc(UINT16_MAX+1); + CHECK(ptr == NULL); + free(ptr); +} + +void Test_NsdlAccessHelper::test_nsdl_c_memory_free() +{ + void* ptr = malloc(7); + __nsdl_c_memory_free(ptr); + + CHECK(ptr != NULL); + + ptr = NULL; + //No need to check anything, since memory leak is the test +} + +void Test_NsdlAccessHelper::test_nsdl_c_send_to_server() +{ + CHECK(__nsdl_c_send_to_server(NULL, SN_NSDL_PROTOCOL_HTTP, NULL, 0, NULL) == 0); + + m2mnsdlinterface_stub::int_value = 1; + m2mnsdlinterface_stub::void_value = malloc(1); + __nsdl_interface_list.clear(); + __nsdl_interface_list.push_back(new M2MNsdlInterface(*observer)); + + CHECK(__nsdl_c_send_to_server((nsdl_s*)m2mnsdlinterface_stub::void_value, SN_NSDL_PROTOCOL_HTTP, NULL, 0, NULL) == 1); + free(m2mnsdlinterface_stub::void_value); + clear_list(); +} + +void Test_NsdlAccessHelper::test_nsdl_c_received_from_server() +{ + CHECK( 0 == __nsdl_c_received_from_server(NULL, NULL, NULL)); + + m2mnsdlinterface_stub::int_value = 1; + m2mnsdlinterface_stub::void_value = malloc(1); + __nsdl_interface_list.clear(); + __nsdl_interface_list.push_back(new M2MNsdlInterface(*observer)); + common_stub::coap_header = (sn_coap_hdr_s *) malloc(sizeof(sn_coap_hdr_s)); + memset(common_stub::coap_header, 0, sizeof(sn_coap_hdr_s)); + common_stub::coap_header->options_list_ptr = (sn_coap_options_list_s *) malloc(sizeof(sn_coap_options_list_s)); + common_stub::coap_header->options_list_ptr->block1_len = 2; + CHECK( 1 == __nsdl_c_received_from_server((nsdl_s*)m2mnsdlinterface_stub::void_value, common_stub::coap_header, NULL)); + free(common_stub::coap_header->options_list_ptr); + free(common_stub::coap_header); + free(m2mnsdlinterface_stub::void_value); + clear_list(); +} + +void Test_NsdlAccessHelper::test_socket_malloc() +{ + void *ptr = __socket_malloc(NULL, 6); + CHECK(ptr != NULL); + + free(ptr); +} + +void Test_NsdlAccessHelper::test_socket_free() +{ + void* ptr = malloc(7); + __socket_free(NULL, ptr); + + ptr = NULL; + //No need to check anything, since memory leak is the test +} + +void Test_NsdlAccessHelper::test_mutex_claim() +{ + __connection_handler = new M2MConnectionHandler(*observer, + NULL, + M2MInterface::UDP, + M2MInterface::LwIP_IPv4); + __mutex_claim(); + + delete __connection_handler; +} + +void Test_NsdlAccessHelper::test_mutex_release() +{ + __connection_handler = new M2MConnectionHandler(*observer, + NULL, + M2MInterface::UDP, + M2MInterface::LwIP_IPv4); + __mutex_release(); + + delete __connection_handler; +} + +void Test_NsdlAccessHelper::clear_list() +{ + M2MNsdlInterfaceList::const_iterator it; + it = __nsdl_interface_list.begin(); + int size = __nsdl_interface_list.size(); + if (!__nsdl_interface_list.empty()) { + for (int i = 0; i < size; i++) { + delete __nsdl_interface_list[i]; + __nsdl_interface_list.erase(i); + } + __nsdl_interface_list.clear(); + } +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/nsdlaccesshelper/test_nsdlaccesshelper.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/nsdlaccesshelper/test_nsdlaccesshelper.h new file mode 100755 index 0000000000..841e20ea51 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/nsdlaccesshelper/test_nsdlaccesshelper.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 TEST_NSDL_ACCESS_HELPER_H +#define TEST_NSDL_ACCESS_HELPER_H + +#include "nsdlaccesshelper.h" +#include "common_stub.h" + +class TestObserver; + +class Test_NsdlAccessHelper +{ +public: + Test_NsdlAccessHelper(); + + virtual ~Test_NsdlAccessHelper(); + + void test_nsdl_c_callback(); + + void test_nsdl_c_memory_alloc(); + + void test_nsdl_c_memory_free(); + + void test_nsdl_c_send_to_server(); + + void test_nsdl_c_received_from_server(); + + void test_socket_malloc(); + + void test_socket_free(); + + void test_mutex_claim(); + + void test_mutex_release(); + + TestObserver *observer; +private: + void clear_list(); +}; + +#endif // TEST_NSDL_ACCESS_HELPER_H diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/common_stub.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/common_stub.cpp new file mode 100644 index 0000000000..af0ee47632 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/common_stub.cpp @@ -0,0 +1,458 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "common_stub.h" +#include "sn_grs.h" +#include + +socket_error_t common_stub::error; +socket_event_t * common_stub::event; +socket_addr * common_stub::addr; +void * common_stub::void_value; +bool common_stub::visited; +bool common_stub::bool_value; +int common_stub::int_value; +int common_stub::int2_value; +addrinfo* common_stub::addrinfo; +uint16_t common_stub::uint_value; +omalw_certificate_list_t *common_stub::cert; +sn_coap_hdr_s *common_stub::coap_header; +sn_nsdl_resource_info_s *common_stub::resource; +pthread_t common_stub::thread; +const char* common_stub::char_value; + +using namespace mbed; +using namespace mbed::Sockets::v0; + +void common_stub::clear() +{ + int_value = -1; + int2_value = -1; + uint_value = 0; + error = SOCKET_ERROR_NONE; + event = NULL; + addr = NULL; + void_value = NULL; + cert = NULL; + visited = false; + bool_value= false; + coap_header = NULL; + resource = NULL; + addrinfo = NULL; + char_value = NULL; +} + +UDPSocket::UDPSocket(socket_stack_t stack) :Socket(stack) +{ +} + +UDPSocket::~UDPSocket() +{ +} + +socket_error_t UDPSocket::connect(const SocketAddr *, const uint16_t ) +{ + return common_stub::error; +} + +//SocketAddr + +void SocketAddr::setAddr(const struct socket_addr *) +{ +} + +void SocketAddr::setAddr(const SocketAddr *) +{ +} + +bool SocketAddr::SocketAddr::is_v4() +{ + return common_stub::bool_value; +} + +void mbed::Ticker::detach() +{ + common_stub::visited = true; +} + + +// SN_NSDL_LIB + +struct nsdl_s *sn_nsdl_init (uint8_t (*sn_nsdl_tx_cb)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *), + uint8_t (*sn_nsdl_rx_cb)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *), + void *(*sn_nsdl_alloc)(uint16_t),void (*sn_nsdl_free)(void *)) +{ + return NULL; +} + +uint16_t sn_nsdl_register_endpoint(struct nsdl_s *, sn_nsdl_ep_parameters_s *) +{ + return common_stub::uint_value; +} + +uint16_t sn_nsdl_unregister_endpoint(struct nsdl_s *) +{ + return common_stub::uint_value; +} + +uint16_t sn_nsdl_update_registration(struct nsdl_s *,uint8_t *, uint8_t) +{ + return common_stub::uint_value; +} + +uint16_t sn_nsdl_send_observation_notification_with_uri_path(struct nsdl_s *, uint8_t *, uint8_t, + uint8_t *, uint16_t, + uint8_t *, uint8_t, + sn_coap_msg_type_e , uint8_t, + uint8_t *, uint16_t) +{ + return common_stub::uint_value; +} +uint16_t sn_nsdl_send_observation_notification(struct nsdl_s *, uint8_t *, uint8_t, + uint8_t *, uint16_t, + uint8_t *, uint8_t, + sn_coap_msg_type_e , uint8_t) +{ + return common_stub::uint_value; +} + +int8_t sn_nsdl_set_endpoint_location(struct nsdl_s *, uint8_t *, uint8_t) +{ + return common_stub::int_value; +} + +int8_t sn_nsdl_destroy(struct nsdl_s *handle) +{ + return common_stub::int_value; +} + +sn_coap_hdr_s *sn_nsdl_build_response(struct nsdl_s *, sn_coap_hdr_s *, uint8_t ) +{ + return common_stub::coap_header; +} + +sn_nsdl_resource_info_s *sn_nsdl_get_resource(struct nsdl_s *, uint16_t, uint8_t *) +{ + return common_stub::resource; +} + +int8_t sn_nsdl_process_coap(struct nsdl_s *, uint8_t *, uint16_t , sn_nsdl_addr_s *) +{ + return common_stub::int_value; +} + +int8_t sn_nsdl_exec(struct nsdl_s *, uint32_t) +{ + return common_stub::int_value; +} + +int8_t sn_nsdl_set_retransmission_parameters(struct nsdl_s *, uint8_t, uint8_t) +{ + return common_stub::int_value; +} + +void sn_nsdl_release_allocated_coap_msg_mem(struct nsdl_s *, sn_coap_hdr_s *header) +{ + if(header && header != common_stub::coap_header){ + if( header->content_type_ptr ){ + free(header->content_type_ptr); + header->content_type_ptr = NULL; + } + if( header->options_list_ptr){ + free(header->options_list_ptr); + header->options_list_ptr = NULL; + } + free(header); + header = NULL; + } +} + +int8_t sn_nsdl_create_resource(struct nsdl_s *, sn_nsdl_resource_info_s *) +{ + return common_stub::int_value; +} + +int8_t sn_nsdl_delete_resource(struct nsdl_s *, uint16_t , uint8_t *) +{ + return common_stub::int_value; +} + +int8_t sn_nsdl_send_coap_message(struct nsdl_s *, sn_nsdl_addr_s *, sn_coap_hdr_s *) +{ + return common_stub::int_value; +} + +int8_t sn_nsdl_update_resource(struct nsdl_s *, sn_nsdl_resource_info_s *) +{ + return common_stub::int_value; +} + +int8_t set_NSP_address(struct nsdl_s *, uint8_t *, uint16_t, sn_nsdl_addr_type_e) +{ + return common_stub::int_value; +} + +uint16_t sn_nsdl_oma_bootstrap(struct nsdl_s *, sn_nsdl_addr_s *, + sn_nsdl_ep_parameters_s *, + sn_nsdl_bs_ep_info_t *) +{ + return common_stub::uint_value; +} + +omalw_certificate_list_t *sn_nsdl_get_certificates(struct nsdl_s *) +{ + return common_stub::cert; +} + +int8_t sn_nsdl_update_certificates(struct nsdl_s *, omalw_certificate_list_t*, uint8_t) +{ + return common_stub::int_value; +} + +int8_t sn_nsdl_create_oma_device_object(struct nsdl_s *, sn_nsdl_oma_device_t *) +{ + return common_stub::int_value; +} + +//Coap Headers + +sn_coap_hdr_s *sn_coap_build_response(struct coap_s *, sn_coap_hdr_s *, uint8_t ) +{ + return common_stub::coap_header; +} + +void sn_coap_parser_release_allocated_coap_msg_mem(struct coap_s *, sn_coap_hdr_s *) +{ +} + +int8_t sn_coap_protocol_set_retransmission_parameters(uint8_t, uint8_t) +{ + return common_stub::int_value; +} + +// IP6String.h +uint_fast8_t ip6tos(const void *ip6addr, char *p) +{ + // Just set at least something there, or the valgrind will scream when + // client tries to use the result string. + p[0] = '\0'; + return 0; +} + +//Socket +Socket::Socket(const socket_stack_t ) : _irq(this) +{ + _socket.api = NULL; +} + +Socket::~Socket() +{ +} + +socket_error_t Socket::open(const socket_address_family_t , const socket_proto_family_t ) +{ + return common_stub::error; +} + +bool Socket::error_check(socket_error_t ) +{ + return common_stub::bool_value; +} + +void Socket::_eventHandler(struct socket_event *) +{ +} + +void Socket::setOnError(const ErrorHandler_t &) +{ +} + +void Socket::setOnReadable(const ReadableHandler_t &) +{ +} + +void Socket::setOnSent(const SentHandler_t & ) +{ +} + +void Socket::_nvEventHandler(void * ) +{ +} + +socket_error_t Socket::getLocalAddr(SocketAddr *) const +{ + return common_stub::error; +} + +socket_error_t Socket::getLocalPort(uint16_t *) const +{ + return common_stub::error; +} + +socket_error_t Socket::getRemoteAddr(SocketAddr *) const +{ + return common_stub::error; +} + +socket_error_t Socket::getRemotePort(uint16_t *) const +{ + return common_stub::error; +} + +socket_error_t Socket::resolve(const char* , const DNSHandler_t & ) +{ + return common_stub::error; +} + +socket_error_t Socket::bind(const char * , const uint16_t ) +{ + return common_stub::error; +} +socket_error_t Socket::bind(const SocketAddr * , const uint16_t ) +{ + return common_stub::error; +} + +socket_error_t Socket::close() +{ + return common_stub::error; +} + +socket_error_t Socket::recv(void * , size_t *) +{ + return common_stub::error; +} +socket_error_t Socket::recv_from(void * , size_t *, SocketAddr *, uint16_t *) +{ + return common_stub::error; +} + +socket_error_t Socket::send(const void * , const size_t ) +{ + return common_stub::error; +} +socket_error_t Socket::send_to(const void * , const size_t , const SocketAddr *, uint16_t ) +{ + return common_stub::error; +} + +bool Socket::isConnected() const { + return common_stub::error; +} + +// pthread +int pthread_equal (pthread_t , pthread_t ) __THROW +{ + return common_stub::int2_value; +} + +pthread_t pthread_self (void) __THROW +{ + return common_stub::thread; +} + +int pthread_detach (pthread_t) __THROW +{ + return common_stub::int_value; +} + +int pthread_create (pthread_t * , + const pthread_attr_t *, + void *(*__start_routine) (void *), + void *) __THROWNL +{ + __start_routine(NULL); + return common_stub::int_value; +} + +int pthread_cancel (pthread_t) +{ + return common_stub::int_value; +} + +int pthread_join (pthread_t , void **) +{ + return common_stub::int_value; +} + +void pthread_exit (void *__retval)/* __attribute__ ((__noreturn__))*/ +{ + +} + +// sys/socket +#ifndef __SOCKADDR_ARG +# define __SOCKADDR_ARG struct sockaddr *__restrict +#endif + +#ifndef __CONST_SOCKADDR_ARG +# define __CONST_SOCKADDR_ARG const struct sockaddr * +#endif + +#ifndef __socklen_t_defined +typedef __socklen_t socklen_t; +# define __socklen_t_defined +#endif + +int bind (int , __CONST_SOCKADDR_ARG , socklen_t ) + __THROW +{ + return common_stub::int_value; +} + +ssize_t sendto (int , const void *, size_t , + int , __CONST_SOCKADDR_ARG , + socklen_t ) +{ + return common_stub::int_value; +} + +ssize_t recvfrom (int , void * , size_t , + int , __SOCKADDR_ARG , + socklen_t * ) +{ + return common_stub::int_value; +} + +int getaddrinfo (const char *__restrict, + const char *__restrict, + const struct addrinfo *__restrict, + struct addrinfo **__restrict addr) +{ + //*addr = (addrinfo*)malloc(sizeof(addrinfo)); + //(*addr)->ai_addr = (sockaddr*)malloc(sizeof(sockaddr)); + *addr = common_stub::addrinfo; + return common_stub::int_value; +} + +void freeaddrinfo (struct addrinfo * addr) +__THROW +{ +// free(addr->ai_addr); +// free(addr); +} + +const char *inet_ntop (int, const void *__restrict, + char *__restrict, socklen_t) + __THROW +{ + return common_stub::char_value; +} + +int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) +{ + return common_stub::int_value; +} + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/common_stub.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/common_stub.h new file mode 100644 index 0000000000..83e4415d06 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/common_stub.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 COMMON_STUB_H +#define COMMON_STUB_H + +#include +#include +#include "sockets/UDPSocket.h" +#include "nsdlaccesshelper.h" +#include "ip6string.h" +#include "Ticker.h" + +//some internal test related stuff +namespace common_stub +{ + extern socket_error_t error; + extern socket_event_t* event; + extern socket_addr* addr; + extern bool visited; + extern bool bool_value; + extern void* void_value; + extern int int_value; + extern int int2_value; + extern uint16_t uint_value; + extern omalw_certificate_list_t *cert; + extern addrinfo* addrinfo; + extern sn_coap_hdr_s *coap_header; + extern sn_nsdl_resource_info_s *resource; + extern pthread_t thread; + extern const char *char_value; + void clear(); +} + +#endif // COMMON_STUB_H diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mbase_stub.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mbase_stub.cpp new file mode 100755 index 0000000000..5d3ba2ebf7 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mbase_stub.cpp @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mbase_stub.h" + +#include + +uint8_t m2mbase_stub::uint8_value; +uint16_t m2mbase_stub::uint16_value; +uint32_t m2mbase_stub::uint32_value; +uint16_t m2mbase_stub::int_value; +int32_t m2mbase_stub::name_id_value; + +bool m2mbase_stub::bool_value; +String *m2mbase_stub::string_value; + +M2MBase::BaseType m2mbase_stub::base_type; +M2MBase::Operation m2mbase_stub::operation; +M2MBase::Mode m2mbase_stub::mode_value; +M2MBase::Observation m2mbase_stub::observation_level_value; + +void *m2mbase_stub::void_value; +M2MObservationHandler *m2mbase_stub::observe; +M2MReportHandler *m2mbase_stub::report; +bool m2mbase_stub::is_value_updated_function_set; + + +void m2mbase_stub::clear() +{ + int_value = 0; + uint8_value = 0; + uint16_value = 0; + uint32_value = 0; + string_value = NULL; + name_id_value = -1; + mode_value = M2MBase::Static; + base_type = M2MBase::Object; + observation_level_value = M2MBase::None; + bool_value = false; + m2mbase_stub::operation = M2MBase::NOT_ALLOWED; + void_value = NULL; + observe = NULL; + report = NULL; + is_value_updated_function_set = false; +} + +M2MBase::M2MBase(const String &/*resource_name*/, + M2MBase::Mode /*mode*/) +{ +} + +M2MBase& M2MBase::operator=(const M2MBase& other) +{ + if (this != &other) { // protect against invalid self-assignment + } + return *this; +} + +M2MBase::M2MBase(const M2MBase& other) +{ + this->operator=(other); +} + +M2MBase::~M2MBase() +{ +} + +void M2MBase::set_operation(M2MBase::Operation opr) +{ + m2mbase_stub::operation = opr; +} + +void M2MBase::set_interface_description(const String &/*desc*/) +{ +} + +void M2MBase::set_resource_type(const String &/*res_type*/) +{ +} + +void M2MBase::set_coap_content_type(const uint8_t /*con_type*/) +{ +} + +void M2MBase::set_instance_id(const uint16_t /*inst_id*/) +{ +} + +void M2MBase::set_observation_number(const uint16_t /*observation_number*/) +{ +} + +void M2MBase::set_max_age(const uint32_t /*max_age*/) +{ +} + +M2MBase::Operation M2MBase::operation() const +{ + return m2mbase_stub::operation; +} + +const String& M2MBase::name() const +{ + return *m2mbase_stub::string_value; +} + +int32_t M2MBase::name_id() const +{ + return m2mbase_stub::name_id_value; +} + +uint16_t M2MBase::instance_id() const +{ + return m2mbase_stub::int_value; +} + +const String& M2MBase::interface_description() const +{ + return *m2mbase_stub::string_value; +} + +const String& M2MBase::resource_type() const +{ + return *m2mbase_stub::string_value; +} + +uint8_t M2MBase::coap_content_type() const +{ + return m2mbase_stub::uint8_value; +} + +uint32_t M2MBase::max_age() const +{ + return m2mbase_stub::uint32_value; +} + +void M2MBase::set_observable(bool /*observable*/) +{ +} + +void M2MBase::add_observation_level(M2MBase::Observation) +{ +} + +void M2MBase::remove_observation_level(M2MBase::Observation) +{ +} + +void M2MBase::set_under_observation(bool /*observed*/, + M2MObservationHandler */*handler*/) +{ +} + +void M2MBase::set_observation_token(const uint8_t */*token*/, + const uint8_t /*length*/) +{ +} + +bool M2MBase::is_observable() const +{ + return m2mbase_stub::bool_value; +} + +M2MBase::Observation M2MBase::observation_level() const +{ + return m2mbase_stub::observation_level_value; +} + +void M2MBase::get_observation_token(uint8_t *&/*token*/, + uint32_t &/*length*/) +{ +} + +void M2MBase::set_base_type(M2MBase::BaseType /*type*/) +{ +} + +M2MBase::BaseType M2MBase::base_type() const +{ + return m2mbase_stub::base_type; +} + +M2MBase::Mode M2MBase::mode() const +{ + return m2mbase_stub::mode_value; +} + +uint16_t M2MBase::observation_number() const +{ + return m2mbase_stub::uint16_value; +} + +void M2MBase::remove_resource_from_coap(const String &) +{ +} + +void M2MBase::remove_object_from_coap() +{ +} + +bool M2MBase::handle_observation_attribute(char *&query) +{ + return m2mbase_stub::bool_value; +} + +void M2MBase::observation_to_be_sent(m2m::Vector, bool) +{ +} + +void *M2MBase::memory_alloc(uint32_t size) +{ + if(size) + return malloc(size); + else + return 0; +} + +void M2MBase::memory_free(void *ptr) +{ + if(ptr) + free(ptr); +} + +uint8_t* M2MBase::alloc_string_copy(const uint8_t* source, uint32_t size) +{ + assert(source != NULL); + + uint8_t* result = (uint8_t*)memory_alloc(size + 1); + if (result) { + memcpy(result, source, size); + result[size] = '\0'; + } + return result; +} + +uint8_t* M2MBase::alloc_copy(const uint8_t* source, uint32_t size) +{ + assert(source != NULL); + + uint8_t* result = (uint8_t*)memory_alloc(size); + if (result) { + memcpy(result, source, size); + } + return result; +} + +M2MReportHandler* M2MBase::report_handler() +{ + return m2mbase_stub::report; +} + +M2MObservationHandler* M2MBase::observation_handler() +{ + return m2mbase_stub::observe; +} + +sn_coap_hdr_s* M2MBase::handle_get_request(nsdl_s */*nsdl*/, + sn_coap_hdr_s */*received_coap_header*/, + M2MObservationHandler */*observation_handler*/) +{ + //Handled in M2MResource, M2MObjectInstance and M2MObject classes + return NULL; +} + +sn_coap_hdr_s* M2MBase::handle_put_request(nsdl_s */*nsdl*/, + sn_coap_hdr_s */*received_coap_header*/, + M2MObservationHandler */*observation_handler*/, + bool &execute_value_updated) +{ + //Handled in M2MResource, M2MObjectInstance and M2MObject classes + return NULL; +} + +sn_coap_hdr_s* M2MBase::handle_post_request(nsdl_s */*nsdl*/, + sn_coap_hdr_s */*received_coap_header*/, + M2MObservationHandler */*observation_handler*/, + bool &) +{ + //Handled in M2MResource, M2MObjectInstance and M2MObject classes + return NULL; +} + +void M2MBase::set_register_uri( bool register_uri) +{ +} + +bool M2MBase::register_uri() +{ + return m2mbase_stub::bool_value; +} + +void M2MBase::set_uri_path(const String &uri_path) +{ +} + +const String& M2MBase::uri_path() const +{ + return *m2mbase_stub::string_value; +} + +bool M2MBase::is_under_observation() const +{ + return m2mbase_stub::bool_value; +} + +void M2MBase::set_value_updated_function(value_updated_callback callback) +{ + +} + +void M2MBase::set_value_updated_function(value_updated_callback2 callback) +{ + +} + +bool M2MBase::is_value_updated_function_set() +{ + return m2mbase_stub::is_value_updated_function_set; +} + +void M2MBase::execute_value_updated(const String& name) +{ + +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mbase_stub.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mbase_stub.h new file mode 100755 index 0000000000..8abe2db655 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mbase_stub.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_BASE_STUB_H +#define M2M_BASE_STUB_H + +#include "m2mbase.h" + +//some internal test related stuff +namespace m2mbase_stub +{ + extern uint8_t uint8_value; + extern uint16_t uint16_value; + extern uint32_t uint32_value; + extern uint16_t int_value; + extern int32_t name_id_value; + extern String *string_value; + extern bool bool_value; + extern M2MBase::BaseType base_type; + extern M2MBase::Mode mode_value; + extern M2MBase::Operation operation; + extern void *void_value; + extern M2MObservationHandler *observe; + extern M2MReportHandler *report; + extern M2MBase::Observation observation_level_value; + extern bool is_value_updated_function_set; + void clear(); +} + +#endif // M2M_BASE_STUB_H + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mconnectionhandler_stub.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mconnectionhandler_stub.cpp new file mode 100755 index 0000000000..333dc0bc7e --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mconnectionhandler_stub.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mconnectionhandler_stub.h" +#include "m2mconnectionsecurity.h" +#include "common_stub.h" + +int m2mconnectionhandler_stub::int_value; +uint16_t m2mconnectionhandler_stub::uint_value; +bool m2mconnectionhandler_stub::bool_value; + +void m2mconnectionhandler_stub::clear() +{ + int_value = -1; + uint_value = 0; + bool_value = false; +} + +M2MConnectionHandler::M2MConnectionHandler(M2MConnectionObserver &observer, + M2MConnectionSecurity* sec, + M2MInterface::BindingMode, + M2MInterface::NetworkStack) +:_observer(observer) +{ + if( sec ){ + delete sec; + sec = NULL; + } +} + +M2MConnectionHandler::~M2MConnectionHandler() +{ +} + +bool M2MConnectionHandler::bind_connection(const uint16_t) +{ + return m2mconnectionhandler_stub::bool_value; +} + +bool M2MConnectionHandler::resolve_server_address(const String&, + const uint16_t, + M2MConnectionObserver::ServerType, + const M2MSecurity* ) +{ + return m2mconnectionhandler_stub::bool_value; +} + +bool M2MConnectionHandler::start_listening_for_data() +{ + return m2mconnectionhandler_stub::bool_value; +} + +bool M2MConnectionHandler::send_data(uint8_t *, + uint16_t , + sn_nsdl_addr_s *) +{ + return m2mconnectionhandler_stub::bool_value; +} + +void M2MConnectionHandler::stop_listening() +{ +} + +int M2MConnectionHandler::send_to_socket(const unsigned char *, size_t ){ + return m2mconnectionhandler_stub::int_value; +} + +int M2MConnectionHandler::receive_from_socket(unsigned char *, size_t){ + return m2mconnectionhandler_stub::int_value; +} + +void M2MConnectionHandler::set_platform_network_handler(void *) +{ +} + +void M2MConnectionHandler::claim_mutex() +{ +} + +void M2MConnectionHandler::release_mutex() +{ +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mconnectionhandler_stub.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mconnectionhandler_stub.h new file mode 100755 index 0000000000..e0a4d278a2 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mconnectionhandler_stub.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_CONNECTION_HANDLER_IMPL_MBED_STUB_H +#define M2M_CONNECTION_HANDLER_IMPL_MBED_STUB_H + +#include "m2mconnectionhandler.h" + +//some internal test related stuff +namespace m2mconnectionhandler_stub +{ + extern int int_value; + extern uint16_t uint_value; + extern bool bool_value; + void clear(); +} + +#endif // M2M_CONNECTION_HANDLER_IMPL_STUB_H + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mconnectionsecurity_stub.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mconnectionsecurity_stub.cpp new file mode 100644 index 0000000000..bb9d9e8b74 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mconnectionsecurity_stub.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mconnectionhandler.h" +#include "m2mconnectionsecurity.h" +#include "m2mtimer.h" +#include "m2msecurity.h" +#include +#include "m2mconnectionsecurity_stub.h" + +bool m2mconnectionsecurityimpl_stub::use_inc_int; +int m2mconnectionsecurityimpl_stub::inc_int_value; +int m2mconnectionsecurityimpl_stub::int_value; + +void m2mconnectionsecurityimpl_stub::clear() +{ + int_value = -1; + use_inc_int = false; + inc_int_value = 0; +} + +M2MConnectionSecurity::M2MConnectionSecurity(M2MConnectionSecurity::SecurityMode mode) +{ + +} + +M2MConnectionSecurity::~M2MConnectionSecurity(){ +} + +void M2MConnectionSecurity::reset(){ +} + +int M2MConnectionSecurity::init(const M2MSecurity *security){ + if(m2mconnectionsecurityimpl_stub::use_inc_int){ + return m2mconnectionsecurityimpl_stub::inc_int_value++; + } + return m2mconnectionsecurityimpl_stub::int_value; +} + +int M2MConnectionSecurity::connect(M2MConnectionHandler* connHandler){ + if(m2mconnectionsecurityimpl_stub::use_inc_int){ + return m2mconnectionsecurityimpl_stub::inc_int_value++; + } + return m2mconnectionsecurityimpl_stub::int_value; +} + +int M2MConnectionSecurity::start_connecting_non_blocking(M2MConnectionHandler* connHandler) +{ + if(m2mconnectionsecurityimpl_stub::use_inc_int){ + return m2mconnectionsecurityimpl_stub::inc_int_value++; + } + return m2mconnectionsecurityimpl_stub::int_value; +} + +int M2MConnectionSecurity::continue_connecting() +{ + if(m2mconnectionsecurityimpl_stub::use_inc_int){ + return m2mconnectionsecurityimpl_stub::inc_int_value++; + } + return m2mconnectionsecurityimpl_stub::int_value; +} + +int M2MConnectionSecurity::send_message(unsigned char *message, int len){ + if(m2mconnectionsecurityimpl_stub::use_inc_int){ + return m2mconnectionsecurityimpl_stub::inc_int_value++; + } + return m2mconnectionsecurityimpl_stub::int_value; +} + +int M2MConnectionSecurity::read(unsigned char* buffer, uint16_t len){ + if(m2mconnectionsecurityimpl_stub::use_inc_int){ + return m2mconnectionsecurityimpl_stub::inc_int_value++; + } + return m2mconnectionsecurityimpl_stub::int_value; +} + +void M2MConnectionSecurity::set_random_number_callback(random_number_cb) +{ + +} + +void M2MConnectionSecurity::set_entropy_callback(mbedtls_entropy) +{ + +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mconnectionsecurity_stub.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mconnectionsecurity_stub.h new file mode 100644 index 0000000000..0e4eda024e --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mconnectionsecurity_stub.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_CONNECTION_SECURITY_IMPL_STUB_H +#define M2M_CONNECTION_SECURITY_IMPL_STUB_H + +//some internal test related stuff +namespace m2mconnectionsecurityimpl_stub +{ + extern int int_value; + extern bool use_inc_int; + extern int inc_int_value; + void clear(); +} + +#endif // M2M_CONNECTION_SECURITY_IMPL_STUB_H + + + + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mdevice_stub.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mdevice_stub.cpp new file mode 100755 index 0000000000..f629881de3 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mdevice_stub.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mdevice_stub.h" + +uint32_t m2mdevice_stub::int_value; +bool m2mdevice_stub::bool_value; +M2MResource* m2mdevice_stub::resource; +String m2mdevice_stub::string_value; + +void m2mdevice_stub::clear() +{ + int_value = -1; + bool_value = false; + string_value = ""; + resource = NULL; +} + +M2MDevice::M2MDevice() +: M2MObject("3") +{ +} + +M2MDevice::~M2MDevice() +{ +} + +M2MDevice* M2MDevice::get_instance() +{ + return new M2MDevice(); +} + +void M2MDevice::delete_instance() +{ +} + +M2MResource* M2MDevice::create_resource(DeviceResource, const String &) +{ + return m2mdevice_stub::resource; +} + +M2MResource* M2MDevice::create_resource(DeviceResource) +{ + return m2mdevice_stub::resource; +} + +bool M2MDevice::delete_resource(DeviceResource) +{ + return m2mdevice_stub::bool_value; +} + +bool M2MDevice::delete_resource_instance(DeviceResource, uint16_t) +{ + return m2mdevice_stub::bool_value; +} + +bool M2MDevice::set_resource_value(DeviceResource, + const String &, + uint16_t ) +{ + return m2mdevice_stub::bool_value; +} + +bool M2MDevice::set_resource_value(DeviceResource, + int64_t, + uint16_t) +{ + return m2mdevice_stub::bool_value; +} + +String M2MDevice::resource_value_string(DeviceResource, + uint16_t) const +{ + return m2mdevice_stub::string_value; +} + +int64_t M2MDevice::resource_value_int(DeviceResource, + uint16_t) const +{ + return m2mdevice_stub::int_value; +} + +bool M2MDevice::is_resource_present(DeviceResource) const +{ + return m2mdevice_stub::bool_value; +} + +uint16_t M2MDevice::per_resource_count(DeviceResource) const +{ + return (uint16_t)m2mdevice_stub::int_value; +} + +uint16_t M2MDevice::total_resource_count() const +{ + return (uint16_t)m2mdevice_stub::int_value; +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mdevice_stub.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mdevice_stub.h new file mode 100755 index 0000000000..2d7680cd5f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mdevice_stub.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_DEVICE_STUB_H +#define M2M_DEVICE_STUB_H + +#include "m2mdevice.h" + +//some internal test related stuff +namespace m2mdevice_stub +{ + extern uint32_t int_value; + extern M2MResource* resource; + extern String string_value; + extern bool bool_value; + void clear(); +} + +#endif // M2M_DEVICE_STUB_H + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mfirmware_stub.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mfirmware_stub.cpp new file mode 100644 index 0000000000..27dd6381ad --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mfirmware_stub.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mfirmware_stub.h" +bool m2mfirmware_stub::has_value; +uint32_t m2mfirmware_stub::int_value; +bool m2mfirmware_stub::bool_value; +M2MResource* m2mfirmware_stub::resource; +String m2mfirmware_stub::string_value; + +void m2mfirmware_stub::clear() +{ + int_value = -1; + bool_value = false; + string_value = ""; + resource = NULL; + has_value = false; +} + +M2MFirmware::M2MFirmware() +: M2MObject("5") +{ +} + +M2MFirmware::~M2MFirmware() +{ +} + +M2MFirmware* M2MFirmware::get_instance() +{ + return new M2MFirmware(); +} + +void M2MFirmware::delete_instance() +{ +} + +M2MResource* M2MFirmware::create_resource(FirmwareResource, const String &) +{ + return m2mfirmware_stub::resource; +} + +bool M2MFirmware::set_resource_value(FirmwareResource, + const uint8_t *, + const uint32_t) +{ + return m2mfirmware_stub::bool_value; +} + + +uint32_t M2MFirmware::resource_value_buffer(FirmwareResource, + uint8_t *&value) const +{ + if( m2mfirmware_stub::has_value ){ + value = (uint8_t *)malloc(5); + return 5; + } + return m2mfirmware_stub::int_value; +} + +bool M2MFirmware::delete_resource(FirmwareResource) +{ + return m2mfirmware_stub::bool_value; +} + +bool M2MFirmware::set_resource_value(FirmwareResource, + const String &) +{ + return m2mfirmware_stub::bool_value; +} + +bool M2MFirmware::set_resource_value(FirmwareResource, + int64_t) +{ + return m2mfirmware_stub::bool_value; +} + +String M2MFirmware::resource_value_string(FirmwareResource) const +{ + return m2mfirmware_stub::string_value; +} + +int64_t M2MFirmware::resource_value_int(FirmwareResource) const +{ + return m2mfirmware_stub::int_value; +} + +bool M2MFirmware::is_resource_present(FirmwareResource) const +{ + return m2mfirmware_stub::bool_value; +} + +uint16_t M2MFirmware::per_resource_count(FirmwareResource) const +{ + return (uint16_t)m2mfirmware_stub::int_value; +} + +uint16_t M2MFirmware::total_resource_count() const +{ + return (uint16_t)m2mfirmware_stub::int_value; +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mfirmware_stub.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mfirmware_stub.h new file mode 100644 index 0000000000..5d51a0e8f7 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mfirmware_stub.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_FIRMWARE_STUB_H +#define M2M_FIRMWARE_STUB_H + +#include "m2mfirmware.h" + +//some internal test related stuff +namespace m2mfirmware_stub +{ + extern uint32_t int_value; + extern M2MResource* resource; + extern String string_value; + extern bool bool_value; + void clear(); + extern bool has_value; +} + +#endif // M2M_FIRMWARE_STUB_H + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2minterfaceimpl_stub.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2minterfaceimpl_stub.cpp new file mode 100755 index 0000000000..77754bb329 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2minterfaceimpl_stub.cpp @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2minterfaceimpl_stub.h" +#include "common_stub.h" + +u_int8_t m2minterfaceimpl_stub::int_value; +String m2minterfaceimpl_stub::string_value; +bool m2minterfaceimpl_stub::bool_value; + +void m2minterfaceimpl_stub::clear() +{ + int_value = 0; + bool_value = false; + string_value = ""; +} + +M2MInterfaceImpl::M2MInterfaceImpl(M2MInterfaceObserver& observer, + const String &, + const String &, + const int32_t, + const uint16_t, + const String &, + M2MInterface::BindingMode, + M2MInterface::NetworkStack, + const String &) +: _observer(observer), + _current_state(0), + _max_states( STATE_MAX_STATES ), + _event_generated(false), + _event_data(NULL) +{ +} + +M2MInterfaceImpl::~M2MInterfaceImpl() +{ +} +void M2MInterfaceImpl::bootstrap(M2MSecurity *) +{ +} + +void M2MInterfaceImpl::cancel_bootstrap() +{ +} + +void M2MInterfaceImpl::register_object(M2MSecurity *, const M2MObjectList &) +{ +} + +void M2MInterfaceImpl::update_registration(M2MSecurity *, const uint32_t) +{ +} + +void M2MInterfaceImpl::unregister_object(M2MSecurity*) +{ +} + +void M2MInterfaceImpl::set_queue_sleep_handler(callback_handler) +{ + +} + +void M2MInterfaceImpl::set_platform_network_handler(void *) +{ + +} + +void M2MInterfaceImpl::set_random_number_callback(random_number_cb) +{ + +} + +void M2MInterfaceImpl::set_entropy_callback(entropy_cb) +{ + +} + +void M2MInterfaceImpl::coap_message_ready(uint8_t *, + uint16_t , + sn_nsdl_addr_s *) +{ + +} + +void M2MInterfaceImpl::client_registered(M2MServer*) +{ + +} + +void M2MInterfaceImpl::registration_error(uint8_t, bool) +{ + +} + +void M2MInterfaceImpl::client_unregistered() +{ + +} + +void M2MInterfaceImpl::bootstrap_done(M2MSecurity *) +{ + +} + +void M2MInterfaceImpl::bootstrap_error() +{ + +} + +void M2MInterfaceImpl::coap_data_processed() +{ + +} + +void M2MInterfaceImpl::data_available(uint8_t*, + uint16_t, + const M2MConnectionObserver::SocketAddress &) +{ + +} + +void M2MInterfaceImpl::socket_error(uint8_t, bool) +{ + +} + +void M2MInterfaceImpl::address_ready(const M2MConnectionObserver::SocketAddress &, + M2MConnectionObserver::ServerType, + const uint16_t) +{ + +} + +void M2MInterfaceImpl::data_sent() +{ +} + +void M2MInterfaceImpl::timer_expired(M2MTimerObserver::Type) +{ + +} + +void M2MInterfaceImpl::registration_updated(const M2MServer &) +{ +} + +void M2MInterfaceImpl::value_updated(M2MBase *) +{ + +} + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2minterfaceimpl_stub.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2minterfaceimpl_stub.h new file mode 100755 index 0000000000..ecf4f39bfd --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2minterfaceimpl_stub.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_INTERFACE_IMPL_STUB_H +#define M2M_INTERFACE_IMPL_STUB_H + +#include "m2minterfaceimpl.h" + +//some internal test related stuff +namespace m2minterfaceimpl_stub +{ + extern u_int8_t int_value; + extern String string_value; + extern bool bool_value; + void clear(); +} + +#endif // M2M_INTERFACE_IMPL_STUB_H + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mnsdlinterface_stub.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mnsdlinterface_stub.cpp new file mode 100755 index 0000000000..f77c1eb260 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mnsdlinterface_stub.cpp @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mnsdlinterface_stub.h" + + +bool m2mnsdlinterface_stub::bool_value; +uint32_t m2mnsdlinterface_stub::int_value; +void * m2mnsdlinterface_stub::void_value; +String m2mnsdlinterface_stub::string_value; +void m2mnsdlinterface_stub::clear() +{ + bool_value = false; + int_value = 0; + string_value = ""; + void_value = NULL; +} + +M2MNsdlInterface::M2MNsdlInterface(M2MNsdlObserver &observer) +: _observer(observer) +{ +} + +M2MNsdlInterface::~M2MNsdlInterface() +{ +} + +bool M2MNsdlInterface::initialize() +{ + return m2mnsdlinterface_stub::bool_value; +} + +void M2MNsdlInterface::create_endpoint(const String &, + const String &, + const int32_t, + const String &, + const uint8_t, + const String &) +{ +} + +void M2MNsdlInterface::delete_endpoint() +{ +} + +bool M2MNsdlInterface::create_nsdl_list_structure(const M2MObjectList &) +{ + return m2mnsdlinterface_stub::bool_value; +} + +bool M2MNsdlInterface::delete_nsdl_resource(const String &) +{ + return m2mnsdlinterface_stub::bool_value; +} + +bool M2MNsdlInterface::create_bootstrap_resource(sn_nsdl_addr_s *, const String& name) +{ + return m2mnsdlinterface_stub::bool_value; +} + +bool M2MNsdlInterface::send_register_message(uint8_t*, + const uint16_t, + sn_nsdl_addr_type_e) +{ + return m2mnsdlinterface_stub::bool_value; +} + +bool M2MNsdlInterface::send_update_registration(const uint32_t) +{ + return m2mnsdlinterface_stub::bool_value; +} + +bool M2MNsdlInterface::send_unregister_message() +{ + return m2mnsdlinterface_stub::bool_value; +} + +void *M2MNsdlInterface::memory_alloc(uint16_t size) +{ + return malloc(size); +} + +void M2MNsdlInterface::memory_free(void *ptr) +{ + free(ptr); + ptr = NULL; +} + +uint8_t M2MNsdlInterface::send_to_server_callback(struct nsdl_s *, + sn_nsdl_capab_e, + uint8_t *, + uint16_t, + sn_nsdl_addr_s *) +{ + return (uint8_t)m2mnsdlinterface_stub::int_value; +} + +uint8_t M2MNsdlInterface::received_from_server_callback(struct nsdl_s *, + sn_coap_hdr_s *, + sn_nsdl_addr_s *) +{ + return (uint8_t)m2mnsdlinterface_stub::int_value; +} + +uint8_t M2MNsdlInterface::resource_callback(struct nsdl_s *, + sn_coap_hdr_s *, + sn_nsdl_addr_s *, + sn_nsdl_capab_e) +{ + return (uint8_t)m2mnsdlinterface_stub::int_value; +} + + +bool M2MNsdlInterface::process_received_data(uint8_t *, + uint16_t , + sn_nsdl_addr_s *) +{ + return m2mnsdlinterface_stub::bool_value; +} + +void M2MNsdlInterface::stop_timers() +{ + +} + +void M2MNsdlInterface::timer_expired(M2MTimerObserver::Type) +{ +} + +void M2MNsdlInterface::observation_to_be_sent(M2MBase *, uint16_t, Vector, bool) +{ +} + +void M2MNsdlInterface::send_delayed_response(M2MBase *) +{ +} + +void M2MNsdlInterface::resource_to_be_deleted(const String &) +{ +} + +void M2MNsdlInterface::value_updated(M2MBase *, const String&) +{ +} + +void M2MNsdlInterface::remove_object(M2MBase *) +{ +} + +nsdl_s* M2MNsdlInterface::get_nsdl_handle() +{ + return (nsdl_s*) m2mnsdlinterface_stub::void_value; +} + +void M2MNsdlInterface::handle_bootstrap_put_message(sn_coap_hdr_s *coap_header, sn_nsdl_addr_s *address) +{ + +} + +void M2MNsdlInterface::handle_bootstrap_finished(sn_coap_hdr_s *coap_header,sn_nsdl_addr_s *address) +{ + +} + +void M2MNsdlInterface::handle_bootstrap_delete(sn_coap_hdr_s *coap_header,sn_nsdl_addr_s *address) +{ + +} + +bool M2MNsdlInterface::parse_bootstrap_message(sn_coap_hdr_s *coap_header, bool is_security_object) +{ + +} + +bool M2MNsdlInterface::validate_security_object() +{ + +} + +void M2MNsdlInterface::handle_bootstrap_error() +{ + +} + +const String& M2MNsdlInterface::endpoint_name() const +{ + return m2mnsdlinterface_stub::string_value; +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mnsdlinterface_stub.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mnsdlinterface_stub.h new file mode 100755 index 0000000000..c510333bca --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mnsdlinterface_stub.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_NSDL_INTERFACE_STUB_H +#define M2M_NSDL_INTERFACE_STUB_H + +#include "m2mnsdlinterface.h" + +//some internal test related stuff +namespace m2mnsdlinterface_stub +{ + extern bool bool_value; + extern uint32_t int_value; + extern void* void_value; + extern String string_value; + void clear(); +} + +#endif // M2M_NSDL_INTERFACE_STUB_H + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mobject_stub.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mobject_stub.cpp new file mode 100755 index 0000000000..1451556ee3 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mobject_stub.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mobject_stub.h" + +u_int16_t m2mobject_stub::int_value; +bool m2mobject_stub::bool_value; +M2MObjectInstance* m2mobject_stub::inst; + +// The statically initialized object list must be bigh enough to cater +// for all the tests, or the utest framework will complain for memory leak. +M2MObjectInstanceList m2mobject_stub::instance_list(12); + +M2MBase::BaseType m2mobject_stub::base_type; +sn_coap_hdr_s *m2mobject_stub::header; + +void m2mobject_stub::clear() +{ + int_value = 0; + bool_value = false; + m2mobject_stub::base_type = M2MBase::Object; + instance_list.clear(); + header = NULL; +} + +M2MObject::M2MObject(const String &object_name) +: M2MBase(object_name,M2MBase::Dynamic) +{ +} + +M2MObject::~M2MObject() +{ +} + +M2MObject& M2MObject::operator=(const M2MObject& ) +{ + return *this; +} + +M2MObject::M2MObject(const M2MObject& other) +: M2MBase(other) +{ + *this = other; +} + +M2MObjectInstance* M2MObject::create_object_instance(uint16_t instance_id) +{ + return m2mobject_stub::inst; +} + +bool M2MObject::remove_object_instance(uint16_t) +{ + return m2mobject_stub::bool_value; +} + +M2MObjectInstance* M2MObject::object_instance(uint16_t) const +{ + return m2mobject_stub::inst; +} + +const M2MObjectInstanceList& M2MObject::instances() const +{ + return m2mobject_stub::instance_list; +} + +uint16_t M2MObject::instance_count() const +{ + return m2mobject_stub::int_value; +} + +M2MBase::BaseType M2MObject::base_type() const +{ + return m2mobject_stub::base_type; +} + +void M2MObject::add_observation_level(M2MBase::Observation) +{ + +} + +void M2MObject::remove_observation_level(M2MBase::Observation) +{ + +} + +sn_coap_hdr_s* M2MObject::handle_get_request(nsdl_s *, + sn_coap_hdr_s *, + M2MObservationHandler *) +{ + return m2mobject_stub::header; +} + +sn_coap_hdr_s* M2MObject::handle_put_request(nsdl_s *, + sn_coap_hdr_s *, + M2MObservationHandler *, + bool &execute) +{ + execute = m2mobject_stub::bool_value; + return m2mobject_stub::header; +} + +sn_coap_hdr_s* M2MObject::handle_post_request(nsdl_s *, + sn_coap_hdr_s *, + M2MObservationHandler *, + bool &) +{ + return m2mobject_stub::header; +} + +void M2MObject::notification_update(uint16_t obj_instance_id) +{ +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mobject_stub.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mobject_stub.h new file mode 100755 index 0000000000..c89a0dcdbd --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mobject_stub.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_OBJECT_STUB_H +#define M2M_OBJECT_STUB_H + +#include "m2mobject.h" +#include "m2mobjectinstance.h" + +//some internal test related stuff +namespace m2mobject_stub +{ + extern u_int16_t int_value; + extern M2MObjectInstance* inst; + extern bool bool_value; + extern M2MObjectInstanceList instance_list; + extern M2MBase::BaseType base_type; + extern sn_coap_hdr_s *header; + void clear(); +} + +#endif // M2M_OBJECT_STUB_H + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mobjectinstance_stub.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mobjectinstance_stub.cpp new file mode 100755 index 0000000000..4b1cacf5d0 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mobjectinstance_stub.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mobjectinstance_stub.h" + +u_int8_t m2mobjectinstance_stub::int_value; +bool m2mobjectinstance_stub::bool_value; +M2MResource* m2mobjectinstance_stub::resource; +M2MResource* m2mobjectinstance_stub::create_resource; + +// The statically initialized list must be bigh enough to cater +// for all the tests, or the utest framework will complain for memory leak. +M2MResourceList m2mobjectinstance_stub::resource_list(12); + +M2MResourceInstance* m2mobjectinstance_stub::create_resource_instance; +sn_coap_hdr_s* m2mobjectinstance_stub::header; +M2MBase::BaseType m2mobjectinstance_stub::base_type; + + +void m2mobjectinstance_stub::clear() +{ + int_value = 0; + bool_value = false; + resource = NULL; + create_resource = NULL; + create_resource_instance = NULL; + header = NULL; + base_type = M2MBase::ObjectInstance; + resource_list.clear(); +} + +M2MObjectInstance& M2MObjectInstance::operator=(const M2MObjectInstance& ) +{ + return *this; +} + +M2MObjectInstance::M2MObjectInstance(const M2MObjectInstance& other) +: M2MBase(other), + _object_callback(other._object_callback) +{ + *this = other; +} + +M2MObjectInstance::M2MObjectInstance(const String &object_name, M2MObjectCallback &object_callback) +: M2MBase(object_name,M2MBase::Dynamic), + _object_callback(object_callback) +{ +} + +M2MObjectInstance::~M2MObjectInstance() +{ +} + +M2MResource* M2MObjectInstance::create_static_resource(const String &, + const String &, + M2MResourceInstance::ResourceType, + const uint8_t *, + const uint8_t, + bool) +{ + return m2mobjectinstance_stub::create_resource; +} + +M2MResource* M2MObjectInstance::create_dynamic_resource(const String &, + const String &, + M2MResourceInstance::ResourceType, + bool, + bool) +{ + return m2mobjectinstance_stub::create_resource; +} + +M2MResourceInstance* M2MObjectInstance::create_static_resource_instance(const String &, + const String &, + M2MResourceInstance::ResourceType, + const uint8_t *, + const uint8_t, + uint16_t) +{ + return m2mobjectinstance_stub::create_resource_instance; +} + +M2MResourceInstance* M2MObjectInstance::create_dynamic_resource_instance(const String &, + const String &, + M2MResourceInstance::ResourceType, + bool, + uint16_t) +{ + return m2mobjectinstance_stub::create_resource_instance; +} + +bool M2MObjectInstance::remove_resource(const String &) +{ + return m2mobjectinstance_stub::bool_value; +} + +bool M2MObjectInstance::remove_resource_instance(const String &, uint16_t) +{ + return m2mobjectinstance_stub::bool_value; +} + +M2MResource* M2MObjectInstance::resource(const String &) const +{ + return m2mobjectinstance_stub::resource; +} + +const M2MResourceList& M2MObjectInstance::resources() const +{ + return m2mobjectinstance_stub::resource_list; +} + +uint16_t M2MObjectInstance::resource_count() const +{ + return m2mobjectinstance_stub::int_value; +} + +uint16_t M2MObjectInstance::resource_count(const String& ) const +{ + return m2mobjectinstance_stub::int_value; +} + +M2MBase::BaseType M2MObjectInstance::base_type() const +{ + return m2mobjectinstance_stub::base_type; +} + +void M2MObjectInstance::add_observation_level(M2MBase::Observation) +{ +} + +void M2MObjectInstance::remove_observation_level(M2MBase::Observation) +{ +} + +sn_coap_hdr_s* M2MObjectInstance::handle_get_request(nsdl_s *, + sn_coap_hdr_s *, + M2MObservationHandler *) +{ + return m2mobjectinstance_stub::header; +} + +sn_coap_hdr_s* M2MObjectInstance::handle_put_request(nsdl_s *, + sn_coap_hdr_s *, + M2MObservationHandler *, + bool &) +{ + return m2mobjectinstance_stub::header; +} + +sn_coap_hdr_s* M2MObjectInstance::handle_post_request(nsdl_s *, + sn_coap_hdr_s *, + M2MObservationHandler *, + bool &execute) +{ + execute = m2mobjectinstance_stub::bool_value; + return m2mobjectinstance_stub::header; +} + +void M2MObjectInstance::notification_update(M2MBase::Observation) +{ +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mobjectinstance_stub.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mobjectinstance_stub.h new file mode 100755 index 0000000000..4a23411da0 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mobjectinstance_stub.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_OBJECT_INSTANCE_STUB_H +#define M2M_OBJECT_INSTANCE_STUB_H + +#include "m2mobjectinstance.h" + +//some internal test related stuff +namespace m2mobjectinstance_stub +{ + extern u_int8_t int_value; + extern bool bool_value; + extern M2MResource *resource; + extern M2MResource* create_resource; + extern M2MResourceInstance* create_resource_instance; + extern sn_coap_hdr_s* header; + extern M2MResourceList resource_list; + extern M2MBase::BaseType base_type; + void clear(); +} + +#endif // M2M_OBJECT_INSTANCE_STUB_H + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mreporthandler_stub.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mreporthandler_stub.cpp new file mode 100755 index 0000000000..5512c808cd --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mreporthandler_stub.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mreporthandler_stub.h" + +bool m2mreporthandler_stub::bool_return; +u_int8_t m2mreporthandler_stub::int_value; + +void m2mreporthandler_stub::clear() +{ + bool_return = false; + int_value = 0; +} + +M2MReportHandler::M2MReportHandler(M2MReportObserver &observer) +: _observer(observer) +{ +} + +M2MReportHandler::~M2MReportHandler() +{ +} + +void M2MReportHandler::set_under_observation(bool) +{ +} + +void M2MReportHandler::set_value(float) +{ +} + +bool M2MReportHandler::parse_notification_attribute(char *&, + M2MBase::BaseType, + M2MResourceInstance::ResourceType resource_type) +{ + return m2mreporthandler_stub::bool_return; +} + +void M2MReportHandler::timer_expired(M2MTimerObserver::Type ) +{ +} + +void M2MReportHandler::set_notification_trigger(uint16_t) +{ +} + +void M2MReportHandler::set_default_values() +{ +} + +uint8_t M2MReportHandler::attribute_flags() +{ + return m2mreporthandler_stub::int_value; +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mreporthandler_stub.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mreporthandler_stub.h new file mode 100755 index 0000000000..655980dc9d --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mreporthandler_stub.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_REPORT_HANDLER_STUB_H +#define M2M_REPORT_HANDLER_STUB_H + +#include "m2mreporthandler.h" + +//some internal test related stuff +namespace m2mreporthandler_stub +{ + extern bool bool_return; + extern u_int8_t int_value; + void clear(); +} + +#endif // M2M_REPORT_HANDLER_STUB_H + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mresource_stub.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mresource_stub.cpp new file mode 100755 index 0000000000..cd2c2576e1 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mresource_stub.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mresource_stub.h" + +uint32_t m2mresource_stub::int_value; +uint8_t* m2mresource_stub::delayed_token; +uint8_t m2mresource_stub::delayed_token_len; +bool m2mresource_stub::bool_value; + +// The statically initialized list must be bigh enough to cater +// for all the tests, or the utest framework will complain for memory leak. +M2MResourceInstanceList m2mresource_stub::list(12); + +M2MResourceInstance *m2mresource_stub::instance; +sn_coap_hdr_s *m2mresource_stub::header; +void m2mresource_stub::clear() +{ + int_value = 0; + delayed_token = NULL; + delayed_token_len = 0; + bool_value = false; + list.clear(); + instance = NULL; +} + +M2MResource& M2MResource::operator=(const M2MResource& other) +{ + return *this; +} + +M2MResource::M2MResource(const M2MResource& other) +: M2MResourceInstance(other) +{ + *this = other; +} + +M2MResource::M2MResource(M2MObjectInstanceCallback &object_instance_callback, + const String &resource_name, + const String &resource_type, + M2MResourceInstance::ResourceType type, + const uint8_t *value, + const uint8_t value_length, + const uint16_t object_instance_id, + const String &object_name, + bool) +: M2MResourceInstance(resource_name, resource_type, type, value, value_length, + object_instance_callback, object_instance_id, object_name) +{ +} + +M2MResource::M2MResource(M2MObjectInstanceCallback &object_instance_callback, + const String &resource_name, + const String &resource_type, + M2MResourceInstance::ResourceType type, + bool, + const uint16_t object_instance_id, + const String &object_name, + bool) +: M2MResourceInstance(resource_name, resource_type, type, + object_instance_callback, object_instance_id, object_name) +{ +} + +M2MResource::~M2MResource() +{ +} + +bool M2MResource::supports_multiple_instances() const +{ + return m2mresource_stub::bool_value; +} + +void M2MResource::get_delayed_token(unsigned char *&token, unsigned char &token_len) +{ + token_len = 0; + if(token) { + free(token); + token = NULL; + } + token = (uint8_t *)malloc(m2mresource_stub::delayed_token_len); + if(token) { + token_len = m2mresource_stub::delayed_token_len; + memcpy((uint8_t *)token, (uint8_t *)m2mresource_stub::delayed_token, token_len); + } +} + +bool M2MResource::remove_resource_instance(uint16_t inst_id) +{ + return m2mresource_stub::bool_value; +} + +M2MResourceInstance* M2MResource::resource_instance(uint16_t inst_id) const +{ + return m2mresource_stub::instance; +} + +const M2MResourceInstanceList& M2MResource::resource_instances() const +{ + return m2mresource_stub::list; +} + +uint16_t M2MResource::resource_instance_count() const +{ + return m2mresource_stub::int_value; +} + +bool M2MResource::handle_observation_attribute(char *&query) +{ + return m2mresource_stub::bool_value; +} + +void M2MResource::add_resource_instance(M2MResourceInstance *) +{ +} + +void M2MResource::add_observation_level(M2MBase::Observation) +{ +} + +void M2MResource::remove_observation_level(M2MBase::Observation) +{ +} + +void M2MResource::notification_update() +{ +} + +sn_coap_hdr_s* M2MResource::handle_get_request(nsdl_s *, + sn_coap_hdr_s *, + M2MObservationHandler *) +{ + return m2mresource_stub::header; +} + +sn_coap_hdr_s* M2MResource::handle_put_request(nsdl_s *, + sn_coap_hdr_s *, + M2MObservationHandler *, + bool &) +{ + return m2mresource_stub::header; +} + +sn_coap_hdr_s* M2MResource::handle_post_request(nsdl_s *, + sn_coap_hdr_s *, + M2MObservationHandler *, + bool &) +{ + return m2mresource_stub::header; +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mresource_stub.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mresource_stub.h new file mode 100755 index 0000000000..505fd11432 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mresource_stub.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_RESOURCE_STUB_H +#define M2M_RESOURCE_STUB_H + +#include "m2mresource.h" + +//some internal test related stuff +namespace m2mresource_stub +{ + extern uint32_t int_value; + extern uint8_t* delayed_token; + extern uint8_t delayed_token_len; + extern bool bool_value; + extern M2MResourceInstanceList list; + extern M2MResourceInstance *instance; + void clear(); + extern sn_coap_hdr_s *header; +} + +#endif // M2M_RESOURCE_STUB_H + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mresourceinstance_stub.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mresourceinstance_stub.cpp new file mode 100755 index 0000000000..794da3e30f --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mresourceinstance_stub.cpp @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mresourceinstance_stub.h" + +uint32_t m2mresourceinstance_stub::int_value; +bool m2mresourceinstance_stub::bool_value; +String *m2mresourceinstance_stub::string_value; +M2MResourceInstance::ResourceType m2mresourceinstance_stub::resource_type; +sn_coap_hdr_s *m2mresourceinstance_stub::header; +uint8_t* m2mresourceinstance_stub::value; +M2MBase::BaseType m2mresourceinstance_stub::base_type; + + +void m2mresourceinstance_stub::clear() +{ + int_value = 0; + bool_value = false; + resource_type = M2MResourceInstance::STRING; + header = NULL; + value = NULL; + base_type = M2MBase::ResourceInstance; + string_value = NULL; +} + +M2MResourceInstance& M2MResourceInstance::operator=(const M2MResourceInstance&) +{ + return *this; +} + +M2MResourceInstance::M2MResourceInstance(const M2MResourceInstance& other) +: M2MBase(other), + _object_instance_callback(other._object_instance_callback)/*, + _object_instance_id(other._object_instance_id), + _object_name(other._object_name)*/ +{ + this->operator=(other); +} + +M2MResourceInstance::M2MResourceInstance(const String &res_name, + const String &, + M2MResourceInstance::ResourceType, + M2MObjectInstanceCallback &object_instance_callback, + const uint16_t /*object_instance_id*/, + const String &/*object_name*/) +: M2MBase(res_name, + M2MBase::Dynamic), + _object_instance_callback(object_instance_callback)/*, +_object_instance_id(object_instance_id), +_object_name(object_name)*/ +{ + m2mresourceinstance_stub::base_type = M2MBase::ResourceInstance; +} + +M2MResourceInstance::M2MResourceInstance(const String &res_name, + const String &, + M2MResourceInstance::ResourceType, + const uint8_t *, + const uint8_t, + M2MObjectInstanceCallback &object_instance_callback, + const uint16_t/* object_instance_id*/, + const String &/*object_name*/) +: M2MBase(res_name, + M2MBase::Static), +_object_instance_callback(object_instance_callback)/*, + _object_instance_id(object_instance_id), + _object_name(object_name)*/ +{ +} + +M2MResourceInstance::~M2MResourceInstance() +{ +} + +M2MBase::BaseType M2MResourceInstance::base_type() const +{ + return m2mresourceinstance_stub::base_type; +} + +M2MResourceInstance::ResourceType M2MResourceInstance::resource_instance_type() const +{ + return m2mresourceinstance_stub::resource_type; +} + +bool M2MResourceInstance::handle_observation_attribute(char *&) +{ + return m2mresourceinstance_stub::bool_value; +} + +void M2MResourceInstance::set_execute_function(execute_callback) +{ +} + +bool M2MResourceInstance::set_value(const uint8_t *, + const uint32_t ) +{ + return m2mresourceinstance_stub::bool_value; +} + +bool M2MResourceInstance::set_value(int64_t value) +{ + return m2mresourceinstance_stub::bool_value; +} + + +void M2MResourceInstance::clear_value() +{ + if (m2mresourceinstance_stub::value) { + free(m2mresourceinstance_stub::value); + m2mresourceinstance_stub::value = NULL; + m2mresourceinstance_stub::int_value = 0; + } +} + +void M2MResourceInstance::execute(void *) +{ +} + +void M2MResourceInstance::get_value(uint8_t *&value, uint32_t &value_length) +{ + value_length = 0; + if(value) { + free(value); + value = NULL; + } + value = (uint8_t *)malloc(m2mresourceinstance_stub::int_value); + if(value) { + value_length = m2mresourceinstance_stub::int_value; + memcpy((uint8_t *)value, (uint8_t *)m2mresourceinstance_stub::value, value_length); + } +} + +int M2MResourceInstance::get_value_int() +{ + // Note: this is a copy-paste from the original version, as the tests + // set only m2mresourceinstance_stub::value. + + int value_int = 0; + // Get the value and convert it into integer. This is not the most + // efficient way, as it takes pointless heap copy to get the zero termination. + uint8_t* buffer = NULL; + uint32_t length; + get_value(buffer,length); + if(buffer) { + value_int = atoi((const char*)buffer); + free(buffer); + } + return value_int; +} + +String M2MResourceInstance::get_value_string() const +{ + // XXX: do a better constructor to avoid pointless malloc + String value; + if (m2mresourceinstance_stub::value) { + value.append_raw((char*)m2mresourceinstance_stub::value, m2mresourceinstance_stub::int_value); + } + + return value; +} + +uint8_t* M2MResourceInstance::value() const +{ + return m2mresourceinstance_stub::value; +} + +uint32_t M2MResourceInstance::value_length() const +{ + return m2mresourceinstance_stub::int_value; +} + +sn_coap_hdr_s* M2MResourceInstance::handle_get_request(nsdl_s *, + sn_coap_hdr_s *, + M2MObservationHandler *) +{ + return m2mresourceinstance_stub::header; +} + +sn_coap_hdr_s* M2MResourceInstance::handle_put_request(nsdl_s *, + sn_coap_hdr_s *, + M2MObservationHandler *, + bool &) +{ + return m2mresourceinstance_stub::header; +} + +void M2MResourceInstance::set_resource_observer(M2MResourceCallback *callback) +{ + +} +const String& M2MResourceInstance::object_name() const +{ + return *m2mresourceinstance_stub::string_value; +} + +uint16_t M2MResourceInstance::object_instance_id() const +{ + return m2mresourceinstance_stub::int_value; +} + +void M2MResourceInstance::set_execute_function(execute_callback_2 callback) +{ +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mresourceinstance_stub.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mresourceinstance_stub.h new file mode 100755 index 0000000000..37625d8bbb --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mresourceinstance_stub.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_RESOURCE_INSTANCE_STUB_H +#define M2M_RESOURCE_INSTANCE_STUB_H + +#include "m2mresourceinstance.h" + +//some internal test related stuff +namespace m2mresourceinstance_stub +{ + extern uint32_t int_value; + extern uint8_t* value; + extern bool bool_value; + extern String *string_value; + extern M2MResourceInstance::ResourceType resource_type; + extern M2MBase::BaseType base_type; + extern sn_coap_hdr_s *header; + void clear(); +} + +#endif // M2M_RESOURCE_INSTANCE_STUB_H + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2msecurity_stub.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2msecurity_stub.cpp new file mode 100755 index 0000000000..3556d4bd25 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2msecurity_stub.cpp @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2msecurity_stub.h" + +bool m2msecurity_stub::has_value; +uint32_t m2msecurity_stub::int_value; +uint32_t m2msecurity_stub::sec_mode; +bool m2msecurity_stub::bool_value; +String *m2msecurity_stub::string_value; +M2MResource* m2msecurity_stub::resource; + +void m2msecurity_stub::clear() +{ + has_value = false; + int_value = -1; + bool_value = false; + string_value = NULL; + resource = NULL; +} + +M2MSecurity::M2MSecurity(ServerType ser_type) +: M2MObject("0"), + _server_type(ser_type), + _server_instance(NULL) +{ +} + +M2MSecurity::~M2MSecurity() +{ +} + +M2MResource* M2MSecurity::create_resource(SecurityResource, uint32_t) +{ + return m2msecurity_stub::resource; +} + +bool M2MSecurity::delete_resource(SecurityResource) +{ + return m2msecurity_stub::bool_value; +} + +bool M2MSecurity::set_resource_value(SecurityResource, + const String &) +{ + return m2msecurity_stub::bool_value; +} + +bool M2MSecurity::set_resource_value(SecurityResource, + uint32_t) +{ + return m2msecurity_stub::bool_value; +} + +bool M2MSecurity::set_resource_value(SecurityResource, + const uint8_t *, + const uint16_t) +{ + return m2msecurity_stub::bool_value; +} + +String M2MSecurity::resource_value_string(SecurityResource) const +{ + return *m2msecurity_stub::string_value; +} + +uint32_t M2MSecurity::resource_value_buffer(SecurityResource, + uint8_t *&value) const +{ + if( m2msecurity_stub::has_value ){ + value = (uint8_t *)malloc(5); + return 5; + } + return m2msecurity_stub::int_value; +} + +uint32_t M2MSecurity::resource_value_buffer(SecurityResource, + const uint8_t *&value) const +{ + if( m2msecurity_stub::has_value ){ + value = NULL; + return 5; + } + return m2msecurity_stub::int_value; +} + +uint32_t M2MSecurity::resource_value_int(SecurityResource res) const +{ + if (res == M2MSecurity::SecurityMode) { + return m2msecurity_stub::sec_mode; + } + else if(res == M2MSecurity::BootstrapServer) { + return m2msecurity_stub::bool_value; + } + else { + return m2msecurity_stub::int_value; + } +} + +bool M2MSecurity::is_resource_present(SecurityResource) const +{ + return m2msecurity_stub::bool_value; +} + +uint16_t M2MSecurity::total_resource_count() const +{ + return (uint16_t)m2msecurity_stub::int_value; +} + +M2MSecurity::ServerType M2MSecurity::server_type() const +{ + return _server_type; +} + +void M2MSecurity::clear_resources() +{ + +} + +M2MResource* M2MSecurity::get_resource(SecurityResource res) const +{ + return m2msecurity_stub::resource; +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2msecurity_stub.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2msecurity_stub.h new file mode 100755 index 0000000000..c87729d951 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2msecurity_stub.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_SECURITY_STUB_H +#define M2M_SECURITY_STUB_H + +#include "m2msecurity.h" + +//some internal test related stuff +namespace m2msecurity_stub +{ + extern bool has_value; + extern uint32_t int_value; + extern uint32_t sec_mode; + extern bool bool_value; + extern String *string_value; + extern M2MResource* resource; + void clear(); +} + +#endif // M2M_SECURITY_STUB_H + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mserver_stub.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mserver_stub.cpp new file mode 100755 index 0000000000..da1b10d639 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mserver_stub.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mserver_stub.h" + +uint32_t m2mserver_stub::int_value; +bool m2mserver_stub::bool_value; +String m2mserver_stub::string_value; +M2MResource* m2mserver_stub::resource; + +void m2mserver_stub::clear() +{ + int_value = 0; + bool_value = false; + string_value = ""; + resource = NULL; +} + +M2MServer::M2MServer() +: M2MObject("2") +{ +} + +M2MServer::~M2MServer() +{ +} + +M2MResource* M2MServer::create_resource(ServerResource, uint32_t) +{ + return m2mserver_stub::resource; +} + +M2MResource* M2MServer::create_resource(ServerResource) +{ + return m2mserver_stub::resource; +} + +bool M2MServer::delete_resource(ServerResource) +{ + return m2mserver_stub::bool_value; +} + +bool M2MServer::set_resource_value(ServerResource, + const String &) +{ + return m2mserver_stub::bool_value; +} + +bool M2MServer::set_resource_value(ServerResource, + uint32_t) +{ + return m2mserver_stub::bool_value; +} + +String M2MServer::resource_value_string(ServerResource) const +{ + return m2mserver_stub::string_value; +} + + +uint32_t M2MServer::resource_value_int(ServerResource) const +{ + return m2mserver_stub::int_value; +} + +bool M2MServer::is_resource_present(ServerResource) const +{ + return m2mserver_stub::bool_value; +} + +uint16_t M2MServer::total_resource_count() const +{ + return (uint16_t)m2mserver_stub::int_value; +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mserver_stub.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mserver_stub.h new file mode 100755 index 0000000000..6e0de89f20 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mserver_stub.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_SERVER_STUB_H +#define M2M_SERVER_STUB_H + +#include "m2mserver.h" +#include "m2mresource.h" + +//some internal test related stuff +namespace m2mserver_stub +{ + extern uint32_t int_value; + extern bool bool_value; + extern String string_value; + extern M2MResource* resource; + void clear(); +} + +#endif // M2M_SERVER_STUB_H + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mstring_stub.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mstring_stub.cpp new file mode 100755 index 0000000000..c163468999 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mstring_stub.cpp @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mstring.h" +#include // strlen +#include // malloc, realloc +#include +#include // min + +namespace m2m { + +const String::size_type String::npos = static_cast(-1); + +char* String::strdup(const char* s) +{ + const size_t len = strlen(s)+1; + char *p2 = static_cast(malloc(len)); + memcpy(p2, s, len); + allocated_ = len; + size_ = len-1; + return p2; +} + +String::String() + : p( strdup("") ) +{ +} + +String::~String() +{ + free(p); + p = 0; +} + +String::String(const String& s) + : p(0) +{ + if( &s != NULL ) { + p = static_cast(malloc(s.size_ + 1)); + + allocated_ = s.size_ + 1; + size_ = s.size_; + memcpy(p, s.p, size_ + 1); + } +} + +String::String(const char* s) + : p(strdup(s)) +{ +} + +String& String::operator=(const char* s) +{ + if ( p != s ) { + // s could point into our own string, so we have to allocate a new string + const size_t len = strlen(s); + char* copy = (char*) malloc( len + 1); + memmove(copy, s, len+1); // trailing 0 + free( p ); + p = copy; + size_ = len; + allocated_ = len+1; + } + return *this; +} + +String& String::operator=(const String& s) +{ + return operator=(s.p); +} + +String& String::operator+=(const String& s) +{ + if (s.size_ > 0) { + this->reserve(size_ + s.size_); + memmove(p+size_, s.p, s.size_+1); // trailing 0 + size_ += s.size_; + } + return *this; +} + +// since p and s may overlap, we have to copy our own string first +String& String::operator+=(const char* s) +{ + const size_type lens = strlen(s); + if (lens > 0) { + if (size_ + lens + 1 <= allocated_) { + memmove(p+size_, s, lens+1); // trailing 0 + size_ += lens; + } else { + String s2( *this ); // copy own data + s2.reserve(size_ + lens); + memmove(s2.p+size_, s, lens+1); // trailing 0 + s2.size_ = size_ + lens; + this->swap( s2 ); + } + } + return *this; +} + +String& String::operator+=(const char c) +{ + push_back(c); + return *this; +} + +void String::push_back(const char c) { + + if (size_ == allocated_ - 1) { + size_t more = (allocated_* 3) / 2; // factor 1.5 + if ( more < 4 ) more = 4; + reserve( size_ + more ); + } + + p[size_] = c; + size_++; + p[size_] = 0; +} + +bool String::operator==(const char* s) const +{ + if( s == NULL ) { + if( p == NULL ) { + return true; + } + return false; + } + bool ret = strcmp(p, s); + return !ret; +} + +bool String::operator==(const String& s) const +{ + bool ret = strcmp(p, s.p); + return !ret; +} + +void String::clear() +{ + size_ = 0; + p[0] = 0; +} + +String String::substr(const size_type pos, size_type length) const +{ + String s; + const size_type len = size_; + + if ( pos <= len ) { + + size_type remain = len - pos; + + if ( length > remain ) + length = remain; + + s.reserve( length ); + + memcpy(s.p, p + pos, length); + s.p[length] = '\0'; + s.size_ = length; + } + return s; +} + + +// checked access, accessing the NUL at end is allowed +char String::at(const size_type i) const +{ + if ( i <= strlen(p) ) { + return p[i]; + } else { + return '\0'; + } +} + +String& String::erase(size_type pos, size_type len) +{ + if (len > 0) { + + if ( pos < size_ ) { // user must not remove trailing 0 + + size_type s2 = size_; + size_type remain = s2 - pos - len; + + if (remain > 0) { + // erase by overwriting + memmove(p + pos, p + pos + len, remain); + } + + //if ( remain < 0 ) remain = 0; + + // remove unused space + this->resize( pos+remain ); + + } + } + return *this; +} + +String& String::append( const char* str, size_type n) { + if (str && n > 0) { + size_t lens = strlen(str); + if (n > lens) + n = lens; + size_t newlen = size_ + n; + this->reserve( newlen ); + memmove(p+size_, str, n); // p and s.p MAY overlap + p[newlen] = 0; // add NUL termination + size_ = newlen; + } + return *this; +} + +String& String::append_raw( const char* str, size_type n) { + if (str && n > 0) { + size_t newlen = size_ + n; + this->reserve( newlen ); + memmove(p+size_, str, n); // p and s.p MAY overlap + p[newlen] = 0; // add NUL termination + size_ = newlen; + } + return *this; +} + +void String::append_int(int param) { + + // max len of "-9223372036854775808" plus zero termination + char conv_buff[20+1]; + + int len = itoa_c(param, conv_buff); + append_raw(conv_buff, len); +} + +int String::compare( size_type pos, size_type len, const String& str ) const { + int r = -1; + if (pos <= size_) { + if ( len > size_ - pos) + len = size_ - pos; // limit len to available length + + const size_type osize = str.size(); + const size_type len2 = std::min(len, osize); + r = strncmp( p + pos, str.p, len2); + if (r==0) // equal so far, now compare sizes + r = len < osize ? -1 : ( len == osize ? 0 : +1 ); + } + return r; +} + +int String::compare( size_type pos, size_type len, const char* str ) const { + int r = -1; + if (pos <= size_) { + + if ( len > size_ - pos) + len = size_ - pos; // limit len to available length + + const size_type osize = strlen(str); + const size_type len2 = std::min(len, osize); + r = strncmp( p + pos, str, len2); + if (r==0) // equal so far, now compare sizes + r = len < osize ? -1 : ( len == osize ? 0 : +1 ); + } + return r; +} + +int String::find_last_of(char c) const { + int r = -1; + char *v; + v = strrchr(p,c); + if (v != NULL) { + r = 0; + char* i = p; + while (v != i) { + i++; + r++; + } + } + return r; +} + +void String::new_realloc( size_type n) { + if (n > 0 ) { + char* pnew = static_cast(realloc(p, n)); // could return NULL + if (pnew) + p = pnew; + } +} + +void String::reserve( const size_type n) { + if (n >= allocated_ ) { + this->new_realloc(n + 1); + allocated_ = n + 1; + } +} + +void String::resize( const size_type n) { + this->resize( n, 0 ); +} + +void String::resize( const size_type n, const char c) { + if (n < size_ ) { + p[n] = 0; + size_ = n; + } + else if (n > size_ ) { + this->reserve( n ); + for (size_type i=size_; i < n; ++i ) + p[i] = c; + p[n] = 0; + size_ = n; + } +} + +void String::swap( String& s ) { + std::swap( allocated_, s.allocated_ ); + std::swap( size_, s.size_ ); + std::swap( p, s.p ); +} + + +// Comparison +bool operator<( const String& s1, const String& s2 ) { + return strcmp( s1.c_str(), s2.c_str() ) < 0; +} + +void reverse(char s[], uint32_t length) +{ + uint32_t i, j; + char c; + + for (i = 0, j = length-1; i 0); + + if (sign < 0) + s[i++] = '-'; + + s[i] = '\0'; + + m2m::reverse(s, i); + return i; +} + +uint8_t* String::convert_integer_to_array(int64_t value, uint8_t &size, uint8_t *array, uint32_t array_size) +{ + uint8_t* buffer = NULL; + size = 0; + if (array) { + value = String::convert_array_to_integer(array, array_size); + } + + if(value < 0xFF) { + size = 1; + } else if(value < 0xFFFF) { + size = 2; + } else if(value < 0xFFFFFF) { + size = 3; + } else if(value < 0xFFFFFFFF) { + size = 4; + } else if(value < 0xFFFFFFFFFF) { + size = 5; + } else if(value < 0xFFFFFFFFFFFF) { + size = 6; + } else if(value < 0xFFFFFFFFFFFFFF) { + size = 7; + } else { + size = 8; + } + + buffer = (uint8_t*)malloc(size); + if (buffer) { + for (int i = 0; i < size; i++) { + buffer[i] = (value >> ((size - i - 1) * 8)); + } + } else { + size = 0; + } + return buffer; +} + +int64_t String::convert_array_to_integer(uint8_t *value, uint32_t size) +{ + int64_t temp_64 = 0; + for (int i = size - 1; i >= 0; i--) { + temp_64 += (uint64_t)(*value++) << i * 8; + } + return temp_64; +} + +} // namespace diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtimer_stub.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtimer_stub.cpp new file mode 100755 index 0000000000..0ef5e49e1a --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtimer_stub.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mtimer_stub.h" + +bool m2mtimer_stub::bool_value; +bool m2mtimer_stub::total_bool_value; + +void m2mtimer_stub::clear() +{ + bool_value = false; + total_bool_value = false; +} + +// Prevents the use of assignment operator +M2MTimer& M2MTimer::operator=(const M2MTimer& /*other*/) +{ + return *this; +} + +// Prevents the use of copy constructor +M2MTimer::M2MTimer(const M2MTimer& other) +: _observer(other._observer) +{ + *this = other; +} + +M2MTimer::M2MTimer(M2MTimerObserver& observer) +: _observer(observer) +{ +} + +M2MTimer::~M2MTimer() +{ +} + +void M2MTimer::start_timer(uint64_t /*interval*/, + M2MTimerObserver::Type /*type*/, + bool /*single_shot*/) +{ +} + +void M2MTimer::start_dtls_timer(uint64_t , uint64_t , M2MTimerObserver::Type ) +{ +} + +void M2MTimer::stop_timer() +{ +} + + +bool M2MTimer::is_intermediate_interval_passed(){ + return m2mtimer_stub::bool_value; +} + +bool M2MTimer::is_total_interval_passed(){ + return m2mtimer_stub::total_bool_value; +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtimer_stub.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtimer_stub.h new file mode 100755 index 0000000000..451eb516e8 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtimer_stub.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_TIMER_STUB_H +#define M2M_TIMER_STUB_H + +#include "m2mtimer.h" + +//some internal test related stuff +namespace m2mtimer_stub +{ + extern bool bool_value; + extern bool total_bool_value; + void clear(); +} + +#endif // M2M_TIMER_STUB_H + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtlvdeserializer_stub.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtlvdeserializer_stub.cpp new file mode 100644 index 0000000000..c077041cfc --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtlvdeserializer_stub.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mtlvdeserializer_stub.h" + +bool m2mtlvdeserializer_stub::bool_value; +bool m2mtlvdeserializer_stub::is_object_bool_value; +M2MTLVDeserializer::Error m2mtlvdeserializer_stub::error; +uint16_t m2mtlvdeserializer_stub::int_value; + +void m2mtlvdeserializer_stub::clear() +{ + bool_value = false; + is_object_bool_value = false; + error = M2MTLVDeserializer::None; + int_value = 0; +} + +M2MTLVDeserializer::M2MTLVDeserializer() +{ +} + +M2MTLVDeserializer::~M2MTLVDeserializer() +{ +} + +bool M2MTLVDeserializer::is_object_instance(uint8_t *) +{ + return m2mtlvdeserializer_stub::is_object_bool_value; +} + +bool M2MTLVDeserializer::is_resource(uint8_t *) +{ + return m2mtlvdeserializer_stub::bool_value; +} + +bool M2MTLVDeserializer::is_multiple_resource(uint8_t *) +{ + return m2mtlvdeserializer_stub::bool_value; +} + +bool M2MTLVDeserializer::is_resource_instance(uint8_t *) +{ + return m2mtlvdeserializer_stub::bool_value; +} + +M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resources(uint8_t*, + uint32_t, + M2MObjectInstance &, + M2MTLVDeserializer::Operation ) +{ + return m2mtlvdeserializer_stub::error; +} + +M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(uint8_t *, + uint32_t, + M2MResource &, + M2MTLVDeserializer::Operation ) +{ + return m2mtlvdeserializer_stub::error; +} + +M2MTLVDeserializer::Error M2MTLVDeserializer::deserialise_object_instances(uint8_t*, + uint32_t , + M2MObject &, + M2MTLVDeserializer::Operation) +{ + return m2mtlvdeserializer_stub::error; +} + +TypeIdLength* TypeIdLength::createTypeIdLength(uint8_t *, uint32_t) +{ + TypeIdLength *til = new TypeIdLength(); + return til; +} + +TypeIdLength* TypeIdLength::deserialize() +{ + return this; +} + +void TypeIdLength::deserialiseID(uint32_t idLength) +{ +} + +void TypeIdLength::deserialiseLength(uint32_t lengthType) +{ +} + +uint16_t M2MTLVDeserializer::instance_id(uint8_t *tlv) +{ + return m2mtlvdeserializer_stub::int_value; +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtlvdeserializer_stub.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtlvdeserializer_stub.h new file mode 100755 index 0000000000..31c1b26b09 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtlvdeserializer_stub.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_TLV_DESERIALIZER_STUB_H +#define M2M_TLV_DESERIALIZER_STUB_H + +#include "m2mtlvdeserializer.h" + +//some internal test related stuff +namespace m2mtlvdeserializer_stub +{ + extern bool bool_value; + extern uint16_t int_value; + extern bool is_object_bool_value; + extern M2MTLVDeserializer::Error error; + void clear(); +} + +#endif // M2M_TLV_DESERIALIZER_STUB_H + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtlvserializer_stub.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtlvserializer_stub.cpp new file mode 100644 index 0000000000..2333fd917b --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtlvserializer_stub.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "m2mtlvserializer_stub.h" + +uint8_t* m2mtlvserializer_stub::uint8_value; + +void m2mtlvserializer_stub::clear() +{ + uint8_value = NULL; +} + +M2MTLVSerializer::M2MTLVSerializer() +{ +} + +M2MTLVSerializer::~M2MTLVSerializer() +{ +} + +uint8_t* M2MTLVSerializer::serialize(M2MObjectInstanceList object_instance_list, uint32_t &) +{ + return m2mtlvserializer_stub::uint8_value; +} + +uint8_t* M2MTLVSerializer::serialize(M2MResourceList resource_list, uint32_t &size) +{ + return m2mtlvserializer_stub::uint8_value; +} + +uint8_t* M2MTLVSerializer::serialize(M2MResource *, uint32_t &) +{ + return m2mtlvserializer_stub::uint8_value; +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtlvserializer_stub.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtlvserializer_stub.h new file mode 100755 index 0000000000..02391de683 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/m2mtlvserializer_stub.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 M2M_TLV_SERIALIZER_STUB_H +#define M2M_TLV_SERIALIZER_STUB_H + +#include "m2mtlvserializer.h" + +//some internal test related stuff +namespace m2mtlvserializer_stub +{ + extern uint8_t* uint8_value; + void clear(); +} + +#endif // M2M_TLV_SERIALIZER_STUB_H + diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/nsdlaccesshelper_stub.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/nsdlaccesshelper_stub.cpp new file mode 100644 index 0000000000..37397b0961 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/nsdlaccesshelper_stub.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "nsdlaccesshelper_stub.h" + +bool nsdlaccesshelper_stub::bool_value; +void* nsdlaccesshelper_stub::void_value; +uint8_t nsdlaccesshelper_stub::int_value; + +M2MNsdlInterfaceList __nsdl_interface_list; +M2MConnectionHandler *__connection_handler = NULL; +#ifdef USE_LINUX +M2MTimerImpl *__timer_impl = NULL; +M2MConnectionHandler *__connection_impl = NULL; +#endif +void nsdlaccesshelper_stub::clear() +{ + bool_value = false; + void_value = NULL; + int_value = 0; +} + +uint8_t __nsdl_c_callback(struct nsdl_s * , + sn_coap_hdr_s *, + sn_nsdl_addr_s *, + sn_nsdl_capab_e ) +{ + return nsdlaccesshelper_stub::int_value; +} + +void *__nsdl_c_memory_alloc(uint16_t) +{ + return nsdlaccesshelper_stub::void_value; +} + +void __nsdl_c_memory_free(void *) +{ +} + +uint8_t __nsdl_c_send_to_server(struct nsdl_s * , + sn_nsdl_capab_e , + uint8_t *, + uint16_t , + sn_nsdl_addr_s *) +{ + return nsdlaccesshelper_stub::int_value; +} + +uint8_t __nsdl_c_received_from_server(struct nsdl_s * , + sn_coap_hdr_s *, + sn_nsdl_addr_s *) +{ + return nsdlaccesshelper_stub::int_value; +} + +void *__socket_malloc( void *, size_t) +{ +return nsdlaccesshelper_stub::void_value; +} + +void __socket_free(void *, void *) +{ +} + +void __mutex_claim() +{ +} + +void __mutex_release() +{ +} diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/nsdlaccesshelper_stub.h b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/nsdlaccesshelper_stub.h new file mode 100644 index 0000000000..d8c6295eac --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient/utest/stub/nsdlaccesshelper_stub.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 NSDLACCESSHELPER_STUB_H +#define NSDLACCESSHELPER_STUB_H + +#include "nsdlaccesshelper.h" + +//some internal test related stuff +namespace nsdlaccesshelper_stub +{ + extern bool bool_value; + extern void *void_value; + extern uint8_t int_value; + void clear(); +} +#endif // NSDLACCESSHELPER_STUB_H diff --git a/features/FEATURE_CLIENT/mbed-client/test/mbedclient_linux/main.cpp b/features/FEATURE_CLIENT/mbed-client/test/mbedclient_linux/main.cpp new file mode 100644 index 0000000000..52934fb903 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/test/mbedclient_linux/main.cpp @@ -0,0 +1,429 @@ +/* + * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 /* For SIGIGN and SIGINT */ +#include "mbed-client/m2minterfacefactory.h" +#include "mbed-client/m2mdevice.h" +#include "mbed-client/m2minterfaceobserver.h" +#include "mbed-client/m2minterface.h" +#include "mbed-client/m2mobjectinstance.h" +#include "mbed-client/m2mresource.h" + +#include "mbed-trace/mbed_trace.h" + +const String &BOOTSTRAP_SERVER_ADDRESS = "coap://10.45.3.10:5693"; +const String &M2M_SERVER_ADDRESS = "coap://10.45.3.10:5683"; +const String &MANUFACTURER = "manufacturer"; +const String &TYPE = "type"; +const String &MODEL_NUMBER = "2015"; +const String &SERIAL_NUMBER = "12345"; + +const uint8_t STATIC_VALUE[] = "Open Mobile Alliance"; + +static void ctrl_c_handle_function(void); +void close_function(); +typedef void (*signalhandler_t)(int); /* Function pointer type for ctrl-c */ + +class MbedClient: public M2MInterfaceObserver { +public: + MbedClient(){ + _security = NULL; + _interface = NULL; + _register_security = NULL; + _device = NULL; + _object = NULL; + _bootstrapped = false; + _error = false; + _registered = false; + _unregistered = false; + _registration_updated = false; + _value = 0; + } + + ~MbedClient() { + if(_security) { + delete _security; + } + if(_register_security){ + delete _register_security; + } + if(_device) { + M2MDevice::delete_instance(); + _device = NULL; + } + if(_object) { + delete _object; + } + if(_interface) { + delete _interface; + } + } + + bool create_interface() { + _interface = M2MInterfaceFactory::create_interface(*this, + "linux-endpoint", + "test", + 60, + 5683, + "", + M2MInterface::UDP, + M2MInterface::LwIP_IPv4, + ""); + printf("Endpoint Name : linux-endpoint\n"); + return (_interface == NULL) ? false : true; + } + + bool bootstrap_successful() { + while(!_bootstrapped && !_error) { + sleep(1); + } + return _bootstrapped; + } + + bool register_successful() { + while(!_registered && !_error) { + sleep(1); + } + return _registered; + } + + bool unregister_successful() { + while(!_unregistered && !_error) { + sleep(1); + } + return _unregistered; + } + + bool registration_update_successful() { + while(!_registration_updated && !_error) { + } + return _registration_updated; + } + + bool create_bootstrap_object() { + bool success = false; + if(_security) { + delete _security; + } + _security = M2MInterfaceFactory::create_security(M2MSecurity::Bootstrap); + if(_security) { + if(_security->set_resource_value(M2MSecurity::M2MServerUri, BOOTSTRAP_SERVER_ADDRESS) && + _security->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::NoSecurity)) { + success = true; + /* Not used now because there is no TLS or DTLS implementation available for stack. + security->set_resource_value(M2MSecurity::ServerPublicKey,certificates->certificate_ptr[0],certificates->certificate_len[0]); + security->set_resource_value(M2MSecurity::PublicKey,certificates->certificate_ptr[1],certificates->certificate_len[1]); + security->set_resource_value(M2MSecurity::Secretkey,certificates->own_private_key_ptr,certificates->own_private_key_len); + */ + } + } + printf("Bootstrap Server Address %s\n", BOOTSTRAP_SERVER_ADDRESS.c_str()); + return success; + } + + bool create_register_object() { + bool success = false; + _register_security = M2MInterfaceFactory::create_security(M2MSecurity::M2MServer); + if(_register_security) { + if(_register_security->set_resource_value(M2MSecurity::M2MServerUri, M2M_SERVER_ADDRESS) && + _register_security->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::NoSecurity)) { + success = true; + /* Not used now because there is no TLS or DTLS implementation available for stack. + security->set_resource_value(M2MSecurity::ServerPublicKey,certificates->certificate_ptr[0],certificates->certificate_len[0]); + security->set_resource_value(M2MSecurity::PublicKey,certificates->certificate_ptr[1],certificates->certificate_len[1]); + security->set_resource_value(M2MSecurity::Secretkey,certificates->own_private_key_ptr,certificates->own_private_key_len); + */ + } + } + return success; + } + + void test_bootstrap() { + _interface->bootstrap(_security); + } + + bool create_device_object() { + bool success = false; + _device = M2MInterfaceFactory::create_device(); + if(_device) { + _device->object_instance()->set_operation(M2MBase::GET_PUT_POST_ALLOWED); + if(_device->create_resource(M2MDevice::Manufacturer,MANUFACTURER) && + _device->create_resource(M2MDevice::DeviceType,TYPE) && + _device->create_resource(M2MDevice::ModelNumber,MODEL_NUMBER) && + _device->create_resource(M2MDevice::SerialNumber,SERIAL_NUMBER)) { + success = true; + } + } + return success; + } + + void execute_function(void *argument) { + if(argument) { + char* arguments = (char*)argument; + printf("Received %s!!\n", arguments); + } + printf("I am executed !!\n"); + } + + bool create_generic_object() { + bool success = false; + _object = M2MInterfaceFactory::create_object("10"); + if(_object) { + _object->set_operation(M2MBase::GET_PUT_POST_ALLOWED); + M2MObjectInstance* inst = _object->create_object_instance(); + if(inst) { + inst->set_operation(M2MBase::GET_PUT_POST_ALLOWED); + inst->set_observable(false); + char buffer[20]; + int size = sprintf(buffer,"%d",_value); + + inst->create_static_resource("0", + "ResourceTest", + M2MResourceInstance::INTEGER, + STATIC_VALUE, + sizeof(STATIC_VALUE)-1); + + M2MResourceInstance* instance = inst->create_dynamic_resource_instance("1", + "ResourceTest", + M2MResourceInstance::INTEGER, + true,0); + + if(instance) { + instance->set_operation(M2MBase::GET_PUT_POST_ALLOWED); + instance->set_value((const uint8_t*)buffer, + (const uint32_t)size); + instance->set_execute_function(execute_callback(this,&MbedClient::execute_function)); + _value++; + } + } + } + return success; + } + + void update_resource() { + if(_object) { + M2MObjectInstance* inst = _object->object_instance(); + if(inst) { + M2MResource* res = inst->resource("1"); + res = inst->resource("1"); + if(res) { + M2MResourceInstance *res_inst = res->resource_instance(0); + if(res_inst) { + char buffer1[20]; + int size1 = sprintf(buffer1,"%d",_value); + res_inst->set_value((const uint8_t*)buffer1, + (const uint32_t)size1); + _value++; + } + } + } + } + } + + void test_register(){ + M2MObjectList object_list; + object_list.push_back(_device); + object_list.push_back(_object); + + _interface->register_object(_register_security,object_list); + } + + void test_update_register() { + uint32_t updated_lifetime = 20; + _registered = false; + _unregistered = false; + _interface->update_registration(_register_security,updated_lifetime); + } + + void test_unregister() { + _interface->unregister_object(NULL); + } + + void bootstrap_done(M2MSecurity *server_object){ + if(server_object) { + _register_security = server_object; + _bootstrapped = true; + printf("\nBootstrapped\n"); + printf("mDS Address %s\n", + _register_security->resource_value_string(M2MSecurity::M2MServerUri).c_str()); + } + } + + void object_registered(M2MSecurity */*security_object*/, const M2MServer &/*server_object*/){ + _registered = true; + printf("\nRegistered\n"); + } + + void object_unregistered(M2MSecurity */*server_object*/){ + _unregistered = true; + printf("\nUnregistered\n"); + } + + void registration_updated(M2MSecurity */*security_object*/, const M2MServer & /*server_object*/){ + _registration_updated = true; + printf("\nregistration updated\n"); + + } + + void error(M2MInterface::Error error){ + _error = true; + close_function(); + printf("\nError occured Error Code : %d\n", (int8_t)error); + + } + + void value_updated(M2MBase *base, M2MBase::BaseType type) { + printf("\nValue updated of Object name %s and Type %d\n", + base->name().c_str(), type); + } + +private: + + M2MInterface *_interface; + M2MSecurity *_security; + M2MSecurity *_register_security; + M2MDevice *_device; + M2MObject *_object; + bool _bootstrapped; + bool _error; + bool _registered; + bool _unregistered; + bool _registration_updated; + int _value; +}; + +void* wait_for_bootstrap(void* arg) { + MbedClient *client; + client = (MbedClient*) arg; + if(client->bootstrap_successful()) { + printf("Registering endpoint\n"); + client->test_register(); + } + return NULL; +} + +void* wait_for_unregister(void* arg) { + MbedClient *client; + client = (MbedClient*) arg; + if(client->unregister_successful()) { + printf("Unregistered done --> exiting\n"); + close_function(); + } + return NULL; +} + +void* send_observation(void* arg) { + MbedClient *client; + client = (MbedClient*) arg; + static uint8_t counter = 0; + while(1) { + sleep(1); + if(counter >= 5 && + client->register_successful()) { + printf("Sending observation\n"); + client->update_resource(); + counter = 0; + } + else + counter++; + } + return NULL; +} + +static MbedClient *m2mclient = NULL; + +static void ctrl_c_handle_function(void) +{ + if(m2mclient && m2mclient->register_successful()) { + printf("Unregistering endpoint\n"); + m2mclient->test_unregister(); + } +} + +void trace_printer(const char* str) +{ + printf("%s\r\n", str); +} + +static pthread_t bootstrap_thread; +static pthread_t unregister_thread; +static pthread_t observation_thread; + +void close_function() { + pthread_cancel(bootstrap_thread); + pthread_cancel(unregister_thread); + pthread_cancel(observation_thread); +} + +int main() { + + MbedClient mbed_client; + + m2mclient = &mbed_client; + + mbed_trace_init(); + mbed_trace_print_function_set( trace_printer ); + mbed_trace_config_set(TRACE_MODE_COLOR|TRACE_ACTIVE_LEVEL_DEBUG|TRACE_CARRIAGE_RETURN); + + signal(SIGINT, (signalhandler_t)ctrl_c_handle_function); + + bool result = mbed_client.create_interface(); + if(true == result) { + printf("\nInterface created\n"); + } + result = mbed_client.create_bootstrap_object(); + if(true == result) { + printf("Bootstrap object created"); + } + + result = mbed_client.create_register_object(); + if(true == result) { + printf("Register object created"); + } + + result = mbed_client.create_device_object(); + if(true == result){ + printf("\nDevice object created !!\n"); + } + + result = mbed_client.create_generic_object(); + + if(true == result) { + printf("\nGeneric object created\n"); + } + +// printf("Bootstrapping endpoint\n"); +// mbed_client.test_bootstrap(); + + printf("Registering endpoint\n"); + mbed_client.test_register(); + + + pthread_create(&bootstrap_thread, NULL, &wait_for_bootstrap, (void*) &mbed_client); + pthread_create(&observation_thread, NULL, &send_observation, (void*) &mbed_client); + pthread_create(&unregister_thread, NULL, &wait_for_unregister, (void*) &mbed_client); + + pthread_join(bootstrap_thread, NULL); + pthread_join(unregister_thread, NULL); + pthread_join(observation_thread, NULL); + + exit(EXIT_SUCCESS); +} + diff --git a/features/FEATURE_CLIENT/mbed-client/version_check.sh b/features/FEATURE_CLIENT/mbed-client/version_check.sh new file mode 100755 index 0000000000..d4f2f64299 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/version_check.sh @@ -0,0 +1,58 @@ +#!/bin/bash +# Copyright (c) 2015 ARM Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# * http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +echo +echo "Check version in module json" +echo +echo $1 +echo $2 + +function version_gt() { + test "$(echo "$@" | tr " " "\n" | sort -V | tail -n 1)" == "$1"; +} + +git clone $1 $PWD/master +git clone $1 $PWD/pull_req +pushd $PWD/pull_req +git checkout $2 +popd +if [ ! -e "$PWD/master/module.json" ] +then + echo "$PWD/master/module.json not found." + exit 1 +fi +if [ ! -e "$PWD/pull_req/module.json" ] +then + echo "$PWD/pull_req/module.json not found." + exit 1 +fi + +OLD_VERSION=`sed -n 's#version##p' master/module.json | sed 's|[^0-9]*\([0-9\.]*\)|\1 |g'` +NEW_VERSION=`sed -n 's#version##p' pull_req/module.json | sed 's|[^0-9]*\([0-9\.]*\)|\1 |g'` + +echo "Version in master branch: $OLD_VERSION" +echo "New version: $NEW_VERSION" + +if [[ "$OLD_VERSION" != "$NEW_VERSION" ]]; then + if version_gt $NEW_VERSION $OLD_VERSION; then + exit 0 + else + echo "Update version in module.json!" + exit 1 +fi +else + echo "Update version in module.json!" + exit 1 +fi diff --git a/features/FEATURE_CLIENT/mbed-client/xsl_script.sh b/features/FEATURE_CLIENT/mbed-client/xsl_script.sh new file mode 100755 index 0000000000..d5320b42b8 --- /dev/null +++ b/features/FEATURE_CLIENT/mbed-client/xsl_script.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# Copyright (c) 2015 ARM Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# * http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +echo +echo "Creating report" +echo + +echo ' + +' >> lcov/index.xml + +for f in lcov/results/*.xml +do +name=${f##*/} +echo ''>> lcov/index.xml +done + +echo '' >> lcov/index.xml + +echo +echo "Report created to lcov/index.xml (outputs html)" +echo \ No newline at end of file